# Every CI control in this checkout: one row per job in .github/workflows, plus the delegated-pending # rows for controls that are real and that no workflow runs. # # The rows are grouped by STAGE, because that is how the workflows are now split. Stage 1 blocks a # merge, stage 2 reports on main after the merge, stage 3 stops a release. A control's stage is the # honest form of "does this gate development", and it is what release_blocking below records. # # Image signing and provenance attestation are still absent. So is any join between the image build # in release.yml and the two evidence workflows that answer the same release tag from their own files # (jpa-release.yml, fileserver-release.yml); that join is registered delegated-pending rather than # left unstated. .github/scripts/verify-gate-matrix.sh checks every row against the repository and is # itself the gate-matrix-lint job below; it pins no gate count, so registering a new control is # adding a row here and nothing else. # # Fields: # release_blocking: true, false, or conditional # mechanism: gradle-custom-task, gradle-plugin-task, contract-test, workflow-job, # or delegated-pending # ref: task, plugin@task, repository-relative test path below src/, or workflow job id # workflow/job: canonical workflow and job that execute or represent the control # execution: check (through Gradle check), explicit (named in the job), or job # # release_blocking is verified, not declared: # true a release gate waits on this job — it is ci-quality-gates.yml::release-gate itself, # one of that job's `needs:`, a name in its REQUIRED_CHECKS, or a job in a workflow # that only runs on a release tag. The lint fails a `true` row that is none of those. # conditional the control is real and gates something, but no release gate can require it: it runs # behind a path filter, a schedule, a manual dispatch, or an input, so its check run # does not exist for every commit a release gate sees. # false advisory. A failure here is a signal, not a stop. gates: # ================================================================================= # STAGE 1 — pull request. These block a merge. # ================================================================================= # # ci-quality-gates.yml — the repository-wide gate. No path filter: it runs on every pull request # and every push to main, which is what makes the leaf test suites, the architecture dependency # gate and the Checkstyle ruleset below cover a diff without any per-adapter job repeating them. - id: format-lint release_blocking: true mechanism: gradle-plugin-task ref: com.diffplug.spotless@spotlessCheck workflow: ci-quality-gates.yml job: quality-gates execution: check - id: unit-and-contract-tests release_blocking: true mechanism: gradle-plugin-task ref: java@test workflow: ci-quality-gates.yml job: quality-gates execution: check - id: conditional-transport-qualification release_blocking: true mechanism: gradle-custom-task ref: conditionalTransportQualification workflow: ci-quality-gates.yml job: quality-gates execution: explicit - id: clean-architecture-dependencies release_blocking: true mechanism: gradle-custom-task ref: verifyCleanArchitectureDependencies workflow: ci-quality-gates.yml job: quality-gates execution: check - id: environment-contract release_blocking: true mechanism: gradle-custom-task ref: verifyEnvKeys workflow: ci-quality-gates.yml job: quality-gates execution: check - id: declared-dependency-absence release_blocking: true mechanism: gradle-custom-task ref: verifyDependencyPolicy workflow: ci-quality-gates.yml job: quality-gates execution: check - id: notification-api-surface release_blocking: true mechanism: gradle-custom-task ref: verifyNotificationApiSurface workflow: ci-quality-gates.yml job: quality-gates execution: check - id: notification-configuration-contract release_blocking: true mechanism: gradle-custom-task ref: verifyNotificationConfiguration workflow: ci-quality-gates.yml job: quality-gates execution: check - id: notification-support-grade-evidence release_blocking: true mechanism: gradle-custom-task ref: verifyNotificationEvidence workflow: ci-quality-gates.yml job: quality-gates execution: check - id: graphql-api-surface release_blocking: true mechanism: gradle-custom-task ref: verifyGraphQlApiSurface workflow: ci-quality-gates.yml job: quality-gates execution: check - id: mongo-api-surface release_blocking: true mechanism: gradle-custom-task ref: verifyMongoApiSurface workflow: ci-quality-gates.yml job: quality-gates execution: check # # The strongest evidence this repository produces, and CI does not run it. Fifteen Compose lanes # start real PostgreSQL, MongoDB, Kafka, MinIO, Mailpit and Keycloak, take a real client-credentials # JWT, and prove things no in-JVM test can: that all-off boots with no external resource, that the # notification handoff delivers exactly once across a restart on the same volume, that the startup # log is silent. It runs from a developer's machine via scripts/run-compose-runtime-smoke.sh and # from nowhere else — no workflow invokes it, so nothing re-runs it on a pull request. # # Registered delegated-pending so the gap is a tracked absence rather than an unstated one. # Executing it in CI needs a Docker-capable runner and a decision about the minutes fifteen # container lanes cost, which is an infrastructure choice rather than a wiring oversight. - id: runtime-smoke-matrix release_blocking: conditional mechanism: delegated-pending ref: runtime-smoke-matrix-lane workflow: ci-quality-gates.yml job: release-gate execution: job # # `conditional-transport-qualification` above is the registered GraphQL control, and it is a # boundary test: a @SpringBootTest over a nested test application with in-memory Basic Auth. Its own # javadoc says so — "the nested application deliberately owns only test authentication and CORS # policy". That is a legitimate transport-boundary proof and it is not release evidence for the # security posture, which is the distinction the Definition of Done draws. # # The real proof exists: the local-graphql Compose lane obtains a Keycloak client-credentials token # and posts it to /graphql on the running bootJar, asserting that anonymous and malformed # credentials are refused and the authenticated query answers. It is part of the runtime smoke # matrix above, so it inherits that control's pending status rather than having none of its own. - id: graphql-runtime-jwt release_blocking: conditional mechanism: delegated-pending ref: graphql-runtime-jwt-lane workflow: ci-quality-gates.yml job: release-gate execution: job # # Checkstyle, not the retired regex. verifyOneTypePerFile parsed Java with # `^public\s+...` line by line; OneTopLevelClass and OuterTypeFilename ask the same two questions # against a parsed file and see the package-private top-level types the regex could not. The task # still exists in src/build.gradle as an aggregate of every leaf's checkstyleMain, but no workflow # names it any more, so this row names what actually runs: checkstyleMain, inside `check`. - id: one-type-per-file release_blocking: true mechanism: gradle-plugin-task ref: checkstyle@checkstyleMain workflow: ci-quality-gates.yml job: quality-gates execution: check - id: trivy-suppression-governance release_blocking: true mechanism: gradle-custom-task ref: verifyTrivyignore workflow: ci-quality-gates.yml job: quality-gates execution: check - id: quarantine-sunset release_blocking: true mechanism: gradle-custom-task ref: verifyQuarantineSunset workflow: ci-quality-gates.yml job: quality-gates execution: check - id: public-path-snapshot release_blocking: true mechanism: gradle-custom-task ref: verifyPublicPathSnapshot workflow: ci-quality-gates.yml job: quality-gates execution: explicit - id: dependency-locks release_blocking: true mechanism: gradle-custom-task ref: verifyDependencyLocks workflow: ci-quality-gates.yml job: quality-gates execution: explicit # # Points at the inventory guard rather than at one suite. The 87 architecture rules used to be # 74-in-one-class plus a scattered remainder, so naming CleanArchitectureTest.java named most of # them and silently omitted the rest; after the split (BOOT-012) it would have named a fifth of # them. ArchRuleDiscoveryContractTest pins every rule in the package by name and fails if one is # declared where ArchUnit cannot discover it, which is the property this gate actually exists to # protect. - id: architecture-contract-test release_blocking: true mechanism: contract-test ref: app-bootstrap/src/test/java/dev/caskeleton/bootstrap/architecture/ArchRuleDiscoveryContractTest.java workflow: ci-quality-gates.yml job: quality-gates execution: check - id: sample-off release_blocking: true mechanism: gradle-custom-task ref: sampleOffTest workflow: ci-quality-gates.yml job: sample-off execution: explicit - id: gate-matrix-lint release_blocking: true mechanism: workflow-job ref: gate-matrix-lint workflow: ci-quality-gates.yml job: gate-matrix-lint execution: job - id: redis-sdk release_blocking: true mechanism: workflow-job ref: redis-sdk workflow: ci-quality-gates.yml job: redis-sdk execution: job - id: jpa-candidate-evidence release_blocking: true mechanism: workflow-job ref: jpa-candidate-evidence workflow: ci-quality-gates.yml job: jpa-candidate-evidence execution: job - id: quality-release-gate release_blocking: true mechanism: workflow-job ref: release-gate workflow: ci-quality-gates.yml job: release-gate execution: job - id: flaky-quarantine release_blocking: false mechanism: workflow-job ref: quarantine workflow: ci-quality-gates.yml job: quarantine execution: job - id: redis-sdk-support-matrix release_blocking: true mechanism: contract-test ref: adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/RedisSupportMatrixTest.java workflow: ci-quality-gates.yml job: quality-gates execution: check # # pr-adapters.yml — the lanes `check` cannot reach: a second servlet container, a real Nginx, # Reactor Netty, one PostgreSQL major per job, one HTTP transport per job. Each job is behind a # per-job path filter computed from the pull request's diff, so no release gate can wait on one. - id: httpclient-contract-stable-contract release_blocking: conditional mechanism: workflow-job ref: httpclient-stable-contract workflow: pr-adapters.yml job: httpclient-stable-contract execution: job - id: httpclient-security-and-compatibility release_blocking: conditional mechanism: workflow-job ref: httpclient-security-and-compatibility workflow: pr-adapters.yml job: httpclient-security-and-compatibility execution: job - id: jpa-postgresql-contract release_blocking: conditional mechanism: workflow-job ref: jpa-postgresql-contract workflow: pr-adapters.yml job: jpa-postgresql-contract execution: job - id: jpa-migration-smoke release_blocking: conditional mechanism: workflow-job ref: jpa-migration-smoke workflow: pr-adapters.yml job: jpa-migration-smoke execution: job - id: web-cross-stack-parity release_blocking: conditional mechanism: workflow-job ref: web-cross-stack-parity workflow: pr-adapters.yml job: web-cross-stack-parity execution: job - id: web-nginx-proxy-contract release_blocking: conditional mechanism: workflow-job ref: web-nginx-proxy-contract workflow: pr-adapters.yml job: web-nginx-proxy-contract execution: job - id: websocket-container-matrix release_blocking: conditional mechanism: workflow-job ref: websocket-container-matrix workflow: pr-adapters.yml job: websocket-container-matrix execution: job - id: websocket-nginx-contract release_blocking: conditional mechanism: workflow-job ref: websocket-nginx-contract workflow: pr-adapters.yml job: websocket-nginx-contract execution: job # # The job every lane in that file reads. It fails closed on an unreadable diff rather than # reporting that nothing changed, because a filter that answers false on a broken comparison # turns off every gate behind it and reports green. - id: pr-adapter-change-filter release_blocking: conditional mechanism: workflow-job ref: changes workflow: pr-adapters.yml job: changes execution: job # # fileserver-pr.yml — path-filtered pull-request gates. They stay in their own file because # FileserverDocumentationCoverageTest requires every job id docs/fileserver/support-matrix.md # names to be defined in a .github/workflows/fileserver-*.yml. # # Path-filtered pull-request gates. They are the only automated check of the fileserver's # ext4 and HTTP contracts, but they start only when the filtered paths change, so no release # gate can wait on them. - id: fileserver-unit-and-architecture release_blocking: conditional mechanism: workflow-job ref: fileserver-unit-and-architecture workflow: fileserver-pr.yml job: fileserver-unit-and-architecture execution: job - id: fileserver-local-ext4-contract release_blocking: conditional mechanism: workflow-job ref: fileserver-local-ext4-contract workflow: fileserver-pr.yml job: fileserver-local-ext4-contract execution: job - id: fileserver-http-contract release_blocking: conditional mechanism: workflow-job ref: fileserver-http-contract workflow: fileserver-pr.yml job: fileserver-http-contract execution: job - id: fileserver-security-suite release_blocking: conditional mechanism: workflow-job ref: fileserver-security-suite workflow: fileserver-pr.yml job: fileserver-security-suite execution: job - id: fileserver-bounded-memory release_blocking: conditional mechanism: workflow-job ref: fileserver-bounded-memory workflow: fileserver-pr.yml job: fileserver-bounded-memory execution: job # # dependency-vulnerability.yml — supply chain. trivy-fs is the one cross-workflow check # ci-quality-gates.yml::release-gate requires by name through REQUIRED_CHECKS. - id: dependency-review release_blocking: conditional mechanism: workflow-job ref: dependency-review workflow: dependency-vulnerability.yml job: dependency-review execution: job - id: dependency-submission release_blocking: false mechanism: workflow-job ref: dependency-submission workflow: dependency-vulnerability.yml job: dependency-submission execution: job - id: filesystem-vulnerability-scan release_blocking: true mechanism: workflow-job ref: trivy-fs workflow: dependency-vulnerability.yml job: trivy-fs execution: job # # link-check.yml — committed documentation links, path-filtered. - id: documentation-links release_blocking: conditional mechanism: workflow-job ref: lychee workflow: link-check.yml job: lychee execution: job # ================================================================================= # STAGE 2 — merged state. These do not block a merge; the merge already happened. # ================================================================================= # # integration-main.yml — push to main, nightly, or dispatch. The documentation-drift gates that # left `check`, and the lanes that need a machine which is not simultaneously compiling. - id: documented-leaf-count release_blocking: false mechanism: gradle-custom-task ref: verifyDocumentedLeafCount workflow: integration-main.yml job: documentation-contracts execution: job - id: runbook-reference-drift release_blocking: false mechanism: gradle-custom-task ref: verifyRunbookReferences workflow: integration-main.yml job: documentation-contracts execution: job - id: readme-command-drift release_blocking: false mechanism: gradle-custom-task ref: verifyReadmeCommands workflow: integration-main.yml job: documentation-contracts execution: job # # Scheduled. httpclient-nightly-http3-experimental is continue-on-error on purpose: HTTP/3 is # an opt-in experiment (-Phttp3.tests.enabled) and a red experiment must not bury a real # nightly regression. Registered false so the matrix says that out loud instead of leaving a # job that cannot fail unrecorded. - id: httpclient-nightly-fault-injection release_blocking: false mechanism: workflow-job ref: httpclient-fault-injection workflow: integration-main.yml job: httpclient-fault-injection execution: job - id: httpclient-nightly-performance release_blocking: false mechanism: workflow-job ref: httpclient-performance workflow: integration-main.yml job: httpclient-performance execution: job - id: httpclient-nightly-http3-experimental release_blocking: false mechanism: workflow-job ref: httpclient-http3-experimental workflow: integration-main.yml job: httpclient-http3-experimental execution: job # # Scheduled load, abuse and shutdown lane. - id: web-load-abuse-and-shutdown release_blocking: false mechanism: workflow-job ref: web-load-abuse-and-shutdown workflow: integration-main.yml job: web-load-abuse-and-shutdown execution: job # # The four documentation-drift gates, as one task. They were `dependsOn` of the root `check` # and are not any more: a README sentence about a renamed task should not fail a # compile-and-test run. This job is what keeps that a demotion rather than a deletion — with # no workflow invoking the aggregate, all four would run nowhere. release_blocking: false is # the demotion stated as a fact the lint can check. - id: documentation-contracts release_blocking: false mechanism: gradle-custom-task ref: verifyDocumentationContracts workflow: integration-main.yml job: documentation-contracts execution: explicit # # Ran inside verifyDocumentationContracts above rather than named in the job, which is why # this row is execution: job. It had no row at all before. - id: test-source-set-registry release_blocking: false mechanism: gradle-custom-task ref: verifyTestSourceSetRegistry workflow: integration-main.yml job: documentation-contracts execution: job # # notification-platform.yml — `pr` is path-filtered and also runs on push to main; nightly-chaos # is schedule/dispatch only. The release-blocking notification controls are the verifyNotification* # rows above, which run inside check on every pull request. # # `pr` is path-filtered (and runs on push to main); nightly-chaos is schedule/dispatch only. # The release-blocking notification controls are the verifyNotification* rows above, which run # inside check on every pull request. - id: notification-platform-pr release_blocking: conditional mechanism: workflow-job ref: pr workflow: notification-platform.yml job: pr execution: job - id: notification-platform-nightly-chaos release_blocking: false mechanism: workflow-job ref: nightly-chaos workflow: notification-platform.yml job: nightly-chaos execution: job # # messaging-certification.yml — path-filtered pull request plus a weekly schedule. # # The messaging platform's only claim that needs a real broker to be true. The gate is the # evidence check rather than the lane, and it depends on the lane: passing means both that every # fault scenario produced the outcome the shared contract fixes and that the committed manifest is # what this run wrote. Before it existed, `CertifiedEvidence` was a hand-authored list and # "certified against a live broker" was a sentence a developer could type. - id: messaging-broker-certification release_blocking: conditional mechanism: gradle-custom-task ref: verifyMessagingCertificationEvidence workflow: messaging-certification.yml job: broker-certification execution: explicit # # object-storage-qualification.yml — pull request, weekly schedule, and two protected dispatch # inputs for the AWS sandbox lane. # # These three ran under `release_blocking: true` while nothing waited on them. object-storage- # qualification.yml has no push-to-main trigger and messaging-certification.yml is behind a path # filter, so neither produces a check run for every commit ci-quality-gates.yml::release-gate # judges; requiring them there would hang on the commits where they never start. They are # conditional — real controls on their own trigger — until someone decides to widen that trigger, # which is a CI-minutes decision about MinIO and Kafka containers, not a wiring oversight. - id: object-storage-minio-managed-contract release_blocking: conditional mechanism: gradle-custom-task ref: objectStorageMinioContractTest workflow: object-storage-qualification.yml job: minio-managed-contract execution: explicit - id: poster-image-migration release_blocking: conditional mechanism: gradle-custom-task ref: posterImageMigrationTest workflow: object-storage-qualification.yml job: poster-image-v7-migration execution: explicit - id: object-storage-minio-managed-fault release_blocking: conditional mechanism: gradle-custom-task ref: objectStorageMinioFaultTest workflow: object-storage-qualification.yml job: minio-managed-fault execution: explicit - id: object-storage-aws-protected-qualification release_blocking: conditional mechanism: delegated-pending ref: approval-gate-b workflow: object-storage-qualification.yml job: aws-managed-common-subset execution: job # # redis-sdk-topology.yml — path-filtered pull request (standalone only) and the nightly matrix. # # Promoted from delegated-pending: the workflow is no longer manual-only. A pull request that # touches the Redis leaf runs the standalone lane, and the full supported-version x topology # matrix runs nightly and on a release candidate. While it was dispatch-only, a release could # claim topology evidence that nobody had produced for that commit. - id: redis-sdk-topology-evidence release_blocking: conditional mechanism: workflow-job ref: topology-evidence workflow: redis-sdk-topology.yml job: topology-evidence execution: job # # The lane that topology-evidence needs. Same trigger as the evidence row above it. - id: redis-sdk-topology-lanes release_blocking: conditional mechanism: workflow-job ref: lanes workflow: redis-sdk-topology.yml job: lanes execution: job # # fileserver-nightly.yml — scheduled only. NFS ambiguity, process-kill and lease behaviour need # hours and real filesystems; a failure is a signal to act on, not a stop on a release that did not # cause it. # # Scheduled only. NFS ambiguity, process-kill and lease behaviour need hours and real # filesystems; a failure is a signal to act on, not a stop on a release that did not cause it. - id: fileserver-nfs-ambiguity release_blocking: false mechanism: workflow-job ref: fileserver-nfs-ambiguity workflow: fileserver-nightly.yml job: fileserver-nfs-ambiguity execution: job - id: fileserver-process-kill-matrix release_blocking: false mechanism: workflow-job ref: fileserver-process-kill-matrix workflow: fileserver-nightly.yml job: fileserver-process-kill-matrix execution: job - id: fileserver-large-file-performance release_blocking: false mechanism: workflow-job ref: fileserver-large-file-performance workflow: fileserver-nightly.yml job: fileserver-large-file-performance execution: job - id: fileserver-multi-instance-lease release_blocking: false mechanism: workflow-job ref: fileserver-multi-instance-lease workflow: fileserver-nightly.yml job: fileserver-multi-instance-lease execution: job # # jpa-nightly.yml — the middle of the PostgreSQL matrix and the suites too slow or too # Docker-heavy for a pull request. # # Scheduled JPA matrix, failure injection, query-plan/security and pool pressure. - id: jpa-full-matrix release_blocking: false mechanism: workflow-job ref: jpa-full-matrix workflow: jpa-nightly.yml job: jpa-full-matrix execution: job - id: jpa-failure-injection release_blocking: false mechanism: workflow-job ref: jpa-failure-injection workflow: jpa-nightly.yml job: jpa-failure-injection execution: job - id: jpa-query-plan-and-security release_blocking: false mechanism: workflow-job ref: jpa-query-plan-and-security workflow: jpa-nightly.yml job: jpa-query-plan-and-security execution: job - id: jpa-pool-pressure release_blocking: false mechanism: workflow-job ref: jpa-pool-pressure workflow: jpa-nightly.yml job: jpa-pool-pressure execution: job # # jpa-next-*.yml — weekly early-warning lanes against unreleased upstream versions. They exist to # find out before the upgrade, so they block nothing. # # Weekly early-warning lanes against unreleased upstream versions. They exist to find out # before the upgrade, so they block nothing. - id: hibernate8-compatibility release_blocking: false mechanism: workflow-job ref: hibernate8-compatibility workflow: jpa-next-hibernate8.yml job: hibernate8-compatibility execution: job - id: jpa4-compatibility release_blocking: false mechanism: workflow-job ref: jpa4-compatibility workflow: jpa-next-jpa4.yml job: jpa4-compatibility execution: job - id: postgresql19-compatibility release_blocking: false mechanism: workflow-job ref: postgresql19-compatibility workflow: jpa-next-postgresql19.yml job: postgresql19-compatibility execution: job # # jpa-r2-evidence.yml — dispatch-only production-profile manifest run. - id: jpa-r2-evidence release_blocking: conditional mechanism: workflow-job ref: jpa-r2-evidence workflow: jpa-r2-evidence.yml job: jpa-r2-evidence execution: job # ================================================================================= # STAGE 3 — release tag. These stop a release. # ================================================================================= # # release.yml — one workflow, one deployable unit. Evidence jobs first, then app-image-release, # which `needs:` all of them: while the image build lived in its own workflow it could publish # while a sibling suite was still running or already red. - id: httpclient-stable-contract release_blocking: true mechanism: gradle-custom-task ref: httpClientStableContractTest workflow: release.yml job: httpclient-release-gate execution: explicit - id: httpclient-security-suite release_blocking: true mechanism: gradle-custom-task ref: httpClientSecurityTest workflow: release.yml job: httpclient-release-gate execution: explicit - id: httpclient-fault-injection release_blocking: true mechanism: gradle-custom-task ref: httpClientFailureInjectionTest workflow: release.yml job: httpclient-release-gate execution: explicit - id: httpclient-performance-certification release_blocking: true mechanism: gradle-custom-task ref: httpClientPerformanceTest workflow: release.yml job: httpclient-release-gate execution: explicit - id: httpclient-spring62-api-surface release_blocking: true mechanism: gradle-custom-task ref: spring62ApiSurfaceScan workflow: release.yml job: httpclient-release-gate execution: explicit # # The 6.2 API-surface scan above proves the common packages compile against the older surface. It # does not prove they run on it, and the two were being conflated: a lane called # "spring62CompatibilityTest" reads as a runtime compatibility proof. The Gradle task is renamed to # say what it does, and the runtime claim is registered here as its own delegated-pending control # so the gap is a tracked absence rather than an unstated one. Executing it needs a Spring # Framework 6.2 distribution resolved into a separate test runtime, which this repository's # Boot 4.0 baseline does not carry. - id: httpclient-spring62-runtime release_blocking: conditional mechanism: delegated-pending ref: spring62-runtime-lane workflow: release.yml job: httpclient-release-gate execution: job - id: httpclient-spring70-compatibility release_blocking: true mechanism: gradle-custom-task ref: spring70CompatibilityTest workflow: release.yml job: httpclient-release-gate execution: explicit - id: httpclient-documentation-drift release_blocking: true mechanism: workflow-job ref: httpclient-documentation workflow: release.yml job: httpclient-documentation execution: job - id: httpclient-event-loop-blocking release_blocking: true mechanism: gradle-custom-task ref: httpClientBlockHoundTest workflow: release.yml job: httpclient-release-gate execution: explicit # # Tag-triggered (`v*`, `web-v*`). The Stable web release gate. - id: web-stable-release-gate release_blocking: true mechanism: workflow-job ref: web-stable-release-gate workflow: release.yml job: web-stable-release-gate execution: job # # Tag-triggered (`v*`, `websocket-v*`). The Stable websocket release gate. - id: websocket-stable-release-gate release_blocking: true mechanism: workflow-job ref: websocket-stable-release-gate workflow: release.yml job: websocket-stable-release-gate execution: job # # Tag-triggered (`v*`). The only job in this repository that produces a deployable artifact. # # One row, not three, because one job is one control: the job builds the app-bootstrap image, # generates its CycloneDX SBOM, refuses to publish on a CRITICAL or HIGH finding, and only then # pushes the semver and sha- tags and records the digest. The scan is a step inside that control # rather than a control of its own, which is the same shape filesystem-vulnerability-scan uses for # the trivy-fs job. `release_blocking: true` holds because the workflow runs only for a release # tag, so the job failing fails that release run. - id: container-image-release release_blocking: true mechanism: workflow-job ref: app-image-release workflow: release.yml job: app-image-release execution: job # # The join this repository cannot express, stated rather than implied. # # Most of it is closed now. app-image-release lives in release.yml and `needs:` the four evidence # jobs in that file, so the image cannot be built, scanned or pushed past a failed web, websocket, # httpclient or architecture gate. `needs:` still reaches only inside one workflow file, and two # evidence workflows are still outside it: jpa-release.yml and fileserver-release.yml both answer # the same `v*` tag and neither can be waited on from here. # # Those two are not in release.yml for a mechanical reason rather than a design one — # JpaReleaseRenderingTest reads `.github/workflows/jpa-release.yml` by that exact path, and # FileserverDocumentationCoverageTest requires the job ids docs/fileserver/support-matrix.md names # to be defined in a `.github/workflows/fileserver-*.yml`. Folding them in means changing a test # and a document in src/ and docs/ in the same commit, which is a decision with owners rather than # a wiring oversight. # # Until then the remaining control is a human one: the GitOps repository promotes a digest whose # tag's jpa-release and fileserver-release runs somebody has looked at, not a digest that merely # exists. Registered here so that sentence lives somewhere a lint can point at, the way # fileserver-pvc-cluster-certification does for the storage claim. - id: container-release-evidence-join release_blocking: conditional mechanism: delegated-pending ref: container-release-evidence-join workflow: release.yml job: app-image-release execution: job # # verifyCleanArchitectureDependencies, verifyPublicPathSnapshot, verifyEnvKeys and the # bootstrap architecture suite, once per release. The four release workflows this replaced ran # the dependency gate six times and the architecture suite four times for one tag, on separate # runners, against one commit. - id: release-architecture-and-surface release_blocking: true mechanism: workflow-job ref: architecture-and-surface workflow: release.yml job: architecture-and-surface execution: job # # jpa-release.yml — tag-triggered (`v*`). jpa-release-promotion needs jpa-release-gate, so the # promotion cannot run past a failed gate. Its own file because JpaReleaseRenderingTest reads that # exact path and holds its matrix to src/config/jpa/release-registry.json. # # Tag-triggered (`v*`). jpa-release-promotion needs jpa-release-gate, so the promotion cannot # run past a failed gate. - id: jpa-release-gate release_blocking: true mechanism: workflow-job ref: jpa-release-gate workflow: jpa-release.yml job: jpa-release-gate execution: job - id: jpa-release-promotion release_blocking: true mechanism: workflow-job ref: jpa-release-promotion workflow: jpa-release.yml job: jpa-release-promotion execution: job - id: jpa-architecture-and-docs release_blocking: true mechanism: workflow-job ref: jpa-architecture-and-docs workflow: jpa-release.yml job: jpa-architecture-and-docs execution: job # # fileserver-release.yml — tag-triggered (`v*`). Its own file for the same reason fileserver-pr.yml # is. # # Tag-triggered: `v*` runs this workflow and a failing job fails that # release. fileserver-pvc-certification checks the manifest only — the cluster half is the # delegated-pending row below it. - id: fileserver-full-verification release_blocking: true mechanism: workflow-job ref: fileserver-full-verification workflow: fileserver-release.yml job: fileserver-full-verification execution: job - id: fileserver-documentation-gate release_blocking: true mechanism: workflow-job ref: fileserver-documentation-gate workflow: fileserver-release.yml job: fileserver-documentation-gate execution: job - id: fileserver-pvc-certification release_blocking: true mechanism: workflow-job ref: fileserver-pvc-certification workflow: fileserver-release.yml job: fileserver-pvc-certification execution: job # # The other half of the PVC claim, and the half no runner can produce. An operator # applies infra/fileserver/kubernetes/pvc-certification-job.yaml to a real cluster and # records the result in docs/fileserver/storage-certification.md. The workflow step # that pretended to do this in CI reported success whenever the cluster secret was # absent, which is every checkout of this template; it is gone, and the claim is # tracked here instead of being green for nothing. - id: fileserver-pvc-cluster-certification release_blocking: conditional mechanism: delegated-pending ref: fileserver-pvc-cluster-lane workflow: fileserver-release.yml job: fileserver-pvc-certification execution: job - id: fileserver-sensitive-telemetry-scan release_blocking: true mechanism: workflow-job ref: fileserver-sensitive-telemetry-scan workflow: fileserver-release.yml job: fileserver-sensitive-telemetry-scan execution: job