diff --git a/docs/OPERATIONS.md b/docs/OPERATIONS.md index b0581b02d..c87cb521a 100644 --- a/docs/OPERATIONS.md +++ b/docs/OPERATIONS.md @@ -18,7 +18,7 @@ Docker Verify builds each service locally (`load: true`, no push) and runs pinned Trivy v0.74.0 against that local image. Docker Publish pushes digest-only candidates: it does not assign normal `sha-*` or `v*` release tags while individual service gates are running. -Each service must pass HIGH/CRITICAL Trivy scanning, then be signed and receive SPDX/SLSA attestations for the same candidate digest. The `promote` job runs only after all nine matrix builds succeed; it validates all nine reports, source commit, digest subjects, signer identity, and verified DSSE predicates before inspecting or writing any tags. +Each service must pass HIGH/CRITICAL Trivy scanning, then be signed and receive SPDX/SLSA attestations for the same candidate digest. The `promote` job runs only after all nine matrix builds succeed; it validates all nine reports, source commit, digest subjects, signer identity, and verified DSSE predicates before inspecting or writing any tags. A changed backend image requires a new service release version in both `services/pom.xml` and its owner POM; an existing version tag may only be reused for the identical digest. Keep contract fixtures aligned with the intended release versions instead of weakening the immutable-tag guard. Use `release-manifest` artifact from successful Docker Publish run as canonical deployment input. It contains complete nine-service `release-manifest.txt`, `release-set.json`, and per-service evidence. Local `scripts/runbooks/promote-release.sh EVIDENCE_DIR SOURCE_SHA ghcr.io/davidhlp/ulticode` supports read-only dry-run only; `--execute` is restricted to Docker Publish on `main`. The workflow uses repository-wide `ulticode-release-tag-writer` concurrency with cancellation disabled. If promotion fails after candidate builds succeed, rerun only the failed `promote` job in that same Actions run, while its nine candidate artifacts remain within their retention period; do not rerun successful `build-and-push` jobs, since a rebuild may produce a different digest and collide with immutable tags. The workflow is push-only and has no `workflow_dispatch`. Do not promote tags through local commands or other writers. This serializes repository-controlled writers, not external registry actors, and GHCR offers no compare-and-swap guarantee here. Existing manifest conflicts fail before registry inspection/writes; all planned tags are read back after promotion, including tags that already existed, before complete manifests are written. Matching existing tags are idempotent; a different digest is a hard failure. A mid-promotion failure may leave already verified tags in place, but emits no complete manifest. Never retarget or delete old tags/digests; retain previous successful release artifact for rollback. diff --git a/scripts/test/promote-release-contract.py b/scripts/test/promote-release-contract.py index b6d7a5452..0aba7f243 100755 --- a/scripts/test/promote-release-contract.py +++ b/scripts/test/promote-release-contract.py @@ -43,7 +43,7 @@ def seed(base): (folder / f"{name}.spdx.json").write_text(json.dumps(spdx)) (folder / f"{name}.provenance.json").write_text(json.dumps(provenance)) (folder / f"{name}.trivy.json").write_text(json.dumps(trivy)) - (folder / f"{name}.version").write_text("1.0.1\n" if service.get("maven_version_property") else "\n") + (folder / f"{name}.version").write_text("1.0.2\n" if service.get("maven_version_property") else "\n") (folder / f"{name}.source-commit").write_text(SHA + "\n") return root @@ -163,7 +163,7 @@ def main(): image = f"{PREFIX}/{service_name}" existing_tags[f"{image}:sha-{SHA[:7]}"] = DIGEST if service.get("maven_version_property"): - existing_tags[f"{image}:v1.0.1"] = DIGEST + existing_tags[f"{image}:v1.0.2"] = DIGEST state.write_text(json.dumps(existing_tags)); log.write_text("") key = f"{PREFIX}/{MATRIX[0]['name']}:sha-{SHA[:7]}" result = call(root, bindir, state, log, "--execute", **GITHUB_WRITER, BAD_FINAL_READBACK=key) diff --git a/scripts/test/supply-chain-contract.sh b/scripts/test/supply-chain-contract.sh index b6c084a2b..1aee36035 100755 --- a/scripts/test/supply-chain-contract.sh +++ b/scripts/test/supply-chain-contract.sh @@ -148,7 +148,7 @@ for service in owner_services: owner_pom = repo / 'services' / service['module'].split('/', 1)[0] / 'pom.xml' owner_properties = ET.parse(owner_pom).getroot().find('m:properties', ns) owner_version = owner_properties.findtext(f'm:{prop}', namespaces=ns) - assert root_version == owner_version == '1.0.1', f'{service["name"]}: release version mismatch ({root_version!r} != {owner_version!r})' + assert root_version == owner_version == '1.0.2', f'{service["name"]}: release version mismatch ({root_version!r} != {owner_version!r})' assert 'actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333' in workflow print('digest-only candidates, common normalized repo and all-service promote gate: PASS') scan = workflow.split(' - name: Scan pushed candidate\n', 1)[1].split(' - name:', 1)[0] diff --git a/services/admin/pom.xml b/services/admin/pom.xml index 5a0c7e441..b789f733e 100644 --- a/services/admin/pom.xml +++ b/services/admin/pom.xml @@ -13,7 +13,7 @@ - 1.0.1 + 1.0.2 backend-admin ${service.version.admin} diff --git a/services/app/pom.xml b/services/app/pom.xml index cc3bef1a0..eb0395426 100644 --- a/services/app/pom.xml +++ b/services/app/pom.xml @@ -13,7 +13,7 @@ - 1.0.1 + 1.0.2 backend-app ${service.version.app} diff --git a/services/auth/pom.xml b/services/auth/pom.xml index 31c16dbce..8d687835d 100644 --- a/services/auth/pom.xml +++ b/services/auth/pom.xml @@ -13,7 +13,7 @@ - 1.0.1 + 1.0.2 backend-auth ${service.version.auth} diff --git a/services/judge/pom.xml b/services/judge/pom.xml index 801378ed1..b7e937c01 100644 --- a/services/judge/pom.xml +++ b/services/judge/pom.xml @@ -15,7 +15,7 @@ - 1.0.1 + 1.0.2 backend-judge diff --git a/services/notification/pom.xml b/services/notification/pom.xml index c7e684efd..5eb6ecc0a 100644 --- a/services/notification/pom.xml +++ b/services/notification/pom.xml @@ -14,7 +14,7 @@ - 1.0.1 + 1.0.2 backend-notification ${service.version.notification} diff --git a/services/pom.xml b/services/pom.xml index 7538cfb18..98e9a3e04 100644 --- a/services/pom.xml +++ b/services/pom.xml @@ -52,13 +52,13 @@ - 1.0.1 - 1.0.1 - 1.0.1 - 1.0.1 - 1.0.1 - 1.0.1 - 1.0.1 + 1.0.2 + 1.0.2 + 1.0.2 + 1.0.2 + 1.0.2 + 1.0.2 + 1.0.2 17 2.21.7 diff --git a/services/search/pom.xml b/services/search/pom.xml index 1cbc6e90a..514bb3b5a 100644 --- a/services/search/pom.xml +++ b/services/search/pom.xml @@ -14,7 +14,7 @@ - 1.0.1 + 1.0.2 backend-search diff --git a/services/submission/pom.xml b/services/submission/pom.xml index 817a8ba36..c8840d258 100644 --- a/services/submission/pom.xml +++ b/services/submission/pom.xml @@ -15,7 +15,7 @@ - 1.0.1 + 1.0.2 backend-submission