pub struct Context {Show 13 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 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>,
/* 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.
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.
Implementations§
Source§impl Context
impl Context
pub fn new(config: Config, options: ContextOptions) -> Self
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 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_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.
pub fn should_skip(&self, stage_name: &str) -> bool
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
pub fn is_strict(&self) -> bool
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 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 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 config
order) whose changelog is present, or an empty string if no
changelogs exist. Config 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, License, 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).