Skip to main content

Context

Struct Context 

Source
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: StageOutputs

Stage→stage handoff outputs (changelog text, header/footer, etc.).

§git_info: Option<GitInfo>§token_type: ScmTokenType

The resolved SCM token type (GitHub, GitLab, or Gitea).

§skip_memento: SkipMemento

Aggregated 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: SkipMemento

Per-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: bool

Whether 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: bool

When 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: bool

When 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

Source

pub fn new(config: Config, options: ContextOptions) -> Self

Source

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).

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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).

Source

pub fn publish_attempted(&self) -> bool

Whether the publish stage entered its body this run (even if it aborted before dispatching any publisher).

Source

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.

Source

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.

Source

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).

Source

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.

Source

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.

Source

pub fn template_vars(&self) -> &TemplateVars

Source

pub fn template_vars_mut(&mut self) -> &mut TemplateVars

Source

pub fn render_template(&self, template: &str) -> Result<String>

Source

pub fn render_template_opt( &self, template: Option<&str>, ) -> Result<Option<String>>

Render a template if present, returning None for None input.

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub fn skip_validate(&self) -> bool

Check whether “validate” is in the skip list.

Source

pub fn is_dry_run(&self) -> bool

Source

pub fn is_snapshot(&self) -> bool

Source

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.

Source

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.

Source

pub fn is_strict(&self) -> bool

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

pub fn is_nightly(&self) -> bool

Source

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).

Source

pub fn version(&self) -> String

Return the current Version template variable, or an empty string if not yet populated.

Source

pub fn verbosity(&self) -> Verbosity

Derive the verbosity level from context options.

Source

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.

Source

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.

Source

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.

Source

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 strings
  • Major, Minor, Patch — semver components
  • Prerelease — prerelease suffix (or empty)
  • BuildMetadata — build metadata from semver tag (or empty)
  • FullCommit, Commit — full commit SHA (Commit is alias for FullCommit)
  • ShortCommit — abbreviated commit SHA
  • Branch — current git branch
  • CommitDate — ISO 8601 author date of HEAD commit
  • CommitTimestamp — unix timestamp of HEAD commit
  • IsGitDirty — “true”/“false”
  • IsGitClean — “true”/“false” (inverse of IsGitDirty)
  • GitTreeState — “clean”/“dirty”
  • GitURL — git remote URL
  • Summary — git describe summary
  • TagSubject — annotated tag subject or commit subject
  • TagContents — full annotated tag message or commit message
  • TagBody — tag message body or commit message body
  • IsSnapshot — from context options
  • IsNightly — from context options
  • IsDraft — “false” (stages may override to “true”)
  • IsSingleTarget — “true”/“false” based on single_target option
  • PreviousTag — 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 archive
  • ArtifactName — output artifact filename, set by archive stage after creating each archive
  • ArtifactPath — absolute path to artifact, set by archive stage after creating each archive
  • ArtifactExt — artifact file extension (e.g. .tar.gz, .exe), set alongside ArtifactName
  • ArtifactID — build config id field, set by build stage per build config
  • Os — target OS, set by archive/nfpm stages per target
  • Arch — target architecture, set by archive/nfpm stages per target
  • Target — full target triple (e.g. x86_64-unknown-linux-gnu), set alongside Os/Arch
  • Checksums — combined checksum file contents, set by checksum stage
Source

pub fn populate_time_vars(&mut self)

Populate time-related template variables.

Sets:

  • Date — UTC time as RFC 3339
  • Timestamp — unix timestamp as string
  • Now — UTC time as RFC 3339
  • Year — 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):

  1. SOURCE_DATE_EPOCH env 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 of metadata.json (which embeds Date) and any user template that consumes Date / Timestamp / Now. Without this branch, two from-clean runs of the same commit emit metadata.json files that differ in the date field, defeating release-asset idempotency.
  2. 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.
Source

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 aliases
  • RustcVersion — host rustc release version (e.g. “1.96.0”), or “” when rustc is unavailable
Source

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.

Source

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 stage
  • extra_file"true" when artifact is an extra file, set by checksum stage
  • extra_name_template — name template override for extra files, set by checksum stage
  • digest — docker image digest (e.g. sha256:abc123...), set by docker stage
  • id — artifact ID from config, set by docker and build stages
  • binary — binary name, set by build stage
Source

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).

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more