6.7.4 From Build to Release Candidate

recommended

A successful Bazel invocation produces outputs. It does not, by itself, produce a release candidate. A release candidate exists only when an immutable set of outputs is joined to complete evidence that says exactly what source, build scope, and builder produced it. That distinction lets later systems approve, sign, or publish one stable subject without asking the build to perform those side effects.

Define a technical eligibility contract

Treat release candidacy as a predicate over a record, not as a directory copied from bazel-bin. A useful record identifies at least:

  • an immutable source revision;
  • the Bazel version and the configuration and platform scope;
  • the intended build and test work;
  • the builder or invocation identities that performed that work;
  • every candidate output by cryptographic digest;
  • the build, test, event-delivery, and artifact-availability evidence required by the release workflow.

The digest is the identity of an output. A filename such as server.tar, a release number, or an image tag is a convenient lookup name, but it can be reassigned. The handoff must therefore say, in effect, “these bytes under these digests,” even when the user-facing workflow also attaches names. Provenance systems use the same shape: the artifact is represented as a subject with a checksum, while source, materials, and builder information describe how that subject came to exist.1

The predicate should return more than a Boolean. Three states are a practical minimum:

StateMeaning
eligibleThe immutable subject and all required evidence are present, mutually consistent, and reachable.
ineligibleComplete evidence proves that required build or test work failed.
unknownRequired work, events, identity, or artifacts are missing, conflicting, stale, or unreachable.

unknown must block promotion just as ineligible does, but the distinction preserves the correct diagnosis. A failed test is evidence of a bad candidate. A missing test result is failure to establish whether a candidate exists at all.

Assemble with Bazel; promote outside the action graph

Keep artifact assembly inside Bazel actions with declared inputs, tools, and outputs. That declaration gives Bazel the graph needed to schedule work and form action cache keys; it is not proof that the action actually uses only that boundary. Enforce an execution policy that isolates undeclared host files and network services, and qualify the action's deterministic behavior with appropriate negative and repeatability tests. Only after those properties are established may the release contract treat reuse of an assembled result as safe.2

Make that qualification part of eligibility evidence. A demonstrated isolation or determinism violation makes the candidate ineligible; missing or unreachable evidence leaves it unknown. Merely seeing declared inputs and outputs in the action graph cannot promote either case to eligible.

Publication has the opposite shape. It changes an external mutable system, normally requires credentials, and may not be safe to repeat. Therefore a rule may build a release archive, image layout, manifest, or bundle, but an explicit workflow step should publish the already identified output. The rules_oci project demonstrates this boundary concretely: image construction is separated from runnable load and push operations, and pushing is an explicit side effect rather than an ordinary cached build action.3 The same design applies beyond OCI images.

This separation answers an important retry question. Rebuilding a candidate may re-execute or cache-hit assembly actions, but it must not create a release, overwrite a tag, or upload bytes merely because bazel build ran again. Publication belongs to 6.7.10 Publishing Artifacts Reliably, after approval and any required signing. Keep publisher credentials there as well; placing them in an action's environment, arguments, or inputs risks exposing them through execution requests, logs, caches, or build evidence. 6.7.5 Build Identities and Secrets develops that credential boundary.

Reconcile the build before declaring a candidate

6.5.8 Complete CI Results with BEP/BES provides the evidence handoff. Start with its immutable intended-work ledger and require every expected partition, invocation, configuration, test shard, run, and attempt to be accounted for. Then require the BEP event graph to be complete enough for the release contract. Among the announcements the collector actually received, an unresolved child identifier exposes a protocol hole after a crash or partial delivery. It cannot expose an announcement or entire invocation that never reached the collector, so the intended-work ledger and required terminal record remain necessary. A successful BuildFinished still describes one command and does not prove that every distributed CI partition ran.4

Event completeness is still not output availability. BEP can refer to output files through NamedSetOfFiles; a consumer must traverse those references, and a remote BES server may be unable to read files that exist only on the Bazel machine.4 For each required release output, establish separately that:

  1. the expected output is named by the completed build evidence;
  2. its digest agrees with the candidate manifest;
  3. an authorized downstream consumer can retrieve the bytes;
  4. retention lasts through approval, signing, and publication.

Do not substitute “the dashboard is green” for this reconciliation. A dashboard may have a successful terminal event while one partition never started, or it may show an artifact link whose bytes have expired. The candidate record should retain these as specific unknown reasons rather than flattening them into a generic release failure.

Keep lifecycle states independent

A reliable pipeline records transitions rather than treating “release” as one large job:

built -> evidence complete -> technically eligible
      -> policy approved -> signed -> published

Each arrow has different authority and failure semantics. Bazel establishes outputs and build evidence. The eligibility service reconciles them. 6.7.9 Bazel Policy and Compliance Checks can contribute technical policy evidence, but approval policy remains a separate decision. 6.7.6 Build Provenance and Attestations binds claims about source, materials, invocation, and builder to the immutable subject. 6.7.8 Signing and Verifying Artifacts binds a signing identity to that subject. Publication finally changes the destination.

Preserve the last successful state when a later transition fails. If signing is unavailable, the candidate remains technically eligible but unsigned; it did not become a build failure. If publication rejects credentials, the signed candidate remains unpublished; it did not become published merely because every Bazel target succeeded. This model makes retries narrow and prevents one subsystem from asserting a state owned by another.

think

Classify: All required builds and tests completed, and the candidate manifest names an archive by digest. The BEP references that archive, but the artifact store returns “not found.” Is the candidate eligible, ineligible, or unknown?

Reveal

It is unknown. The available evidence does not prove a build or test failure, so ineligible would be misleading. But the immutable subject is not reachable, so the technical handoff is incomplete and cannot be promoted. Restore or reproduce the artifact under the expected digest, then evaluate the same contract again.

Test the boundary with negative cases

Build one known candidate in a clean environment and capture its subject manifest and complete-result record. Then mutate one dimension at a time:

  • omit one required CI partition or test attempt;
  • attach evidence from a different source revision or configuration;
  • remove one referenced artifact from storage;
  • replace an output while retaining its mutable filename or tag;
  • deny access to the artifact for the eligibility consumer;
  • fail signing or publication after eligibility succeeds;
  • rerun the Bazel build after the candidate has been recorded.

The first five cases must not produce eligible. The signing and publication failures must not rewrite the build result or falsely advance the lifecycle. The final rebuild must have no publication side effect. These tests prove both halves of the design: the predicate fails closed when the subject or evidence is incomplete, and the build stays safe to repeat because release authority remains outside cacheable actions.

The runnable release eligibility contract turns that test plan into a small, read-only verifier. Its contract states the expected subject, work, source, builder, configuration, and technical-policy evidence. The negative cases then vary completeness, failure, identity, digest, reachability, authorization, and downstream state one dimension at a time. This is deliberately a release-contract model—not a simulation of BES, an artifact backend, signing, or publication.

key takeaway

A release candidate is not whatever happens to be under bazel-bin after a green command. It is an immutable set of digest-identified outputs joined to complete, consistent, and reachable evidence for a stated source, builder, configuration, and work scope. Failed work makes the candidate ineligible; missing or conflicting evidence leaves eligibility unknown.

Use Bazel actions for hermetic, cacheable assembly. Keep approval, signing credentials, and publication side effects in explicit later stages that consume the immutable handoff. Then a rebuild can safely reproduce or reuse outputs without publishing them, and a failure after the build cannot masquerade as either a build failure or a successful release.

Check your understanding · 4 questions

1.Which evidence is still required when every received BEP announcement has a corresponding event?

Select all that apply

2.Match each evidence outcome to its release-candidate state:

Drag each answer onto the matching prompt, or click an answer and then click a prompt

Answers
Complete evidence records a required integration test failure
A required CI partition has no result or terminal record
All required evidence agrees with the immutable subject

3.Which cases must block technical eligibility even though the output keeps the expected filename?

Select all that apply

4.Classify the boundary between Bazel assembly and later release stages:

Choose True or False for each sentence

Once isolation and deterministic behavior are established, repeating a Bazel build may reuse assembly outputs without publishing them.
A signing failure should rewrite an eligible candidate as a build failure.
Publisher credentials belong in an ordinary cacheable packaging action.
Publication consumes an immutable handoff and changes a separate lifecycle state.
0 of 4 answered

Footnotes

  1. SLSA Artifact Security with Bazel — artifact subject digests and the separation of source, materials, and builder claims

  2. Artifact-Based Build Systems — declared actions, hermetic inputs, and safe output reuse

  3. rules_oci — daemonless OCI image rules for Bazel — separation of image construction from explicit runnable load and push operations

  4. Build Event Protocol — event-graph completeness, BuildFinished, BES transport, and referenced-file availability 1 2