IMPORTANT: Developer documentation for the current development branch. This content is unreleased, may change without notice, and must not be treated as Buildish release documentation.
Candidate Release And Promotion
Candidate Release And Promotion
The candidate lifecycle publishes one or more immutable candidates and promotes one explicitly selected candidate to the final release. Voting or approval is external: Buildish records exact candidate evidence but does not decide whether a candidate passed.
This separation lets a manual decision, a GitHub Issue bot, a foundation-specific voting process, or another approval system gate final publication without changing candidate identity or promotion semantics.
Minimal configuration
1component:
2 id: example
3 display_name: Example
4versioning:
5 scheme: semver
6 final_tag_template: "v{version}"
7source:
8 selection: explicit-ref-or-default-branch
9 default_branch: main
10 snapshot:
11 mode: platform-generated
12 checks:
13 platform: github
14 required:
15 - Required Checks
16lifecycle:
17 mode: candidate
18# Optional. Omit this block to publish without custom notes.
19release_notes:
20 path_template: release-notes/{version}.md
21candidate:
22 label: rc
23 start_number: 1
24 visibility: public-prerelease
25 retention: retain-published
26artifacts:
27 produced: []
28 checksums: []
29publication:
30 authoritative:
31 kind: github-release
32 repository: example/example
33tags:
34 final_mode: exact-source-commit
35 moving: []
36policy_profiles: {}
The default candidate number is one. With this configuration, version 1.2.3 starts at
v1.2.3-rc1. Configured notes are required: resolution reads the rendered path from the exact
selected source commit and rejects a missing, empty, invalid UTF-8, or oversized file. The notes,
source path, and SHA-256 are carried in candidate state and candidate-manifest.json; promotion
reuses those exact bytes and rejects a configured path change. Omit release_notes when a component
does not publish custom notes.
Create candidates
Run .github/workflows/release-candidate.yml with the exact version and optional source ref or
candidate-label override. The workflow:
- resolves the next unused candidate number and exact source commit;
- verifies configured source checks on that commit;
- creates the immutable candidate tag;
- stages the GitHub candidate and any configured artifacts;
- creates and attaches
candidate-manifest.json; - verifies the tag, release metadata, asset inventory, manifest bytes, size, and SHA-256;
- applies configured visibility.
public-prerelease produces a public GitHub prerelease. draft retains a non-public draft. A later
run for the same version and label selects the next number after the highest existing matching tag;
published candidates are retained.
For example, a rejected or superseded v1.2.3-rc1 can remain available while a new run publishes
v1.2.3-rc2 from another exact commit.
Zero-based numbering
Projects that prefer RC0 can choose it explicitly:
1candidate:
2 label: rc
3 start_number: 0
4 visibility: draft
5 retention: retain-published
That configuration begins at v1.2.3-rc0. Numbering is project policy; it has no effect on the
unsuffixed final version or final tag.
Independent verification
Run .github/workflows/release-verify-candidate.yml with:
- the exact candidate tag;
- the lowercase SHA-256 of
candidate-manifest.json.
The read-only workflow downloads the durable manifest from the candidate GitHub Release and checks the supplied digest, candidate identity, source commit, release metadata, and asset identities. It also retains the verified manifest and result as a workflow artifact for inspection.
Exact promotion
After the external gate accepts a candidate, run .github/workflows/release-promote.yml with:
version, such as1.2.3;candidate_tag, such asv1.2.3-rc2;candidate_manifest_digest, the exact lowercase SHA-256 selected by the gate.
Promotion never discovers “the latest RC”. It downloads and verifies the named candidate manifest,
downloads each candidate asset named by that manifest, verifies the bytes, and creates
PromotionState, including any candidate-bound release notes. The remaining jobs create the final
tag, stage and verify the final release using those exact notes, publish it, and attach
release-manifest-v1.json.
The final manifest records the promoted candidate and its manifest digest. Per-artifact promotion evidence distinguishes byte-identical assets, immutable registry identities, and hosting-platform snapshots generated from tags at the same exact source revision.
Optional vote package
Voting is not a precondition of candidate publication. A component that wants reusable voting materials can add a generic profile:
1vote_materials:
2 profile: generic
3 release_name: Example
4 verification_guide_url: https://example.org/releases/verify/
5 instructions: Verify the candidate manifest and all referenced artifacts.
Dispatch the candidate workflow with vote_profile: generic, or call create-vote-package over the
exact candidate manifest. VotePackageV1 binds the rendered opening/result templates to that
manifest’s digest. Vote duration, voter eligibility, quorum, veto rules, and outcome remain the
responsibility of the external authority.
The optional ASF profile provides ASF-specific terminology and trust-root data without changing the generic candidate or promotion contracts.