Skip to main content

Triggers

A trigger is an object in your workspace that starts pipelines. It is not declared in .loha.yml.

You usually do not create one by hand: when you connect a repository that already has a committed .loha.yml, Loha creates a trigger for it and registers the webhook. You create one manually when you want a second trigger on the same repository, an inline pipeline, or a manual-only entry point.

To create and configure one, see Creating a trigger. This page explains what a trigger is.

The three types​

TypeStarted by
WebhookAn HTTP call to a URL Loha generates, normally from your Git host
ManualYou, via Run now or the API
ScheduleA cron expression, in Thai time

A schedule trigger fires on a cron expression in Thai time (Asia/Bangkok), never more often than every 15 minutes. Nothing in your repository needs to change. The run reads the pipeline from the trigger's config source (inline, or the committed .loha.yml on the trigger's branch) and is attributed to the trigger's service account when one is assigned. Scheduled triggers are rolled out per workspace; ask your Loha contact if the option is not shown.

A webhook trigger listens for one or more events: push, pull_request, or tag. It can also carry branch filters.

A trigger also has a config source: where its pipeline definition comes from. It can be inlined on the trigger, or read from a .loha.yml committed in the repository.

Who decides whether a push builds​

Every trigger is in one of two modes, and the mode decides which rules apply.

ModeWhat decides
Trigger filters (default)The trigger's own event list and branch filters. on: in your config is ignored.
Follow the pipeline fileThe on: block of the .loha.yml at the commit that was pushed.

Switching an existing trigger between modes shows you what would change first — see Creating a trigger.

Follow mode is available on triggers whose pipeline comes from a committed file — there is nothing to follow otherwise. Turn it on with Follow the pipeline file on the trigger form; the branch and event fields are then replaced by a note pointing at the file, because your rules live in one place, not two.

Which mode am I in?

Open the trigger. If you can edit event and branch filters, you are in trigger-filter mode and on: is not consulted. If you see "which events build is decided by the on: block in .loha.yml", you are following the file.

In trigger-filter mode, tightening on: changes nothing

This is the single most common misunderstanding. Tightening on: push: branches: [main] will not stop builds on other branches while the trigger is in the default mode. Either set the branch filter on the trigger, or switch the trigger to follow the file.

Skipped events and required checks​

When a push does not match — in either mode — Loha records the event and the reason, and posts no status to your Git host. You can see every inbound event and why it did or did not build on the repository's Activity tab.

Do not mark loha/ci a required status check on a repo whose events can be skipped

A skipped event posts nothing, so a required loha/ci check waits forever: GitHub shows "Expected — waiting for status to be reported" and the pull request cannot merge. There is no status value that means "deliberately not run" — the provider APIs have none — so the only safe combination is: mark the check required only where every pull request is guaranteed to build.

The on: block​

on: is required in every .loha.yml. In follow mode it is what decides whether an event builds. In the default trigger-filter mode it records which events the pipeline is written for and is used by the dashboard editor, but it does not gate execution — see the table above. Either way the fields must be written correctly for the config to parse.

Push​

on:
push:
branches: [main, release/*]

You can also filter by changed paths and tags:

on:
push:
branches: [main]
paths:
- 'src/**'
- 'package.json'
paths_ignore:
- 'docs/**'
tags:
- 'v*.*.*'

If paths: is set, the pipeline runs only when at least one matching file changed in the push. Documentation-only changes won't burn build minutes on a full test suite.

Available context: the commit SHA, branch name, commit message, and author. See .loha.yml schema for the full list.

Pull request​

Fires on pull request lifecycle events: opened, synchronize (new commits pushed), reopened. Useful for lint, type-check, and test gates that block merging until they pass.

on:
pull_request:
branches: [main]
paths:
- 'src/**'

branches: here filters by the target branch: the branch the PR wants to merge into.

A pull-request build runs against the merge-result tree by default, what main will look like after the PR merges, so you catch conflicts early. If you need the head commit instead, set checkout: head.

Available context: PR number, source branch, target branch, head SHA, base SHA, PR title, author.

Pull requests from forks

For security, pull-request builds from forks do not receive secrets or the trigger's service-account token (LOHA_TOKEN). Otherwise a fork PR could exfiltrate them by running echo $TOKEN. A step that lists secrets: still runs, without them, and the build shows a warning.

A fork PR build also cannot run free-form commands: run: steps and the command-running tasks loha/run-command, loha/run-tests, loha/run-lint and loha/type-check fail the build with UNTRUSTED_CONTEXT. Other official tasks run, with fewer capabilities: no stored secrets, no LOHA_TOKEN, no image push (image-build tasks build without pushing, and the build warns per step), no cache (cache steps do nothing), git credentials only for cloning the pull request's own repository without submodules, and a stricter network policy for the build pods. A loha/git-clone step that clones any other repository fails the build, and a task that would write to a repository, such as loha/git-update-manifest, gets no git credentials (the build warns per step). Retrying such a build keeps the same limits. A pull request whose source repository Loha cannot identify is treated as a fork.

Manual dispatch​

Run a pipeline on demand from the dashboard's Run now button or via the API. Useful for releases, one-off deploys, or rerunning against a specific branch. In the product this is a trigger of type manual.

on:
workflow_dispatch: true

workflow_dispatch is a boolean toggle: set it to true to make the pipeline manually runnable. Custom input parameters are not supported in V1; pass environment-specific values with trigger-scoped variables instead.

Run from the terminal

Manual runs can also be fired from the Loha CLI with loha deploy --repo <id> --trigger <id> (or via POST /api/v1/triggers/{id}/run). The CLI is coming soon; the API is live today.

Combining events​

A config can name more than one event. A common pattern:

on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch: true

To actually get all three behaviours you need the matching triggers: a webhook trigger with push and pull_request selected, plus a manual trigger for emergency runs.

Who a run is attributed to​

Every run records exactly one actor, never two:

  • Manual dispatch is attributed to the user who clicked Run (or whose token called the API).
  • Automatic runs (a webhook event, or a scheduled run once cron ships) have no person behind them. By default they're recorded as a system action. If the trigger has a service account assigned, the run is attributed to that service account instead, so "who deployed this?" has a real answer in the audit log even when the cause was a push, not a person.

Service-account triggers​

A webhook or scheduled trigger can be backed by a workspace service account. This does two things:

  • Attribution: automatic runs are owned by the service account by name, not left anonymous.
  • Token injection (optional): when enabled on the trigger, each run is given a short-lived, run-bound credential as the LOHA_TOKEN environment variable, so the build's own steps can call the API (for example, to deploy a downstream repo). The token is ephemeral (it expires shortly after the run and is revoked when the run finishes) and is scoped no wider than the service account's own scopes.

Disabling the service account is a kill-switch: runs from its triggers are rejected immediately, and any key it owns stops working.

Scheduled pipelines​

Create a trigger in Schedule mode and give it a five-field cron expression. Loha evaluates it in Asia/Bangkok and shows the next three runs before you save. A schedule trigger may optionally have a repository; with one, the config source can be the committed .loha.yml on the chosen branch. Pushes to that repository never fire a schedule trigger; only the clock does.

A schedule with a repository can skip runs when nothing changed: if the head of its branch still matches the last scheduled run's commit, that slot is skipped and logged in Trigger activity (a failed run never counts, and if the Git host can't be reached the run goes ahead). See Schedule mode.

If the platform was unavailable when a run was due, it fires once when it comes back and then resumes the normal cadence; missed slots are not replayed. If a schedule can no longer be computed (for example an unparseable cron), it stops firing and the trigger page shows a warning telling you to edit the cron. The per-workspace cap on scheduled triggers and the minimum interval are part of your limit preset.

Where to go next​