ci(oci): OCI Distribution Spec conformance harness (S12 Step 7)

Why

S12 (Container/OCI local) ships endpoint by endpoint across the OCI local plan's steps. Each endpoint MR has to show how many upstream OCI Distribution Spec conformance specs it turns green, and reviewers need to diff that pass set across MRs. Nothing in the repo runs the upstream suite yet, so this MR stands up that gate.

This is Step 7 of the OCI local plan. Only GET /v2/ exists today, so the suite passes about 2 of 80 specs. The conformance:oci job is allow_failure: true until Step 18 removes it once the full suite passes.

What (the non-obvious parts)

  • go test -c, not go build. The upstream suite is package conformance with no main, so only go test -c produces a runnable binary. It builds in a throwaway module so its dependencies never enter our go.mod.
  • psql seed, not a management API. AR has no repository-creation API yet and does not auto-create on push, so provision.sh seeds the namespace and repository rows directly as a test fixture. The S12 spec wording now describes that seed rather than the API it does not implement.
  • development_stubs build. AR runs with the bootstrap-token validator, a dev stand-in for the S08 auth that is not built yet. The suite authenticates with that token.
  • Broken-harness visibility. Under allow_failure, a harness that dies before the suite would look identical to the expected failing-spec baseline. teardown writes a sentinel JUnit so a setup failure surfaces as a distinct HARNESS test instead of an empty report.
  • Binary cache. The compiled suite is cached, keyed by the pinned upstream commit, with when: always so it persists across the expected failing runs.

Test plan

  • mise run conformance locally (needs Go, psql, and curl) builds the suite, boots AR, seeds the target, runs the suite, and writes conformance-oci.xml.
  • CI conformance:oci runs the same run.sh against a Postgres service and archives the JUnit even on failure.
  • shellcheck passes on both scripts. The signal trap, sentinel JUnit, and DSN parsing were tested during review.
Context for LLM agents

Design rationale:

  • psql seed over management API: no repository-creation API exists at Step 7, so the harness seeds rows directly. The S12 spec was amended to match, following the code-first pattern.
  • allow_failure until Step 18: gating on all-pass would block every endpoint MR until the suite is complete. The tracked signal is each MR's pass-count delta, read from the JUnit at runtime rather than hardcoded.
  • The sentinel JUnit, cache:when:always plus the -s reuse guard, the INT/TERM re-raise, and the comment corrections came from a /review-branch plus /walk-findings pass on this branch.

Non-goals:

  • No GC coordination. That lands in S20.
  • No object store configuration. Blobs are not pushed until Step 8 and later, so AR boots database-only.
  • No real S08 auth. The bootstrap-token stand-in covers the auth-challenge specs until S08 ships.
  • The conformance:oci changes: rule stays broad because the binary cache makes re-runs cheap. Residual S12 prose about an object store and the S08 auth contract describes the end-state setup and is left for the S12 reimplementation.

Merge request reports

Loading
Loading