Release / release (push) Successful in 6s
Replicate the dsh-facet release stack: a Gitea Actions workflow (.gitea/workflows/release.yml) + .gitea/scripts/release.sh read the commit subjects since the last tag, bump package.json, prepend CHANGELOG.md, tag vX.Y.Z and publish the release via API. Agreed install ref is #semver:^0.1.0, and tags are what 'dsh plugin --profile web update' moves to, so the workflow is what makes updates work. Add the release.test.sh suite (43 checks), npm scripts (test:release / release:plan / release:notes), AGENTS.md with the commit conventions, CHANGELOG.md seed, and the README *Releases* rules.
200 lines
7.0 KiB
Bash
Executable File
200 lines
7.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# Tests for the release script, in throwaway git repositories.
|
|
#
|
|
# These paths only occur at moments you cannot stage by hand — a repository with
|
|
# no tags, a range that asks for no release, a version whose patch number is
|
|
# already two digits — and getting them wrong publishes a wrong version or no
|
|
# release at all. Run with: bash .gitea/scripts/release.test.sh
|
|
|
|
set -euo pipefail
|
|
|
|
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
RELEASE="$HERE/release.sh"
|
|
PASS=0
|
|
FAIL=0
|
|
|
|
# A fresh repository with one commit, optionally tagged.
|
|
new_repo() {
|
|
local dir
|
|
dir="$(mktemp -d)"
|
|
cd "$dir"
|
|
git init -q
|
|
git config user.email test@example.com
|
|
git config user.name Test
|
|
printf '{\n "name": "thing",\n "version": "%s"\n}\n' "${1:-0.1.0}" > package.json
|
|
git add -A
|
|
git commit -qm "Scaffold the thing"
|
|
echo "$dir"
|
|
}
|
|
|
|
commit() {
|
|
git commit -q --allow-empty -m "$1"
|
|
}
|
|
|
|
tag() {
|
|
git tag "$1"
|
|
}
|
|
|
|
check() {
|
|
local label="$1" expected="$2" actual="$3"
|
|
if [ "$expected" = "$actual" ]; then
|
|
PASS=$((PASS + 1))
|
|
printf ' ok %s\n' "$label"
|
|
else
|
|
FAIL=$((FAIL + 1))
|
|
printf ' FAIL %s\n expected: %s\n actual: %s\n' "$label" "$expected" "$actual"
|
|
fi
|
|
}
|
|
|
|
check_contains() {
|
|
local label="$1" needle="$2" haystack="$3"
|
|
if printf '%s' "$haystack" | grep -qF -- "$needle"; then
|
|
PASS=$((PASS + 1))
|
|
printf ' ok %s\n' "$label"
|
|
else
|
|
FAIL=$((FAIL + 1))
|
|
printf ' FAIL %s\n missing: %s\n in: %s\n' "$label" "$needle" "$haystack"
|
|
fi
|
|
}
|
|
|
|
check_absent() {
|
|
local label="$1" needle="$2" haystack="$3"
|
|
if printf '%s' "$haystack" | grep -qF -- "$needle"; then
|
|
FAIL=$((FAIL + 1))
|
|
printf ' FAIL %s\n should not contain: %s\n' "$label" "$needle"
|
|
else
|
|
PASS=$((PASS + 1))
|
|
printf ' ok %s\n' "$label"
|
|
fi
|
|
}
|
|
|
|
echo "semver arithmetic"
|
|
check "patch" "0.1.1" "$(bash "$RELEASE" apply-bump 0.1.0 patch)"
|
|
check "minor" "0.2.0" "$(bash "$RELEASE" apply-bump 0.1.5 minor)"
|
|
check "major" "1.0.0" "$(bash "$RELEASE" apply-bump 0.9.9 major)"
|
|
check "patch to 10" "0.1.10" "$(bash "$RELEASE" apply-bump 0.1.9 patch)"
|
|
check "minor to 10" "0.10.0" "$(bash "$RELEASE" apply-bump 0.9.3 minor)"
|
|
check "prerelease" "0.1.1" "$(bash "$RELEASE" apply-bump 0.1.0-rc.1 patch)"
|
|
|
|
echo
|
|
echo "first release with no tags"
|
|
new_repo 0.2.0 >/dev/null
|
|
check "version is the declared one" "0.2.0" "$(bash "$RELEASE" next-version patch)"
|
|
check "no tag yet" "" "$(bash "$RELEASE" last-tag)"
|
|
cd /;
|
|
|
|
echo
|
|
echo "subsequent releases move forward from the tag"
|
|
new_repo 0.1.0 >/dev/null
|
|
tag v0.1.3
|
|
check "patch" "0.1.4" "$(bash "$RELEASE" next-version patch)"
|
|
check "minor" "0.2.0" "$(bash "$RELEASE" next-version minor)"
|
|
check "major" "1.0.0" "$(bash "$RELEASE" next-version major)"
|
|
commit "Fix the thing"
|
|
check "bump defaults to patch" "patch" "$(bash "$RELEASE" bump "v0.1.3..HEAD")"
|
|
commit "Add a capability [minor]"
|
|
check "marker raises the bump" "minor" "$(bash "$RELEASE" bump "v0.1.3..HEAD")"
|
|
check "and the version follows" "0.2.0" "$(bash "$RELEASE" next-version "$(bash "$RELEASE" bump "v0.1.3..HEAD")")"
|
|
commit "Rewrite everything [major]"
|
|
check "major outranks minor" "major" "$(bash "$RELEASE" bump "v0.1.3..HEAD")"
|
|
cd /;
|
|
|
|
echo
|
|
echo "the subject decides the bump"
|
|
new_repo 0.1.0 >/dev/null
|
|
tag v0.1.0
|
|
check "prose is a patch" "patch" "$(bash "$RELEASE" bump "v0.1.0..HEAD")"
|
|
commit "feat: add the recall index"
|
|
check "feat is a minor" "minor" "$(bash "$RELEASE" bump "v0.1.0..HEAD")"
|
|
check "so 0.1 -> 0.2" "0.2.0" "$(bash "$RELEASE" next-version "$(bash "$RELEASE" bump "v0.1.0..HEAD")")"
|
|
cd /;
|
|
|
|
new_repo 0.1.0 >/dev/null
|
|
tag v0.1.0
|
|
commit "feat(scope): add the scope filter"
|
|
check "a scoped feat counts" "minor" "$(bash "$RELEASE" bump "v0.1.0..HEAD")"
|
|
cd /;
|
|
|
|
new_repo 0.1.0 >/dev/null
|
|
tag v0.1.0
|
|
commit "Fix the feature flag leak"
|
|
check "feat inside a word is not a feature" "no" "$(bash "$RELEASE" is-feature "Fix the feature flag leak")"
|
|
check "so it stays a patch" "patch" "$(bash "$RELEASE" bump "v0.1.0..HEAD")"
|
|
cd /;
|
|
|
|
new_repo 0.1.0 >/dev/null
|
|
tag v0.1.0
|
|
commit "feat!: move the index to sqlite"
|
|
check "a bang is breaking" "yes" "$(bash "$RELEASE" is-breaking "feat!: move the index to sqlite")"
|
|
check "so it is a major" "major" "$(bash "$RELEASE" bump "v0.1.0..HEAD")"
|
|
check "and 0.1 -> 1.0" "1.0.0" "$(bash "$RELEASE" next-version "$(bash "$RELEASE" bump "v0.1.0..HEAD")")"
|
|
NOTES="$(bash "$RELEASE" notes "v0.1.0..HEAD")"
|
|
check_contains "breaking gets a section" "### Breaking" "$NOTES"
|
|
check_contains "and is listed there" "- move the index to sqlite" "$NOTES"
|
|
check_absent "not under Added" "### Added" "$NOTES"
|
|
cd /;
|
|
|
|
echo
|
|
echo "skip release"
|
|
new_repo 0.1.0 >/dev/null
|
|
tag v0.1.0
|
|
commit "Update the README [skip release]"
|
|
check "skip is detected" "yes" "$(bash "$RELEASE" wants-skip "v0.1.0..HEAD")"
|
|
check_absent "skipped work is not in the notes" "Update the README" "$(bash "$RELEASE" notes "v0.1.0..HEAD")"
|
|
commit "Fix a real bug"
|
|
check "a later real change does not un-skip" "yes" "$(bash "$RELEASE" wants-skip "v0.1.0..HEAD")"
|
|
check "so nothing is released" "no" "$(bash "$RELEASE" should-release "v0.1.0..HEAD")"
|
|
cd /;
|
|
|
|
echo
|
|
echo "notes only cover the range"
|
|
new_repo 0.1.0 >/dev/null
|
|
tag v0.1.0
|
|
commit "Fix the leaked handle"
|
|
commit "Add the status card"
|
|
NOTES="$(bash "$RELEASE" notes "v0.1.0..HEAD")"
|
|
check_contains "includes the new work" "Add the status card" "$NOTES"
|
|
check_contains "includes the fix" "Fix the leaked handle" "$NOTES"
|
|
check_absent "excludes released work" "Scaffold the thing" "$NOTES"
|
|
check "a range with real work releases" "yes" "$(bash "$RELEASE" should-release "v0.1.0..HEAD")"
|
|
cd /;
|
|
|
|
echo
|
|
echo "conventional commits are grouped, plain ones are not"
|
|
new_repo 0.1.0 >/dev/null
|
|
tag v0.1.0
|
|
commit "feat: add the release workflow"
|
|
commit "fix: stop the runner tagging twice"
|
|
commit "docs: explain the markers"
|
|
NOTES="$(bash "$RELEASE" notes "v0.1.0..HEAD")"
|
|
check_contains "grouped heading" "### Added" "$NOTES"
|
|
check_contains "grouped fix" "### Fixed" "$NOTES"
|
|
check_contains "prefix stripped" "- add the release workflow" "$NOTES"
|
|
check_absent "no raw prefix" "feat: add" "$NOTES"
|
|
cd /;
|
|
|
|
echo
|
|
new_repo 0.1.0 >/dev/null
|
|
tag v0.1.0
|
|
commit "Background only the warm-up, and use the framework's own parameter name"
|
|
commit "Make the settings card behave like the other cards"
|
|
NOTES="$(bash "$RELEASE" notes "v0.1.0..HEAD")"
|
|
check_absent "prose commits get no invented headings" "### Added" "$NOTES"
|
|
check_contains "and stay as bullets" "- Make the settings card behave" "$NOTES"
|
|
cd /;
|
|
|
|
echo
|
|
echo "an empty range says so rather than printing nothing"
|
|
new_repo 0.1.0 >/dev/null
|
|
tag v0.1.0
|
|
check "empty range" "_No changes._" "$(bash "$RELEASE" notes "v0.1.0..HEAD")"
|
|
# The release commit is itself a push to master; without this the next run would
|
|
# publish a release describing nothing.
|
|
check "an empty range releases nothing" "no" "$(bash "$RELEASE" should-release "v0.1.0..HEAD")"
|
|
cd /;
|
|
|
|
echo
|
|
printf 'passed %d, failed %d\n' "$PASS" "$FAIL"
|
|
[ "$FAIL" -eq 0 ]
|