Skip to content

Ops Reference

Reference for the *.op.ts file contract: the built-in step builders and retry profiles, how search attributes are emitted, what bounds an ApplyOp delete on each target, and the files chant build generates. For how to define, gate, and run an Op, see Ops.

Pre-built step builders:

BuilderWhat it does
shell(cmd, opts?)Run an arbitrary shell command
build(path)Run chant build
kubectlApply(manifest, opts?)Server-side apply a manifest as chant’s field manager
helmInstall(name, chart, opts?)helm upgrade --install
waitForStack(stackFile, opts?)Poll until a chant stack output file is ready
gitlabPipeline(projectId, ref, opts?)Trigger a GitLab pipeline and wait
lifecycleSnapshot(env, opts?)chant lifecycle snapshot
teardown(path, opts?)Build + destroy

Each step takes an optional profile that controls Temporal retry and timeout settings:

ProfileSuitable for
fastIdempotent (default)Quick, safe-to-retry steps
longInfraSlow infra changes (cluster create, Helm install)
k8sWaitPolling until K8s resources are ready
humanGateSteps that may take hours

Each generated workflow auto-emits upsertSearchAttributes() calls so workflow runs are filterable in the Temporal UI without hand-coded boilerplate. Two emission points:

  1. Initial call at workflow start: OpName plus any searchAttributes you declare on the Op
  2. Per-phase call at the start of each phase (and each onFailure phase): Phase set to the current phase name

Declare custom attributes on the Op:

export default Op({
name: "alb-deploy",
overview: "Deploy ALB stack",
searchAttributes: {
Environment: "staging",
Region: "us-east-1",
},
phases: [
phase("Build", [/* ... */]),
phase("Deploy", [/* ... */]),
],
});

The generated workflow.ts produces:

export async function albDeployWorkflow(): Promise<void> {
upsertSearchAttributes({
OpName: ["alb-deploy"],
Environment: ["staging"],
Region: ["us-east-1"],
});
// Phase: Build
upsertSearchAttributes({ Phase: ["Build"] });
// ...
// Phase: Deploy
upsertSearchAttributes({ Phase: ["Deploy"] });
// ...
}

For an Op with N phases this is N+1 upsert calls total. Values are wrapped as single-element arrays for the classic @temporalio/workflow API.

Registration is separate. Auto-emit assumes the attributes are already registered server-side. Declare them with the SearchAttribute resource so chant build emits the registration commands. See also chant lifecycle for snapshotting registered attributes against a live cluster.

User-provided keys merge over the OpName default; if you set searchAttributes: { OpName: "custom" } the user value wins.

Activity steps support an optional outcomeAttribute field that captures the activity’s return value and surfaces it as a workflow search attribute:

phase("Diff", [
{
kind: "activity",
fn: "lifecycleDiff",
args: { env: "prod", live: true },
// Capture lifecycleDiff's `drifted` field and tag the run Drift=true/false
outcomeAttribute: { name: "Drift", from: "drifted" },
},
]),

The serializer turns this into:

const __r0 = await lifecycleDiff({"env":"prod","live":true});
upsertSearchAttributes({ "Drift": [String(__r0?.drifted)] });

from is a dot-path into the return value; when omitted, the whole return value is stringified. Counters are workflow-scoped (__r0, __r1, …), and parallel phases destructure Promise.all results so each outcome attribute fires after the corresponding activity returns.

delete controls how apply treats resources no longer declared. The delete rides the target’s own delete path, and what bounds that path differs per target:

targetdelete pathwhat bounds it
kubectla sweep filtered by app.kubernetes.io/managed-by=chant (and by the stack when ownership.stack is set), restricted to the namespaces the apply touchedthe ownership marker — an unmarked object is never touched
armpruneArmOrphans, which lists the resource group and deletes only resources carrying chant’s ownership tagthe ownership tag — an untagged resource is never touched
cloudformationthe stack deletes resources removed from its templatethe stack — a resource CloudFormation did not create is not in it

All three are owned-only by construction.

chant build emits three files per Op under dist/ops/<name>/:

FilePurpose
workflow.tsTemporal workflow function — phases, gates, onFailure
activities.tsRe-exports all pre-built activity implementations
worker.tsWorker bootstrap — reads profile from chant.config.js

See Ops for how to define, gate, and run an Op.