Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .agents/skills/elsa-release/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ description: Release Elsa from elsa-core as one tag, one GitHub release and one

- `.github/workflows/packages.yml` runs on `release: published`, pushes to `main` and `release/*`, and `workflow_dispatch`. A release or push only tests, builds and uploads the `elsa-nuget-packages` artifact. It never publishes. Publication needs an approved `workflow_dispatch` with `publish_preview_feedz` (Feedz: a branch, or a `3.10.x` prerelease tag) or `publish_nuget` (nuget.org: a release-version tag, including stable `3.10.x`). Stable 3.10.x Feedz is owned only by `publish-consolidated-original-candidate.yml`.
- Stable `3.10.x` nuget.org publishing is blocked until re-pin ([#9016](https://github.com/elsa-workflows/elsa-core/issues/9016)). Both the `packages.yml` promote path and `publish-consolidated-original-candidate.yml` run `scripts/validate_packages_id_set.py` on the current pin (run/artifact `11412848210`, 225 packages) before any push, so that set cannot be published as 3.10.0. After #9016 re-pins a fresh candidate from the `release/3.10.0` tip, nuget.org promotion and the candidate Feedz publish can proceed. Neither workflow is part of the ordinary release-train helper.
- `studio-npm-pair.yml` only proves that the two Studio npm archives can be built and consumed locally. Nothing in core publishes them to npm or Feedz yet. Stable 3.10.x nuget.org publication is blocked until re-pin ([#9016](https://github.com/elsa-workflows/elsa-core/issues/9016)) (part of [#8725](https://github.com/elsa-workflows/elsa-core/issues/8725)); npm publication remains pending.
- `studio-npm-pair.yml` only proves that the two Studio npm archives can be built and consumed locally. `packages.yml` `publish_npm` publishes `@elsa-workflows/elsa-studio-wasm` and `@elsa-workflows/elsa-studio-wasm-react` to Feedz from a 3.10.x prerelease tag. Stable Feedz publication waits for the 231-ID nuget.org promote guard. The npmjs.com upload is not in this job until trusted publishing is confirmed for `elsa-workflows/elsa-core`. Stable 3.10.x nuget.org publication is blocked until re-pin ([#9016](https://github.com/elsa-workflows/elsa-core/issues/9016)) (part of [#8725](https://github.com/elsa-workflows/elsa-core/issues/8725)).
- The Apps container workflow lived in `elsa-apps` and core has no replacement yet. The container stage is blocked until it is re-homed in core.

## Interpret the request
Expand Down
6 changes: 3 additions & 3 deletions .agents/skills/elsa-release/references/runbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ Studio, Extensions and Apps are folded into `elsa-core`; a release is one `elsa-
What `elsa-core` actually does today (check `origin/main` before relying on it):

- `.github/workflows/packages.yml` builds and uploads packages on `release: published` and on pushes to `main` and `release/*`. Those events never publish. Publication is an approved `workflow_dispatch`: `publish_preview_feedz` (Feedz, from a branch or a `3.10.x` prerelease tag) or `publish_nuget` (nuget.org, from a release-version tag). Stable `3.10.x` Feedz is owned only by `publish-consolidated-original-candidate.yml`.
- Its `./build.sh Compile+Pack` packs Core only. Stable `3.10.x` nuget.org publishing is blocked until re-pin ([#9016](https://github.com/elsa-workflows/elsa-core/issues/9016)). A `publish_nuget` dispatch on a stable `3.10.x` tag does not pack: it downloads the current pin (run/artifact `11412848210`), verifies each `.nupkg` sha256 against that candidate's seal, and runs `scripts/validate_packages_id_set.py` (231 IDs plus the three Studio ClientLib assets per package) before any push. The Oct 6 225-package set fails that guard. That pin's archive size and expiry (`2026-11-05T12:13:30Z`) come from `stable-original-envelope.json`; the replacement candidate's expiry is unknown until it is built. After the freeze, once the [3.10] picks and advisory fixes have landed, #9016 builds a fresh candidate from the `release/3.10.0` tip and re-pins it. `Elsa.SamplePackage` is not packable. The five `Elsa.Secrets.*` IDs and the four `Elsa.Studio.Host.*` IDs stay unpackable and `Elsa.Templates` is not in core. The whole-product 3.10.0 candidate is [prepared without publishing](#consolidated-3100-candidate-preparation-nonpublishing); `publish-consolidated-original-candidate.yml` is the only Feedz publisher for those stable 3.10.x bytes and runs the same 231-ID guard before its Feedz push (also blocked until re-pin (#9016)).
- `studio-npm-pair.yml` is a local proof of the two Studio npm archives. No core workflow publishes them. Stable 3.10.x nuget.org publication is blocked until re-pin ([#9016](https://github.com/elsa-workflows/elsa-core/issues/9016)) (part of [#8725](https://github.com/elsa-workflows/elsa-core/issues/8725)); npm publication remains pending.
- Its `./build.sh Compile+Pack` packs Core only on branch pushes and non-`3.10.0` tags. A `3.10.0` tag `release` event (and a non-promote dispatch from that tag) packs the 231-ID set through `prepare_consolidated_release_candidate.py`. Stable `3.10.x` nuget.org publishing is blocked until re-pin ([#9016](https://github.com/elsa-workflows/elsa-core/issues/9016)). A `publish_nuget` dispatch on a stable `3.10.x` tag does not pack: it downloads the current pin (run/artifact `11412848210`), verifies each `.nupkg` sha256 against that candidate's seal, and runs `scripts/validate_packages_id_set.py` (231 IDs plus the three Studio ClientLib assets per package) before any push. The Oct 6 225-package set fails that guard. That pin's archive size and expiry (`2026-11-05T12:13:30Z`) come from `stable-original-envelope.json`; the replacement candidate's expiry is unknown until it is built. After the freeze, once the [3.10] picks and advisory fixes have landed, #9016 builds a fresh candidate from the `release/3.10.0` tip and re-pins it. `Elsa.SamplePackage` is not packable. The five `Elsa.Secrets.*` IDs and the four `Elsa.Studio.Host.*` IDs stay unpackable and `Elsa.Templates` is not in core. The whole-product 3.10.0 candidate is [prepared without publishing](#consolidated-3100-candidate-preparation-nonpublishing); `publish-consolidated-original-candidate.yml` is the only Feedz publisher for those stable 3.10.x bytes and runs the same 231-ID guard before its Feedz push (also blocked until re-pin (#9016)).
- `studio-npm-pair.yml` is a local proof of the two Studio npm archives. `packages.yml` `publish_npm` publishes `@elsa-workflows/elsa-studio-wasm` and `@elsa-workflows/elsa-studio-wasm-react` to Feedz from a 3.10.x prerelease tag. The npmjs.com upload is not in this job until trusted publishing is confirmed for `elsa-workflows/elsa-core`. Stable `3.10.x` stays fail-closed until the 231-ID nuget.org promote guard can pass. The pair builder accepts 3.8–3.10 versions only.
- Core has no container-image publishing workflow. The Apps workflow it used lived in `elsa-apps`.

## 1. Resolve the plan and preflight the Core and Templates repositories
Expand Down Expand Up @@ -43,7 +43,7 @@ repository's `.github/workflows/packages.yml` actually reads:

| Repository | Secrets read by `packages.yml` | Also confirm |
| --- | --- | --- |
| `elsa-core` | `NUGET_USER` (nuget.org policy owner), `FEEDZ_API_KEY` | nuget.org Trusted Publishing policy for `packages.yml` |
| `elsa-core` | `NUGET_USER` (nuget.org policy owner), `FEEDZ_API_KEY`, `FEEDZ_API_KEY_BASE64` (Feedz npm) | nuget.org Trusted Publishing policy for `packages.yml` |
| `elsa-templates` | `NUGET_USER`, `FEEDZ_API_KEY` | nuget.org policy |

Never print or copy a secret value. The check stops on any API error rather
Expand Down
146 changes: 143 additions & 3 deletions .github/workflows/packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ on:
required: true
type: boolean
default: false
publish_npm:
description: Publish the Studio npm pair to Feedz for this run (requires publisher approval). Live for 3.10.x prerelease tags. npmjs.com is not in this job until trusted publishing is confirmed. Stable 3.10.x stays fail-closed until the 231-ID nuget.org promote guard can pass.
required: true
type: boolean
default: false
deploy_coverage:
description: Deploy coverage to GitHub Pages for this run (requires deployment approval).
required: true
Expand Down Expand Up @@ -56,6 +61,7 @@ jobs:
REF: ${{ github.ref }}
PUBLISH_PREVIEW_FEEDZ: ${{ inputs.publish_preview_feedz }}
PUBLISH_NUGET: ${{ inputs.publish_nuget }}
PUBLISH_NPM: ${{ inputs.publish_npm }}
DEPLOY_COVERAGE: ${{ inputs.deploy_coverage }}
run: python3 scripts/validate_packages_publication_selection.py

Expand Down Expand Up @@ -313,7 +319,7 @@ jobs:
- test_component
- validate_publication_selection
runs-on: ubuntu-latest
timeout-minutes: 30
timeout-minutes: 180
# Push and release events build as before; the selection check only runs on
# manual dispatch, and a dispatch it rejects must not build.
if: ${{ !cancelled() && github.event_name != 'pull_request' && needs.test_unit_integration.result == 'success' && needs.test_component.result == 'success' && (github.event_name != 'workflow_dispatch' || needs.validate_publication_selection.result == 'success') }}
Expand Down Expand Up @@ -372,12 +378,32 @@ jobs:
- uses: actions/setup-dotnet@v4
if: ${{ !(github.event_name == 'workflow_dispatch' && inputs.publish_nuget && startsWith(github.ref, 'refs/tags/3.10.') && !contains(github.ref_name, '-')) }}
with:
dotnet-version: 10.x
dotnet-version: |
8.0.x
9.0.x
10.x

- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
if: ${{ (github.event_name == 'release' || github.event_name == 'workflow_dispatch') && github.ref == 'refs/tags/3.10.0' && !(github.event_name == 'workflow_dispatch' && inputs.publish_nuget) }}
with:
python-version: '3.12'

- name: Compile+Pack
if: ${{ !(github.event_name == 'workflow_dispatch' && inputs.publish_nuget && startsWith(github.ref, 'refs/tags/3.10.') && !contains(github.ref_name, '-')) }}
if: ${{ !((github.event_name == 'workflow_dispatch' && inputs.publish_nuget && startsWith(github.ref, 'refs/tags/3.10.') && !contains(github.ref_name, '-')) || ((github.event_name == 'release' || github.event_name == 'workflow_dispatch') && github.ref == 'refs/tags/3.10.0')) }}
run: ./build.sh Compile+Pack --version "${VERSION}" --analyseCode true

# --version 3.10.0 matches the refs/tags/3.10.0 guard above. The inventory
# baseline is per branch: this file on release/3.10.0 is this branch's
# evaluation. It is not main's inventory; the two are not the same.
- name: Pack consolidated 3.10.0 set
if: ${{ (github.event_name == 'release' || github.event_name == 'workflow_dispatch') && github.ref == 'refs/tags/3.10.0' && !(github.event_name == 'workflow_dispatch' && inputs.publish_nuget) }}
env:
PACKAGES_DIR: ${{ github.workspace }}/packages
run: |
set -euo pipefail
python3 scripts/integration-program/prepare_consolidated_release_candidate.py --version 3.10.0 --output "$RUNNER_TEMP/consolidated-candidate" --remote-sources
python3 scripts/validate_packages_id_set.py

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
Expand Down Expand Up @@ -492,6 +518,120 @@ jobs:
feed-source: ${{ env.nuget_feed_source }}
api-key: ${{ steps.nuget_login.outputs.NUGET_API_KEY }}

build_npm:
name: Build Studio npm pair
needs: [build, validate_publication_selection]
runs-on: ubuntu-latest
timeout-minutes: 120
env:
PYTHONDONTWRITEBYTECODE: '1'
if: ${{ github.event_name == 'workflow_dispatch' && inputs.publish_npm && startsWith(github.ref, 'refs/tags/') }}
permissions:
contents: read
steps:
- name: Check out the Studio npm pair
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false

- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: '3.12'

- uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1
with:
dotnet-version: '10.0.300'

- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: '22'

- name: Build the Studio npm pair
run: |
set -euo pipefail
python3 scripts/integration-program/prove_studio_npm_pair.py \
--commit "${GITHUB_SHA}" --version "${GITHUB_REF_NAME}" \
--run-id "${GITHUB_RUN_ID}" --run-attempt "${GITHUB_RUN_ATTEMPT}" \
--release-candidate --output "$RUNNER_TEMP/studio-npm-pair"
Comment thread
cursor[bot] marked this conversation as resolved.
Resolved

- name: Upload Studio npm pair
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: studio-npm-pair
path: ${{ runner.temp }}/studio-npm-pair/retained/*.tgz
if-no-files-found: error
retention-days: 30

publish_npm:
name: Publish Studio npm pair
needs: [build_npm, validate_publication_selection]
runs-on: ubuntu-latest
timeout-minutes: 30
if: ${{ github.event_name == 'workflow_dispatch' && inputs.publish_npm && startsWith(github.ref, 'refs/tags/') }}
permissions:
contents: read
steps:
- name: Fail closed on stable 3.10.x
if: ${{ startsWith(github.ref, 'refs/tags/3.10.') && !contains(github.ref_name, '-') }}
run: |
echo "Stable 3.10.x Studio npm pair stays fail-closed until the 231-ID nuget.org promote guard can pass."
exit 1

- name: Configure Feedz registry
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: '22'
registry-url: https://f.feedz.io/elsa-workflows/elsa-3/npm/

- name: Download Studio npm pair
uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7
with:
name: studio-npm-pair
path: ${{ runner.temp }}/studio-npm-pair

- name: Verify Studio npm pair
run: |
set -euo pipefail
dir="$RUNNER_TEMP/studio-npm-pair"
wasm="elsa-workflows-elsa-studio-wasm-${GITHUB_REF_NAME}.tgz"
react="elsa-workflows-elsa-studio-wasm-react-${GITHUB_REF_NAME}.tgz"
test -f "$dir/$wasm"
test -f "$dir/$react"
count=$(find "$dir" -maxdepth 1 -name '*.tgz' | wc -l)
test "$count" -eq 2

- name: npm publish to Feedz
env:
NODE_AUTH_TOKEN: ${{ secrets.FEEDZ_API_KEY_BASE64 }}
run: |
set -euo pipefail
if [ -z "${NODE_AUTH_TOKEN:-}" ]; then
echo "::error::Feedz npm key resolved empty; nothing was published."
exit 1
fi
status=0
for file in "$RUNNER_TEMP"/studio-npm-pair/*.tgz
do
version=$(tar -xzOf "$file" package/package.json \
| node -e "let s='';process.stdin.on('data',d=>s+=d).on('end',()=>console.log(JSON.parse(s).version))")
case "$version" in
*-*) tag=next ;;
*) tag=latest ;;
esac
echo "Publishing $file ($version) with --tag $tag"
if output=$(npm publish "$file" --access public --tag "$tag" 2>&1); then
echo "$output"
else
echo "$output"
if echo "$output" | grep -qiE 'EPUBLISHCONFLICT|cannot publish over'; then
echo "::notice::$file is already published at this version - skipping"
else
status=1
fi
fi
done
exit $status

deploy_coverage:
name: Deploy coverage to GitHub Pages
needs: [coverage_report, validate_publication_selection]
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/validate-packages-gates.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ on:
- 'scripts/integration-program/test_prepare_consolidated_release_candidate.py'
- 'scripts/integration-program/consolidated-candidate-inventory-baseline.json'
- 'scripts/integration-program/prove_consolidated*.py'
- 'scripts/integration-program/prove_studio_npm_pair.py'
- 'scripts/integration-program/test_prove_studio_npm_pair.py'
Comment thread
elsa-workflows-review-bot[bot] marked this conversation as resolved.
Resolved
- 'scripts/integration-program/test_prove_consolidated*.py'
- 'scripts/integration-program/consolidated-package-consumer/**'
- 'build/Build.cs'
Expand Down Expand Up @@ -49,6 +51,8 @@ on:
- 'scripts/integration-program/test_prepare_consolidated_release_candidate.py'
- 'scripts/integration-program/consolidated-candidate-inventory-baseline.json'
- 'scripts/integration-program/prove_consolidated*.py'
- 'scripts/integration-program/prove_studio_npm_pair.py'
- 'scripts/integration-program/test_prove_studio_npm_pair.py'
- 'scripts/integration-program/test_prove_consolidated*.py'
- 'scripts/integration-program/consolidated-package-consumer/**'
- 'build/Build.cs'
Expand Down
Loading
Loading