Skip to content

ci: add release workflow (semver tag → GHCR + cosign + GH Release)#125

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

ci: add release workflow (semver tag → GHCR + cosign + GH Release)#125
rg4444 merged 1 commit into
mainfrom
slice-1/release-workflow

Conversation

@rg4444
Copy link
Copy Markdown
Contributor

@rg4444 rg4444 commented May 22, 2026

Slice 1.2 — Release workflow

Adds .github/workflows/release.yml. Follow-up to #1 (Makefile rename).

Behaviour

Triggers on:

  • semver tag push: v[0-9]+.[0-9]+.[0-9]+ and pre-release variants (v0.1.0-rc1 etc.)
  • workflow_dispatch — dry-run mode for testing the build without publishing

On a tag push:

Step What
Build Multi-arch Docker (linux/amd64, linux/arm64) via deploy/Dockerfile.processgit, BuildKit GHA cache
Push ghcr.io/algomation-ai/processgit — tags :0.1.0 (immutable) + :0.1, :0, :latest (moving, stable only)
Sign Cosign keyless via Sigstore (GitHub OIDC) — no private keys to manage
Verify Inline cosign verify smoke test against the just-signed image
Tarball Source archive + SHA-256, attached to the GitHub Release
Release GitHub Release with auto-generated notes (git log since previous semver tag)

Pre-release tags only receive the immutable :VERSION tag — they do not move :MAJOR, :MAJOR.MINOR, or :latest.

One-time setup required BEFORE first tag push

Settings → Actions → General → Workflow permissions must be set to Read and write permissions. Without this, the GHCR push will fail.

After the first release, also: Org → Packages → processgit → Change visibility → Public (so users can docker pull without docker login).

After this merges — ship v0.1.0

  1. (Optional) Actions → Release → Run workflow → leave dry_run: true → Run. Validates multi-arch build without publishing.
  2. git checkout main && git pull --ff-only
    git tag -a v0.1.0 -m "ProcessGit v0.1.0 — first release"
    git push origin v0.1.0
  3. Workflow fires automatically. ~15–25 min first run, ~6–8 min subsequent (GHA buildx cache).

Verify a published image

docker pull ghcr.io/algomation-ai/processgit:0.1.0

cosign verify ghcr.io/algomation-ai/processgit:0.1.0 \
  --certificate-identity-regexp '^https://github.com/Algomation-AI/ProcessGit/\.github/workflows/release\.yml@.*' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com

(Reprinted in every release's notes.)

Validation done

  • YAML syntax of release.yml validated (python3 -c 'yaml.safe_load')
  • Manually reviewed against GitHub Actions schema (network sandbox blocked local actionlint install — module proxy domains not in allowlist)
  • All action versions are current released majors (actions/checkout@v5, docker/build-push-action@v6, sigstore/cosign-installer@v3, softprops/action-gh-release@v2, docker/metadata-action@v5)

Next slices (not in this PR)

  • Slice 2: release.json manifest schema + generator script; cmd/update.go (processgit update subcommand) — for self-update from the binary
  • Slice 3: processgit-updater sidecar (Go, /var/run/docker.sock) for Docker deployments
  • Slice 4: Admin UI page at /-/admin/updates
  • Cleanups: pin gitea/gitea:latest base image, fix root Dockerfile line 47 (/src/gitea ref), pin upstream Gitea ref in UPSTREAM.md

Adds .github/workflows/release.yml. On every semver tag push
(`v[0-9]+.[0-9]+.[0-9]+`, including pre-releases like -rc1), it:

  - Builds a multi-arch Docker image (linux/amd64, linux/arm64) via
    deploy/Dockerfile.processgit
  - Pushes to ghcr.io/algomation-ai/processgit with tags:
      :VERSION                    (immutable per release)
      :MAJOR.MINOR, :MAJOR, :latest   (moving, stable only)
    Pre-release tags only get the immutable :VERSION-X tag.
  - Signs the image with cosign keyless via Sigstore (OIDC), no key
    management required.
  - Runs an inline cosign verify smoke test against the just-signed
    image.
  - Builds and attaches a source tarball + SHA-256.
  - Creates a GitHub Release with auto-generated notes (git log
    since the previous semver tag) including the verify command.

Also supports workflow_dispatch with a dry_run input (default true)
for testing the build path without publishing.

Required permissions (in workflow):
  contents: write   -- create GitHub Release
  packages: write   -- push to ghcr.io
  id-token: write   -- cosign keyless OIDC signing

Required one-time repo setup BEFORE the first tag push:
  Settings -> Actions -> General -> Workflow permissions
    -> "Read and write permissions"

Verify a published image:
  cosign verify ghcr.io/algomation-ai/processgit:VERSION \
    --certificate-identity-regexp \
      '^https://github.com/Algomation-AI/ProcessGit/\.github/workflows/release\.yml@.*' \
    --certificate-oidc-issuer https://token.actions.githubusercontent.com

Co-authored-by: Claude <noreply@anthropic.com>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 60b4f51fd5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

echo ""
echo "${COMPARE_LINE}"
echo ""
git log --pretty=format:"- %s (%h) — @%an" "${RANGE}" | head -200
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Replace piped git log | head with bounded git log

With set -euo pipefail enabled in this step, git log ... | head -200 can fail the job when more than 200 commits are in RANGE (common on initial releases): head exits after 200 lines, git log receives SIGPIPE, and the pipeline status becomes non-zero, aborting release-note generation and therefore the release workflow. Use git log -n 200 ... (or otherwise avoid this pipe) so large ranges do not break publishing.

Useful? React with 👍 / 👎.

@rg4444 rg4444 merged commit ef1c1c6 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