Skip to content

Commit ec5e4c5

Browse files
Merge pull request #19 from alexphillips-dev/fix/main-history-guard-allows-promotion-merges
Allow main promotion merges in history guard
2 parents 367a83f + 4aa0f25 commit ec5e4c5

2 files changed

Lines changed: 66 additions & 4 deletions

File tree

scripts/main_branch_history_guard.sh

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,72 @@ if [[ -z "${RANGE}" ]]; then
5353
exit 0
5454
fi
5555

56+
ensure_allowed_merge_refs() {
57+
local missing=()
58+
local branch=""
59+
for branch in dev beta; do
60+
if git rev-parse --verify "refs/remotes/origin/${branch}^{commit}" >/dev/null 2>&1; then
61+
continue
62+
fi
63+
missing+=("${branch}")
64+
done
65+
66+
if [[ "${#missing[@]}" -eq 0 ]]; then
67+
return
68+
fi
69+
70+
git fetch --no-tags origin "${missing[@]}" >/dev/null 2>&1 || true
71+
}
72+
73+
merge_commit_allowed() {
74+
local commit="${1:-}"
75+
local parent_refs=""
76+
local parent_list=()
77+
local parent_index=0
78+
local parent_commit=""
79+
local allowed_ref=""
80+
81+
parent_refs="$(git show -s --format=%P "${commit}" 2>/dev/null || true)"
82+
if [[ -z "${parent_refs}" ]]; then
83+
return 1
84+
fi
85+
86+
# Non-first parents identify the merged branch tip(s).
87+
read -r -a parent_list <<< "${parent_refs}"
88+
for (( parent_index=1; parent_index<${#parent_list[@]}; parent_index++ )); do
89+
parent_commit="${parent_list[$parent_index]}"
90+
for allowed_ref in refs/remotes/origin/dev refs/heads/dev refs/remotes/origin/beta refs/heads/beta; do
91+
if ! git rev-parse --verify "${allowed_ref}^{commit}" >/dev/null 2>&1; then
92+
continue
93+
fi
94+
if git merge-base --is-ancestor "${parent_commit}" "${allowed_ref}"; then
95+
return 0
96+
fi
97+
done
98+
done
99+
100+
return 1
101+
}
102+
56103
MERGES="$(git rev-list --merges "${RANGE}" || true)"
57104
if [[ -n "${MERGES}" ]]; then
58-
echo "ERROR: merge commits are not allowed in the checked main-branch range (${RANGE})." >&2
59-
echo "${MERGES}" >&2
60-
exit 1
105+
BAD_MERGES=()
106+
MERGE_COMMIT=""
107+
108+
ensure_allowed_merge_refs
109+
110+
while IFS= read -r MERGE_COMMIT; do
111+
[[ -z "${MERGE_COMMIT}" ]] && continue
112+
if ! merge_commit_allowed "${MERGE_COMMIT}"; then
113+
BAD_MERGES+=("${MERGE_COMMIT}")
114+
fi
115+
done <<< "${MERGES}"
116+
117+
if [[ "${#BAD_MERGES[@]}" -gt 0 ]]; then
118+
echo "ERROR: main-branch merge commits must promote only dev/beta history in the checked range (${RANGE})." >&2
119+
printf '%s\n' "${BAD_MERGES[@]}" >&2
120+
exit 1
121+
fi
61122
fi
62123

63124
echo "Main branch history guard passed: range=${RANGE}"

tests/versioning-guard.test.mjs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,8 @@ test('standards guard scripts exist with expected core checks', () => {
425425
assert.match(mainBranchHistoryGuard, /Main branch history guard skipped/);
426426
assert.match(mainBranchHistoryGuard, /FVPLUS_MAIN_HISTORY_BASE_REF/);
427427
assert.match(mainBranchHistoryGuard, /@\{upstream\}\.\.HEAD/);
428-
assert.match(mainBranchHistoryGuard, /merge commits are not allowed/);
428+
assert.match(mainBranchHistoryGuard, /merge_commit_allowed/);
429+
assert.match(mainBranchHistoryGuard, /main-branch merge commits must promote only dev\/beta history/);
429430
assert.match(mainBranchHistoryGuard, /Main branch history guard passed/);
430431
assert.match(unraidMatrixSmoke, /FVPLUS_UNRAID_MATRIX/);
431432
assert.match(unraidMatrixSmoke, /Skipping Unraid matrix smoke checks/);

0 commit comments

Comments
 (0)