feat: actions/changelog-armed — the version-keyed arming guard
Port box's changelog-armed.sh as the first composite action, establishing the pattern #6 and #7 copy: action.yml passes inputs as env vars, the co-located script stays directly runnable, and the shared libs are sourced relative to the action so they travel with it at the consumer's pinned ref. Port deltas per issue #5: the version goes through version_read (#3) so the guard works for package-json trees, and the bare-version emptiness check consults changelog_section (#4) — the guard and the publisher cannot disagree about what a section is. Messages and the header essay keep the box#108 / rig#66 / rig#44 / cast#108 history; this is the guard rig and cast regain at adoption. CI gains an action-exercise job driving uses: ./actions/changelog-armed against a scratch armed tree — the composite wiring proven, not just the script. Closes #5 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
366d08e2d4
commit
dde6b253f5
4 changed files with 419 additions and 0 deletions
22
.github/workflows/ci.yml
vendored
22
.github/workflows/ci.yml
vendored
|
|
@ -34,3 +34,25 @@ jobs:
|
||||||
# quietly stop running (issue #3's test contract).
|
# quietly stop running (issue #3's test contract).
|
||||||
CEREMONY_REQUIRE_NPM: 1
|
CEREMONY_REQUIRE_NPM: 1
|
||||||
run: bash test/run.sh
|
run: bash test/run.sh
|
||||||
|
|
||||||
|
# Exercises the composite actions the way a consumer does — action.yml
|
||||||
|
# resolving, $GITHUB_ACTION_PATH, the relative lib sourcing — which the
|
||||||
|
# test suite, driving the scripts directly, cannot prove (issue #5's
|
||||||
|
# acceptance criterion).
|
||||||
|
action-exercise:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Construct an armed scratch tree in the workspace
|
||||||
|
# This repo carries no VERSION or CHANGELOG.md of its own (until
|
||||||
|
# #11 dogfoods); the guard reads the workspace, so give it a
|
||||||
|
# transient armed tree there. The changelog is scratch-named so a
|
||||||
|
# future real CHANGELOG.md is never shadowed; VERSION cannot be —
|
||||||
|
# the file backend hardcodes it — so if #11 ever adds a real one,
|
||||||
|
# this write must go.
|
||||||
|
run: |
|
||||||
|
printf '0.0.1-dev\n' > VERSION
|
||||||
|
printf '# Changelog\n\n## Unreleased\n\n- Scratch entry.\n' > CHANGELOG.scratch.md
|
||||||
|
- uses: ./actions/changelog-armed
|
||||||
|
with:
|
||||||
|
changelog: CHANGELOG.scratch.md
|
||||||
|
|
|
||||||
24
actions/changelog-armed/action.yml
Normal file
24
actions/changelog-armed/action.yml
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
name: Changelog armed
|
||||||
|
description: >-
|
||||||
|
Assert the changelog is armed for the tree's version state — the
|
||||||
|
version-keyed guard (box#108, rig#66; the unconditional form was reverted
|
||||||
|
by rig#44 and cast#108). The caller must have checked out its own
|
||||||
|
repository first: the guard reads the consumer's tree at the workspace.
|
||||||
|
inputs:
|
||||||
|
version-source:
|
||||||
|
description: Where the tree's version lives ("file" or "package-json")
|
||||||
|
required: false
|
||||||
|
default: file
|
||||||
|
changelog:
|
||||||
|
description: Path to the changelog, relative to the workspace
|
||||||
|
required: false
|
||||||
|
default: CHANGELOG.md
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
steps:
|
||||||
|
- name: changelog armed
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
CHANGELOG: ${{ inputs.changelog }}
|
||||||
|
VERSION_SOURCE: ${{ inputs.version-source }}
|
||||||
|
run: bash "$GITHUB_ACTION_PATH/changelog-armed.sh"
|
||||||
158
actions/changelog-armed/changelog-armed.sh
Normal file
158
actions/changelog-armed/changelog-armed.sh
Normal file
|
|
@ -0,0 +1,158 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# changelog-armed.sh [<changelog>] [<version-source>] — assert that the
|
||||||
|
# changelog is ARMED: that there is a heading for the next PR's entry to
|
||||||
|
# land under, and that it is the right one for the state this tree is in.
|
||||||
|
#
|
||||||
|
# Ported from box .github/scripts/changelog-armed.sh (box#108, confirmed
|
||||||
|
# cross-repo as rig#66) — box is the only repo that carries this guard
|
||||||
|
# today. Rig and cast LOST it: the naive form — "always require
|
||||||
|
# '## Unreleased' on top" — is false by construction on the ceremony PR's
|
||||||
|
# own tree, which legitimately stamps that heading away, so rig#44 and
|
||||||
|
# cast#108 both had to revert exactly that. This version-keyed form is the
|
||||||
|
# guard rig and cast regain when they adopt ceremony (#13, #15). Anyone
|
||||||
|
# tempted to simplify this back to the unconditional form should read
|
||||||
|
# those two reverts first.
|
||||||
|
#
|
||||||
|
# The failure it exists to catch (box#108, rig#66) leaves no trace: the
|
||||||
|
# ceremony PR stamps '## Unreleased' into '## X.Y.Z — DATE' by hand, and
|
||||||
|
# nothing puts the heading back. A PR authored BEFORE the release wrote its
|
||||||
|
# entry under '## Unreleased'; that heading is gone by the time it merges, so
|
||||||
|
# git lands the entry under whatever heading now occupies that position — the
|
||||||
|
# just-shipped section — CLEANLY, with no conflict. The one signal an author
|
||||||
|
# would trust ("git told me to look") is absent exactly when the result is
|
||||||
|
# wrong, and the drift is only ever discovered by reading the file.
|
||||||
|
#
|
||||||
|
# The rule, keyed on the tree's version (a VERSION file or package.json,
|
||||||
|
# per version-source), because the two states are genuinely different:
|
||||||
|
#
|
||||||
|
# version ends in -dev -> the top section MUST be '## Unreleased'
|
||||||
|
# version is bare -> the top section may be '## Unreleased' (armed,
|
||||||
|
# the ceremony's own re-arm) or the stamped
|
||||||
|
# section for exactly that version — AND the
|
||||||
|
# section for that version must exist and carry
|
||||||
|
# prose, because it is the one about to ship
|
||||||
|
#
|
||||||
|
# The consequence worth stating plainly: a ceremony PR that stamps and forgets
|
||||||
|
# to re-arm still passes here — its version is bare, and a bare tree is
|
||||||
|
# allowed to be stamped. It goes red the moment the '-dev' bump lands on main,
|
||||||
|
# which the release workflow does automatically in the same job as the
|
||||||
|
# publish. So the guard does not block the release; it refuses to let main
|
||||||
|
# SIT disarmed, which is the window a late PR can fall into.
|
||||||
|
#
|
||||||
|
# A file of its own (not inlined in action.yml) so
|
||||||
|
# test/changelog-armed.test.sh can drive it against constructed trees for
|
||||||
|
# both states — the same discipline as the libs it sources.
|
||||||
|
|
||||||
|
changelog="${1:-${CHANGELOG:-CHANGELOG.md}}"
|
||||||
|
version_source="${2:-${VERSION_SOURCE:-file}}"
|
||||||
|
|
||||||
|
# The shared libs travel with this action: a consumer's
|
||||||
|
# `uses: heavy-duty/ceremony/actions/changelog-armed@<tag>` downloads this
|
||||||
|
# whole repository at that ref, so ../../lib is always present and always at
|
||||||
|
# the same ref — no checkout step, no version skew possible.
|
||||||
|
here="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
# shellcheck source=lib/version.sh
|
||||||
|
. "$here/../../lib/version.sh"
|
||||||
|
# shellcheck source=lib/changelog.sh
|
||||||
|
. "$here/../../lib/changelog.sh"
|
||||||
|
|
||||||
|
[ -f "$changelog" ] || { echo "changelog-armed: no such file: $changelog" >&2; exit 1; }
|
||||||
|
|
||||||
|
# version_read refuses loudly on a missing or empty source; the wrapper line
|
||||||
|
# names the guard so a workflow log shows which check refused.
|
||||||
|
ver="$(version_read "$version_source")" || {
|
||||||
|
echo "changelog-armed: cannot read the version (version-source: $version_source)" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# The TOP section: the first '## ' heading in the file. Everything above it is
|
||||||
|
# the changelog's own preamble and belongs to no section.
|
||||||
|
top="$(grep -m1 '^## ' "$changelog" || true)"
|
||||||
|
[ -n "$top" ] || {
|
||||||
|
echo "changelog-armed: $changelog has no '## ' section at all — nothing for a PR entry to land under" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# '## 0.7.0 — 2026-07-19' -> '0.7.0'. Split on whitespace, the same shape
|
||||||
|
# changelog_section matches on, so the two cannot disagree about what a
|
||||||
|
# section header is.
|
||||||
|
top_ver="$(printf '%s\n' "$top" | awk '{ print $2 }')"
|
||||||
|
|
||||||
|
# version_is_dev is the single definition of the -dev special case (#3): an
|
||||||
|
# rc is a pre-release, not a dev tree, and keys on the bare rules below.
|
||||||
|
if version_is_dev "$ver"; then
|
||||||
|
if [ "$top_ver" != "Unreleased" ]; then
|
||||||
|
cat >&2 <<EOF
|
||||||
|
changelog-armed: the version is '$ver' (a development tree) but the top
|
||||||
|
section of $changelog is:
|
||||||
|
|
||||||
|
$top
|
||||||
|
|
||||||
|
A -dev tree MUST carry '## Unreleased' at the top. Without it, a PR that
|
||||||
|
wrote its entry under '## Unreleased' before the release merges CLEANLY into
|
||||||
|
the section above — the one that already shipped — and the changelog quietly
|
||||||
|
misattributes it (box#108, rig#66).
|
||||||
|
|
||||||
|
The fix is to re-arm: add an empty '## Unreleased' immediately above
|
||||||
|
'$top'. The release ceremony is supposed to do this in the same edit that
|
||||||
|
stamps the version.
|
||||||
|
EOF
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# A bare version is the ceremony tree and the merge commit that publishes
|
||||||
|
# it. Both arrangements are legal there: re-armed ('## Unreleased' back on
|
||||||
|
# top, above the section just stamped) or not yet re-armed (the stamped
|
||||||
|
# section still on top). What is NOT legal is a stamped top section naming
|
||||||
|
# some OTHER version — that is a ceremony that stamped the wrong number,
|
||||||
|
# and the release workflow would publish a body that is not this release's.
|
||||||
|
if [ "$top_ver" != "Unreleased" ] && [ "$top_ver" != "$ver" ]; then
|
||||||
|
cat >&2 <<EOF
|
||||||
|
changelog-armed: the version is '$ver' but the top section of $changelog is:
|
||||||
|
|
||||||
|
$top
|
||||||
|
|
||||||
|
A bare version means this tree is a release. Its top section must be either
|
||||||
|
'## Unreleased' (re-armed after stamping) or the stamped section for '$ver'
|
||||||
|
itself. A stamped section naming a different version means the ceremony
|
||||||
|
stamped the wrong number, and the published release body would come from
|
||||||
|
the wrong section.
|
||||||
|
EOF
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# The top heading is deliberately left UNCONSTRAINED above — both ceremony
|
||||||
|
# shapes must stay legal, which is the rig#44 / cast#108 lesson and is not
|
||||||
|
# negotiable. That asymmetry leaves a gap of its own, the HALF-ceremony
|
||||||
|
# tree: version bumped to the release, a populated '## Unreleased' still on
|
||||||
|
# top, and no stamped section for the version anywhere. The test above is
|
||||||
|
# false on its first clause, short-circuits, and passes. Nothing else
|
||||||
|
# refuses until the publisher extracts the notes — which happens AFTER the
|
||||||
|
# merge, on main, and publishes a release with an empty body, the worst
|
||||||
|
# place for this to land. So make the same assert one step earlier through
|
||||||
|
# the very extractor the publisher uses — changelog_section (#4) — so the
|
||||||
|
# guard and the publisher cannot disagree about what a section is or when
|
||||||
|
# one counts as empty (rig#67).
|
||||||
|
if [ -z "$(changelog_section "$changelog" "$ver")" ]; then
|
||||||
|
cat >&2 <<EOF
|
||||||
|
changelog-armed: the version is '$ver' but $changelog has no non-empty
|
||||||
|
section for '$ver'. The top section is:
|
||||||
|
|
||||||
|
$top
|
||||||
|
|
||||||
|
This is a HALF-DONE ceremony: the version was bumped but its section was
|
||||||
|
never stamped — the stamp is MISSING, not misnumbered. A bare version means
|
||||||
|
this tree is a release, and the section it is about to publish has to exist
|
||||||
|
and have prose in it. Left alone, this passes CI, merges, and only then does
|
||||||
|
the publisher refuse to extract the notes — on main, after the fact, with
|
||||||
|
the release already half-shipped.
|
||||||
|
|
||||||
|
The fix is the ceremony's first edit: stamp '## Unreleased' into
|
||||||
|
'## $ver — DATE', then put an empty '## Unreleased' back above it.
|
||||||
|
EOF
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "changelog-armed: version '$ver' agrees with the top section ($top_ver)"
|
||||||
215
test/changelog-armed.test.sh
Normal file
215
test/changelog-armed.test.sh
Normal file
|
|
@ -0,0 +1,215 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Contract tests for actions/changelog-armed (issue #5). Constructed fixture
|
||||||
|
# trees — a dir with a changelog plus a VERSION file or package.json, not
|
||||||
|
# git repos — the same discipline as the box suite this guard is ported
|
||||||
|
# from. set -u, not -e: failing commands are behavior for the harness to
|
||||||
|
# inspect.
|
||||||
|
set -u
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
# shellcheck source=test/harness.sh
|
||||||
|
. "$ROOT/test/harness.sh"
|
||||||
|
|
||||||
|
SCRIPT="$ROOT/actions/changelog-armed/changelog-armed.sh"
|
||||||
|
|
||||||
|
TMP="$(mktemp -d)"
|
||||||
|
trap 'rm -rf "$TMP"' EXIT
|
||||||
|
|
||||||
|
# The guard reads the consumer's tree at its working directory, so every
|
||||||
|
# case runs from inside a constructed fixture tree.
|
||||||
|
in_tree() {
|
||||||
|
local dir="$1"
|
||||||
|
shift
|
||||||
|
(cd "$TMP/$dir" && bash "$SCRIPT" "$@")
|
||||||
|
}
|
||||||
|
|
||||||
|
# tree <name> <version> — a fixture tree with a VERSION file; the changelog
|
||||||
|
# body arrives on stdin.
|
||||||
|
tree() {
|
||||||
|
mkdir -p "$TMP/$1"
|
||||||
|
printf '%s\n' "$2" >"$TMP/$1/VERSION"
|
||||||
|
cat >"$TMP/$1/CHANGELOG.md"
|
||||||
|
}
|
||||||
|
|
||||||
|
# pkg_tree <name> <version> — the same, package-json backend.
|
||||||
|
pkg_tree() {
|
||||||
|
mkdir -p "$TMP/$1"
|
||||||
|
printf '{ "name": "fixture", "version": "%s" }\n' "$2" >"$TMP/$1/package.json"
|
||||||
|
cat >"$TMP/$1/CHANGELOG.md"
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- the -dev rows: top section MUST be '## Unreleased' ----------------------
|
||||||
|
|
||||||
|
tree dev-armed 1.2.4-dev <<'EOF'
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
- Pending entry.
|
||||||
|
|
||||||
|
## 1.2.3 — 2026-07-20
|
||||||
|
|
||||||
|
- The shipped entry.
|
||||||
|
EOF
|
||||||
|
check "-dev + Unreleased on top passes" 0 "agrees" in_tree dev-armed
|
||||||
|
|
||||||
|
tree dev-stamped 1.2.4-dev <<'EOF'
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
## 1.2.3 — 2026-07-20
|
||||||
|
|
||||||
|
- The shipped entry.
|
||||||
|
EOF
|
||||||
|
check "-dev + stamped top fails" 1 "development tree" in_tree dev-stamped
|
||||||
|
check "-dev failure names the file" 1 "CHANGELOG.md" in_tree dev-stamped
|
||||||
|
check "-dev failure teaches the re-arm fix" 1 "re-arm" in_tree dev-stamped
|
||||||
|
|
||||||
|
# --- the bare rows: both ceremony shapes legal, half-ceremonies refused -----
|
||||||
|
|
||||||
|
tree bare-armed 1.2.3 <<'EOF'
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
## 1.2.3 — 2026-07-20
|
||||||
|
|
||||||
|
- The shipped entry.
|
||||||
|
EOF
|
||||||
|
check "bare + re-armed tree passes" 0 "agrees" in_tree bare-armed
|
||||||
|
|
||||||
|
tree bare-stamped 1.2.3 <<'EOF'
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
## 1.2.3 — 2026-07-20
|
||||||
|
|
||||||
|
- The shipped entry.
|
||||||
|
|
||||||
|
## 1.2.2 — 2026-07-01
|
||||||
|
|
||||||
|
- Older entry.
|
||||||
|
EOF
|
||||||
|
check "bare + own stamped section on top passes" 0 "agrees" in_tree bare-stamped
|
||||||
|
|
||||||
|
tree bare-empty-stamp 1.2.3 <<'EOF'
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
## 1.2.3 — 2026-07-20
|
||||||
|
|
||||||
|
## 1.2.2 — 2026-07-01
|
||||||
|
|
||||||
|
- Older entry.
|
||||||
|
EOF
|
||||||
|
check "bare + own stamped section but EMPTY fails" 1 "no non-empty" \
|
||||||
|
in_tree bare-empty-stamp
|
||||||
|
|
||||||
|
tree bare-wrong-stamp 1.2.3 <<'EOF'
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
## 9.9.9 — 2026-07-20
|
||||||
|
|
||||||
|
- An entry under the wrong number.
|
||||||
|
EOF
|
||||||
|
check "bare + top section naming another version fails" 1 "stamped the wrong number" \
|
||||||
|
in_tree bare-wrong-stamp
|
||||||
|
|
||||||
|
tree bare-half-ceremony 1.2.3 <<'EOF'
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
- Pending entry that was never stamped.
|
||||||
|
|
||||||
|
## 1.2.2 — 2026-07-01
|
||||||
|
|
||||||
|
- Older entry.
|
||||||
|
EOF
|
||||||
|
check "bare + no section for the version anywhere fails" 1 "HALF-DONE ceremony" \
|
||||||
|
in_tree bare-half-ceremony
|
||||||
|
|
||||||
|
# Whole-version matching: 1.2.3 must not be satisfied by a 1.2.3-rc1 section.
|
||||||
|
tree bare-rc-only 1.2.3 <<'EOF'
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
## 1.2.3-rc1 — 2026-07-15
|
||||||
|
|
||||||
|
- The candidate's entry.
|
||||||
|
EOF
|
||||||
|
check "bare: an rc section never satisfies the bare version" 1 "HALF-DONE ceremony" \
|
||||||
|
in_tree bare-rc-only
|
||||||
|
|
||||||
|
# An rc is a pre-release, not a dev tree (#3's version_is_dev): it keys on
|
||||||
|
# the bare rules, so a stamped rc section of its own is shippable.
|
||||||
|
tree rc-stamped 2.0.0-rc1 <<'EOF'
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
## 2.0.0-rc1 — 2026-07-20
|
||||||
|
|
||||||
|
- The candidate's entry.
|
||||||
|
EOF
|
||||||
|
check "rc keys as bare, own stamped section passes" 0 "agrees" in_tree rc-stamped
|
||||||
|
|
||||||
|
# --- degenerate trees --------------------------------------------------------
|
||||||
|
|
||||||
|
tree no-sections 1.2.3-dev <<'EOF'
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
Only preamble prose, no sections.
|
||||||
|
EOF
|
||||||
|
check "changelog with no '## ' at all fails" 1 "nothing for a PR entry to land under" \
|
||||||
|
in_tree no-sections
|
||||||
|
|
||||||
|
mkdir -p "$TMP/no-changelog"
|
||||||
|
printf '1.2.3\n' >"$TMP/no-changelog/VERSION"
|
||||||
|
check "missing changelog fails" 1 "no such file" in_tree no-changelog
|
||||||
|
|
||||||
|
mkdir -p "$TMP/no-version"
|
||||||
|
printf '# Changelog\n\n## Unreleased\n' >"$TMP/no-version/CHANGELOG.md"
|
||||||
|
check "missing version source fails" 1 "cannot read the version" in_tree no-version
|
||||||
|
|
||||||
|
check "unknown version-source refused" 1 "unknown backend" \
|
||||||
|
in_tree dev-armed CHANGELOG.md carrier-pigeon
|
||||||
|
|
||||||
|
# --- the package-json backend ------------------------------------------------
|
||||||
|
|
||||||
|
pkg_tree pkg-dev-armed 0.2.0-dev <<'EOF'
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
- Pending entry.
|
||||||
|
|
||||||
|
## 0.1.0 — 2026-07-20
|
||||||
|
|
||||||
|
- The shipped entry.
|
||||||
|
EOF
|
||||||
|
check "package-json: -dev + armed passes" 0 "agrees" \
|
||||||
|
in_tree pkg-dev-armed CHANGELOG.md package-json
|
||||||
|
|
||||||
|
pkg_tree pkg-bare-armed 0.1.0 <<'EOF'
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
## Unreleased
|
||||||
|
|
||||||
|
## 0.1.0 — 2026-07-20
|
||||||
|
|
||||||
|
- The shipped entry.
|
||||||
|
EOF
|
||||||
|
check "package-json: bare + armed passes" 0 "agrees" \
|
||||||
|
in_tree pkg-bare-armed CHANGELOG.md package-json
|
||||||
|
|
||||||
|
# --- the action's wiring: inputs arrive as env vars --------------------------
|
||||||
|
|
||||||
|
mkdir -p "$TMP/env-tree"
|
||||||
|
printf '1.2.4-dev\n' >"$TMP/env-tree/VERSION"
|
||||||
|
printf '# Changelog\n\n## Unreleased\n\n- Pending.\n' >"$TMP/env-tree/NOTES.md"
|
||||||
|
# A non-default changelog name proves the env var is honored, not the default.
|
||||||
|
env_tree() {
|
||||||
|
(cd "$TMP/env-tree" && CHANGELOG=NOTES.md VERSION_SOURCE=file bash "$SCRIPT")
|
||||||
|
}
|
||||||
|
check "env vars drive the script the way action.yml does" 0 "agrees" env_tree
|
||||||
|
|
||||||
|
summary
|
||||||
Loading…
Reference in a new issue