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.