#!/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 "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 ]