Releases
A release version is a signed, unchangeable set of artifacts from files, build runs, other releases or a query. Promotion and export refuse a version whose stored files no longer match its signed manifest.
Create a release version from a build run and a file:
relic release create app 1.4.0 --build app/42 --file libs-local/docs/guide.pdf
Create a release version from a sources file:
relic release create app 1.5.0 -f release.yaml
The file lists ReleaseSource messages (files, builds, releases or
query) in YAML or JSON:
- builds:
- {name: app, number: "42", dependencies: true}
- files:
- {path: libs-local/docs/guide.pdf}
Create a draft:
relic release create app 1.6.0 --build app/50 --draft
Add another release to the draft:
relic release update app 1.6.0 --release base/2.1
Finalize the draft:
relic release finalize app 1.6.0
List the releases (--project "" for those outside projects):
relic release list
List one release's versions:
relic release list app -o json
Show one version and its artifacts:
relic release get app 1.4.0
Tag a version (no tag clears it):
relic release tag app 1.4.0 stable
Delete a version:
relic release delete app 1.3.0
Promoting
A promotion copies each artifact into a local repository whose environments
setting names the environment: the only one, else the first by name of the
artifact's source format, else the first generic one. An artifact that fits
none is left out and named in the promotion's messages; when none fits, the
promotion fails. --move is performed as a copy.
Promote a version to PROD:
relic release promote app 1.4.0 PROD
Promote a version to QA, into qa-generic only:
relic release promote app 1.4.0 QA --include qa-generic
Promotion gates
A promotion gate is a condition a version must meet to be promoted to an
environment. Each decision is recorded as evidence of type
https://relic.build/promotion-gate/v1.
The condition is a CEL expression over these variables:
| Variable | Holds |
|---|---|
release | project, name, version, tag, createdBy, and artifacts, each with repository, path, sha256 and size |
environment | the target environment |
evidence | the version's evidence, each with predicateType, predicate, verified, keyAlias and createdBy |
scan | finding counts: critical, high, medium, low, unknown, malicious, and unscanned artifacts |
signed | whether the manifest verifies with Relic's release key and the stored artifacts still match it |
Two gates for PROD:
apiVersion: relic.build/v1
kind: PromotionGate
metadata: {name: prod-clean}
spec:
environment: PROD
condition: signed && scan.critical == 0 && scan.malicious == 0 && scan.unscanned == 0
description: no critical or malicious findings
---
apiVersion: relic.build/v1
kind: PromotionGate
metadata: {name: prod-provenance}
spec:
environment: PROD
condition: evidence.exists(e, e.predicateType == "https://slsa.dev/provenance/v1" && e.verified)
description: verified build provenance
Apply the gates:
relic apply -f gates.yaml
List the gates:
relic get promotiongates
Moving releases between servers
Export a version with its manifest, signed by the release-bundles key, and
print the key's fingerprint:
relic release export app 1.4.0 --file app-1.4.0.zip
A server imports only files signed by its own key or a trusted key. Save the exporting server's public key:
relic release public-key >build-server.pem
On the importing server, trust the key under a name of your choice (administrators). Check that the fingerprint it prints matches export's:
relic --context airgap release trust-key build-server build-server.pem
Trusted keys also verify evidence.
Import the file (administrators):
relic --context airgap release import app-1.4.0.zip
Import refuses an unsigned manifest, a signature that does not verify, an untrusted key (the error names its fingerprint), and contents that differ from the manifest.