From 24e4f2b7f787352287486f912d5872825b20a2d7 Mon Sep 17 00:00:00 2001 From: Adam Moussa Date: Fri, 18 Sep 2026 19:12:21 -0400 Subject: [PATCH] fix(governance): diff G3 and G13 from the merge base, not the base tip The gate computed changed files with a two-dot diff against the PR base tip, so everything main gained after the branch point counted as this change. A branch behind main that touched C# failed G13 whenever main had merged Terraform in between, which is how #152 failed after #154, #156 and #158 landed. The merge queue no longer requires branches to be current, so the false positive would have hit every stale PR. Both diffs now start at the merge base. Push and merge-group runs are unchanged because their base is an ancestor of the head. --- scripts/governance-check.sh | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/scripts/governance-check.sh b/scripts/governance-check.sh index b0a9dfb..effae29 100755 --- a/scripts/governance-check.sh +++ b/scripts/governance-check.sh @@ -41,6 +41,16 @@ if ! git rev-parse --verify --quiet "${BASE_REF}^{commit}" >/dev/null; then exit 1 fi +# Diff the change set from the merge base, not from the base tip. A two-dot +# diff against a moving base reports everything the base gained after the +# branch point as if this change reverted it, so a branch behind main that +# touches C# would fail G13 whenever main had merged Terraform in the meantime. +# The merge queue no longer requires branches to be current, so this matters. +DIFF_BASE="$(git merge-base "${BASE_REF}" "${HEAD_REF}")" || { + bad "G3: no merge base between '${BASE_REF}' and '${HEAD_REF}'." + exit 1 +} + log "G1: restore" "$DOTNET" restore "$SOLUTION" ok "G1: restore" @@ -52,16 +62,16 @@ log "G2: architecture boundary tests (dependency direction)" --nologo ok "G2: ArchitectureTests" -log "G3: changed-file formatting (${BASE_REF}..${HEAD_REF})" +log "G3: changed-file formatting (${BASE_REF}...${HEAD_REF}, merge base ${DIFF_BASE:0:7})" changed_cs=() while IFS= read -r f; do changed_cs+=("$f") done < <( - git diff --name-only --diff-filter=ACMR "${BASE_REF}" "${HEAD_REF}" -- '*.cs' + git diff --name-only --diff-filter=ACMR "${DIFF_BASE}" "${HEAD_REF}" -- '*.cs' ) if (( ${#changed_cs[@]} == 0 )); then - printf '\033[33mSKIP\033[0m G3: no changed C# files between %s..%s\n' "${BASE_REF}" "${HEAD_REF}" + printf '\033[33mSKIP\033[0m G3: no changed C# files between %s...%s\n' "${BASE_REF}" "${HEAD_REF}" else printf ' checking %d changed C# file(s)\n' "${#changed_cs[@]}" "$DOTNET" format "$SOLUTION" \ @@ -89,9 +99,9 @@ python3 scripts/test_require_commit_checks.py python3 scripts/test_check_app_terraform_isolation.py ok "Release promotion scripts" -log "G13: application and Terraform isolation (${BASE_REF}..${HEAD_REF})" +log "G13: application and Terraform isolation (${BASE_REF}...${HEAD_REF}, merge base ${DIFF_BASE:0:7})" python3 scripts/check_app_terraform_isolation.py < <( - git diff --name-only --diff-filter=ACMR "${BASE_REF}" "${HEAD_REF}" + git diff --name-only --diff-filter=ACMR "${DIFF_BASE}" "${HEAD_REF}" ) ok "G13: application and Terraform isolation"