mirror of
https://github.com/cozystack/cozystack.git
synced 2026-10-28 07:37:49 +09:00
Extract the promote-time changelog generation into a reusable workflow (changelog-generate.yaml, workflow_call) and add a dispatchable wrapper (changelog-rc.yaml) so a maintainer can generate the release changelog the moment an rc goes green, while there is still time to review it. The reusable core keeps promote-rc's observable behaviour: detached rc-tag checkout, read-only app token for the AI step, the validate-changelog.sh gate, non-blocking AI failure, and the same changelog-vX.Y.Z artifact. .release-tooling is overlaid from github.ref_name, which under workflow_call is the caller's dispatch ref (and coincides with the reusable workflow's own ref for a local uses:), so "current tooling against an old rc tag" is preserved. Secrets are declared explicitly rather than inherited, so a caller that forgets one fails at parse time. The rc tag is parsed by a shared hack/parse-rc-tag.sh that REJECTS whitespace outright (a stripped 'v1. 6.0-rc.2' would silently become a different tag). promote-rc parses it ONCE in a cheap `parse` job that both `promote` and `changelog` depend on — so they still run in parallel with each other while consuming one validated tag, and a whitespace tag fails the whole promotion rather than letting promote succeed while the changelog job rejects the same input and the PR opens empty. The reusable core mirrors the reject-whitespace policy inline because its parse must run before any checkout. changelog-rc.yaml verifies the rc staging branch release-X.Y.Z-rc.N exists UP FRONT (in parse, which generate depends on), so a missing branch fails in seconds rather than after a 30-minute AI run, then commits the result there as docs/changelogs/vX.Y.Z.md idempotently (compare-before-push). promote-rc's changelog job is a thin uses: call. Source selection — validate-then-fall-through across the rc tag tree, the rc staging branch (the rc-time pickup), then AI generation, discarding any invalid source with a loud warning so it never suppresses a valid lower-priority one — lives in hack/select-changelog-source.sh, executed after the tooling overlay. open-pr carries the picked-up file onto release-X.Y.Z and finalize publishes it. Contract and behaviour bats are repointed and extended: the shared parser, the source-selection script, and promote's parse policy are all exercised by execution on adversarial inputs; the remaining grep pins match executable lines with exact counts so a comment or dead block cannot satisfy them. docs/release.md lists the new workflow and the rc-time entry point. actionlint and zizmor (default and pedantic) are clean. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
65 lines
2.6 KiB
Bash
Executable File
65 lines
2.6 KiB
Bash
Executable File
#!/bin/sh
|
|
# Usage: select-changelog-source.sh <version> <rc_branch>
|
|
#
|
|
# Decide which pre-existing changelog (if any) release generation should use,
|
|
# WITHOUT running the AI — validate-then-fall-through across the sources, so an
|
|
# invalid higher-priority file can never silently suppress a valid lower-priority
|
|
# one:
|
|
#
|
|
# 1. docs/changelogs/vX.Y.Z.md already in the working tree (the rc TAG tree) —
|
|
# a maintainer hand-wrote it before the tag was cut.
|
|
# 2. docs/changelogs/vX.Y.Z.md on the rc STAGING branch <rc_branch> —
|
|
# changelog-rc.yaml committed it there at rc time (the "copy" pickup).
|
|
#
|
|
# Each candidate is validated with validate-changelog.sh; an invalid one is
|
|
# reported with a ::warning:: and DISCARDED (rm) so the next source is tried.
|
|
# Exactly one machine-readable line is printed as the LAST line of stdout:
|
|
#
|
|
# source=rc-tag | source=rc-branch | source=none
|
|
#
|
|
# On rc-tag / rc-branch the usable changelog is left at docs/changelogs/vX.Y.Z.md.
|
|
# On none nothing usable was found and the caller must generate. The ::warning::
|
|
# annotations for discarded files are printed to stdout too, ahead of that line.
|
|
#
|
|
# Run from the repo root AFTER the .release-tooling overlay, with `origin`
|
|
# fetch-authenticated (changelog-preserve.sh fetches the branch).
|
|
# validate-changelog.sh and changelog-preserve.sh must sit beside this script.
|
|
#
|
|
# Exit 0 = a decision was reached (source line printed). Exit 1 = bad args.
|
|
|
|
set -eu
|
|
|
|
VERSION="${1:?usage: select-changelog-source.sh <version> <rc_branch>}"
|
|
RC_BRANCH="${2:?usage: select-changelog-source.sh <version> <rc_branch>}"
|
|
|
|
HERE="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
|
|
VALIDATE="${HERE}/validate-changelog.sh"
|
|
PRESERVE="${HERE}/changelog-preserve.sh"
|
|
CL="docs/changelogs/v${VERSION}.md"
|
|
|
|
# 1. The rc tag tree — validate before trusting it.
|
|
if [ -s "$CL" ]; then
|
|
if REASON="$("$VALIDATE" "$CL" "$VERSION" 2>&1)"; then
|
|
echo "::notice::Using ${CL} already in the rc tag tree (${REASON})."
|
|
echo "source=rc-tag"
|
|
exit 0
|
|
fi
|
|
echo "::warning::${CL} is in the rc tag tree but is NOT usable (${REASON}); discarding it and trying the rc staging branch ${RC_BRANCH}."
|
|
rm -f "$CL"
|
|
fi
|
|
|
|
# 2. The rc staging branch — fetch, then validate before trusting it.
|
|
mkdir -p docs/changelogs
|
|
if "$PRESERVE" "$RC_BRANCH" "$VERSION" "$CL"; then
|
|
if REASON="$("$VALIDATE" "$CL" "$VERSION" 2>&1)"; then
|
|
echo "::notice::Copied ${CL} from rc staging branch ${RC_BRANCH} (${REASON})."
|
|
echo "source=rc-branch"
|
|
exit 0
|
|
fi
|
|
echo "::warning::${CL} on rc staging branch ${RC_BRANCH} is NOT usable (${REASON}); discarding it and generating."
|
|
rm -f "$CL"
|
|
fi
|
|
|
|
echo "source=none"
|
|
exit 0
|