Summary
CI is in good shape. Release automation is the gap: cutting a version is
entirely manual, and publish-image.yml produces an image that nothing
references until a human edits action.yml by hand.
Surfaced on 2026-08-24 while pinning this action from yo61/python-template.
What exists
| workflow | trigger | does |
|---|
ci.yml | push | npm lint, jest with coverage, docker build |
commitlint.yml | push, pull_request | dogfoods the action twice — once against the branch Dockerfile, once against the published digest |
publish-image.yml | push tag v* | builds, pushes :VERSION and :MAJOR to ghcr, pulls it back to smoke-test, reports the digest to the step summary |
dependabot.yml | weekly | dependency updates |
Actions are SHA-pinned with version comments, permissions: {} at workflow
level, persist-credentials: false throughout. No complaints.
What's missing
1. No version-bump / changelog / tag automation
Nothing computes the next version, writes CHANGELOG.md, or creates the tag.
publish-image.yml only reacts to a tag someone pushed by hand.
.versionrc.json is still present from upstream's commit-and-tag-version
setup, but the release job that used it was removed when this fork replaced
Docker Hub publishing with ghcr — see the comment in ci.yml. So the config is
orphaned: it configures a tool nothing runs.
Every other yo61 repo uses release-please. That would fit here, with the
release PR merge creating the tag that publish-image.yml already reacts to.
2. Publishing a tag produces an image nothing points at
action.yml pins the runtime image by digest (correctly — a SHA pin downstream
is worthless if the image tag it resolves to is mutable). But that makes
releasing circular:
- push tag
vX.Y.Z publish-image.yml builds a new image with a new digestaction.yml still names the previous digest- a human reads the step summary and commits the new digest
- that commit is not in the tag
The workflow acknowledges this — its last step prints "Update action.yml to
this digest if it is not already." — but nothing enforces or automates it.
Live example, caused by cutting v6.3.1 today:
tag v6.3.1 -> commit 501ff7bb
action.yml @ 501ff7bb -> sha256:78d47699… (the v6.3.0 image)
publish-image.yml built -> sha256:59972d25… (pushed as :6.3.1 and :6)
Nothing is broken: v6.3.1 resolves to an action.yml naming a real,
published, smoke-tested image, and consumers pinning that SHA get exactly what
was tested. But ghcr…:6.3.1 is now an orphan nothing references, and the
mutable :6 tag was repointed at it.
Worth deciding what the intended invariant is. Options:
- Two-phase release — publish the image first, then a follow-up commit
updates action.yml to the new digest and that commit gets tagged. Correct,
but two commits per release. - Build reproducibly and pre-compute — derive the digest before tagging so
action.yml can name it in the same commit. Needs a reproducible build. - Accept it and automate step 4 — let the publish workflow open a PR
updating action.yml, and treat the digest as trailing the tag by one commit.
Simplest, and matches how it already behaves.
3. Minor: checkout pin lags in one workflow
publish-image.yml uses actions/checkout@de0fac2e… (v6.0.2); ci.yml and
commitlint.yml use @3d3c42e5… (v7.0.1). Harmless, but the inconsistency
suggests Dependabot did not group them.
Out of scope
- The CI workflows themselves — they work and follow house standards.
- Migrating off ghcr.
Note on the frozen dependency resolution
Not a defect, but a consequence worth recording: the digest pin also freezes
npm resolution. package.json declares @commitlint/cli ^21.2.1, but the
caret resolved when the image was built, so the action runs whatever was
current then, not what npm serves today. Commitlint will not drift forward in
CI on its own — a bump requires a rebuild and a digest change, which is exactly
what item 2 is about.
Summary
CI is in good shape. Release automation is the gap: cutting a version is
entirely manual, and
publish-image.ymlproduces an image that nothingreferences until a human edits
action.ymlby hand.Surfaced on 2026-08-24 while pinning this action from
yo61/python-template.What exists
ci.ymlpushdocker buildcommitlint.ymlpush,pull_requestDockerfile, once against the published digestpublish-image.ymlpushtagv*:VERSIONand:MAJORto ghcr, pulls it back to smoke-test, reports the digest to the step summarydependabot.ymlActions are SHA-pinned with version comments,
permissions: {}at workflowlevel,
persist-credentials: falsethroughout. No complaints.What's missing
1. No version-bump / changelog / tag automation
Nothing computes the next version, writes
CHANGELOG.md, or creates the tag.publish-image.ymlonly reacts to a tag someone pushed by hand..versionrc.jsonis still present from upstream'scommit-and-tag-versionsetup, but the release job that used it was removed when this fork replaced
Docker Hub publishing with ghcr — see the comment in
ci.yml. So the config isorphaned: it configures a tool nothing runs.
Every other yo61 repo uses release-please. That would fit here, with the
release PR merge creating the tag that
publish-image.ymlalready reacts to.2. Publishing a tag produces an image nothing points at
action.ymlpins the runtime image by digest (correctly — a SHA pin downstreamis worthless if the image tag it resolves to is mutable). But that makes
releasing circular:
vX.Y.Zpublish-image.ymlbuilds a new image with a new digestaction.ymlstill names the previous digestThe workflow acknowledges this — its last step prints "Update
action.ymltothis digest if it is not already." — but nothing enforces or automates it.
Live example, caused by cutting
v6.3.1today:Nothing is broken:
v6.3.1resolves to anaction.ymlnaming a real,published, smoke-tested image, and consumers pinning that SHA get exactly what
was tested. But
ghcr…:6.3.1is now an orphan nothing references, and themutable
:6tag was repointed at it.Worth deciding what the intended invariant is. Options:
updates
action.ymlto the new digest and that commit gets tagged. Correct,but two commits per release.
action.ymlcan name it in the same commit. Needs a reproducible build.updating
action.yml, and treat the digest as trailing the tag by one commit.Simplest, and matches how it already behaves.
3. Minor: checkout pin lags in one workflow
publish-image.ymlusesactions/checkout@de0fac2e…(v6.0.2);ci.ymlandcommitlint.ymluse@3d3c42e5…(v7.0.1). Harmless, but the inconsistencysuggests Dependabot did not group them.
Out of scope
Note on the frozen dependency resolution
Not a defect, but a consequence worth recording: the digest pin also freezes
npm resolution.
package.jsondeclares@commitlint/cli ^21.2.1, but thecaret resolved when the image was built, so the action runs whatever was
current then, not what npm serves today. Commitlint will not drift forward in
CI on its own — a bump requires a rebuild and a digest change, which is exactly
what item 2 is about.