mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 03:43:11 +00:00
ci: consolidate required checks behind ci-complete
This commit is contained in:
parent
03a0a6514d
commit
1188a4c1cb
11 changed files with 161 additions and 188 deletions
35
.github/workflows/architecture-quality.yml
vendored
35
.github/workflows/architecture-quality.yml
vendored
|
|
@ -1,35 +0,0 @@
|
|||
name: Architecture and changed-file quality
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
# Required by the merge queue; see ci.yml.
|
||||
merge_group:
|
||||
push:
|
||||
branches: [main]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
architecture:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up .NET
|
||||
uses: actions/setup-dotnet@v6
|
||||
with:
|
||||
dotnet-version: "8.0.x"
|
||||
|
||||
# CI and local run the same complete repository gate.
|
||||
- name: Repository quality gate
|
||||
shell: bash
|
||||
env:
|
||||
# A merge group carries its own base and head; github.event.before is
|
||||
# empty on that event.
|
||||
BASE_REF: ${{ github.event.pull_request.base.sha || github.event.merge_group.base_sha || github.event.before }}
|
||||
HEAD_REF: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha || github.sha }}
|
||||
run: bash scripts/governance-check.sh
|
||||
60
.github/workflows/ci-terraform.yaml
vendored
60
.github/workflows/ci-terraform.yaml
vendored
|
|
@ -1,60 +0,0 @@
|
|||
name: Terraform CI
|
||||
|
||||
# Static checks only. Plans run in HCP Terraform as speculative VCS runs on the
|
||||
# PR (shoc-backend-dev and shoc-backend-staging). Applies are HCP auto-apply
|
||||
# on merge to main (dev) and on a vX.Y.Z-staging tag (staging).
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main, dev]
|
||||
paths:
|
||||
- "terraform/**"
|
||||
- "scripts/**"
|
||||
- ".github/workflows/ci-terraform.yaml"
|
||||
- ".github/workflows/deploy.yaml"
|
||||
- ".github/workflows/deploy-tag.yaml"
|
||||
- ".github/workflows/release.yaml"
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- "terraform/**"
|
||||
- "scripts/**"
|
||||
- ".github/workflows/ci-terraform.yaml"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
terraform:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- uses: hashicorp/setup-terraform@dfe3c3f87815947d99a8997f908cb6525fc44e9e # v4.0.1
|
||||
with:
|
||||
terraform_version: "1.9.8"
|
||||
terraform_wrapper: false
|
||||
|
||||
- name: Terraform fmt
|
||||
run: terraform fmt -check -recursive terraform
|
||||
|
||||
- name: Validate live/dev
|
||||
run: |
|
||||
terraform -chdir=terraform/live/dev init -backend=false
|
||||
terraform -chdir=terraform/live/dev validate
|
||||
|
||||
- name: Validate live/staging
|
||||
run: |
|
||||
terraform -chdir=terraform/live/staging init -backend=false
|
||||
terraform -chdir=terraform/live/staging validate
|
||||
|
||||
- name: Import plan guard tests
|
||||
run: python3 scripts/test-terraform-import-plan-check.py
|
||||
|
||||
- name: Release promotion script tests
|
||||
run: |
|
||||
python3 scripts/test_next_release_tag.py
|
||||
python3 scripts/test_require_commit_checks.py
|
||||
python3 scripts/test_check_app_terraform_isolation.py
|
||||
85
.github/workflows/ci.yml
vendored
85
.github/workflows/ci.yml
vendored
|
|
@ -2,7 +2,6 @@ name: Backend CI
|
|||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main, dev, staging]
|
||||
# The merge queue builds main plus the queued pull requests on a temporary
|
||||
# branch and only counts checks that ran on the merge_group event.
|
||||
merge_group:
|
||||
|
|
@ -12,14 +11,15 @@ on:
|
|||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
build-and-test:
|
||||
name: Build and test
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
concurrency:
|
||||
group: backend-ci-${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
|
|
@ -29,6 +29,14 @@ jobs:
|
|||
with:
|
||||
dotnet-version: "8.0.x"
|
||||
|
||||
- name: Cache NuGet packages
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.nuget/packages
|
||||
key: nuget-${{ runner.os }}-${{ hashFiles('**/*.csproj', '**/*.props') }}
|
||||
restore-keys: |
|
||||
nuget-${{ runner.os }}-
|
||||
|
||||
- name: Restore
|
||||
run: dotnet restore SeaHavenIndustries.sln
|
||||
|
||||
|
|
@ -37,3 +45,72 @@ jobs:
|
|||
|
||||
- name: Test
|
||||
run: dotnet test SeaHavenIndustries.sln --no-build --configuration Release
|
||||
|
||||
architecture:
|
||||
name: architecture
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up .NET
|
||||
uses: actions/setup-dotnet@v6
|
||||
with:
|
||||
dotnet-version: "8.0.x"
|
||||
|
||||
- name: Cache NuGet packages
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.nuget/packages
|
||||
key: nuget-${{ runner.os }}-${{ hashFiles('**/*.csproj', '**/*.props') }}
|
||||
restore-keys: |
|
||||
nuget-${{ runner.os }}-
|
||||
|
||||
- name: Set up Terraform
|
||||
uses: hashicorp/setup-terraform@dfe3c3f87815947d99a8997f908cb6525fc44e9e # v4.0.1
|
||||
with:
|
||||
terraform_version: "1.9.8"
|
||||
terraform_wrapper: false
|
||||
|
||||
- name: Repository quality gate
|
||||
shell: bash
|
||||
env:
|
||||
GOVERNANCE_SKIP_BUILD_TEST: "1"
|
||||
# A merge group carries its own base and head; github.event.before is
|
||||
# empty on that event.
|
||||
BASE_REF: ${{ github.event.pull_request.base.sha || github.event.merge_group.base_sha || github.event.before }}
|
||||
HEAD_REF: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha || github.sha }}
|
||||
run: bash scripts/governance-check.sh
|
||||
|
||||
review:
|
||||
name: review
|
||||
if: github.event_name != 'push'
|
||||
uses: Sea-Haven-Industries/.github/.github/workflows/callable-dependency-review.yaml@4a6cbfd362140a68810f0f46d338026863b8e827 # v1.0.10
|
||||
|
||||
ci-complete:
|
||||
name: ci-complete
|
||||
if: always()
|
||||
needs: [build-and-test, architecture, review]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: All required jobs passed
|
||||
shell: bash
|
||||
env:
|
||||
BUILD: ${{ needs.build-and-test.result }}
|
||||
ARCH: ${{ needs.architecture.result }}
|
||||
REVIEW: ${{ needs.review.result }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
if [[ "${BUILD}" != "success" || "${ARCH}" != "success" ]]; then
|
||||
echo "Build and test or architecture did not succeed: build=${BUILD} architecture=${ARCH}"
|
||||
exit 1
|
||||
fi
|
||||
# review is skipped on push to main; it must succeed on pull_request
|
||||
# and merge_group.
|
||||
if [[ "${REVIEW}" != "success" && "${REVIEW}" != "skipped" ]]; then
|
||||
echo "review did not succeed: ${REVIEW}"
|
||||
exit 1
|
||||
fi
|
||||
|
|
|
|||
12
.github/workflows/dependency-review.yml
vendored
12
.github/workflows/dependency-review.yml
vendored
|
|
@ -1,12 +0,0 @@
|
|||
name: Dependency Review
|
||||
on:
|
||||
pull_request:
|
||||
# The dependency-review action resolves the diff from merge_group.base_sha and
|
||||
# head_sha itself, so the same job satisfies the required check in the merge
|
||||
# queue. One job, no conditions, one check run per event.
|
||||
merge_group:
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
review:
|
||||
uses: Sea-Haven-Industries/.github/.github/workflows/callable-dependency-review.yaml@4a6cbfd362140a68810f0f46d338026863b8e827 # v1.0.10
|
||||
2
.github/workflows/deploy.yaml
vendored
2
.github/workflows/deploy.yaml
vendored
|
|
@ -31,8 +31,6 @@ on:
|
|||
- "terraform/**"
|
||||
- "**/*.md"
|
||||
- ".github/workflows/ci.yml"
|
||||
- ".github/workflows/ci-terraform.yaml"
|
||||
- ".github/workflows/architecture-quality.yml"
|
||||
- ".github/workflows/release.yaml"
|
||||
- ".github/workflows/deploy-tag.yaml"
|
||||
|
||||
|
|
|
|||
|
|
@ -44,8 +44,9 @@ bash scripts/governance-check.sh
|
|||
```
|
||||
|
||||
The command restores, verifies architecture and changed-file formatting, builds
|
||||
Release, and runs the full test suite. CI (`architecture-quality` workflow)
|
||||
calls the same script. See `QUALITY_GATES.md`.
|
||||
Release, runs the full test suite, and validates Terraform. CI (`ci.yml`)
|
||||
calls the same script from the `architecture` job (skipping G4/G5) and
|
||||
aggregates results as `ci-complete`. See `QUALITY_GATES.md`.
|
||||
|
||||
## Hard rules (deviation needs an ADR; no wildcard suppressions)
|
||||
|
||||
|
|
|
|||
|
|
@ -6,32 +6,32 @@
|
|||
> rule lives in `ARCHITECTURE_AND_CODE_QUALITY.md`.
|
||||
>
|
||||
> **CI and local run the same check.** Every gate below is executed by
|
||||
> `scripts/governance-check.sh`. The `architecture-quality` workflow calls that
|
||||
> script so a green run means the same thing locally and in CI. Do not add a
|
||||
> check to CI that is not also runnable locally through the script (and vice
|
||||
> versa).
|
||||
> `scripts/governance-check.sh` locally. The `architecture` job in `ci.yml`
|
||||
> calls that script (skipping G4/G5, which the `Build and test` job owns). Do
|
||||
> not add a check to CI that is not also runnable locally through the script
|
||||
> (and vice versa), except G4/G5 which the local script still runs.
|
||||
|
||||
## Gate inventory
|
||||
|
||||
| # | Gate | Protects (architecture §) | Local command | CI step |
|
||||
|---|------|---------------------------|---------------|---------|
|
||||
| G1 | Restore | build integrity | `dotnet restore SeaHavenIndustries.sln` | `architecture-quality` → `governance-check.sh` |
|
||||
| G1 | Restore | build integrity | `dotnet restore SeaHavenIndustries.sln` | `ci.yml` `architecture` → `governance-check.sh` |
|
||||
| G2 | Architecture boundary tests | §1, §3 (dependency direction) | `dotnet test Api.SeaHavenIndustries.Tests ... --filter FullyQualifiedName~ArchitectureTests --no-restore` | same script |
|
||||
| G3 | Changed-file formatting | §1 (conventions) | `dotnet format SeaHavenIndustries.sln --no-restore --verify-no-changes --include <changed .cs>` | same script |
|
||||
| G4 | Release build | compile correctness | `dotnet build SeaHavenIndustries.sln -c Release --no-restore` | `architecture-quality` and `ci` |
|
||||
| G5 | Full test suite | behavior | `dotnet test SeaHavenIndustries.sln -c Release --no-build` | `architecture-quality` and `ci` |
|
||||
| G4 | Release build | compile correctness | `dotnet build SeaHavenIndustries.sln -c Release --no-restore` | `ci.yml` `Build and test` (local script still runs it) |
|
||||
| G5 | Full test suite | behavior | `dotnet test SeaHavenIndustries.sln -c Release --no-build` | `ci.yml` `Build and test` (local script still runs it) |
|
||||
| G6 | Migration gates | §7 | see §"Migration gates" below | on-demand / release |
|
||||
| G7 | Cancellation forwarding | §6 | behavior tests on changed I/O paths + analyzer | review-enforced on changed paths |
|
||||
| G8 | Error disclosure | §5 | `SanitizedErrorsTests` (part of G5) | `ci` |
|
||||
| G8 | Error disclosure | §5 | `SanitizedErrorsTests` (part of G5) | `ci.yml` `Build and test` |
|
||||
| G9 | Board-backed regression | review framework | `REVIEW_AND_PR_FRAMEWORK.md` inventory | review-enforced |
|
||||
| G10 | Terraform import plan safety | live infrastructure adoption | `python scripts/test-terraform-import-plan-check.py` | `architecture-quality` → `governance-check.sh` |
|
||||
| G11 | Terraform static validation | import configuration integrity | commands below | `ci-terraform` on PRs to `main` or `dev` |
|
||||
| G13 | App/Terraform isolation | separate delivery lanes | `python3 scripts/check_app_terraform_isolation.py` | `architecture-quality` → `governance-check.sh` |
|
||||
| G10 | Terraform import plan safety | live infrastructure adoption | `python scripts/test-terraform-import-plan-check.py` | `ci.yml` `architecture` → `governance-check.sh` |
|
||||
| G11 | Terraform static validation | import configuration integrity | commands below | `ci.yml` `architecture` → `governance-check.sh` |
|
||||
| G13 | App/Terraform isolation | separate delivery lanes | `python3 scripts/check_app_terraform_isolation.py` | `ci.yml` `architecture` (live classifier: PR + local) |
|
||||
|
||||
## How to run locally
|
||||
|
||||
```bash
|
||||
# Complete local repository gate (mirrors the architecture-quality workflow):
|
||||
# Complete local repository gate (G1–G5, G10, G11, G13):
|
||||
bash scripts/governance-check.sh
|
||||
|
||||
# By default it compares against the default branch for changed-file formatting.
|
||||
|
|
@ -51,8 +51,11 @@ The script:
|
|||
6. verifies that the Terraform plan guard rejects create, delete, replacement,
|
||||
unmanaged resource types, and updates not allowlisted by exact address (G10).
|
||||
7. runs the release-tag, commit-check, and isolation unit tests.
|
||||
8. rejects a diff that contains both `terraform/` and deployable application
|
||||
files (G13).
|
||||
8. runs Terraform fmt/validate for `live/dev` and `live/staging` (G11).
|
||||
9. rejects a diff that contains both `terraform/` and deployable application
|
||||
files (G13). Live G13 skips on `merge_group` and `push`. The architecture
|
||||
job in CI sets `GOVERNANCE_SKIP_BUILD_TEST=1` so steps 4–5 run only locally
|
||||
and in the Build and test job.
|
||||
|
||||
G10 permits only exact approved resource address/type pairs for the
|
||||
environment-owned boundary: Elastic
|
||||
|
|
@ -65,9 +68,10 @@ Controlled mode requires one
|
|||
also requires `--environment dev` or `--environment staging`; an empty or
|
||||
incomplete environment plan fails.
|
||||
|
||||
G11 runs `terraform fmt -check -recursive terraform`, `terraform init -backend=false`,
|
||||
and `terraform validate` for both `live/dev` and `live/staging` on every PR to
|
||||
`main` or `dev`. Org-baseline CloudFormation owns the HCP role substrate, and Terraform
|
||||
G11 runs `terraform fmt -check -recursive terraform`, `terraform init -backend=false
|
||||
-input=false -lockfile=readonly`, and `terraform validate` for both `live/dev`
|
||||
and `live/staging` from `governance-check.sh` on every CI event, including
|
||||
merge groups. Org-baseline CloudFormation owns the HCP role substrate, and Terraform
|
||||
owns the environment GitHub deploy roles, so no backend CDK or bootstrap root
|
||||
remains in the matrix. HCP plan/apply roles stay in org-baseline; this
|
||||
repository never manages `hcptf-*` roles.
|
||||
|
|
@ -129,8 +133,9 @@ non-empty. A future namespace move that makes reflection return zero types will
|
|||
Runtime/semantic properties (cancellation actually cancelling, a query
|
||||
executing in SQL, a transaction actually committing atomically) are proven by
|
||||
behavior tests or provider evidence, never by reflection.
|
||||
- A passing script proves G1–G5 ran in sequence. It does not prove the
|
||||
provider-backed or review-owned gates G6–G9.
|
||||
- A passing local script proves G1–G5, G10, G11, and G13 ran (G4/G5 are skipped
|
||||
in the CI architecture job). It does not prove the provider-backed or
|
||||
review-owned gates G6–G9.
|
||||
|
||||
## Pass / fail / skip / not-run reporting
|
||||
|
||||
|
|
@ -149,8 +154,9 @@ or not-run. Never infer a pass from silence.
|
|||
## Adding or changing a gate
|
||||
|
||||
- Any new executable check goes into `scripts/governance-check.sh` **and** the
|
||||
`architecture-quality` workflow together (or into the full CI for G4/G5-type
|
||||
checks). One source of truth for local and CI.
|
||||
`architecture` job in `ci.yml` together (or into the Build and test job for
|
||||
G4/G5-type checks). One source of truth for local and CI. The required
|
||||
merge-queue check is `ci-complete`.
|
||||
- A new rule documents its meaning in `ARCHITECTURE_AND_CODE_QUALITY.md` and its
|
||||
command/mapping here.
|
||||
- Explicit, documented exceptions only — no wildcard suppressions (see
|
||||
|
|
|
|||
|
|
@ -78,10 +78,9 @@ one follows the G6 rules in [`QUALITY_GATES.md`](QUALITY_GATES.md).
|
|||
- The PR body uses the three-section layout the template pre-fills: Summary,
|
||||
Changes and value, Ticket. The reasoning is in
|
||||
[`REVIEW_AND_PR_FRAMEWORK.md`](REVIEW_AND_PR_FRAMEWORK.md).
|
||||
- `main` requires a code-owner review and the `Build and test`,
|
||||
`architecture` and `review / dependency-review` checks. PRs merge through the
|
||||
merge queue, so a branch does not need to be updated with `main` before it
|
||||
merges.
|
||||
- `main` requires a code-owner review and the `ci-complete` check. PRs merge
|
||||
through the merge queue, so a branch does not need to be updated with `main`
|
||||
before it merges.
|
||||
- Application code and `terraform/` do not change in the same PR (G13).
|
||||
|
||||
## Deployment
|
||||
|
|
|
|||
|
|
@ -2,9 +2,10 @@
|
|||
#
|
||||
# governance-check.sh — local/CI parity governance gate for the Seahaven backend.
|
||||
#
|
||||
# Runs G1 restore, G2 ArchitectureTests, G3 changed-file formatting, G4 Release
|
||||
# build, and G5 full tests exactly as the `architecture-quality` workflow does.
|
||||
# A green run here means the same thing locally and in that CI workflow.
|
||||
# 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.
|
||||
#
|
||||
# Usage:
|
||||
# bash scripts/governance-check.sh
|
||||
|
|
@ -14,6 +15,7 @@ set -euo pipefail
|
|||
|
||||
SOLUTION="SeaHavenIndustries.sln"
|
||||
ARCH_TEST_PROJECT="Api.SeaHavenIndustries.Tests/Api.SeaHavenIndustries.Tests.csproj"
|
||||
LIVE_ROOTS=(terraform/live/dev terraform/live/staging)
|
||||
|
||||
log() { printf '\n\033[1m== %s ==\033[0m\n' "$1"; }
|
||||
ok() { printf '\033[32mPASS\033[0m %s\n' "$1"; }
|
||||
|
|
@ -81,13 +83,18 @@ else
|
|||
ok "G3: changed-file formatting"
|
||||
fi
|
||||
|
||||
log "G4: Release build"
|
||||
"$DOTNET" build "$SOLUTION" -c Release --no-restore --nologo
|
||||
ok "G4: Release build"
|
||||
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"
|
||||
|
||||
log "G5: full test suite"
|
||||
"$DOTNET" test "$SOLUTION" -c Release --no-build --nologo
|
||||
ok "G5: full test suite"
|
||||
log "G5: full test suite"
|
||||
"$DOTNET" test "$SOLUTION" -c Release --no-build --nologo
|
||||
ok "G5: full test suite"
|
||||
fi
|
||||
|
||||
log "G10: Terraform import plan safety"
|
||||
python scripts/test-terraform-import-plan-check.py
|
||||
|
|
@ -99,10 +106,26 @@ 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}, 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"
|
||||
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
|
||||
|
||||
log "governance-check: all required repository gates passed"
|
||||
|
|
|
|||
|
|
@ -12,8 +12,7 @@ import urllib.parse
|
|||
import urllib.request
|
||||
|
||||
REQUIRED_CHECK_NAMES = (
|
||||
"Build and test",
|
||||
"architecture",
|
||||
"ci-complete",
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -12,26 +12,20 @@ class ClassifyChecksTests(unittest.TestCase):
|
|||
def test_success(self) -> None:
|
||||
state, _ = classify_checks(
|
||||
[
|
||||
{"name": "Build and test", "status": "completed", "conclusion": "success"},
|
||||
{"name": "architecture", "status": "completed", "conclusion": "success"},
|
||||
{"name": "ci-complete", "status": "completed", "conclusion": "success"},
|
||||
]
|
||||
)
|
||||
self.assertEqual(state, "success")
|
||||
|
||||
def test_pending_missing(self) -> None:
|
||||
state, details = classify_checks(
|
||||
[
|
||||
{"name": "Build and test", "status": "completed", "conclusion": "success"},
|
||||
]
|
||||
)
|
||||
state, details = classify_checks([])
|
||||
self.assertEqual(state, "pending")
|
||||
self.assertTrue(any("architecture" in line for line in details))
|
||||
self.assertTrue(any("ci-complete" in line for line in details))
|
||||
|
||||
def test_pending_in_progress(self) -> None:
|
||||
state, _ = classify_checks(
|
||||
[
|
||||
{"name": "Build and test", "status": "in_progress", "conclusion": None},
|
||||
{"name": "architecture", "status": "completed", "conclusion": "success"},
|
||||
{"name": "ci-complete", "status": "in_progress", "conclusion": None},
|
||||
]
|
||||
)
|
||||
self.assertEqual(state, "pending")
|
||||
|
|
@ -39,8 +33,7 @@ class ClassifyChecksTests(unittest.TestCase):
|
|||
def test_failure(self) -> None:
|
||||
state, _ = classify_checks(
|
||||
[
|
||||
{"name": "Build and test", "status": "completed", "conclusion": "failure"},
|
||||
{"name": "architecture", "status": "completed", "conclusion": "success"},
|
||||
{"name": "ci-complete", "status": "completed", "conclusion": "failure"},
|
||||
]
|
||||
)
|
||||
self.assertEqual(state, "failure")
|
||||
|
|
@ -49,7 +42,7 @@ class ClassifyChecksTests(unittest.TestCase):
|
|||
state, _ = classify_checks(
|
||||
[
|
||||
{
|
||||
"name": "Build and test",
|
||||
"name": "ci-complete",
|
||||
"id": 1,
|
||||
"started_at": "2026-09-16T12:00:00Z",
|
||||
"completed_at": "2026-09-16T12:05:00Z",
|
||||
|
|
@ -57,21 +50,13 @@ class ClassifyChecksTests(unittest.TestCase):
|
|||
"conclusion": "failure",
|
||||
},
|
||||
{
|
||||
"name": "Build and test",
|
||||
"name": "ci-complete",
|
||||
"id": 3,
|
||||
"started_at": "2026-09-16T12:10:00Z",
|
||||
"completed_at": "2026-09-16T12:12:00Z",
|
||||
"status": "completed",
|
||||
"conclusion": "success",
|
||||
},
|
||||
{
|
||||
"name": "architecture",
|
||||
"id": 2,
|
||||
"started_at": "2026-09-16T12:00:00Z",
|
||||
"completed_at": "2026-09-16T12:04:00Z",
|
||||
"status": "completed",
|
||||
"conclusion": "success",
|
||||
},
|
||||
]
|
||||
)
|
||||
self.assertEqual(state, "success")
|
||||
|
|
@ -80,7 +65,7 @@ class ClassifyChecksTests(unittest.TestCase):
|
|||
state, _ = classify_checks(
|
||||
[
|
||||
{
|
||||
"name": "architecture",
|
||||
"name": "ci-complete",
|
||||
"id": 9,
|
||||
"started_at": "2026-09-16T13:00:00Z",
|
||||
"completed_at": "2026-09-16T13:02:00Z",
|
||||
|
|
@ -88,21 +73,13 @@ class ClassifyChecksTests(unittest.TestCase):
|
|||
"conclusion": "failure",
|
||||
},
|
||||
{
|
||||
"name": "architecture",
|
||||
"name": "ci-complete",
|
||||
"id": 4,
|
||||
"started_at": "2026-09-16T12:00:00Z",
|
||||
"completed_at": "2026-09-16T12:01:00Z",
|
||||
"status": "completed",
|
||||
"conclusion": "success",
|
||||
},
|
||||
{
|
||||
"name": "Build and test",
|
||||
"id": 5,
|
||||
"started_at": "2026-09-16T12:00:00Z",
|
||||
"completed_at": "2026-09-16T12:03:00Z",
|
||||
"status": "completed",
|
||||
"conclusion": "success",
|
||||
},
|
||||
]
|
||||
)
|
||||
self.assertEqual(state, "failure")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue