pub enum StepKind {
Subprocess,
BuildImage,
PackageNativeTarball,
MuslStaticPreflight,
SignNativeTarball,
SubPipeline,
GhaWorkflow,
Import,
WaitFor,
ManifestStitch,
}Expand description
What a pipeline step does.
On the TOML side this is kind = "subprocess" | "build-image". The default
— and the value omitted from every existing pipeline file — is
StepKind::Subprocess.
Variants§
Subprocess
Run argv (the existing semantics).
BuildImage
Build a container image from the catalog (R381). The image is looked
up by image (catalog name); the runner materialises a
task::ForgeCommand::BuildImage from the catalog entry.
PackageNativeTarball
Package a static musl Rust binary + workload-spec manifest into a
.tar.gz for the native runtime under Kamaji (R407-T2, W154).
Catalog entry referenced by image must declare
ProduceTarget::NativeTarball;
binary_path points at the cross-compiled binary an earlier step
produced. No systemd unit is emitted — Kamaji directly
fork+exec+cgroup+pidfd-supervises the binary at deploy time.
MuslStaticPreflight
Gate a workspace member against
crate::preflight::KNOWN_GLIBC_ONLY_CRATES (R407-T3, W154). Walks
the package’s transitive dep closure via cargo metadata; fails if
any glibc-only crate appears. Routes the pipeline author to the
container fallback (runtime = "container") with a clear,
actionable error rather than dying mid-cross-build with a linker
error. Pure host file I/O — no remote variant.
SignNativeTarball
Sign a native tarball produced by an earlier
StepKind::PackageNativeTarball step (R407-T5, W154). Extends the
Sigstore keyless-OIDC trust model already used for OCI images to the
native-tarball artifact shape via cosign sign-blob. The step
resolves the on-disk tarball path the same way packaging writes it
(<camp_root>/.yah/cache/native/<image>-<triple>.tar.gz) and emits
<tarball>.sig, <tarball>.crt, and <tarball>.bundle next to it.
Catalog entry referenced by image must declare
ProduceTarget::NativeTarball.
Pure host file I/O — runs Native even on Remote runners.
SubPipeline
Invoke another pipeline as a child of this step (W201). Resolution
target + propagation rules live on QedStep::sub_pipeline. The
runner runs the resolved child as a nested [QedRun] parented to the
caller, then aggregates ProducedArtifacts and named outputs per
SubPipelineCollect. Has no argv / runtime of its own — runtime
is whichever the child resolves to.
GhaWorkflow
Run a .github/workflows/*.yml through the native W200 GHA runtime
(W200-F9). Step config lives on QedStep::gha_workflow; the runner
dispatches to yah_qed_gha::execute_workflow, then lifts each
yah_qed_gha::ProducedArtifact into ProducedArtifact and aggregates
into the parent’s Outcome::Publish — same surface as a producing
Subprocess step or a SubPipeline child with propagate.produces.
Import
Import a .github/workflows/*.yml as a QED source and expand it into
the native subgraph at plan time (W224 “import, don’t emulate”;
R533-F1). Step config lives on QedStep::import: the source path, a
blake3 content hash pinning that source, and a materialize toggle.
Unlike StepKind::GhaWorkflow — which treats the YAML as a foreign
runtime to execute as one black-box step — Import treats it as an
interchange format. The expansion is virtual by default
(recomputed at plan time, never persisted ⇒ zero drift by
construction); the pinned hash is the guardrail that detects a drifted
source. The expansion logic lives in crate::import; F1’s expansion
delegates to the recast W200 GHA front-end, and R533-F4 swaps in the
mechanical tier-1/2 → native map.
WaitFor
Block until a network endpoint becomes reachable, then advance (R513-F3,
W207 Gap #5). The classic case is a health-gate between a background
sidecar (yah-camp, vite preview) and the step that talks to it: poll
the server’s /health until it answers, so the consumer step never races
a not-yet-listening port. Config (the target + timeout/interval) lives on
QedStep::wait_for; the step runs no argv of its own and produces
nothing — it is a pure gate. validate() rejects argv and a missing
[wait_for] block the same way StepKind::SubPipeline does.
ManifestStitch
Stitch N per-arch images (already pushed by earlier build-image steps
routed to arch-matched build-workers) into one multi-arch manifest list
(R590-F2). Config lives on QedStep::manifest_stitch: the arch-agnostic
target tag consumers pull, and the arch-specific sources to fold in.
The step shells docker buildx imagetools create — a registry-only
operation, so it runs host-native even under --where=remote (the fleet
does the builds; the stitch runs where qed runs). No argv of its own;
validate() rejects argv and requires a [manifest_stitch] block with
a target + at least one source.
Trait Implementations§
impl Copy for StepKind
Source§impl<'de> Deserialize<'de> for StepKind
impl<'de> Deserialize<'de> for StepKind
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for StepKind
impl StructuralPartialEq for StepKind
Auto Trait Implementations§
impl Freeze for StepKind
impl RefUnwindSafe for StepKind
impl Send for StepKind
impl Sync for StepKind
impl Unpin for StepKind
impl UnsafeUnpin for StepKind
impl UnwindSafe for StepKind
Blanket Implementations§
impl<T> Allocation for T
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
impl<T> Fruit for T
impl<A, B, T> HttpServerConnExec<A, B> for Twhere
B: Body,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more