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.
Workflow Composition
Workflow Composition
Components own thin workflows that call the CLI. The CLI does not choose GitHub Environment names, repository secret names, runner groups, or an organization’s approval policy.
The checked-in Buildish workflows show a GitHub-authoritative, platform-generated-source composition. Other components can split or combine jobs differently as long as they preserve the state, integrity, and permission boundaries below.
Current workflows
| Workflow | Purpose | Mutation boundary |
|---|---|---|
release-direct.yml |
Publish an exact final release without an RC | final tag and GitHub Release |
release-candidate.yml |
Publish the next exact candidate and durable manifest | candidate tag and GitHub prerelease/draft |
release-promote.yml |
Promote one named candidate manifest | final tag and GitHub Release |
release-verify-candidate.yml |
Independently verify one named candidate | read-only |
All external actions use immutable commit pins. Workflow-level permissions default to
contents: read; only jobs that mutate GitHub refs or Releases receive contents: write.
Handoff rules
Small scalar identities may cross a job boundary through GITHUB_OUTPUT. Complete state crosses the
boundary as a JSON file:
- direct state for direct publication;
- candidate state inside candidate publication;
- promotion state for final candidate promotion;
- publication results for final manifest creation.
The producing job emits a SHA-256 for each release-critical state or result. A consuming job verifies the exact bytes after downloading the workflow artifact and before invoking a mutation command.
GitHub workflow artifacts are only a same-run transport. Cross-run promotion uses
candidate-manifest.json attached to the candidate GitHub Release. The external gate retains the
candidate tag and manifest SHA-256; the promotion workflow requires both.
Concurrency
Mutation workflows use one non-canceling group per repository and exact version:
1concurrency:
2 group: buildish-release-${{ github.repository }}-${{ inputs.version }}
3 cancel-in-progress: false
This prevents direct, candidate, and promotion runs for the same version from racing. Waiting is intentional: cancelling a run after it created a tag or staged a release does not roll that external state back.
The CLI itself does not implement a distributed lock. Maintainer-shell invocations and custom workflows must provide equivalent serialization when they can target the same release identity.
GitHub Environments
The checked-in workflows do not prescribe GitHub Environment names. A component may attach an environment to every write job, only to final publication, or to additional build/signing jobs.
If project policy says approval is required before all release mutations, inspect every job with
contents: write, including tag creation and final manifest attachment, and give each the intended
environment:. Environment-scoped secrets gate only jobs that actually declare that environment.
The local harness validates workflow shape and command behavior. It cannot prove that required reviewers, deployment branches, or environment secrets are configured correctly in GitHub.
Source checks and build jobs
An optional source.checks block selects a hosting-platform check gate. The implemented
platform: github adapter requires exactly named successful or intentionally skipped check runs or
legacy status contexts on the exact source commit. Unrelated observations are ignored, so the
release workflow does not wait on its own in-progress jobs.
Same-run component tests are workflow-owned jobs, not a boolean promise in release config. A thin
component workflow may run them before the mutation jobs, may rely on named results from its normal
CI workflow, or may compose both controls. Omitting source.checks means the release CLI applies no
external platform-status gate; it does not claim that tests ran elsewhere.
The checked-in workflows publish no separately built artifact. A component that selects
source.snapshot.mode: built-asset or other produced artifacts adds component-specific build,
verification, and artifact-transfer jobs, then passes the exact files to the relevant stage command.
See Source artifacts and signing.
External gates and automation
The candidate workflow stops after publishing a verified candidate. The promotion workflow starts from explicit immutable inputs. Nothing between them assumes how approval was obtained.
An automated voting or approval service can therefore dispatch promotion only after its own policy passes. It must preserve and submit the exact candidate tag and manifest SHA-256. It must not replace those inputs with “latest candidate” discovery.
The current workflows expose workflow_dispatch. A component may add its own workflow_call
wrapper, bot, or GitHub App integration without changing the CLI contracts.
Other hosting platforms
GitHub is the only implemented platform adapter today. Provider-neutral state and manifests carry generic identities and typed extension points. A future GitLab or Forgejo adapter should add its own config, publication extension, and workflow integration rather than placing provider fields in the core models.