Release notes: read the version from the commit, not a step output
Build and release image / build (push) Successful in 9s

The v0.1.3 release was created with the placeholder body instead of the notes
in docs/releases/v0.1.3.md, even though the file is present at the tagged
commit. The only difference between the check that failed and the tag that
worked is where the value came from: the image tag used the step output
directly, while the notes check used it through a step-level environment
variable.

Rather than keep guessing at that, the version now comes from the checked-out
Cargo.toml. The tag points at that commit, so the two agree by construction —
this removes the cross-step dependency entirely instead of depending on it
arriving intact. The step also logs which notes it used and warns when it falls
back, so a silent placeholder cannot happen again.
This commit is contained in:
DSH Agent committed 2026-09-20 03:01:51 -04:00
1 parent 3288b8314e
commit 451cdd19da
1 file changed
+20 -12
+20 -12
View File
@@ -192,27 +192,35 @@ jobs:
env:
GITEA_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
REPO: ${{ github.repository }}
VERSION: ${{ steps.version.outputs.version }}
IMAGE: ${{ steps.version.outputs.image }}
DIGEST: ${{ steps.push.outputs.digest }}
IMAGE: ${{ steps.version.outputs.image }}
run: |
set -eu
API="https://${REGISTRY}/api/v1"
TAG="${{ github.ref_name }}"
# Read the version from the checked-out commit rather than from a
# previous step's output. The tag points at this commit, so the two
# agree by construction, and this avoids the release quietly falling
# back to generic notes if the output ever arrives empty.
VERSION=$(grep -m1 '^version' Cargo.toml | sed 's/.*"\(.*\)".*/\1/')
echo "publishing release for ${VERSION} (tag ${TAG})"
# Hand-written notes when they exist, because the interesting part of
# a release here is what the operator has to do, not which commits
# landed. Falls back to a short factual note.
# landed. Falls back to a short factual note, and says which it used.
if [ -f "docs/releases/${VERSION}.md" ]; then
NOTES=$(cat "docs/releases/${VERSION}.md")
echo "using docs/releases/${VERSION}.md (${#NOTES} bytes)"
else
NOTES=$(printf 'Release %s.\n\nSee the repository README for deployment instructions.' "$VERSION")
echo "::warning::docs/releases/${VERSION}.md is missing; writing a placeholder"
fi
BODY=$(NOTES="$NOTES" node -e '
VERSION="$VERSION" NOTES="$NOTES" node -e '
const { NOTES, VERSION, IMAGE, DIGEST, REGISTRY } = process.env;
const ref = REGISTRY + "/" + IMAGE + ":" + VERSION;
process.stdout.write(JSON.stringify({
require("fs").writeFileSync("/tmp/release.json", JSON.stringify({
body: NOTES +
"\n\n---\n\n" +
"**Image:** `" + ref + "`\n\n" +
@@ -222,28 +230,28 @@ jobs:
tag_name: "v" + VERSION,
draft: false,
prerelease: false,
}));')
}));'
# A re-run of the same tag updates the release in place rather than
# failing on the duplicate.
curl -s -H "Authorization: token ${GITEA_TOKEN}" \
"${API}/repos/${REPO}/releases/tags/v${VERSION}" > /tmp/release.json || echo '{}' > /tmp/release.json
"${API}/repos/${REPO}/releases/tags/${TAG}" > /tmp/existing.json || echo '{}' > /tmp/existing.json
EXISTING=$(node -e '
const fs = require("fs");
try {
const r = JSON.parse(fs.readFileSync("/tmp/release.json", "utf8"));
const r = JSON.parse(fs.readFileSync("/tmp/existing.json", "utf8"));
process.stdout.write(r && r.id ? String(r.id) : "");
} catch { process.stdout.write(""); }
')
if [ -n "$EXISTING" ]; then
curl -sf -X PATCH -H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" -d "$BODY" \
-H "Content-Type: application/json" --data-binary @/tmp/release.json \
"${API}/repos/${REPO}/releases/${EXISTING}" > /dev/null
echo "updated release v${VERSION}"
echo "updated release ${TAG}"
else
curl -sf -X POST -H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" -d "$BODY" \
-H "Content-Type: application/json" --data-binary @/tmp/release.json \
"${API}/repos/${REPO}/releases" > /dev/null
echo "created release v${VERSION}"
echo "created release ${TAG}"
fi