返回 CodeWhale
ensure-release-on-main.sh
根目录 / scripts / release / ensure-release-on-main.sh
1 #!/usr/bin/env bash
2 # Verify a release commit is reachable from the canonical main branch.
3 #
4 # GitHub only processes "Closes #N" keywords when the closing commit lands on
5 # the repository default branch. Refuse branch-only release tags so release
6 # assets cannot ship from commits that main does not contain.
7 set -euo pipefail
8
9 usage() {
10 cat >&2 <<'EOF'
11 usage: ensure-release-on-main.sh [--remote <name>] [--main <branch>] <commit-ish>
12
13 Defaults:
14 --remote origin
15 --main main
16 EOF
17 }
18
19 remote="origin"
20 main_branch="main"
21
22 while [[ $# -gt 0 ]]; do
23 case "$1" in
24 --remote)
25 remote="${2:?missing value for --remote}"
26 shift 2
27 ;;
28 --main)
29 main_branch="${2:?missing value for --main}"
30 shift 2
31 ;;
32 -h|--help)
33 usage
34 exit 0
35 ;;
36 -*)
37 echo "error: unknown option '$1'" >&2
38 usage
39 exit 2
40 ;;
41 *)
42 break
43 ;;
44 esac
45 done
46
47 if [[ $# -ne 1 ]]; then
48 usage
49 exit 2
50 fi
51
52 repo="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
53 cd "${repo}"
54
55 commit="$1"
56 sha="$(git rev-parse --verify "${commit}^{commit}" 2>/dev/null)" || {
57 echo "error: '${commit}' is not a commit" >&2
58 exit 2
59 }
60
61 main_ref="refs/remotes/${remote}/${main_branch}"
62 git fetch --no-tags "${remote}" "+refs/heads/${main_branch}:${main_ref}" >/dev/null
63
64 main_sha="$(git rev-parse --verify "${main_ref}^{commit}" 2>/dev/null)" || {
65 echo "error: could not resolve ${main_ref}" >&2
66 exit 2
67 }
68
69 if git merge-base --is-ancestor "${sha}" "${main_sha}"; then
70 echo "Release source ${sha} is reachable from ${remote}/${main_branch} (${main_sha})."
71 exit 0
72 fi
73
74 cat >&2 <<EOF
75 ::error::Release source ${sha} is not reachable from ${remote}/${main_branch} (${main_sha}).
76 Merge the release PR into ${main_branch} before tagging so GitHub processes
77 closing keywords and the release PR shows as merged.
78 EOF
79 exit 1
80
80 lines BASH