You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The release pipeline currently creates the GitHub Release before several finalization steps run. If any of those steps fails (notably OpenUPM signing), the release is already public and the failure produces a misleading false-positive: a published release whose assets are incomplete or unsigned. We want to restructure the workflow into a proper "build everything → atomically publish" shape, where the GitHub Release is created only when every asset (signed UPM package included) is already prepared and ready to attach.
Problem
In .github/workflows/release.yml today:
release-unity-plugin is the job that creates the GitHub Release + tag (softprops/action-gh-release@v2). It runs after tests.
sign-and-publish-upm (added in ci: sign OpenUPM package via Unity UPM CLI on release #776) has needs: release-unity-plugin and runs after the release exists. It is marked continue-on-error: true, so if signing fails or the secrets are missing, the workflow still reports green, but the release that's now public is unsigned.
Release notes (the body) are generated inside release-unity-plugin's own steps (Generate release description writes release.md from git log), so the notes are tightly coupled to the release-creation step.
This shape has two concrete problems:
Signing is a soft afterthought. A signing failure leaves a public, unsigned release in place. The new OpenUPM `trackingMode: githubRelease` consumer would pick up that unsigned release.
Release notes can't be inspected before publication. They're only materialized as a step output during the release-creation job — there's no chance to gather/verify them earlier.
Proposed shape
Restructure the workflow so the GitHub Release is the last thing that happens, gated on every artifact already being prepared:
prepare-release-notes (new) — runs early in parallel with tests. Generates release.md exactly as the current Generate release description step does. Uploads it as a workflow artifact.
build-signed-upm-package (new — extracted from the current sign-and-publish-upm) — runs in parallel with tests/builds. Verifies signing secrets, installs Unity UPM CLI, runs `upm pack --organization-id`, verifies the archive contains `package/.attestation.p7m` and that its basename begins with `com.ivanmurzak.unity.mcp-`. Uploads the signed `.tgz` as a workflow artifact.
release-unity-plugin (modified — the atomic publish point) — needs: is extended to include both new jobs and the existing build-unity-installer / build-and-zip-mcp-server. Downloads all three asset artifacts (.unitypackage, server .zips, signed .tgz) and the release-notes artifact. Creates tag + release with the pre-built notes and uploads every asset in the same softprops/action-gh-release@v2 call (or via per-asset upload steps inside this job — the key requirement is that the tag/release is only created once all assets are on disk in this job).
publish-unity-installer / publish-mcp-server / sign-and-publish-upm as separate post-release jobs — these collapse away. If we keep them as separate jobs for runner/scheduling reasons, they must needs: the release-unity-plugin job and only do the upload (the build/sign work already happened upstream), but in that case the upload failing still strands a release with incomplete assets — so prefer folding the uploads into release-unity-plugin itself.
Hard-gate signing (decision)
The current `continue-on-error: true` design was added so missing secrets wouldn't break releases. That trade-off is being reversed for this restructure: signing is now a hard gate. If `UPM_SERVICE_ACCOUNT_KEY_ID` / `UPM_SERVICE_ACCOUNT_KEY_SECRET` / `UPM_ORG_ID` are missing, the `build-signed-upm-package` job fails fast with a clear error explaining how to configure them (see `docs/openupm-signing.md`), and the release pipeline fails as a whole. No release is created. Forces secret configuration before the next release ships.
Update `docs/openupm-signing.md` to reflect that signing is now blocking, and remove the soft-fail language.
Acceptance criteria
build-signed-upm-package job exists and produces a signed .tgz artifact whose name is fixed/predictable (e.g. signed-upm-package). Runs in parallel with tests; does not depend on release-unity-plugin.
prepare-release-notes job exists and produces a release-notes artifact containing release.md. Runs in parallel with tests; does not depend on release-unity-plugin.
release-unity-pluginneeds: includes build-signed-upm-package, prepare-release-notes, plus the existing test/build dependencies. The release/tag is created only when ALL prerequisite jobs (including signing) succeeded.
All release assets (.unitypackage, server .zips, signed .tgz) are uploaded as part of the same atomic release-creation step inside release-unity-plugin (no post-release upload jobs that can strand a release with missing assets).
The sign-and-publish-upm post-release job is removed (its signing work moved to build-signed-upm-package, its upload work folded into release-unity-plugin).
Missing UPM signing secrets cause the pipeline to fail fast with a clear error message; no GitHub Release is created.
docs/openupm-signing.md is updated to reflect that signing is blocking and to remove the soft-fail language.
Summary
The release pipeline currently creates the GitHub Release before several finalization steps run. If any of those steps fails (notably OpenUPM signing), the release is already public and the failure produces a misleading false-positive: a published release whose assets are incomplete or unsigned. We want to restructure the workflow into a proper "build everything → atomically publish" shape, where the GitHub Release is created only when every asset (signed UPM package included) is already prepared and ready to attach.
Problem
In
.github/workflows/release.ymltoday:release-unity-pluginis the job that creates the GitHub Release + tag (softprops/action-gh-release@v2). It runs after tests.sign-and-publish-upm(added in ci: sign OpenUPM package via Unity UPM CLI on release #776) hasneeds: release-unity-pluginand runs after the release exists. It is markedcontinue-on-error: true, so if signing fails or the secrets are missing, the workflow still reports green, but the release that's now public is unsigned.release-unity-plugin's own steps (Generate release descriptionwritesrelease.mdfromgit log), so the notes are tightly coupled to the release-creation step.This shape has two concrete problems:
Proposed shape
Restructure the workflow so the GitHub Release is the last thing that happens, gated on every artifact already being prepared:
prepare-release-notes(new) — runs early in parallel with tests. Generatesrelease.mdexactly as the currentGenerate release descriptionstep does. Uploads it as a workflow artifact.build-signed-upm-package(new — extracted from the currentsign-and-publish-upm) — runs in parallel with tests/builds. Verifies signing secrets, installs Unity UPM CLI, runs `upm pack --organization-id`, verifies the archive contains `package/.attestation.p7m` and that its basename begins with `com.ivanmurzak.unity.mcp-`. Uploads the signed `.tgz` as a workflow artifact.release-unity-plugin(modified — the atomic publish point) —needs:is extended to include both new jobs and the existingbuild-unity-installer/build-and-zip-mcp-server. Downloads all three asset artifacts (.unitypackage, server.zips, signed.tgz) and the release-notes artifact. Creates tag + release with the pre-built notes and uploads every asset in the samesoftprops/action-gh-release@v2call (or via per-asset upload steps inside this job — the key requirement is that the tag/release is only created once all assets are on disk in this job).publish-unity-installer/publish-mcp-server/sign-and-publish-upmas separate post-release jobs — these collapse away. If we keep them as separate jobs for runner/scheduling reasons, they mustneeds:therelease-unity-pluginjob and only do the upload (the build/sign work already happened upstream), but in that case the upload failing still strands a release with incomplete assets — so prefer folding the uploads intorelease-unity-pluginitself.Hard-gate signing (decision)
The current `continue-on-error: true` design was added so missing secrets wouldn't break releases. That trade-off is being reversed for this restructure: signing is now a hard gate. If `UPM_SERVICE_ACCOUNT_KEY_ID` / `UPM_SERVICE_ACCOUNT_KEY_SECRET` / `UPM_ORG_ID` are missing, the `build-signed-upm-package` job fails fast with a clear error explaining how to configure them (see `docs/openupm-signing.md`), and the release pipeline fails as a whole. No release is created. Forces secret configuration before the next release ships.
Update `docs/openupm-signing.md` to reflect that signing is now blocking, and remove the soft-fail language.
Acceptance criteria
build-signed-upm-packagejob exists and produces a signed.tgzartifact whose name is fixed/predictable (e.g.signed-upm-package). Runs in parallel with tests; does not depend onrelease-unity-plugin.prepare-release-notesjob exists and produces arelease-notesartifact containingrelease.md. Runs in parallel with tests; does not depend onrelease-unity-plugin.release-unity-pluginneeds:includesbuild-signed-upm-package,prepare-release-notes, plus the existing test/build dependencies. The release/tag is created only when ALL prerequisite jobs (including signing) succeeded..unitypackage, server.zips, signed.tgz) are uploaded as part of the same atomic release-creation step insiderelease-unity-plugin(no post-release upload jobs that can strand a release with missing assets).sign-and-publish-upmpost-release job is removed (its signing work moved tobuild-signed-upm-package, its upload work folded intorelease-unity-plugin).docs/openupm-signing.mdis updated to reflect that signing is blocking and to remove the soft-fail language.Context links