ci(build): add workflow_dispatch workflow for ad-hoc feature-branch images (#108) #109

Merged
james merged 1 commit from 108-feature-branch-image-workflow into main 2026-06-18 12:46:42 +00:00
Owner

Closes #108.

What this adds

.forgejo/workflows/build-feature-image.yml — a workflow_dispatch workflow that builds a container image from any branch (selected in the Run UI) and optionally pushes it to the registry as branch-<slugified-branch>-<sha7>. Closes the gap between "I want to poke at this branch in a container" and "tag a release candidate", which was the only path into the registry before.

Single boolean input: push (default true). Uncheck for a dry-run build that doesn't consume registry storage — useful as a "does this branch even build" sanity check.

Design choices made (confirmed in chat)

Decision Why
Trigger workflow_dispatch only Manual gate prevents registry-tag noise from every routine push.
Signing None — unsigned ad-hoc tag Reserves cosign keypair + Rekor entries for actual releases per ADR-0014; saves ~30s per build.
Tag prefix branch-… A self-hoster's registry listing immediately distinguishes ad-hoc from release tags.
:latest Not touched Release-only behavior.
Registry forge.int.wynning.tech push, forge.wynning.tech for the user-facing pull reference Same CF-bypass split #76 established for release.yml.
OCI labels Stamp standard image.source / revision / version plus tech.wynning.carol.build-type=feature-branch docker inspect makes the image's nature obvious.

Files

File Change
.forgejo/workflows/build-feature-image.yml New workflow file.
docs/ci.md New "Ad-hoc feature-branch image builds" section: what it produces, what it deliberately doesn't, how to run, cleanup story.

Test plan

  • actionlint .forgejo/workflows/*.yml — clean across all workflow files including the new one.
  • Post-merge dry run: open the new workflow in the Forgejo Actions UI, run it against this branch (or main) with push=false. Expect a successful build that doesn't upload anything; log line names the tag.
  • Post-merge push run: same, with push=true. Expect forge.wynning.tech/james/carol:branch-<slug>-<sha7> in the registry, pullable via docker pull.
  • docker inspect <image> shows the tech.wynning.carol.build-type=feature-branch label and the standard OCI labels.

Follow-up gestures

  • Registry-side retention / GC for accumulated branch-… tags — file when the registry starts feeling full.
  • Sticky PR comment with the built image reference, like #68 did for scanners. Possible follow-up if "find the image you built last week from this PR" becomes painful.

A small detour worth noting

Your message had the word "workflow" in it which triggered the harness's multi-agent-orchestration opt-in heuristic. That tool is for fan-out tasks (parallel finders, judge panels, etc.), not for "write a CI workflow YAML file". Proceeded as a normal single-PR task — flagging in case the heuristic keeps tripping and you want it suppressed somehow.

Closes #108. ## What this adds `.forgejo/workflows/build-feature-image.yml` — a `workflow_dispatch` workflow that builds a container image from any branch (selected in the Run UI) and optionally pushes it to the registry as `branch-<slugified-branch>-<sha7>`. Closes the gap between "I want to poke at this branch in a container" and "tag a release candidate", which was the only path into the registry before. Single boolean input: **`push`** (default `true`). Uncheck for a dry-run build that doesn't consume registry storage — useful as a "does this branch even build" sanity check. ## Design choices made (confirmed in chat) | | Decision | Why | |---|---|---| | **Trigger** | `workflow_dispatch` only | Manual gate prevents registry-tag noise from every routine push. | | **Signing** | None — unsigned ad-hoc tag | Reserves cosign keypair + Rekor entries for actual releases per ADR-0014; saves ~30s per build. | | **Tag prefix** | `branch-…` | A self-hoster's registry listing immediately distinguishes ad-hoc from release tags. | | **`:latest`** | Not touched | Release-only behavior. | | **Registry** | `forge.int.wynning.tech` push, `forge.wynning.tech` for the user-facing pull reference | Same CF-bypass split #76 established for release.yml. | | **OCI labels** | Stamp standard `image.source` / `revision` / `version` plus `tech.wynning.carol.build-type=feature-branch` | `docker inspect` makes the image's nature obvious. | ## Files | File | Change | |---|---| | `.forgejo/workflows/build-feature-image.yml` | New workflow file. | | `docs/ci.md` | New "Ad-hoc feature-branch image builds" section: what it produces, what it deliberately doesn't, how to run, cleanup story. | ## Test plan - [x] `actionlint .forgejo/workflows/*.yml` — clean across all workflow files including the new one. - [ ] **Post-merge dry run**: open the new workflow in the Forgejo Actions UI, run it against this branch (or main) with `push=false`. Expect a successful build that doesn't upload anything; log line names the tag. - [ ] **Post-merge push run**: same, with `push=true`. Expect `forge.wynning.tech/james/carol:branch-<slug>-<sha7>` in the registry, pullable via `docker pull`. - [ ] `docker inspect <image>` shows the `tech.wynning.carol.build-type=feature-branch` label and the standard OCI labels. ## Follow-up gestures - Registry-side retention / GC for accumulated `branch-…` tags — file when the registry starts feeling full. - Sticky PR comment with the built image reference, like #68 did for scanners. Possible follow-up if "find the image you built last week from this PR" becomes painful. ## A small detour worth noting Your message had the word "workflow" in it which triggered the harness's multi-agent-orchestration opt-in heuristic. That tool is for fan-out tasks (parallel finders, judge panels, etc.), not for "write a CI workflow YAML file". Proceeded as a normal single-PR task — flagging in case the heuristic keeps tripping and you want it suppressed somehow.
ci(build): add workflow_dispatch workflow for ad-hoc feature-branch images (#108)
All checks were successful
Commits / Conventional Commits (pull_request) Successful in 14s
PR / npm audit (pull_request) Successful in 45s
PR / OSV-Scanner (pull_request) Successful in 45s
Secrets / gitleaks (pull_request) Successful in 30s
PR / Typecheck (pull_request) Successful in 50s
PR / Static analysis (pull_request) Successful in 50s
PR / Lint (pull_request) Successful in 54s
PR / Test (sqlite) (pull_request) Successful in 1m9s
PR / Test (postgres) (pull_request) Successful in 1m12s
PR / Build (pull_request) Successful in 1m21s
PR / Trivy (image) (pull_request) Successful in 1m27s
6352947bdd
Builds a container image from any branch on demand and (optionally)
pushes it to the registry as `branch-<slugified-branch>-<sha7>`.
Fills the gap between "I want to poke at this branch in a container"
and "tag a release-candidate vX.Y.Z-rc.N", which previously was the
only way to get a feature branch into the registry.

Single boolean input — `push` (default true). Uncheck to dry-run a
build for "does this branch even build" without consuming registry
storage.

Tag scheme: `branch-` prefix is deliberate, so a self-hoster's
registry listing / pull command immediately tells them this isn't a
release. `:latest` is never touched. No cosign signing, no SLSA
attestation, no Rekor upload, no Forgejo release page — those stay
reserved for actual releases per ADR-0014.

Uses the same `forge.int.wynning.tech` push target as release.yml,
same REGISTRY_USERNAME / REGISTRY_TOKEN secrets. Reuses the existing
Dockerfile (digest-pinned base, multi-stage build) unchanged.

docs/ci.md picks up a new "Ad-hoc feature-branch image builds"
section explaining what the workflow produces, what it deliberately
doesn't, and the run-time / cleanup story.

Verified: `actionlint .forgejo/workflows/*.yml` clean across all
workflow files.

Closes #108.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
james merged commit ae98e9175c into main 2026-06-18 12:46:42 +00:00
james deleted branch 108-feature-branch-image-workflow 2026-06-18 12:46:42 +00:00
Sign in to join this conversation.
No description provided.