Triggers

Run on pushes, pull requests, schedules, comments, labels, or by hand.

A workflow's on array declares what starts it. Triggers are functions with typed options, so a misspelled filter is a compile error, not a workflow that silently never fires.

Push

on.push({ branches: ["main"], tags: ["v*"], paths: ["src/**"] })

All filters are optional; a bare on.push() fires on every push. paths scopes the trigger to commits touching matching files, which keeps docs-only changes from burning CI minutes.

Pull request

on.pullRequest({ branches: ["main"], actions: ["opened", "updated"] })

Actions cover opened, updated, reopened, and ready_for_review, so you can run the expensive suite only when a draft graduates. The run's ctx.pr carries the pull request, ready for the body to comment on.

Schedule

on.schedule("0 3 * * *")

Standard cron. Nightly builds, dependency checks, report generation.

Manual

on.manual()

Adds a run button on the CI page, for workflows that should only happen on purpose: deploys, data migrations, release cuts.

Comment commands

on.comment("deploy-preview")

Fires when someone writes /deploy-preview in the PR or issue conversation. The triggering entity arrives in ctx, so the workflow knows which PR asked. This is how you build the "type a command in the thread" automations other platforms need a bot framework for.

Issue labeled

on.issueLabeled("needs-repro")

Fires when the label is added to an issue. Combined with the substrate context, it turns labels into automation hooks: label an issue needs-repro and a workflow can spin up the reproduction environment and comment the link.