Workflow API

The CI workflow API: defineWorkflow, triggers, helpers, and the run context.

Everything importable from @plainalpha/ci in a .plain/workflows file. For the guided introduction, start with Workflows.

defineWorkflow

defineWorkflow(name: string, {
  on: Trigger[],
  run: async ({ ctx }) => void,
  network?: { allow: string[] },
  concurrency?: { group: string; cancelInProgress?: boolean },
  timeoutMs?: number,
});

Registration is by call, so one file can define several workflows; identity is the name, not the filename.

Triggers

on.push({ branches?: string[], tags?: string[], paths?: string[] })
on.pullRequest({ branches?: string[], paths?: string[],
                 actions?: ("opened"|"updated"|"reopened"|"ready_for_review")[] })
on.schedule(cron: string)
on.manual()
on.comment(command: string)        // "/command" in a PR or issue conversation
on.issueLabeled(label: string)

Details and examples: Triggers.

Shell helpers

await sh(command, { cwd?, env?, allowFailure? })  // streamed to the run log
await pm.install()                                // pnpm/npm/yarn/bun by lockfile
await pm.run(script)
await pm.exec(bin, args)
await git.clone(...); await git.checkout(...); await git.commit(...)

sh rejects on a non-zero exit unless allowFailure: true, in which case it resolves with the exit code for you to inspect.

Secrets, env, and artifacts

secret.get(name)   // decrypted CI secret; throws if missing
secret.has(name)
env.get(name)      // base environment
await ctx.artifact.write(name, data)   // run-scoped storage
await ctx.artifact.read(name)

See Secrets and environment for where secrets are managed and how redaction works.

The run context

run receives { ctx }:

FieldContents
ctx.orgOrganisation id and slug
ctx.gitref, branch, sha, and baseRef on PR runs
ctx.triggerThe event that started the run
ctx.pr, ctx.issue, ctx.commitThe triggering entity, when there is one
ctx.issues, ctx.comments, ctx.docs, ctx.labels, ctx.relationsWrite surfaces into the platform
ctx.artifactRun-scoped artifact storage

The write surfaces are what make workflows more than build scripts: a run can file the issue it found, comment on the PR that triggered it, or update a doc, with the run as the attributed author.

AI in workflows

const answer = await ai.chat(prompt);

ai.chat gives a run model access for steps like summarising a diff or drafting a changelog entry. Hosted runs meter it against the organisation's AI budget; locally it explains what to configure.