pub struct Context {Show 16 fields
pub config: Config,
pub artifacts: ArtifactRegistry,
pub options: ContextOptions,
pub stage_outputs: StageOutputs,
pub git_info: Option<GitInfo>,
pub token_type: ScmTokenType,
pub skip_memento: SkipMemento,
pub emission_skips: SkipMemento,
pub publish_report: Option<PublishReport>,
pub publish_attempted: bool,
pub verify_release: Option<VerifyReleaseSummary>,
pub determinism: Option<DeterminismState>,
pub pending_outcome: Option<PublisherOutcome>,
pub pending_evidence: Option<PublishEvidence>,
pub literal_message: bool,
pub redact_body: bool,
/* private fields */
}Fields§
§config: Config§artifacts: ArtifactRegistry§options: ContextOptions§stage_outputs: StageOutputsStage→stage handoff outputs (changelog text, header/footer, etc.).
git_info: Option<GitInfo>§token_type: ScmTokenTypeThe resolved SCM token type (GitHub, GitLab, or Gitea).
skip_memento: SkipMementoAggregated skips from per-sub-config loops (signs, docker_signs,
publishers, …). Drained by the pipeline runner at end-of-pipeline so
the summary shows what was intentionally skipped — mirroring
the skip-memento pattern. The inner Arc<Mutex<…>>
lets parallel stage workers contribute without extra plumbing.
emission_skips: SkipMementoPer-expectation skips recorded by the emission-validate pass on a
target-restricted build (an expectation whose target subset was not
built in this run, or a cross-platform aggregate with no eligible
artifact). Kept SEPARATE from Self::skip_memento on purpose: that
memento is drained into the default-visible end-of-pipeline summary,
while these skips surface only as verbose lines plus an aggregate
count in the stage’s one RESULT line — a sharded run would otherwise
print one summary line per unbuilt-target expectation.
publish_report: Option<PublishReport>Trait-based publisher dispatch report, set by PublishStage::run
when the per-publisher dispatcher finishes. None until the
publish stage executes (or when publishing is skipped entirely
via snapshot mode / --skip=publish). Downstream stages
(SnapcraftPublishStage, AnnounceStage, future Submitter-group
stages) consult this to apply the submitter-gate / announce-gate
rules — see PublishReport::any_failed.
publish_attempted: boolWhether PublishStage::run entered its body this run. Set before
the pre-dispatch guards (rerun refusal, runtime allowlist), so a
guard abort leaves this true with publish_report still None
— the summary placeholder row uses the pair to distinguish
“publish skipped” from “publish aborted before dispatch”.
verify_release: Option<VerifyReleaseSummary>Verify-release verdict, set by VerifyReleaseStage::run immediately
before it returns (clean pass OR bail!). None until the gate runs
its checks — it stays None on the disabled / skipped / dry-run /
snapshot early-returns, where no published release exists to verify.
Read by the run-summary builder so the end-of-pipeline Summary states
the verify-release outcome on a SEPARATE axis from the publisher rows:
the gate runs after the irreversible publish, so the publishes still
read succeeded while this slot records whether the published release
has unverified defects to investigate.
determinism: Option<DeterminismState>SOURCE_DATE_EPOCH seed + non-determinism allow-list state for the
run. None until a stage (typically BuildStage) seeds it from
resolve_reproducible_epoch(commit_timestamp); downstream stages
(stage-sbom, stage-archive, stage-sign) read sde to derive
deterministic timestamps. Lazy-init by design: tests and snapshot
runs without a clean commit can still proceed.
pending_outcome: Option<PublisherOutcome>Per-publisher outcome override published by Publisher::run when
the artifact reached a non-Succeeded terminal state but run
still returned Ok (e.g. chocolatey moderation skip,
winget/krew/homebrew PR-already-exists skip). Dispatch consumes
this slot via take_pending_outcome() immediately after run
returns Ok so the per-publisher row in the summary table reads
pending-moderation / pending-validation instead of
succeeded. The slot is single-shot: any unread value is
cleared at the start of every run call.
pending_evidence: Option<PublishEvidence>Partial [PublishEvidence] published by Publisher::run BEFORE it
returned Err, so a publisher that did irreversible work for the
first N items and then failed on item N+1 can still hand the
rollback path the authoritative record of what actually went live.
The cargo publisher is the motivating case: a multi-crate publish
that succeeds on crate A then fails on crate B must yank A. On the
Ok path run returns its evidence directly; on the Err path
dispatch consumes this slot via Context::take_pending_evidence
and records it on the failed publisher’s report row so rollback has
something to act on. Single-shot — drained at the start of every
run and cleared on the Ok path.
literal_message: boolWhen true, announce message BODIES are treated as already-final text and
are NOT run through Tera at send time. Set by anodizer notify so an
operator-supplied (possibly untrusted) message — e.g. an on_error error
string — cannot expand an Env-reference into a secret when the
provider sends it. Only message bodies are affected; titles and other
templated fields still render normally.
redact_body: boolWhen true (the default), outbound announce message BODIES have
known-secret env values masked before send (same policy as log
redaction). anodizer notify --allow-secrets sets this false to send a
secret deliberately over a trusted channel. Only the outbound body is
affected; anodizer’s own logs are redacted unconditionally regardless of
this flag.
Implementations§
Source§impl Context
impl Context
pub fn new(config: Config, options: ContextOptions) -> Self
Sourcepub fn redact(&self, s: &str) -> String
pub fn redact(&self, s: &str) -> String
Redact known-secret env values from outbound announce text, using the
same combined env (template engine env + process env) and the same
policy as log redaction. Always redacts; gating on redact_body is the
caller’s responsibility (see render_message_with_default).
Sourcepub fn env_var(&self, name: &str) -> Option<String>
pub fn env_var(&self, name: &str) -> Option<String>
Read an environment variable through the injected source.
Production reads std::env::var(name).ok(). Tests inject a
MapEnvSource via
TestContextBuilder::env
so deterministic branches can be exercised without mutating the
process env.
Sourcepub fn set_env_source<S: EnvSource + 'static>(&mut self, src: S)
pub fn set_env_source<S: EnvSource + 'static>(&mut self, src: S)
Replace the injected environment-variable source.
Production migration code uses this when wrapping an
already-constructed context; tests reach this indirectly through
TestContextBuilder::env.
Sourcepub fn set_env_source_arc(&mut self, src: Arc<dyn EnvSource>)
pub fn set_env_source_arc(&mut self, src: Arc<dyn EnvSource>)
Replace the injected environment-variable source with an already-boxed
Arc<dyn EnvSource>. Used to RESTORE a previously captured base source
after a temporary overlay (see
Context::begin_cargo_trusted_publishing) without re-wrapping it.
Sourcepub fn begin_cargo_trusted_publishing(&mut self, token: String)
pub fn begin_cargo_trusted_publishing(&mut self, token: String)
Overlay a minted crates.io Trusted-Publishing token as
CARGO_REGISTRY_TOKEN for the cargo publish+rollback lifecycle.
The current env source is captured as the base, then wrapped in a
LayeredEnvSource that overrides
CARGO_REGISTRY_TOKEN with token. This makes the token visible to
env-driven paths that read through Context::env_source — notably
the rollback scope-availability gate — so a partial OIDC publish can
still yank, even though no ambient token exists. The token is also
retained as a marker so a later rollback() knows a minted token is
live and must be revoked after the yank.
Paired with Context::end_cargo_trusted_publishing, which restores
the base source and returns the token for best-effort revocation.
Sourcepub fn cargo_trusted_publishing_token(&self) -> Option<&str>
pub fn cargo_trusted_publishing_token(&self) -> Option<&str>
The minted crates.io Trusted-Publishing token, if an overlay is active.
rollback() reads this to learn (i) that the yank must inject a minted
token, and (ii) that the token must be revoked once the yank completes.
Sourcepub fn end_cargo_trusted_publishing(&mut self) -> Option<String>
pub fn end_cargo_trusted_publishing(&mut self) -> Option<String>
Tear down the Trusted-Publishing overlay: restore the captured base env
source, drop the marker, and return the minted token so the caller can
revoke it (best-effort). Returns None when no overlay is active (the
auth: token / ambient path never mints, so its long-lived token is
neither overlaid nor revoked).
Sourcepub fn env_source(&self) -> &dyn EnvSource
pub fn env_source(&self) -> &dyn EnvSource
Borrow the injected environment-variable source as a trait
object so callers can pass it into helpers that take
&dyn EnvSource / &E: EnvSource + ?Sized without re-binding
each var through Context::env_var.
Sourcepub fn env_source_arc(&self) -> Arc<dyn EnvSource>
pub fn env_source_arc(&self) -> Arc<dyn EnvSource>
Clone the injected environment-variable source as an Arc so
callers can move it into a tokio::spawn future or any other
'static closure. Production-default value is
ProcessEnvSource; tests may replace it via
Context::set_env_source.
Sourcepub fn record_publisher_outcome(&mut self, outcome: PublisherOutcome)
pub fn record_publisher_outcome(&mut self, outcome: PublisherOutcome)
Publisher-facing override: when Publisher::run returns Ok
but the terminal outcome is something other than Succeeded
(chocolatey moderation skip, winget/krew/homebrew
PR-already-exists skip, …) call this before returning so
dispatch records the correct PublisherOutcome on the report.
Without this, dispatch defaults to Succeeded on any Ok and
the summary table silently misreports the skip as success.
Sourcepub fn take_pending_outcome(&mut self) -> Option<PublisherOutcome>
pub fn take_pending_outcome(&mut self) -> Option<PublisherOutcome>
Dispatch-side consumer: take the pending outcome override (if
any) recorded by the publisher’s run. Single-shot — the slot
is empty after this call.
Sourcepub fn record_pending_evidence(&mut self, evidence: PublishEvidence)
pub fn record_pending_evidence(&mut self, evidence: PublishEvidence)
Publisher-side recorder: stash the partial evidence accumulated
before a failing run returns Err, so dispatch can attach it to
the failed report row and rollback has the authoritative record of
what went live. See Context::pending_evidence.
Sourcepub fn take_pending_evidence(&mut self) -> Option<PublishEvidence>
pub fn take_pending_evidence(&mut self) -> Option<PublishEvidence>
Dispatch-side consumer: take the partial evidence (if any) a publisher recorded before failing. Single-shot — empty after this call.
Sourcepub fn publish_report(&self) -> Option<&PublishReport>
pub fn publish_report(&self) -> Option<&PublishReport>
Borrow the publisher dispatch report set by PublishStage::run,
or None if the publish stage hasn’t run yet (or was skipped).
Sourcepub fn publish_attempted(&self) -> bool
pub fn publish_attempted(&self) -> bool
Whether the publish stage entered its body this run (even if it aborted before dispatching any publisher).
Sourcepub fn set_publish_attempted(&mut self)
pub fn set_publish_attempted(&mut self)
Record that the publish stage entered its body. Called by
PublishStage::run ahead of its pre-dispatch guards so guard
aborts are distinguishable from a skipped stage.
Sourcepub fn set_publish_report(&mut self, r: PublishReport)
pub fn set_publish_report(&mut self, r: PublishReport)
Store the publisher dispatch report. Overwrites any prior value.
Written by the publish stage during a normal release run; rehydrated by
--announce-only from the on-disk <dist>/run-<id>/report.json so the
announce stage sees an equivalent context without re-publishing.
Sourcepub fn built_crate_names(&self) -> Option<&HashSet<String>>
pub fn built_crate_names(&self) -> Option<&HashSet<String>>
Borrow the set of crate names the build stage actually built, or
None if the build stage has not run in this pipeline (merge mode).
Sourcepub fn set_built_crate_names(&mut self, names: HashSet<String>)
pub fn set_built_crate_names(&mut self, names: HashSet<String>)
Record the distinct crate names that received at least one in-scope build job. Called once by the build stage after job planning.
Sourcepub fn remember_skip(&self, stage: &str, label: &str, reason: &str)
pub fn remember_skip(&self, stage: &str, label: &str, reason: &str)
Record an intentional skip from a per-sub-config loop
(signs, docker_signs, publishers, …). stage identifies the
owning stage, label identifies the sub-config (id / name / index),
reason is short user-facing text. Duplicate (stage, label, reason)
tuples are dropped on insert so a per-artifact inner loop cannot emit
N copies of the same skip message.
pub fn template_vars(&self) -> &TemplateVars
pub fn template_vars_mut(&mut self) -> &mut TemplateVars
pub fn render_template(&self, template: &str) -> Result<String>
Sourcepub fn render_template_for_version(
&self,
template: &str,
version: &str,
tag: &str,
) -> Result<String>
pub fn render_template_for_version( &self, template: &str, version: &str, tag: &str, ) -> Result<String>
Render template with the FULL version-derived var set (Version, Tag,
Major/Minor/Patch, RawVersion, Prerelease, BuildMetadata,
Base) re-derived from version/tag rather than the context’s own git
version — used by promotion to reconstruct the immutable tag a prior
release pushed for a specific --version. Overriding only Version+Tag
would leave {{ .Major }} etc. resolving to the CONTEXT version, so a
{{ .Major }}.{{ .Minor }}.{{ .Patch }} tag template would render the
wrong source tag whenever the context version differs from the target.
A non-semver version (no parse) falls back to overriding Version+Tag
and BLANKING the seven semver-part vars (RawVersion, Base, Major,
Minor, Patch, Prerelease, BuildMetadata), so a semver-part template
cannot silently resolve the context version — it renders empty instead of
inheriting the cloned context’s parts. Does not mutate self.
Sourcepub fn render_template_opt(
&self,
template: Option<&str>,
) -> Result<Option<String>>
pub fn render_template_opt( &self, template: Option<&str>, ) -> Result<Option<String>>
Render a template if present, returning None for None input.
Sourcepub fn skip_with_log(
&self,
skip: &Option<StringOrBool>,
log: &StageLogger,
label: &str,
) -> Result<bool>
pub fn skip_with_log( &self, skip: &Option<StringOrBool>, log: &StageLogger, label: &str, ) -> Result<bool>
Evaluate a skip field, logging at INFO level when it resolves to true.
Returns Ok(false) when skip is None or evaluates falsy. On
truthy, writes "{label} skipped" via log.status and returns
Ok(true). A malformed skip: template propagates as Err so the
caller fails fast — silently treating a render error as “not skipped”
(the prior behavior) shipped configs that the user thought would
suppress a stage but actually ran it.
Sourcepub fn should_skip(&self, stage_name: &str) -> bool
pub fn should_skip(&self, stage_name: &str) -> bool
Whether stage_name (or a publisher name — the skip list is unified) is
in the operator’s --skip denylist.
Sourcepub fn publisher_deselected(&self, name: &str) -> bool
pub fn publisher_deselected(&self, name: &str) -> bool
Whether the named publisher is excluded from this run by operator selection. Combines the two selectors the publish dispatch consults before running any publisher:
--skip(skip_stages, the UNIFIED denylist holding stage names AND publisher names) ALWAYS wins: a publisher named there is deselected regardless of any allowlist.--publishers(publisher_allowlist): an EMPTY allowlist deselects nothing (every publisher runs); a NON-EMPTY allowlist deselects every publisher not listed in it.
Returns true when the publisher should be reported
crate::publish_report::SkipReason::Deselected instead of dispatched.
Sourcepub fn any_publisher_selected(&self, names: &[&str]) -> bool
pub fn any_publisher_selected(&self, names: &[&str]) -> bool
Whether ANY of the named publishers survives the operator-selection
filter — the positive dual of Self::publisher_deselected over a
set. One helper for both registers (“is any consumer selected?” and
its negation “are all consumers deselected?”) so callers never
hand-roll De Morgan twins that can drift apart.
Sourcepub fn deselected_reason(&self, name: &str) -> String
pub fn deselected_reason(&self, name: &str) -> String
A distinguished, operator-facing summary line for a deselected
publisher, naming WHICH selector excluded it so the operator can fix
their command. --skip always wins, so it is tested first: a publisher
named in both selectors reports the denylist cause.
Shared by the dispatch chokepoint and the out-of-dispatch publish
stages (blob / snapcraft-publish / docker / docker-sign / announce) so the
“skipped X — excluded via –skip” / “… — not in –publishers allowlist”
wording is identical everywhere a publisher is deselected. Call only
when Self::publisher_deselected is true.
Sourcepub fn skip_validate(&self) -> bool
pub fn skip_validate(&self) -> bool
Check whether “validate” is in the skip list.
pub fn is_dry_run(&self) -> bool
pub fn is_snapshot(&self) -> bool
Sourcepub fn is_target_restricted_build(&self) -> bool
pub fn is_target_restricted_build(&self) -> bool
Whether this run builds only a subset of the configured targets — either
a --split / --targets determinism shard (partial_target) or a
host-only --single-target build.
A publisher whose eligible artifact is legitimately absent on a
restricted build (e.g. a Windows-only publisher on a Linux single-target
snapshot) must self-skip its schema validation rather than error: the
artifact lands on another target, not a misconfiguration. On a FULL build
the same absence IS a misconfiguration and must surface. --single-target
(single_target) is clap-exclusive with --targets / --host-targets
(which populate partial_target), but NOT with --split (a split shard
resolves its own partial_target from partial.by yet may still be
scoped to the host target), so both signals can be set at once; this OR
is the single “restricted build” predicate the per-publisher validators
gate their no-artifact skip on, correct whether one or both are set.
Sourcepub fn is_publish_only(&self) -> bool
pub fn is_publish_only(&self) -> bool
Whether this run is anodizer release --publish-only (publishing a
preserved dist rather than building from source).
Build-time concerns (notably the binary_signs: per-binary signing
loop, whose output is embedded into archives at build time and has no
publish-time consumer) are gated off this in publish-only mode, where
the runner carries only publish-time credentials.
pub fn is_strict(&self) -> bool
Sourcepub fn preflight_is_strict(&self) -> bool
pub fn preflight_is_strict(&self) -> bool
Effective preflight strictness: the global --strict, the scoped
--strict-preflight, or the config-level preflight.strict — any one
turns it on. Under strict preflight, indeterminate probe outcomes
(Unknown publisher state, 5xx / rate-limit / network failure /
undeterminable permissions) become hard blockers instead of warnings.
Definitive failures keep their required→blocker / optional→warning
severity either way.
Sourcepub fn set_render_strict(&self, on: bool) -> bool
pub fn set_render_strict(&self, on: bool) -> bool
Toggle the runtime strict-render flag (see the render_strict field).
The pre-publish guard calls this with true before its render pass and
restores the prior value after, so render-error swallowing is suppressed
only for that in-memory validation — production publish renders stay
lenient unless the user passed the global --strict. Returns the prior
value so the caller can restore it.
Sourcepub fn render_is_strict(&self) -> bool
pub fn render_is_strict(&self) -> bool
Whether template renders should propagate errors (strict) rather than warn-and-fall-back-to-raw (lenient).
True when EITHER the guard’s transient render_strict flag is set OR the
user passed the global --strict, so a malformed publisher/announce
template fails loud under the guard and under --strict everywhere.
Sourcepub fn strict_guard(&self, log: &StageLogger, msg: &str) -> Result<()>
pub fn strict_guard(&self, log: &StageLogger, msg: &str) -> Result<()>
In strict mode, return an error. In normal mode, log a warning and continue. Use this for any situation where a configured feature silently skips.
Sourcepub fn skip_in_snapshot(&self, log: &StageLogger, stage: &str) -> bool
pub fn skip_in_snapshot(&self, log: &StageLogger, stage: &str) -> bool
Defense-in-depth helper for upload-style stages.
Returns true (after logging the skip) when the context is in snapshot
mode. Stages that perform external uploads (registries, package indexes,
object storage, snap store, …) call this at entry so they no-op even
when invoked directly without the orchestration layer’s auto-skip.
Centralising the check keeps every publish stage consistent and avoids
per-stage copy-paste.
Sourcepub fn render_template_strict(
&self,
template: &str,
label: &str,
log: &StageLogger,
) -> Result<String>
pub fn render_template_strict( &self, template: &str, label: &str, log: &StageLogger, ) -> Result<String>
Render a template, failing in strict mode on error, or falling back to the raw string.
pub fn is_nightly(&self) -> bool
Sourcepub fn set_release_url(&mut self, url: &str)
pub fn set_release_url(&mut self, url: &str)
Set the ReleaseURL template variable.
Should be called after a GitHub release is created, with the URL of
the created release (e.g. https://github.com/owner/repo/releases/tag/v1.0.0).
Sourcepub fn version(&self) -> String
pub fn version(&self) -> String
Return the current Version template variable, or an empty string if
not yet populated.
Sourcepub fn resolve_reproducible_mtime(&self) -> Option<u64>
pub fn resolve_reproducible_mtime(&self) -> Option<u64>
Reproducible-mtime seed shared by every stage that stamps a build timestamp into a produced artifact (release archives, source archives, PyPI wheels + sdists).
Resolution ladder, single-sourced here so archives and wheels never pick different timestamps in one run:
- when ANY build in the crate universe is
reproducible: true, the commit timestamp wins outright — a reproducible build pins its own output to the commit, so a stray ambientSOURCE_DATE_EPOCHmust not override it; - otherwise
SOURCE_DATE_EPOCH(the standard reproducibility contract, set by the determinism harness on every child), falling back to the commit timestamp.
Returns None when neither a commit timestamp nor SOURCE_DATE_EPOCH
is available (writers then leave the default wall-clock stamp).
Sourcepub fn retry_policy(&self) -> RetryPolicy
pub fn retry_policy(&self) -> RetryPolicy
Resolve the user’s retry: block into a concrete [RetryPolicy],
applying defaults when retry: is unset. Equivalent to
ctx.config.retry.unwrap_or_default().to_policy() but centralizes
the lookup so a future refactor can hang validation / clamping off
a single seam.
Sourcepub fn retry_deadline(&self) -> Option<Instant>
pub fn retry_deadline(&self) -> Option<Instant>
Resolve the retry wall-clock budget into an absolute deadline anchored at
the moment of this call. Always Some: retry.max_elapsed when the user
sets it, otherwise crate::retry::DEFAULT_MAX_ELAPSED (15 min) — so a
publisher that threads this into crate::retry::retry_sync_deadline /
crate::retry::retry_async_deadline is bounded by default and the
operator can raise or lower the ceiling with one config field. The
Option return lets it feed those engines verbatim (their None means
unbounded, reserved for callers with no context). Computed once at the
start of a publish sequence so a long transient storm exits cleanly
(resumable) instead of being SIGKILLed mid-write by the outer job timeout.
Sourcepub fn logger(&self, stage: &'static str) -> StageLogger
pub fn logger(&self, stage: &'static str) -> StageLogger
Create a StageLogger for the given stage name, pre-attached to
the context’s env-pairs list so that subprocess stderr / stdout
flowing through StageLogger::check_output is automatically
redacted. The env list combines the template-engine env
(process + config + .env files) and the current std::env::vars
snapshot, so any secret value reachable to a hook or subprocess is
available for scrubbing.
Sourcepub fn populate_git_vars(&mut self)
pub fn populate_git_vars(&mut self)
Populate template variables from self.git_info.
Must be called after self.git_info is set. Sets the following vars:
Tag,Version,RawVersion— tag and version stringsMajor,Minor,Patch— semver componentsPrerelease— prerelease suffix (or empty)BuildMetadata— build metadata from semver tag (or empty)FullCommit,Commit— full commit SHA (Commitis alias forFullCommit)ShortCommit— abbreviated commit SHABranch— current git branchCommitDate— ISO 8601 author date of HEAD commitCommitTimestamp— unix timestamp of HEAD commitIsGitDirty— “true”/“false”IsGitClean— “true”/“false” (inverse ofIsGitDirty)GitTreeState— “clean”/“dirty”GitURL— git remote URLSummary— git describe summaryTagSubject— annotated tag subject or commit subjectTagContents— full annotated tag message or commit messageTagBody— tag message body or commit message bodyIsSnapshot— from context optionsIsNightly— from context optionsIsDraft— “false” (stages may override to “true”)IsSingleTarget— “true”/“false” based on single_target optionPreviousTag— previous matching tag, stripped in monorepo mode (or empty)PrefixedTag— full tag with monorepo prefix, or tag_prefix-prepended (Pro addition)PrefixedPreviousTag— full previous tag with prefix (Pro addition)PrefixedSummary— full summary with prefix (Pro addition)IsRelease— “true” if not snapshot and not nightly (Pro addition)IsMerging— “true” if running with –merge flag (Pro addition)
Stage-scoped variables (NOT set here; set per-artifact during stage execution):
Binary— binary name, set by build stage per binary and archive stage per archiveArtifactName— output artifact filename, set by archive stage after creating each archiveArtifactPath— absolute path to artifact, set by archive stage after creating each archiveArtifactExt— artifact file extension (e.g..tar.gz,.exe), set alongside ArtifactNameArtifactID— build configidfield, set by build stage per build configOs— target OS, set by archive/nfpm stages per targetArch— target architecture, set by archive/nfpm stages per targetTarget— full target triple (e.g.x86_64-unknown-linux-gnu), set alongside Os/ArchChecksums— combined checksum file contents, set by checksum stage
Sourcepub fn populate_time_vars(&mut self)
pub fn populate_time_vars(&mut self)
Populate time-related template variables.
Sets:
Date— UTC time as RFC 3339Timestamp— unix timestamp as stringNow— UTC time as RFC 3339Year— four-digit year (e.g. “2026”)Month— zero-padded month (e.g. “03”)Day— zero-padded day (e.g. “30”)Hour— zero-padded hour (e.g. “14”)Minute— zero-padded minute (e.g. “05”)
Time source resolution (first match wins):
SOURCE_DATE_EPOCHenv var — the standard reproducibility contract (set by the determinism harness on every child release subprocess, and the conventional way external CI / packagers signal a fixed epoch). This is load-bearing for byte-stability ofmetadata.json(which embedsDate) and any user template that consumesDate/Timestamp/Now. Without this branch, two from-clean runs of the same commit emit metadata.json files that differ in thedatefield, defeating release-asset idempotency.chrono::Utc::now()— wall-clock fallback. The legacy semantics for runs without SDE wired in. Note that the template docs explicitly call.Now“not deterministic” — under SDE-aware reproducible builds we deviate from that behavior intentionally.
Sourcepub fn populate_runtime_vars(&mut self)
pub fn populate_runtime_vars(&mut self)
Populate runtime environment variables.
Sets:
RuntimeGoos— host OS in Go-compatible naming (e.g. “linux”, “darwin”, “windows”)RuntimeGoarch— host architecture in Go-compatible naming (e.g. “amd64”, “arm64”)Runtime_Goos/Runtime_Goarch— nested aliasesRustcVersion— host rustc release version (e.g. “1.96.0”), or “” when rustc is unavailable
Sourcepub fn populate_release_notes_var(&mut self)
pub fn populate_release_notes_var(&mut self)
Populate the ReleaseNotes template variable from stored changelogs.
Should be called after the changelog stage has run and populated
self.stage_outputs.changelogs. Uses the first crate (by crate
universe order — top-level crates: then every workspaces[].crates
entry) whose changelog is present, or an empty string if no
changelogs exist. Universe order is deterministic, unlike HashMap
iteration order.
Sourcepub fn refresh_artifacts_var(&mut self)
pub fn refresh_artifacts_var(&mut self)
Refresh the Artifacts structured template variable from the current
artifact registry. Should be called before rendering release body and
announce templates so they can iterate over all artifacts.
Each artifact is serialized as a map with keys: name, path, target,
kind, crate_name, and metadata.
Known metadata keys (populated by individual stages):
format— archive format (e.g."tar.gz","zip"), set by archive stageextra_file—"true"when artifact is an extra file, set by checksum stageextra_name_template— name template override for extra files, set by checksum stagedigest— docker image digest (e.g.sha256:abc123...), set by docker stageid— artifact ID from config, set by docker and build stagesbinary— binary name, set by build stage
Sourcepub fn populate_metadata_var(&mut self) -> Result<()>
pub fn populate_metadata_var(&mut self) -> Result<()>
Populate the Metadata structured template variable from config.metadata.
Exposes the project metadata block as a nested map with PascalCase keys
the .Metadata.* namespace:
Description, Homepage, Documentation, License, Repository,
Maintainers, ModTimestamp, FullDescription (resolved),
CommitAuthor.{Name,Email}.
Missing fields default to empty strings / empty arrays.
full_description supports Inline, FromFile (template-rendered
path, read from disk), and FromUrl (template-rendered URL +
headers, fetched through crate::content_source::resolve which
applies retries, body caps, and CR/LF header-injection guards).