#!/usr/bin/env bash # Test: promote.sh extracts a tag's tree into the public repo working dir (excluding .git + .github, # and anything marked `export-ignore` in .gitattributes — internal docs), keeps CHANGELOG.md public, # commits "Release " and creates the tag. The public repo's own .git is preserved. set -euo pipefail here="$(cd "$(dirname "$0")" && pwd)" work="$(mktemp -d)"; trap 'rm -rf "$work"' EXIT export GIT_AUTHOR_NAME=t GIT_AUTHOR_EMAIL=t@t GIT_COMMITTER_NAME=t GIT_COMMITTER_EMAIL=t@t # source repo with a tag, a .github dir, an .env.example, a public CHANGELOG.md, and internal files # that .gitattributes marks export-ignore (must NOT reach the public repo). git init -q "$work/src" mkdir -p "$work/src/.github/workflows" "$work/src/docs/superpowers" printf 'app\n' > "$work/src/app.txt" printf 'CLUSEV_REPOSITORY=\n' > "$work/src/.env.example" printf 'name: ci\n' > "$work/src/.github/workflows/ci.yml" printf '# Changelog\n' > "$work/src/CHANGELOG.md" printf '/CLAUDE.md export-ignore\n/docs export-ignore\n' > "$work/src/.gitattributes" printf 'internal\n' > "$work/src/CLAUDE.md" printf 'internal spec\n' > "$work/src/docs/superpowers/spec.md" git -C "$work/src" add -A && git -C "$work/src" commit -qm init && git -C "$work/src" tag v1.0.0 # empty public repo (its own history) git init -q "$work/pub" bash "$here/promote.sh" "$work/src" v1.0.0 "$work/pub" "Release v1.0.0" test -f "$work/pub/app.txt" || { echo "FAIL: tree not copied"; exit 1; } test -f "$work/pub/.env.example" || { echo "FAIL: .env.example missing"; exit 1; } test -f "$work/pub/CHANGELOG.md" || { echo "FAIL: CHANGELOG.md must stay public (Versions page fetches it)"; exit 1; } test ! -d "$work/pub/.github" || { echo "FAIL: .github leaked to public"; exit 1; } test ! -f "$work/pub/CLAUDE.md" || { echo "FAIL: internal CLAUDE.md leaked to public"; exit 1; } test ! -d "$work/pub/docs" || { echo "FAIL: internal docs/ leaked to public"; exit 1; } test -d "$work/pub/.git" || { echo "FAIL: public .git clobbered"; exit 1; } git -C "$work/pub" rev-parse v1.0.0 >/dev/null 2>&1 || { echo "FAIL: tag missing"; exit 1; } git -C "$work/pub" log -1 --pretty=%s | grep -qx 'Release v1.0.0' || { echo "FAIL: commit message"; exit 1; } # Beta -> stable: stable re-tags the SAME source commit, so the extracted tree is byte-identical # to the last promotion. Promote a second tag (same tree) into the SAME pub repo and assert it # still creates the tag — guards against `git commit` aborting on "nothing to commit". git -C "$work/src" tag v1.0.1 v1.0.0 bash "$here/promote.sh" "$work/src" v1.0.1 "$work/pub" "Release v1.0.1" git -C "$work/pub" rev-parse v1.0.1 >/dev/null 2>&1 || { echo "FAIL: identical-tree tag missing"; exit 1; } git -C "$work/pub" log -1 --pretty=%s | grep -qx 'Release v1.0.1' || { echo "FAIL: identical-tree commit message"; exit 1; } # Leak guard: a tree that still carries an internal-only doc (i.e. a tag cut before the # export-ignore fixes) must be REFUSED, with no tag created. git init -q "$work/leaky" printf 'app\n' > "$work/leaky/app.txt" printf 'internal notes\n' > "$work/leaky/CLAUDE.md" # present (not export-ignored here) -> pre-fix tree git -C "$work/leaky" add -A && git -C "$work/leaky" commit -qm init && git -C "$work/leaky" tag v9.9.9 git init -q "$work/pub2" if bash "$here/promote.sh" "$work/leaky" v9.9.9 "$work/pub2" "Release v9.9.9" 2>/dev/null; then echo "FAIL: leak guard did not refuse a tree carrying an internal doc"; exit 1 fi git -C "$work/pub2" rev-parse v9.9.9 >/dev/null 2>&1 && { echo "FAIL: tag created despite leak guard"; exit 1; } echo "PASS"