Skip to content

Releases: cshuttle/workflows

v1.5.0 — tag the ref, record provenance

Choose a tag to compare

@cshuttle cshuttle released this 04 Aug 17:16
8421ec0

Supersedes v1.4.0, whose fix did not work.

v1.4.0 moved tag creation to the git-data API on the belief that it sidesteps GitHub's workflow-file protection. It does not — creating a ref at a commit whose .github/workflows differ from the default branch fails over the API exactly as over git push, reported less helpfully as Resource not accessible by integration. The constraint is the token, not the transport, and GITHUB_TOKEN cannot hold the workflow scope by any route.

The real problem

Since v1.1.1 the tag landed on each image's build commit. Any CI change merged after the last image build makes that commit's workflows differ from the default branch — and that is exactly when someone reaches for a release. VirtualWindow hit it on both attempts.

The change

Provenance stops living in where the tag points and moves into content:

  • The tag lands on the ref being released, whose workflows are the default branch's by definition, so the restriction can never apply.
  • The tag message and release body name the build commit of every image:
    ghcr.io/cshuttle/virtualwindow:v1.1.0sha256:…, built from 4749ed9

"Which commit is this version?" is still answerable — from the release rather than the ref. The provenance guard is untouched: every image is still proven to have been built from this branch's history.

The rejected alternative was a workflow-scoped PAT in every releasing repo — a long-lived credential in eight repos, in an estate working to retire the one it has.

Minor: behaviour change; callers do nothing.

v1.4.0 — tag via the API

Choose a tag to compare

@cshuttle cshuttle released this 04 Aug 16:23
537e58c

Fixes a failure that would have hit every repo eventually — the first two successes were luck.

What broke

VirtualWindow's release promoted both images correctly, then died pushing the tag:

! [remote rejected] v1.1.0 (refusing to allow a GitHub App to create or update
  workflow `.github/workflows/ggshield.yml` without `workflows` permission)

Since v1.1.1 the tag lands on the commit the image came from, so a version names code actually in it. That commit routinely predates a later CI change — and a token-authenticated push carrying a workflow file that differs from the default branch is refused. workflows is a PAT scope; GITHUB_TOKEN cannot be granted it, so no permissions change would have helped.

Topology and Atlas passed only because their tagged commits happened to carry workflow files identical to main's.

The fix

Create the tag through the git-data API. A tag object pointing at an existing commit introduces no file changes, so the restriction does not apply. Still annotated, same message, same commit — and the job no longer needs write access to the checkout to tag.

Minor: a behaviour fix with a mechanism change; callers do nothing.

v1.3.0 — independently-built component images

Choose a tag to compare

@cshuttle cshuttle released this 04 Aug 14:47
2c069c8

Third repo onto the model, third finding — a guard that was right for the case it was written against and wrong for the next one.

The problem

release-image required every image in a release to resolve to one build commit. Correct for Atlas: one workflow builds the SPA and its sidecar, so a mismatch means a half-updated pair shipping under a single version.

VirtualWindow builds its two images from disjoint path filters — prototype/+docker/ versus config-service/. They change independently and are almost never built by the same commit; right now they sit 5 commits apart. Under the strict rule the repo could not be released at all.

The change

require-same-commit, default true, so repos that need the check keep it. Opting out drops only the all-from-one-commit constraint — each image is still verified against the branch history, so a stale build or one from another branch is still refused — and the tag lands on the newest resolved commit rather than the oldest, which would name a commit predating shipped code.

Minor: callers gain an input some of them need; nothing breaks for a caller that omits it.

v1.2.0 — ghcr-token for user-owned packages

Choose a tag to compare

@cshuttle cshuttle released this 04 Aug 13:26
afc5766

Found by the first real release, which failed with:

ghcr.io/cshuttle/topology:latest does not exist — nothing to promote.

It existed. The registry returns the same not found for an unauthorised read, and on a personal account a package bootstrapped by a manual push is user-owned — so the repo-scoped GITHUB_TOKEN 403s on it, reads included.

  • Optional ghcr-token secret, used for the crane login when supplied. Repos that push with a classic PAT pass the same PAT. Omit it and GITHUB_TOKEN is used exactly as before.
  • The error message no longer asserts absence for what is almost always auth. It prints crane's own message and names both remedies: pass the token, or grant the repo access under the package's Manage Actions access settings and drop the secret.

Minor, not patch: callers gain an input some of them need to set, and nothing breaks for a caller that omits it.

v1.1.1 — release guard finds the build's commit

Choose a tag to compare

@cshuttle cshuttle released this 04 Aug 13:19
e18db22

Fixes the guard in `release-image.yml`, found on first contact with a real repo.

The bug. The guard demanded the promoted digest be tagged with the ref HEAD sha. But build workflows carry paths filters, so a docs- or CI-only commit moves the branch without producing an image — and from then on the repo cannot be released at all until someone touches a build input. Topology hit it immediately: adding its own release workflow is such a commit.

The fix. Walk back from the ref and find the most recent commit whose per-commit tag carries this digest. That keeps what the check bought — proof the image came from this branch, not a stale or foreign build — and answers a question the first version never asked: which commit is this image? The git tag is now created on that commit, so a version names code that is actually in it.

Also rejects a multi-image release whose images resolve to different build commits, rather than shipping a mismatched pair.

Cost. One crane ls per image, then local matching — Topology already has 65 tags, so the naive approach is a registry round trip per commit per tag form. New verify-depth input (default 50) bounds the search.

Verified against the live registry both ways before shipping: HEAD-is-the-build resolves at 0 behind; a CI-only commit on top resolves to the build 1 behind, which previously failed outright.

Why patch. A fix, and no caller changes anything to take it.

v1.1.0 — the shared release workflow

Choose a tag to compare

@cshuttle cshuttle released this 03 Aug 03:51
96afdd6

Adds release-image.yml — the shared release workflow for repos whose artifact is one or more container images.

What it does

Cutting a release promotes the image digest CI already built and tested for that commit; it never rebuilds. A rebuild on the tag would produce a second digest from identical source — a different artifact from the one that was tested, for twice the build minutes.

Callers wire a workflow_dispatch button taking a version and an optional summary, because the version is a human decision: a major here means the deploy needs a human step, which no commit message reliably encodes.

Two guards

  • A tag is never reused — checked against the remote, not the local clone. Released tags are immutable; a bad release is superseded by a patch, never fixed by moving a tag.
  • The digest must belong to the running commit. The promoted digest must also be reachable under a commit-sha tag for the ref being released, so a build still in flight — or one that failed after merge — cannot be released by accident. Repos tag per-commit three different ways, so all three forms are tried.

Also in this release

  • STANDARDS.md gains a Releases and versioning section.
  • docs/adr/0001-release-and-versioning-model.md records the model and the rejected alternatives, establishing docs/adr/ in this repo.

Why minor

A new capability that no existing consumer has to react to. Nothing about the four existing reusable workflows changed, so pinned callers can move to v1.1.0 whenever they like.

Cut by hand from a green selftest — this repo publishes no image, so it cannot use its own workflow.

v1.0.0 — first pinnable release of the shared CI

Choose a tag to compare

@cshuttle cshuttle released this 03 Aug 02:00
23a26c9

First release of the estate's shared CI: the reusable GitHub Actions workflows in .github/workflows/ and the shared Lefthook hook config in lefthook/.

Why this exists

These definitions are consumed by 30 repos across the estate — 33 reusable-workflow references plus the shared Lefthook hooks in 4 repos. Until now every consumer pointed at @main, so a commit here changed 30 repos' CI the instant it merged: no pull request anywhere, no record of which repo ran which version, and no way to decline a change at an inconvenient moment. Every third-party action in the estate is pinned by commit SHA precisely to avoid that; our own shared CI was the exception.

v1.0.0 is the first state a consumer can pin to.

Tag policy

Released tags here are immutable and are never moved, and there is deliberately no floating v1. A broken shared workflow is remedied by a superseding patch release — moving a tag would silently change every consumer that already pinned, which is the exact failure this model removes.

What's in it

  • ggshield-scan.yml — pre-merge GitGuardian secret scan (the estate's most widely consumed gate)
  • kustomize-validate.yml — kustomize render + kubeconform schema validation for GitOps content repos
  • komodo-deploy.yml — HMAC-signed Komodo stack deploy trigger, fired after an image push succeeds
  • mirror-image.yml — mirror a badly-peered upstream image into a registry you control
  • lefthook/base.yml — shared advisory pre-commit and pre-push hooks

No behaviour changed in this release; it names the current state so consumers can stop floating.

Part of the release + publish cycle map — spec in #38.