From 62595642e3f50bd36764986529f988893d9fc108 Mon Sep 17 00:00:00 2001 From: miguelgfierro Date: Tue, 28 Apr 2026 11:52:43 +0200 Subject: [PATCH 1/6] ci: add release workflow and bump version to 26.04.28 Adds .github/workflows/release.yml that builds the frontend, bundles it into the wheel, builds wheel + sdist with uv, and creates a GitHub Release with the artifacts attached. Triggers on tag push matching the CalVer pattern, plus manual workflow_dispatch. Bumps the package version to 26.04.28 to reflect the actual cut date, and relabels the corresponding CHANGELOG section. The 26.02.07 entry was prepared but never tagged, so this is the first real release of the SvelteKit-based Studio as its own package. The workflow guards against drift by failing the build if the tag does not match pyproject.toml's version field. --- .github/workflows/release.yml | 121 ++++++++++++++++++++++++++++++++++ CHANGELOG.md | 2 +- pyproject.toml | 2 +- 3 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..f912871 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,121 @@ +name: Release + +on: + push: + tags: + - '[0-9]+.[0-9]+.[0-9]+' + workflow_dispatch: + inputs: + tag: + description: 'Existing tag to release (e.g., 26.04.28). Must already be pushed to the repo.' + required: true + type: string + +permissions: + contents: read + +concurrency: + group: release-${{ github.ref }} + cancel-in-progress: false + +jobs: + build: + name: Build wheel + sdist + runs-on: ubuntu-latest + outputs: + tag: ${{ steps.tag.outputs.value }} + steps: + - name: Resolve tag + id: tag + run: | + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + echo "value=${{ inputs.tag }}" >> "$GITHUB_OUTPUT" + else + echo "value=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT" + fi + + - uses: actions/checkout@v4 + with: + ref: ${{ steps.tag.outputs.value }} + + - name: Verify tag matches pyproject version + run: | + tag="${{ steps.tag.outputs.value }}" + pv=$(grep -E '^version' pyproject.toml | head -1 | sed -E 's/.*"(.*)".*/\1/') + if [ "$tag" != "$pv" ]; then + echo "::error::Tag '$tag' does not match pyproject.toml version '$pv'." + exit 1 + fi + + - uses: actions/setup-node@v4 + with: + node-version: '22' + cache: npm + cache-dependency-path: studio-frontend/package-lock.json + + - name: Build frontend + working-directory: studio-frontend + run: | + npm ci + npm run build + + - name: Stage frontend into package + run: | + mkdir -p src/fireflyframework_agentic_studio/static + cp -r studio-frontend/build/. src/fireflyframework_agentic_studio/static/ + + - uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 + with: + enable-cache: true + + - uses: actions/setup-python@v5 + with: + python-version: '3.13' + + - name: Build distributions + run: uv build + + - uses: actions/upload-artifact@v4 + with: + name: dist + path: dist/ + retention-days: 7 + + release: + name: Create GitHub Release + needs: build + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ needs.build.outputs.tag }} + + - uses: actions/download-artifact@v4 + with: + name: dist + path: dist/ + + - name: Extract release notes from CHANGELOG + run: | + tag="${{ needs.build.outputs.tag }}" + awk -v tag="$tag" ' + $0 ~ "^## \\[" tag "\\]" { found=1; next } + found && /^## \[/ { exit } + found { print } + ' CHANGELOG.md > /tmp/notes.md + if [ ! -s /tmp/notes.md ]; then + printf "Release %s\n" "$tag" > /tmp/notes.md + fi + + - name: Create GitHub Release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + tag="${{ needs.build.outputs.tag }}" + gh release create "$tag" \ + --title "$tag" \ + --notes-file /tmp/notes.md \ + --verify-tag \ + dist/* diff --git a/CHANGELOG.md b/CHANGELOG.md index e82e834..6f64ac7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to `fireflyframework-agentic-studio` will be documented in t The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [26.02.07] — Initial Release +## [26.04.28] — Initial Release Studio extracted from `fireflyframework-agentic` (formerly `fireflyframework-genai`) into its own repository. See [MIGRATION](README.md#migration-from-fireflyframework-agenticstudio) diff --git a/pyproject.toml b/pyproject.toml index e31f99b..ec72366 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "fireflyframework-agentic-studio" -version = "26.02.07" +version = "26.04.28" description = "Visual IDE and runtime for fireflyframework-agentic. Drag-and-drop pipeline builder, code generation, AI assistant, project API, scheduling, and tunnel exposure." readme = "README.md" license = { text = "Apache-2.0" } From f74e15ea680762defb896c7db1e7b7749b9eb939 Mon Sep 17 00:00:00 2001 From: miguelgfierro Date: Tue, 28 Apr 2026 12:02:12 +0200 Subject: [PATCH 2/6] ci: align release workflow with fireflyframework-agentic style Collapses release.yml to a single job mirroring the agentic repo: top-level contents: write permission, gh release create with --generate-notes, github.ref_name for the tag. Drops the separate build/release split, the workflow_dispatch entrypoint, the artifact upload/download dance, the CHANGELOG notes extraction, and the tag-vs-pyproject drift check. Keeps the studio-specific frontend build steps (npm ci + npm run build + stage into static/) before uv build, since studio bundles the SvelteKit output into the wheel. --- .github/workflows/release.yml | 90 ++++------------------------------- 1 file changed, 8 insertions(+), 82 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f912871..816ab7c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,50 +2,17 @@ name: Release on: push: - tags: - - '[0-9]+.[0-9]+.[0-9]+' - workflow_dispatch: - inputs: - tag: - description: 'Existing tag to release (e.g., 26.04.28). Must already be pushed to the repo.' - required: true - type: string + tags: ['[0-9]+.[0-9]+.[0-9]+'] permissions: - contents: read - -concurrency: - group: release-${{ github.ref }} - cancel-in-progress: false + contents: write jobs: - build: - name: Build wheel + sdist + release: + name: Build & Release runs-on: ubuntu-latest - outputs: - tag: ${{ steps.tag.outputs.value }} steps: - - name: Resolve tag - id: tag - run: | - if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then - echo "value=${{ inputs.tag }}" >> "$GITHUB_OUTPUT" - else - echo "value=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT" - fi - - uses: actions/checkout@v4 - with: - ref: ${{ steps.tag.outputs.value }} - - - name: Verify tag matches pyproject version - run: | - tag="${{ steps.tag.outputs.value }}" - pv=$(grep -E '^version' pyproject.toml | head -1 | sed -E 's/.*"(.*)".*/\1/') - if [ "$tag" != "$pv" ]; then - echo "::error::Tag '$tag' does not match pyproject.toml version '$pv'." - exit 1 - fi - uses: actions/setup-node@v4 with: @@ -67,55 +34,14 @@ jobs: - uses: astral-sh/setup-uv@e58605a9b6da7c637471fab8847a5e5a6b8df081 # v5 with: enable-cache: true - - uses: actions/setup-python@v5 with: python-version: '3.13' - - name: Build distributions - run: uv build - - - uses: actions/upload-artifact@v4 - with: - name: dist - path: dist/ - retention-days: 7 - - release: - name: Create GitHub Release - needs: build - runs-on: ubuntu-latest - permissions: - contents: write - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ needs.build.outputs.tag }} - - - uses: actions/download-artifact@v4 - with: - name: dist - path: dist/ - - - name: Extract release notes from CHANGELOG - run: | - tag="${{ needs.build.outputs.tag }}" - awk -v tag="$tag" ' - $0 ~ "^## \\[" tag "\\]" { found=1; next } - found && /^## \[/ { exit } - found { print } - ' CHANGELOG.md > /tmp/notes.md - if [ ! -s /tmp/notes.md ]; then - printf "Release %s\n" "$tag" > /tmp/notes.md - fi + - run: uv build - name: Create GitHub Release env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - tag="${{ needs.build.outputs.tag }}" - gh release create "$tag" \ - --title "$tag" \ - --notes-file /tmp/notes.md \ - --verify-tag \ - dist/* + GH_TOKEN: ${{ github.token }} + TAG_NAME: ${{ github.ref_name }} + run: gh release create "$TAG_NAME" dist/* --generate-notes From dee2d98c2ec5208a874a6b4702998cddef41b929 Mon Sep 17 00:00:00 2001 From: miguelgfierro Date: Tue, 28 Apr 2026 12:12:17 +0200 Subject: [PATCH 3/6] ci: switch tag pattern to 'v*' to match agentic Aligns the release trigger with fireflyframework-agentic, which uses tags: ['v*'] on GitHub. Means the tag for the first release will be v26.04.28 (the package version stays 26.04.28 in pyproject). --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 816ab7c..74f84e5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,7 +2,7 @@ name: Release on: push: - tags: ['[0-9]+.[0-9]+.[0-9]+'] + tags: ['v*'] permissions: contents: write From fd8369a342a86a10ac3411e0c24187b690c895c7 Mon Sep 17 00:00:00 2001 From: miguelgfierro Date: Tue, 28 Apr 2026 12:20:07 +0200 Subject: [PATCH 4/6] fix(deps): pin fireflyframework-agentic to tag v26.04.28 The previous source pointed at branch refactor/rename-to-agentic on the agentic repo, which has been deleted (the rename was merged). CI on main has been broken since then because uv sync cannot resolve the dependency. Pinning to tag v26.04.28 (the latest release of fireflyframework- agentic, published today) makes the resolution stable and aligns studio's release with the agentic version it depends on. --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index ec72366..2ed3a5c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -62,7 +62,7 @@ build-backend = "uv_build" # TODO: remove once fireflyframework-agentic is published to PyPI. # Until then, resolve it directly from GitHub. [tool.uv.sources] -fireflyframework-agentic = { git = "https://github.com/fireflyframework/fireflyframework-agentic.git", branch = "refactor/rename-to-agentic" } +fireflyframework-agentic = { git = "https://github.com/fireflyframework/fireflyframework-agentic.git", tag = "v26.04.28" } [tool.ruff] target-version = "py313" From 769da4a31e2c82714d1a4cad2d89f725f4ec7624 Mon Sep 17 00:00:00 2001 From: miguelgfierro Date: Tue, 28 Apr 2026 12:26:44 +0200 Subject: [PATCH 5/6] fix(assistant): import __version__ from fireflyframework_agentic root The two get_framework_docs implementations imported __version__ from fireflyframework_agentic._version, but that submodule does not exist in the package. The version is exposed directly at the top level (__init__.py: __version__ = version("fireflyframework-agentic")). Pyright flagged this as reportMissingImports once the dependency started resolving again. Runtime behavior is unchanged because the broken import was already wrapped in a try/except Exception that fell through to docs["version"] = "unknown". --- src/fireflyframework_agentic_studio/assistant/agent.py | 2 +- src/fireflyframework_agentic_studio/assistant/smith.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fireflyframework_agentic_studio/assistant/agent.py b/src/fireflyframework_agentic_studio/assistant/agent.py index 1d6a630..1705068 100644 --- a/src/fireflyframework_agentic_studio/assistant/agent.py +++ b/src/fireflyframework_agentic_studio/assistant/agent.py @@ -521,7 +521,7 @@ async def get_framework_docs() -> str: # Framework version try: - from fireflyframework_agentic._version import __version__ + from fireflyframework_agentic import __version__ docs["version"] = __version__ except Exception: diff --git a/src/fireflyframework_agentic_studio/assistant/smith.py b/src/fireflyframework_agentic_studio/assistant/smith.py index c8a84b0..8a83d2c 100644 --- a/src/fireflyframework_agentic_studio/assistant/smith.py +++ b/src/fireflyframework_agentic_studio/assistant/smith.py @@ -382,7 +382,7 @@ async def get_framework_docs() -> str: docs: dict[str, Any] = {} try: - from fireflyframework_agentic._version import __version__ + from fireflyframework_agentic import __version__ docs["version"] = __version__ except Exception: From 3574a53e0e3a99e220e66fbea453a8bc0994ce92 Mon Sep 17 00:00:00 2001 From: miguelgfierro Date: Tue, 28 Apr 2026 12:37:56 +0200 Subject: [PATCH 6/6] chore(deps): track fireflyframework-agentic main, leave tag option as comment Switches the uv source from tag = "v26.04.28" to branch = "main" so studio picks up agentic changes without needing a bump on this side each time. Keeps the tag-pinning syntax as a comment above for when we want a reproducible build. --- pyproject.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 2ed3a5c..d4e767c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -61,8 +61,10 @@ build-backend = "uv_build" # TODO: remove once fireflyframework-agentic is published to PyPI. # Until then, resolve it directly from GitHub. +# To pin a reproducible release instead of tracking main, swap the line below for: +# fireflyframework-agentic = { git = "https://github.com/fireflyframework/fireflyframework-agentic.git", tag = "v26.04.28" } [tool.uv.sources] -fireflyframework-agentic = { git = "https://github.com/fireflyframework/fireflyframework-agentic.git", tag = "v26.04.28" } +fireflyframework-agentic = { git = "https://github.com/fireflyframework/fireflyframework-agentic.git", branch = "main" } [tool.ruff] target-version = "py313"