Release Surfaces¶
The Make release surface prepares and validates reproducible package evidence. GitHub workflows own protected credentials, artifact transfer, environment approval, and publication. Keeping these responsibilities separate allows a release candidate to be inspected locally without reproducing a privileged deployment context.
flowchart LR
M[Package metadata and source] --> G[Version guard]
G --> B[Build wheel and sdist]
B --> T[Twine validation]
B --> S[SBOM generation]
T --> A[Staged release artifacts]
S --> A
A --> W[Release workflow]
W --> P[PyPI, GHCR, or GitHub Release]
Make responsibilities¶
| Contract | Responsibility | Evidence |
|---|---|---|
makes/bijux-py/ci/build.mk |
build wheel and source distribution, run twine check, execute configured pre/post checks |
package build or release directory and twine-check.log |
makes/bijux-py/ci/sbom.mk |
resolve version, produce production and development CycloneDX documents, summarize, and optionally validate | package SBOM directory |
makes/bijux-py/repository/publish.mk |
verify version and distribution set, stage TestPyPI or PyPI upload, optionally verify an installed TestPyPI package | validated distributions and command result |
makes/publish.mk |
bind repository version resolver and publication guard, with release policy defaults | guarded package version |
make build PACKAGE=<slug> and make sbom PACKAGE=<slug> use the root package
catalog. Publication targets are profile-level because upload policy and
installation verification belong to a specific distribution.
Version and distribution guard¶
The version resolver reads package metadata. The publication guard rejects an
unresolved 0.0.0, disallowed prerelease or local versions, package/version
mismatches, and inconsistent distribution filenames. A guarded publication
requires both a wheel and source distribution before upload.
release-dry runs a package-defined post-build check when configured. A
message that no dry-run command exists is an explicit absence of that extra
claim, not a repository-wide release certification.
SBOM evidence boundary¶
The sbom generator captures production and development dependency views and
writes a summary. Its pip-audit generation commands are tolerant so partial
diagnostic output can be retained. Therefore make sbom alone is not a strict
CycloneDX acceptance claim.
Use the profile validator when certification is required:
make sbom PACKAGE=bijux-canon-runtime
make -f "$PWD/makes/packages/bijux-canon-runtime.mk" \
-C packages/bijux-canon-runtime sbom-validate
The validator refuses a missing CycloneDX CLI, an empty SBOM directory, or an invalid document.
Publication controls¶
Upload is disabled by default in the reusable contract. When enabled, the
target requires a token, uses non-interactive Twine, and may skip an already
published file only when SKIP_EXISTING=1. TestPyPI installation verification
creates an isolated environment and runs the profile's configured smoke
command.
Credentials never belong in package profiles or generated artifacts. Workflow permissions and protected environments determine which publication jobs may receive them.
Workflow handoff¶
A publication workflow consumes previously built, identified artifacts. It must not rebuild a different candidate after approval. Review the artifact name, producer run, digest or checksums, target environment, permissions, and downstream receipt before treating publication as complete.
| State | Valid claim |
|---|---|
| build target passed | distributions were built and locally validated |
| strict SBOM validation passed | generated CycloneDX documents are structurally valid |
| release artifact uploaded to Actions | candidate is retained for downstream jobs |
| package registry accepted upload | named distribution is published |
| post-publication install passed | published distribution can be resolved and executes its smoke contract |
Release confidence comes from preserving this custody chain, not from treating one green job as proof of every stage.