ci: release through the standards' shared Velopack workflow; publishers fail instead of skip #77

Merged
KofTwentyTwo merged 2 commits from ci/shared-velopack-release into main 2026-10-09 23:03:21 +00:00
KofTwentyTwo commented 2026-10-09 22:50:37 +00:00 (Migrated from github.com)

What

Releases now build through the standards' shared release-velopack.yml (standards#5, pinned to e8ab30f), which gives SLSA Build L3 provenance and lets exception EX-0004 close after the first successful run. release.yml keeps only what is gclo's, and every publisher fails instead of skipping when it cannot publish, so a green run means every channel shipped (#76, part of #62; blocks #67).

  • release.yml: verify (tag on main) → gates (the full ci workflow, now including the FlaUI suite as a blocking gate since it is a required check on main; the ui-tests-advisory input is removed, closes #54) → release (shared workflow: locked restore, Release build, tests + 100% coverage gate, publish, vpk pack, Syft SBOMs, SHA256SUMS, provenance, draft-then-publish) → caller-side packages (Scoop/Chocolatey manifests PR + choco push), winget, and opt-in nuget. Publishers run in the release environment (created; deployment rule: tags v*) and fail on a missing DEPS_PAT, CHOCO_API_KEY, WINGET_TOKEN/WINGET_PACKAGE_ID, or NUGET_API_KEY when NUGET_PUBLISH is true. Separate jobs, so a failed publisher re-runs alone after its token is added.
  • Lock files: the locked release publish had never run (-p:RestoreLockedMode=true arrived in #68 after the last tag) and failed locally: -r win-x64 --self-contained -p:PublishSingleFile=true changes every project's restore graph (RID graph; Microsoft.NET.ILLink.Tasks via the single-file analyzer). gclo.Engine, gclo.ViewModels and gclo.Cli now declare RuntimeIdentifiers=win-x64 and EnableSingleFileAnalyzer=true, and the lock files carry both graphs, so the plain locked restore and the publish agree.
  • Asset names follow the shared workflow: gclo-cli-win-x64-<version>.zip, gclo-<version>.cdx.json, gclo-cli-<version>.cdx.json; generated release notes replace New-ReleaseNotes.ps1 (deleted). Update-PackageManifests.ps1, bucket/gclo.json (autoupdate URL) and PackagingManifestTests follow; the tests accept both names because 1.0.0's manifests still point at the unversioned asset.
  • LICENSE ships inside the published app and CLI through the project files (the shared workflow does not add it).
  • Docs: docs/RELEASING.md rewritten (required tokens table, rehearsal prerelease step, per-job recovery), ADR 0007, README "Verifying a release" (--signer-repo KofTwentyTwo/standards), SECURITY.md, CONTRIBUTING gate table, ADR 0003, threat model T11 + revision row. #7 lists the tokens to add.

How it was tested

  • dotnet restore gclo.slnx -p:Platform=x64 --locked-mode passes; dotnet build … -warnaserror 0 warnings; gclo.Engine.Tests 422/422 and gclo.Cli.Tests 129/129 with 100% line coverage on all three packages; dotnet format --verify-no-changes --severity warn clean; PSScriptAnalyzer 0 findings; actionlint clean on both workflows.
  • The shared workflow's exact publish commands pass locked mode locally and include LICENSE:
    dotnet publish gclo.Cli/gclo.Cli.csproj -c Release -r win-x64 --self-contained -p:RestoreLockedMode=true -p:PublishSingleFile=true
    dotnet publish gclo/gclo.csproj -c Release -p:Platform=x64 -r win-x64 --self-contained -p:RestoreLockedMode=true -p:WindowsPackageType=None -p:WindowsAppSDKSelfContained=true -p:PublishTrimmed=false
    
  • Not yet exercised on a real tag: the shared workflow has never run (its author asked for gclo's next prerelease to be its first). Per #67 the rehearsal is v1.0.1-beta.2, after the release environment holds the tokens listed on #7.

🤖 Generated with Claude Code

## What Releases now build through the standards' shared `release-velopack.yml` (standards#5, pinned to `e8ab30f`), which gives SLSA Build L3 provenance and lets exception EX-0004 close after the first successful run. `release.yml` keeps only what is gclo's, and every publisher **fails instead of skipping** when it cannot publish, so a green run means every channel shipped (#76, part of #62; blocks #67). - `release.yml`: `verify` (tag on `main`) → `gates` (the full `ci` workflow, now including the FlaUI suite as a blocking gate since it is a required check on `main`; the `ui-tests-advisory` input is removed, closes #54) → `release` (shared workflow: locked restore, Release build, tests + 100% coverage gate, publish, vpk pack, Syft SBOMs, `SHA256SUMS`, provenance, draft-then-publish) → caller-side `packages` (Scoop/Chocolatey manifests PR + `choco push`), `winget`, and opt-in `nuget`. Publishers run in the `release` environment (created; deployment rule: tags `v*`) and fail on a missing `DEPS_PAT`, `CHOCO_API_KEY`, `WINGET_TOKEN`/`WINGET_PACKAGE_ID`, or `NUGET_API_KEY` when `NUGET_PUBLISH` is `true`. Separate jobs, so a failed publisher re-runs alone after its token is added. - **Lock files:** the locked release publish had never run (`-p:RestoreLockedMode=true` arrived in #68 after the last tag) and failed locally: `-r win-x64 --self-contained -p:PublishSingleFile=true` changes every project's restore graph (RID graph; `Microsoft.NET.ILLink.Tasks` via the single-file analyzer). `gclo.Engine`, `gclo.ViewModels` and `gclo.Cli` now declare `RuntimeIdentifiers=win-x64` and `EnableSingleFileAnalyzer=true`, and the lock files carry both graphs, so the plain locked restore and the publish agree. - Asset names follow the shared workflow: `gclo-cli-win-x64-<version>.zip`, `gclo-<version>.cdx.json`, `gclo-cli-<version>.cdx.json`; generated release notes replace `New-ReleaseNotes.ps1` (deleted). `Update-PackageManifests.ps1`, `bucket/gclo.json` (autoupdate URL) and `PackagingManifestTests` follow; the tests accept both names because 1.0.0's manifests still point at the unversioned asset. - LICENSE ships inside the published app and CLI through the project files (the shared workflow does not add it). - Docs: `docs/RELEASING.md` rewritten (required tokens table, rehearsal prerelease step, per-job recovery), ADR 0007, README "Verifying a release" (`--signer-repo KofTwentyTwo/standards`), SECURITY.md, CONTRIBUTING gate table, ADR 0003, threat model T11 + revision row. #7 lists the tokens to add. ## How it was tested - `dotnet restore gclo.slnx -p:Platform=x64 --locked-mode` passes; `dotnet build … -warnaserror` 0 warnings; `gclo.Engine.Tests` 422/422 and `gclo.Cli.Tests` 129/129 with 100% line coverage on all three packages; `dotnet format --verify-no-changes --severity warn` clean; PSScriptAnalyzer 0 findings; `actionlint` clean on both workflows. - The shared workflow's exact publish commands pass locked mode locally and include `LICENSE`: ```powershell dotnet publish gclo.Cli/gclo.Cli.csproj -c Release -r win-x64 --self-contained -p:RestoreLockedMode=true -p:PublishSingleFile=true dotnet publish gclo/gclo.csproj -c Release -p:Platform=x64 -r win-x64 --self-contained -p:RestoreLockedMode=true -p:WindowsPackageType=None -p:WindowsAppSDKSelfContained=true -p:PublishTrimmed=false ``` - Not yet exercised on a real tag: the shared workflow has never run (its author asked for gclo's next prerelease to be its first). Per #67 the rehearsal is `v1.0.1-beta.2`, after the `release` environment holds the tokens listed on #7. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.