Skip to main content

Creating a trigger

A trigger is the object that decides when a pipeline runs. Connecting a repository and committing a .loha.yml is not enough on its own: without a trigger, nothing ever fires.

This guide covers creating one, the webhook behind it, and rotating its secret.

Prefer to ask an agent?

An AI client connected to Loha's MCP server can show you what already exists, which is the fastest way to tell whether a repo is wired up:

  • "List the triggers in my Loha workspace and tell me which repositories have none."

Creating a trigger is dashboard-only for now. Agents can read triggers and run them, but not create them. Using AI with Loha

Create one​

From Triggers → New trigger, or from a repository's Triggers tab.

The first choice is the firing mode, and it changes every field after it:

ModeFires whenUse it for
RepositoryYour Git host sends a webhook for a repo you've connectedNormal CI: build on push, on pull request, on tag
WebhookAny external system calls a URL Loha gives youNightly jobs from a scheduler, deploys from another tool
ManualYou click Run nowOn-demand jobs, one-off deploys

Presets cover the common shapes (push to main, merge requests, release on tag, external system, on demand) and just prefill the fields below, so you can start from one and adjust.

Repository mode​

Pick the event repository. The webhook dialect Loha expects follows from that repo's host, so there's nothing to choose: GitHub, GitLab, and Gitea are each detected, and Forgejo (including Loha Repos) uses Gitea's dialect because it sends Gitea's headers.

Then pick the events:

EventFires on
pushA commit pushed to a branch
pull_requestA pull/merge request opened, updated, reopened, or closed
tagA tag pushed

tag is its own event, not a variant of push.

Branch filters narrow it further. An empty filter means every branch.

Filter here, not in your pipeline

Only the trigger decides whether a build starts. Inside a build, a job or step if: can skip work by branch or event, but it cannot stop the build from being created. For per-branch or per-tag pipelines you can also create separate triggers: one filtered to main running your staging config, another filtered to tags running your production config.

Webhook mode​

No repository, and you choose the provider yourself. Loha gives you a URL and a secret; whatever calls that URL starts a build.

Pick generic unless the caller is a forge sending that forge's signature format.

Schedule mode​

Pick On a schedule, then either click a preset (every hour, every night at 02:00, weekdays at 09:00, every Monday) or type a cron expression. The form shows the next three runs in Thai time. Rules:

  • Five fields (minute hour day-of-month month day-of-week). Three-letter names such as MON, JUL or mon-fri are allowed. @daily-style aliases and the L, W, # extensions are not accepted.
  • As in classic cron, if you restrict both day-of-month and day-of-week, the schedule fires when either matches.
  • Never more often than every 15 minutes; your limit preset may require a longer gap.
  • The number of enabled scheduled triggers per workspace is capped by your preset. Disable one to make room.
  • A repository is optional. With one, the config source can be the committed .loha.yml on the chosen branch; pushes to that repository never fire the trigger.

Skip if there are no new commits. With a repository chosen, you can turn this on to save builds on quiet days. Before each scheduled run, Loha looks at the head of the branch the schedule builds (the trigger's branch, main if none is set) and compares it with the commit of the last scheduled run. If nothing new was committed, that slot is skipped and appears in Trigger activity with the reason No new commits since last scheduled run. A failed scheduled run does not count, so the next slot runs again even with no new commits. If Loha cannot reach your Git host to check, the run happens anyway. The option needs a repository: without one there is no branch to compare, and the switch stays off.

A scheduled trigger can still be run by hand unless you turn off Allow manual run. The trigger page shows Next run and Last scheduled run; every firing, including a skipped one, appears in Trigger activity with its reason. If the schedule can no longer be computed (for example an unparseable cron), the trigger stops firing and its page shows a warning: edit the cron to fix it.

Where the pipeline comes from​

Every trigger has a config source:

  • Repo file: read .loha.yml from the repository at the commit that triggered the run. This is the normal choice: your pipeline is versioned with your code.
  • Inline: the YAML lives on the trigger itself. Useful when the pipeline shouldn't be in the repo, or when the repo isn't yours.

You can also set a resource class on the trigger, which overrides what the config asks for.

The webhook in your Git host​

Loha registers it for you when it can. Creating a repository-mode trigger on GitLab, GitHub, Gitea or Forgejo makes Loha add the webhook to that repository itself, using the access token stored on the repo host. When that works the dialog says so, there is nothing to copy, and the next matching push starts a build.

Whether it can comes down to one thing: the stored token has to be allowed to manage webhooks, which is a wider permission than the read access Loha otherwise needs. See what permissions the token needs. If it isn't, nothing breaks. Loha hands you the URL and secret and you add them by hand, exactly as below.

Triggers that predate this​

A trigger created before Loha registered webhooks, or one whose registration was refused at the time, shows a Register webhook button on its Settings tab. Pressing it does the same thing creating a trigger does, and it is safe to press even if you already added the webhook by hand: Loha looks for a hook already pointing at this trigger and updates that one rather than adding a second. It is also how you retry after widening the token.

Two cases are always manual, by nature:

  • External webhook triggers (generic), where the caller is your own system and there is no API for Loha to register anything against.
  • Any repository on a host Loha has no client for.

Adding it by hand​

Copy the webhook URL and secret from the dialog shown on creation, then add them in your Git host:

HostWhereSecret field
GitHubSettings → Webhooks → Add webhookSecret: signed as X-Hub-Signature-256
GitLabSettings → WebhooksSecret token: sent verbatim as X-Gitlab-Token
Gitea / ForgejoSettings → Webhooks → GiteaSecret: signed as X-Gitea-Signature
Anything else—Generic HMAC in X-Loha-Signature

GitLab is the odd one out: it sends the secret as a token, not as an HMAC of the body. Everything else signs the payload.

Select the events in your host that match the events you chose on the trigger. If they disagree, Loha receives deliveries it ignores.

The secret is shown once

It's revealed on creation and never again. If you lose it, rotate: you can't read it back. When Loha registered the webhook for you the secret is never shown at all: it went straight onto the hook, so there is nothing for you to keep.

Test it​

Push a commit that matches your filter, or use Run now on the trigger. A new build should appear under Builds within a second or two.

If nothing happens, check your Git host's webhook delivery log first: it shows the response Loha returned. A 401 means the secret doesn't match; a 404 means the URL is wrong.

Rotating the secret​

Rotate secret on the trigger's Settings tab issues a new secret.

If Loha registered the webhook, it also pushes the new secret to your Git host, and there is nothing to copy. If that push fails (an unreachable host, a token that has since lost its permission), Loha says so and names the date the trigger will stop firing, and shows you the secret so you can update the host by hand before then. Don't dismiss that one: the rotation has already happened in Loha, so the hook out there is on a clock.

For a webhook you added by hand, the old secret keeps working for 7 days. That overlap exists so you can update your Git host without dropping deliveries: rotate, paste the new secret into the host, and the old one expires on its own. You don't need to do both at the same instant.

Deleting a trigger​

Deleting stops future runs. Builds it already produced stay in your history. If Loha registered the webhook, it is removed from your Git host too, so there's no dead hook left POSTing at a URL that no longer exists.

Following the pipeline file instead​

By default a trigger carries its own event and branch filters, and the on: block in your .loha.yml is not consulted. If you would rather your rules live in one place — in git, travelling with the code — turn on Follow the pipeline file on a trigger whose pipeline comes from a committed file.

In that mode:

  • the on: block of the .loha.yml at the commit that was pushed decides whether a build runs;
  • the event and branch fields on the trigger are replaced by a note pointing at the file;
  • moving a branch rule is a commit, reviewed like any other change.

The trade-off is that every push reaches Loha and is evaluated, so a branch-heavy repository produces more skipped entries on the Activity tab. Filter it by outcome to see only what built.

Switching an existing trigger​

Changing the mode can change which pushes build, so Loha shows you what would change before you save it. Tick or untick Follow the pipeline file on an existing trigger and it replays that trigger's recent events under the new mode:

3 of the last 20 events would have decided differently. A push to feat/cache that built would now be skipped — Branch does not match on.push.branches

If nothing would change, it says so. If it cannot check — the config is unreadable, or the trigger has no recent events — it says that too, rather than implying the switch is unsafe. It never blocks the save; it is there so the change is not a blind toggle.

One limitation, which the preview states itself: it reads your pipeline file once, at the default branch. Follow mode reads it at each pushed commit, so if the on: block changed recently the real result can differ from the forecast.

See also​