chore(governance): enforce backend architecture and quality gates (#31)
* docs(governance): add canonical governance docs, unified quality-gate script, and CI parity
- ARCHITECTURE_AND_CODE_QUALITY.md: canonical layering, EF allowlist,
transaction/commit convention, cancellation, migrations, error disclosure,
Big-O/perf, ADR exceptions (supersedes BACKEND_ARCHITECTURE.md)
- QUALITY_GATES.md: gate inventory + pass/fail/skip semantics; local==CI
- REVIEW_AND_PR_FRAMEWORK.md: exact-head review, board-backed regression
inventory, security/perf evidence, ADR exceptions, no godfile theater
- AGENTS.md: repo-specific delta + precedence pointers
- scripts/governance-check.sh: unified G1 restore + G2 ArchitectureTests +
G3 changed-file format (portable bash)
- .github/workflows/architecture-quality.yml: call the same local script
- ArchitectureTests.cs: add business-service interface-dependency invariant
* fix(governance): make backend gate complete
* fix(ci): enforce governance on every pull request
2026-07-24 17:41:10 -03:00
|
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
|
#
|
|
|
|
|
|
# governance-check.sh — local/CI parity governance gate for the Seahaven backend.
|
|
|
|
|
|
#
|
2026-09-19 15:36:40 -04:00
|
|
|
|
# Locally this runs G1–G5, G10, G11, promotion-script tests, and live G13.
|
|
|
|
|
|
# The architecture job in ci.yml sets GOVERNANCE_SKIP_BUILD_TEST=1 so G4/G5
|
|
|
|
|
|
# run only in the Build and test job. Live G13 runs on pull_request and local
|
|
|
|
|
|
# invocations; it skips merge_group and push.
|
chore(governance): enforce backend architecture and quality gates (#31)
* docs(governance): add canonical governance docs, unified quality-gate script, and CI parity
- ARCHITECTURE_AND_CODE_QUALITY.md: canonical layering, EF allowlist,
transaction/commit convention, cancellation, migrations, error disclosure,
Big-O/perf, ADR exceptions (supersedes BACKEND_ARCHITECTURE.md)
- QUALITY_GATES.md: gate inventory + pass/fail/skip semantics; local==CI
- REVIEW_AND_PR_FRAMEWORK.md: exact-head review, board-backed regression
inventory, security/perf evidence, ADR exceptions, no godfile theater
- AGENTS.md: repo-specific delta + precedence pointers
- scripts/governance-check.sh: unified G1 restore + G2 ArchitectureTests +
G3 changed-file format (portable bash)
- .github/workflows/architecture-quality.yml: call the same local script
- ArchitectureTests.cs: add business-service interface-dependency invariant
* fix(governance): make backend gate complete
* fix(ci): enforce governance on every pull request
2026-07-24 17:41:10 -03:00
|
|
|
|
#
|
|
|
|
|
|
# Usage:
|
|
|
|
|
|
# bash scripts/governance-check.sh
|
2026-09-16 14:02:46 -04:00
|
|
|
|
# BASE_REF=origin/main bash scripts/governance-check.sh
|
chore(governance): enforce backend architecture and quality gates (#31)
* docs(governance): add canonical governance docs, unified quality-gate script, and CI parity
- ARCHITECTURE_AND_CODE_QUALITY.md: canonical layering, EF allowlist,
transaction/commit convention, cancellation, migrations, error disclosure,
Big-O/perf, ADR exceptions (supersedes BACKEND_ARCHITECTURE.md)
- QUALITY_GATES.md: gate inventory + pass/fail/skip semantics; local==CI
- REVIEW_AND_PR_FRAMEWORK.md: exact-head review, board-backed regression
inventory, security/perf evidence, ADR exceptions, no godfile theater
- AGENTS.md: repo-specific delta + precedence pointers
- scripts/governance-check.sh: unified G1 restore + G2 ArchitectureTests +
G3 changed-file format (portable bash)
- .github/workflows/architecture-quality.yml: call the same local script
- ArchitectureTests.cs: add business-service interface-dependency invariant
* fix(governance): make backend gate complete
* fix(ci): enforce governance on every pull request
2026-07-24 17:41:10 -03:00
|
|
|
|
# BASE_REF=<base-sha> HEAD_REF=<head-sha> bash scripts/governance-check.sh
|
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
|
|
|
|
|
|
|
SOLUTION="SeaHavenIndustries.sln"
|
|
|
|
|
|
ARCH_TEST_PROJECT="Api.SeaHavenIndustries.Tests/Api.SeaHavenIndustries.Tests.csproj"
|
2026-09-19 15:36:40 -04:00
|
|
|
|
LIVE_ROOTS=(terraform/live/dev terraform/live/staging)
|
chore(governance): enforce backend architecture and quality gates (#31)
* docs(governance): add canonical governance docs, unified quality-gate script, and CI parity
- ARCHITECTURE_AND_CODE_QUALITY.md: canonical layering, EF allowlist,
transaction/commit convention, cancellation, migrations, error disclosure,
Big-O/perf, ADR exceptions (supersedes BACKEND_ARCHITECTURE.md)
- QUALITY_GATES.md: gate inventory + pass/fail/skip semantics; local==CI
- REVIEW_AND_PR_FRAMEWORK.md: exact-head review, board-backed regression
inventory, security/perf evidence, ADR exceptions, no godfile theater
- AGENTS.md: repo-specific delta + precedence pointers
- scripts/governance-check.sh: unified G1 restore + G2 ArchitectureTests +
G3 changed-file format (portable bash)
- .github/workflows/architecture-quality.yml: call the same local script
- ArchitectureTests.cs: add business-service interface-dependency invariant
* fix(governance): make backend gate complete
* fix(ci): enforce governance on every pull request
2026-07-24 17:41:10 -03:00
|
|
|
|
|
|
|
|
|
|
log() { printf '\n\033[1m== %s ==\033[0m\n' "$1"; }
|
|
|
|
|
|
ok() { printf '\033[32mPASS\033[0m %s\n' "$1"; }
|
|
|
|
|
|
bad() { printf '\033[31mFAIL\033[0m %s\n' "$1"; }
|
|
|
|
|
|
|
|
|
|
|
|
if [[ -n "${DOTNET_BIN:-}" ]]; then
|
|
|
|
|
|
DOTNET="$DOTNET_BIN"
|
|
|
|
|
|
elif command -v dotnet >/dev/null 2>&1; then
|
|
|
|
|
|
DOTNET="$(command -v dotnet)"
|
|
|
|
|
|
elif [[ -x "$HOME/.dotnet/dotnet" ]]; then
|
|
|
|
|
|
DOTNET="$HOME/.dotnet/dotnet"
|
|
|
|
|
|
else
|
|
|
|
|
|
bad "dotnet is unavailable; set DOTNET_BIN or install the repository SDK."
|
|
|
|
|
|
exit 1
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
2026-09-16 14:02:46 -04:00
|
|
|
|
# Comparison point for changed-file formatting. Default to main locally; CI
|
|
|
|
|
|
# overrides BASE_REF/HEAD_REF with the PR base/head SHAs.
|
|
|
|
|
|
BASE_REF="${BASE_REF:-origin/main}"
|
chore(governance): enforce backend architecture and quality gates (#31)
* docs(governance): add canonical governance docs, unified quality-gate script, and CI parity
- ARCHITECTURE_AND_CODE_QUALITY.md: canonical layering, EF allowlist,
transaction/commit convention, cancellation, migrations, error disclosure,
Big-O/perf, ADR exceptions (supersedes BACKEND_ARCHITECTURE.md)
- QUALITY_GATES.md: gate inventory + pass/fail/skip semantics; local==CI
- REVIEW_AND_PR_FRAMEWORK.md: exact-head review, board-backed regression
inventory, security/perf evidence, ADR exceptions, no godfile theater
- AGENTS.md: repo-specific delta + precedence pointers
- scripts/governance-check.sh: unified G1 restore + G2 ArchitectureTests +
G3 changed-file format (portable bash)
- .github/workflows/architecture-quality.yml: call the same local script
- ArchitectureTests.cs: add business-service interface-dependency invariant
* fix(governance): make backend gate complete
* fix(ci): enforce governance on every pull request
2026-07-24 17:41:10 -03:00
|
|
|
|
HEAD_REF="${HEAD_REF:-HEAD}"
|
|
|
|
|
|
|
|
|
|
|
|
# Resolve the base ref before using it for a diff.
|
|
|
|
|
|
if ! git rev-parse --verify --quiet "${BASE_REF}^{commit}" >/dev/null; then
|
|
|
|
|
|
bad "G3: BASE_REF '${BASE_REF}' does not resolve to a commit (run: git fetch origin)."
|
|
|
|
|
|
exit 1
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
2026-09-18 19:12:21 -04:00
|
|
|
|
# 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
|
|
|
|
|
|
}
|
|
|
|
|
|
|
chore(governance): enforce backend architecture and quality gates (#31)
* docs(governance): add canonical governance docs, unified quality-gate script, and CI parity
- ARCHITECTURE_AND_CODE_QUALITY.md: canonical layering, EF allowlist,
transaction/commit convention, cancellation, migrations, error disclosure,
Big-O/perf, ADR exceptions (supersedes BACKEND_ARCHITECTURE.md)
- QUALITY_GATES.md: gate inventory + pass/fail/skip semantics; local==CI
- REVIEW_AND_PR_FRAMEWORK.md: exact-head review, board-backed regression
inventory, security/perf evidence, ADR exceptions, no godfile theater
- AGENTS.md: repo-specific delta + precedence pointers
- scripts/governance-check.sh: unified G1 restore + G2 ArchitectureTests +
G3 changed-file format (portable bash)
- .github/workflows/architecture-quality.yml: call the same local script
- ArchitectureTests.cs: add business-service interface-dependency invariant
* fix(governance): make backend gate complete
* fix(ci): enforce governance on every pull request
2026-07-24 17:41:10 -03:00
|
|
|
|
log "G1: restore"
|
|
|
|
|
|
"$DOTNET" restore "$SOLUTION"
|
|
|
|
|
|
ok "G1: restore"
|
|
|
|
|
|
|
|
|
|
|
|
log "G2: architecture boundary tests (dependency direction)"
|
|
|
|
|
|
"$DOTNET" test "$ARCH_TEST_PROJECT" \
|
|
|
|
|
|
--no-restore \
|
|
|
|
|
|
--filter "FullyQualifiedName~ArchitectureTests" \
|
|
|
|
|
|
--nologo
|
|
|
|
|
|
ok "G2: ArchitectureTests"
|
|
|
|
|
|
|
2026-09-18 19:12:21 -04:00
|
|
|
|
log "G3: changed-file formatting (${BASE_REF}...${HEAD_REF}, merge base ${DIFF_BASE:0:7})"
|
chore(governance): enforce backend architecture and quality gates (#31)
* docs(governance): add canonical governance docs, unified quality-gate script, and CI parity
- ARCHITECTURE_AND_CODE_QUALITY.md: canonical layering, EF allowlist,
transaction/commit convention, cancellation, migrations, error disclosure,
Big-O/perf, ADR exceptions (supersedes BACKEND_ARCHITECTURE.md)
- QUALITY_GATES.md: gate inventory + pass/fail/skip semantics; local==CI
- REVIEW_AND_PR_FRAMEWORK.md: exact-head review, board-backed regression
inventory, security/perf evidence, ADR exceptions, no godfile theater
- AGENTS.md: repo-specific delta + precedence pointers
- scripts/governance-check.sh: unified G1 restore + G2 ArchitectureTests +
G3 changed-file format (portable bash)
- .github/workflows/architecture-quality.yml: call the same local script
- ArchitectureTests.cs: add business-service interface-dependency invariant
* fix(governance): make backend gate complete
* fix(ci): enforce governance on every pull request
2026-07-24 17:41:10 -03:00
|
|
|
|
changed_cs=()
|
|
|
|
|
|
while IFS= read -r f; do
|
|
|
|
|
|
changed_cs+=("$f")
|
|
|
|
|
|
done < <(
|
2026-09-18 19:12:21 -04:00
|
|
|
|
git diff --name-only --diff-filter=ACMR "${DIFF_BASE}" "${HEAD_REF}" -- '*.cs'
|
chore(governance): enforce backend architecture and quality gates (#31)
* docs(governance): add canonical governance docs, unified quality-gate script, and CI parity
- ARCHITECTURE_AND_CODE_QUALITY.md: canonical layering, EF allowlist,
transaction/commit convention, cancellation, migrations, error disclosure,
Big-O/perf, ADR exceptions (supersedes BACKEND_ARCHITECTURE.md)
- QUALITY_GATES.md: gate inventory + pass/fail/skip semantics; local==CI
- REVIEW_AND_PR_FRAMEWORK.md: exact-head review, board-backed regression
inventory, security/perf evidence, ADR exceptions, no godfile theater
- AGENTS.md: repo-specific delta + precedence pointers
- scripts/governance-check.sh: unified G1 restore + G2 ArchitectureTests +
G3 changed-file format (portable bash)
- .github/workflows/architecture-quality.yml: call the same local script
- ArchitectureTests.cs: add business-service interface-dependency invariant
* fix(governance): make backend gate complete
* fix(ci): enforce governance on every pull request
2026-07-24 17:41:10 -03:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
if (( ${#changed_cs[@]} == 0 )); then
|
2026-09-18 19:12:21 -04:00
|
|
|
|
printf '\033[33mSKIP\033[0m G3: no changed C# files between %s...%s\n' "${BASE_REF}" "${HEAD_REF}"
|
chore(governance): enforce backend architecture and quality gates (#31)
* docs(governance): add canonical governance docs, unified quality-gate script, and CI parity
- ARCHITECTURE_AND_CODE_QUALITY.md: canonical layering, EF allowlist,
transaction/commit convention, cancellation, migrations, error disclosure,
Big-O/perf, ADR exceptions (supersedes BACKEND_ARCHITECTURE.md)
- QUALITY_GATES.md: gate inventory + pass/fail/skip semantics; local==CI
- REVIEW_AND_PR_FRAMEWORK.md: exact-head review, board-backed regression
inventory, security/perf evidence, ADR exceptions, no godfile theater
- AGENTS.md: repo-specific delta + precedence pointers
- scripts/governance-check.sh: unified G1 restore + G2 ArchitectureTests +
G3 changed-file format (portable bash)
- .github/workflows/architecture-quality.yml: call the same local script
- ArchitectureTests.cs: add business-service interface-dependency invariant
* fix(governance): make backend gate complete
* fix(ci): enforce governance on every pull request
2026-07-24 17:41:10 -03:00
|
|
|
|
else
|
|
|
|
|
|
printf ' checking %d changed C# file(s)\n' "${#changed_cs[@]}"
|
|
|
|
|
|
"$DOTNET" format "$SOLUTION" \
|
|
|
|
|
|
--no-restore \
|
|
|
|
|
|
--verify-no-changes \
|
|
|
|
|
|
--include "${changed_cs[@]}"
|
|
|
|
|
|
ok "G3: changed-file formatting"
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
2026-09-19 15:36:40 -04:00
|
|
|
|
if [[ "${GOVERNANCE_SKIP_BUILD_TEST:-}" == "1" ]]; then
|
|
|
|
|
|
printf '\033[33mSKIP\033[0m G4: Release build (CI Build and test job owns it)\n'
|
|
|
|
|
|
printf '\033[33mSKIP\033[0m G5: full test suite (CI Build and test job owns it)\n'
|
|
|
|
|
|
else
|
|
|
|
|
|
log "G4: Release build"
|
|
|
|
|
|
"$DOTNET" build "$SOLUTION" -c Release --no-restore --nologo
|
|
|
|
|
|
ok "G4: Release build"
|
chore(governance): enforce backend architecture and quality gates (#31)
* docs(governance): add canonical governance docs, unified quality-gate script, and CI parity
- ARCHITECTURE_AND_CODE_QUALITY.md: canonical layering, EF allowlist,
transaction/commit convention, cancellation, migrations, error disclosure,
Big-O/perf, ADR exceptions (supersedes BACKEND_ARCHITECTURE.md)
- QUALITY_GATES.md: gate inventory + pass/fail/skip semantics; local==CI
- REVIEW_AND_PR_FRAMEWORK.md: exact-head review, board-backed regression
inventory, security/perf evidence, ADR exceptions, no godfile theater
- AGENTS.md: repo-specific delta + precedence pointers
- scripts/governance-check.sh: unified G1 restore + G2 ArchitectureTests +
G3 changed-file format (portable bash)
- .github/workflows/architecture-quality.yml: call the same local script
- ArchitectureTests.cs: add business-service interface-dependency invariant
* fix(governance): make backend gate complete
* fix(ci): enforce governance on every pull request
2026-07-24 17:41:10 -03:00
|
|
|
|
|
2026-09-19 15:36:40 -04:00
|
|
|
|
log "G5: full test suite"
|
|
|
|
|
|
"$DOTNET" test "$SOLUTION" -c Release --no-build --nologo
|
|
|
|
|
|
ok "G5: full test suite"
|
|
|
|
|
|
fi
|
chore(governance): enforce backend architecture and quality gates (#31)
* docs(governance): add canonical governance docs, unified quality-gate script, and CI parity
- ARCHITECTURE_AND_CODE_QUALITY.md: canonical layering, EF allowlist,
transaction/commit convention, cancellation, migrations, error disclosure,
Big-O/perf, ADR exceptions (supersedes BACKEND_ARCHITECTURE.md)
- QUALITY_GATES.md: gate inventory + pass/fail/skip semantics; local==CI
- REVIEW_AND_PR_FRAMEWORK.md: exact-head review, board-backed regression
inventory, security/perf evidence, ADR exceptions, no godfile theater
- AGENTS.md: repo-specific delta + precedence pointers
- scripts/governance-check.sh: unified G1 restore + G2 ArchitectureTests +
G3 changed-file format (portable bash)
- .github/workflows/architecture-quality.yml: call the same local script
- ArchitectureTests.cs: add business-service interface-dependency invariant
* fix(governance): make backend gate complete
* fix(ci): enforce governance on every pull request
2026-07-24 17:41:10 -03:00
|
|
|
|
|
2026-08-31 11:51:18 -04:00
|
|
|
|
log "G10: Terraform import plan safety"
|
|
|
|
|
|
python scripts/test-terraform-import-plan-check.py
|
|
|
|
|
|
ok "G10: Terraform import plan safety"
|
|
|
|
|
|
|
2026-09-16 14:02:46 -04:00
|
|
|
|
log "Release promotion scripts"
|
|
|
|
|
|
python3 scripts/test_next_release_tag.py
|
|
|
|
|
|
python3 scripts/test_require_commit_checks.py
|
|
|
|
|
|
python3 scripts/test_check_app_terraform_isolation.py
|
|
|
|
|
|
ok "Release promotion scripts"
|
|
|
|
|
|
|
2026-09-19 15:36:40 -04:00
|
|
|
|
log "G11: Terraform formatting and validation"
|
|
|
|
|
|
if ! command -v terraform >/dev/null 2>&1; then
|
|
|
|
|
|
bad "G11: terraform is unavailable; install Terraform or set PATH."
|
|
|
|
|
|
exit 1
|
|
|
|
|
|
fi
|
|
|
|
|
|
terraform fmt -check -recursive terraform
|
|
|
|
|
|
for live_root in "${LIVE_ROOTS[@]}"; do
|
|
|
|
|
|
terraform -chdir="${live_root}" init -backend=false -input=false -lockfile=readonly -no-color
|
|
|
|
|
|
terraform -chdir="${live_root}" validate -no-color
|
|
|
|
|
|
done
|
|
|
|
|
|
ok "G11: Terraform formatting and validation"
|
|
|
|
|
|
|
|
|
|
|
|
if [[ -n "${GITHUB_EVENT_NAME:-}" && "${GITHUB_EVENT_NAME}" != "pull_request" ]]; then
|
|
|
|
|
|
printf '\033[33mSKIP\033[0m G13: live isolation is a pull-request property (event: %s)\n' "${GITHUB_EVENT_NAME}"
|
|
|
|
|
|
else
|
|
|
|
|
|
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 "${DIFF_BASE}" "${HEAD_REF}"
|
|
|
|
|
|
)
|
|
|
|
|
|
ok "G13: application and Terraform isolation"
|
|
|
|
|
|
fi
|
2026-09-03 10:12:06 -04:00
|
|
|
|
|
chore(governance): enforce backend architecture and quality gates (#31)
* docs(governance): add canonical governance docs, unified quality-gate script, and CI parity
- ARCHITECTURE_AND_CODE_QUALITY.md: canonical layering, EF allowlist,
transaction/commit convention, cancellation, migrations, error disclosure,
Big-O/perf, ADR exceptions (supersedes BACKEND_ARCHITECTURE.md)
- QUALITY_GATES.md: gate inventory + pass/fail/skip semantics; local==CI
- REVIEW_AND_PR_FRAMEWORK.md: exact-head review, board-backed regression
inventory, security/perf evidence, ADR exceptions, no godfile theater
- AGENTS.md: repo-specific delta + precedence pointers
- scripts/governance-check.sh: unified G1 restore + G2 ArchitectureTests +
G3 changed-file format (portable bash)
- .github/workflows/architecture-quality.yml: call the same local script
- ArchitectureTests.cs: add business-service interface-dependency invariant
* fix(governance): make backend gate complete
* fix(ci): enforce governance on every pull request
2026-07-24 17:41:10 -03:00
|
|
|
|
log "governance-check: all required repository gates passed"
|