clusev/scripts/promote.sh

53 lines
2.4 KiB
Bash
Executable File

#!/usr/bin/env bash
# Promote a tag's tree from the source repo into the PUBLIC repo working dir as one clean release
# commit + tag. Excludes .git (via git archive) and .github (private CI stays private). The public
# repo's own .git is preserved. The PUSH is done by the calling workflow (it holds the credentials).
# usage: promote.sh <src-repo> <tag> <public-repo-dir> <commit-message>
set -euo pipefail
src="${1:?src repo required}"
tag="${2:?tag required}"
pub="${3:?public repo dir required}"
msg="${4:?commit message required}"
git -C "$src" rev-parse "$tag" >/dev/null 2>&1 || { echo "unknown tag: $tag" >&2; exit 1; }
# Fail fast BEFORE mutating the public tree if this release was already promoted — re-promoting a
# published release must be deliberate, not a silent half-commit left on the runner.
if git -C "$pub" rev-parse -q --verify "refs/tags/$tag" >/dev/null 2>&1; then
echo "tag already promoted in public repo: $tag" >&2
exit 1
fi
# Clear the public working tree but KEEP its .git.
find "$pub" -mindepth 1 -maxdepth 1 ! -name '.git' -exec rm -rf {} +
# Extract exactly the tag's tree (git archive omits .git automatically).
git -C "$src" archive --format=tar "$tag" | tar -x -C "$pub"
# Private CI never goes public.
rm -rf "${pub:?}/.github"
# Leak guard — never publish a tree that still carries a private identifier or an internal doc. This
# makes promote.sh safe even for a tag cut BEFORE the export-ignore / URL-neutralisation fixes: such
# a tree is refused (the public repo is left untouched) instead of leaking the dev/staging repos.
leak=0
for f in CLAUDE.md rules.md handoff.md kickoff-prompt.md docs; do
[ -e "$pub/$f" ] && { echo "leak-guard: internal path present in the tree: $f" >&2; leak=1; }
done
if grep -rIl -e 'git\.bave\.dev' -e 'boban/clusev' -e 'clusev-staging' "$pub" >/dev/null 2>&1; then
echo "leak-guard: private repo identifier in the tree to be published:" >&2
grep -rIl -e 'git\.bave\.dev' -e 'boban/clusev' -e 'clusev-staging' "$pub" >&2
leak=1
fi
if [ "$leak" -ne 0 ]; then
echo "leak-guard: REFUSING to publish $tag — promote a tag cut after the leak-safety fixes (>= v0.9.58)." >&2
exit 1
fi
git -C "$pub" add -A
# --allow-empty: stable promotion re-tags the same source commit as the last beta, so the
# extracted tree is byte-identical and there is nothing to stage — still produce a release commit.
git -C "$pub" commit -q --allow-empty -m "$msg"
git -C "$pub" tag "$tag"