Skip to content

ci: emit signed release.json from the release workflow#127

Merged
rg4444 merged 1 commit into
mainfrom
slice-2/workflow-emit-release-json
May 23, 2026
Merged

ci: emit signed release.json from the release workflow#127
rg4444 merged 1 commit into
mainfrom
slice-2/workflow-emit-release-json

Conversation

@rg4444
Copy link
Copy Markdown
Contributor

@rg4444 rg4444 commented May 23, 2026

Slice 2 wiring — emit signed release.json from the release workflow

Final piece of the Slice 1 / Slice 2A foundation. Layers cleanly on top of #125 (workflow scaffold) and #126 (release-helper + schema). After this lands, tagging v0.1.0 produces a complete signed release.

What this PR adds to release.yml

5 new steps + 4 new release-asset entries:

  1. Set up Go (uses go-version-file: go.mod → matches repo's Go 1.25)
  2. Build release-helpergo build of the stdlib-only Go tool from Slice 2A: release.json schema + generator + processgit update check #126
  3. Generate release.json — runs release-helper with env vars wired from buildx / metadata step outputs
  4. Sign release.json (cosign keyless blob signing) — produces three signature artifacts:
    • release.json.sig (detached signature)
    • release.json.crt (signing certificate)
    • release.json.cosign.bundle (self-contained verification bundle)
  5. Verify release.json signature — inline smoke test

GitHub Release files: list extended with all four new artifacts.

Verifying release.json on a deployment

cosign verify-blob \
  --signature release.json.sig \
  --certificate release.json.crt \
  --certificate-identity-regexp '^https://github.com/Algomation-AI/ProcessGit/\.github/workflows/release\.yml@.*' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  release.json

Or, using the self-contained bundle (no separate .sig/.crt needed):

cosign verify-blob \
  --bundle release.json.cosign.bundle \
  --certificate-identity-regexp '^https://github.com/Algomation-AI/ProcessGit/\.github/workflows/release\.yml@.*' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  release.json

Wiring details

  • IMAGE_DIGEST comes from steps.build.outputs.digest (the multi-arch index digest from docker/build-push-action)
  • IMAGE_ADDITIONAL_TAGS is computed from steps.meta.outputs.tags: drops the primary :VERSION entry, strips to bare tag names, joins CSV
  • SOURCE_TARBALL_URL is constructed deterministically from the GitHub Release download URL pattern; SHA256 + size are read from the artifacts the existing "Create source tarball" step already produced
  • SIGNING_IDENTITY_REGEX and SIGNING_ISSUER are hard-coded to match the workflow's own OIDC identity, so consumers can derive verification commands from the manifest alone

Validation done

  • YAML syntax of the edited release.yml validated
  • release-helper already independently validated in Slice 2A: release.json schema + generator + processgit update check #126 (compiles, emits valid JSON, output validates against release.schema.json)
  • Step ordering verified: Set up Go is early; Build release-helper, Generate release.json, sign, verify all run AFTER the image build (need digest) and AFTER the source tarball (need its sha+size)

After this merges → first real release

  1. git checkout main && git pull --ff-only
  2. git tag -a v0.1.0 -m "ProcessGit v0.1.0 — first release"
  3. git push origin v0.1.0

Expected workflow output: signed multi-arch image at ghcr.io/algomation-ai/processgit:0.1.0 + signed release.json + source tarball + auto-generated changelog, all attached to a single GitHub Release.

Next slices

  • Slice 2B: processgit update download + apply (binary self-update for bare-metal installs)
  • Slice 3: processgit-updater sidecar for Docker self-update
  • Slice 4: Admin UI page at /-/admin/updates

Layers on top of the release workflow (#125) and the release-helper /
schema landed in #126. On every semver tag push, the workflow now also:

  1. Sets up Go (uses go.mod for version)
  2. Builds the release-helper binary (build/release-helper)
  3. Runs release-helper with env vars wired from the buildx / metadata
     step outputs, producing dist/release.json
  4. Signs release.json as a blob with cosign keyless (Sigstore OIDC):
       dist/release.json.sig            -- detached signature
       dist/release.json.crt            -- signing certificate
       dist/release.json.cosign.bundle  -- self-contained verification bundle
  5. Verifies the blob signature inline as a smoke test
  6. Attaches release.json + all three signature artifacts to the
     GitHub Release alongside the source tarball

Wiring details:

  - IMAGE_DIGEST comes from steps.build.outputs.digest (the multi-arch
    index digest produced by docker/build-push-action).
  - IMAGE_ADDITIONAL_TAGS is computed from steps.meta.outputs.tags by
    excluding the primary `:VERSION` tag and stripping to bare tag-names.
  - SOURCE_TARBALL_URL is constructed deterministically from the GH
    Release download URL pattern; SHA256 + size are read from the
    artifacts produced by the existing "Create source tarball" step.
  - SIGNING_IDENTITY_REGEX and SIGNING_ISSUER are hard-coded to match the
    workflow's own OIDC identity, so consumers can derive a verify
    command from the manifest alone.

Verifying release.json on a deployment:

  cosign verify-blob \
    --signature release.json.sig \
    --certificate release.json.crt \
    --certificate-identity-regexp \
      '^https://github.com/Algomation-AI/ProcessGit/\.github/workflows/release\.yml@.*' \
    --certificate-oidc-issuer https://token.actions.githubusercontent.com \
    release.json

After this lands, tagging v0.1.0 produces:
  - signed multi-arch image at ghcr.io/algomation-ai/processgit
  - signed release.json describing the image + signing identity
  - source tarball + sha256
all as assets of a single GitHub Release.

Co-authored-by: Claude <noreply@anthropic.com>
@rg4444 rg4444 merged commit a213e75 into main May 23, 2026
8 of 23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant