First Lume Docs firstlume.io ENPT PT Talk to us

Git triggers

A push on a stack's branch can start its run by itself. Triggers are off by default, so nothing changes until someone turns them on. Turning one on doesn't start a run either: it counts from the next push.

This works today with Gitea, for stacks created from the organization's Git connection. A stack that clones with its own token can't use it.

Whoever can push runs code. With the trigger on, anyone who can write to the branch runs code with the stack's credentials, already at the plan, before any approval. Protect the branch in Gitea.

Set it up

Generating the secret and creating the webhook are manual steps for now. Installing the webhook from the UI is planned.

1. Generate the webhook secret

curl -X POST -H "Authorization: Bearer $TOKEN" \
  https://firstlume.example.com/api/v1/orgs/{org}/git/webhook-secret

The response has what the webhook needs:

{
  "url": "https://firstlume.example.com/webhooks/v1/gitea/<connection-id>",
  "secret": "flw_...",
  "content_type": "json",
  "events": ["push", "pull_request", "pull_request_sync"]
}
  • The secret appears only in this response, and it serves every repository of the connection.
  • Calling this again replaces the secret. Webhooks signing with the old one are refused until you update them.
  • The URL comes from FIRSTLUME_PUBLIC_URL (controlPlane.publicURL in Helm).
  • An organization with no Git connection gets a 404.

2. Create the webhook in Gitea

In each repository, create a webhook of type gitea with that URL and secret, content_type json and the events push, pull_request and pull_request_sync. It takes admin rights on the repository. With Gitea's API:

curl -X POST -H "Authorization: token $GITEA_TOKEN" -H "Content-Type: application/json" \
  https://gitea.example.com/api/v1/repos/{owner}/{repo}/hooks -d '{
    "type": "gitea",
    "active": true,
    "events": ["push", "pull_request", "pull_request_sync"],
    "config": {"url": "<url>", "secret": "<secret>", "content_type": "json"}
  }'

Only push starts runs today. Pull request events are accepted and ignored, until plan on pull request exists.

Gitea refuses private addresses by default, and the delivery fails with webhook can only call allowed HTTP servers. On an internal installation, allow First Lume's host in Gitea's app.ini and restart Gitea:

[webhook]
ALLOWED_HOST_LIST = firstlume.example.com

3. Turn it on

Set On push in the settings of the organization, a folder or the stack. It is inherited like the other settings. In the API, it is git_on_push:

curl -s -X PUT -H "$H" $O/folders/$F/settings -d '{"git_on_push": "plan"}'

A PUT replaces what the level defines. Send the level's other settings and variables along with it.

Value A push that affects the stack...
off (default) does nothing
plan creates a plan run, which never applies
apply creates an apply run, which waits for approval if require_approval is on, and applies by itself if it isn't

With apply and approval on, approving applies exactly the pushed commit. With approval off, nobody reviews the plan before it changes the infrastructure. A merge is also a push on the branch, so it counts. A trigger never creates a destroy run.

4. Check it

Push a commit and open Git events. The push appears there, with the decision for each stack.

What counts as affected

A stack is affected when a file changes inside its path. With path at the root, every file counts.

Modules outside the path only count if they are declared in .firstlume/config.yaml, with paths relative to the repository's root:

triggers:
  paths:              # also affected when these change
    - modules/**
    - root.hcl
  ignore:             # doesn't count when only these changed
    - "**/*.md"

A module that isn't declared starts no run, and its change stays unapplied. A drift check will show the difference.

When there is no way to tell what changed, every stack on the branch counts as affected: a force push, a new branch, or a comparison of the commits that fails or comes back incomplete. A config.yaml that is invalid or can't be read at that commit makes its stack count too, so the run fails and shows why. Running too much ends in no_changes, while running too little would leave a change unapplied.

Pushes to other branches, tags and deleted branches start nothing.

A newer push replaces what is old

A run is tied to the commit of its push, and each push creates at most one run per stack, even if Gitea delivers it twice. When a newer push reaches the branch:

  • runs of earlier pushes still in the queue are canceled
  • runs of earlier pushes awaiting approval are discarded, with the message superseded by <commit>
  • a run that is already executing finishes, and the new one waits in the queue

Runs started by a person are never touched.

Why didn't it run?

The stack's Runs tab shows when the last push started nothing, and why. The Git events page, in the Git connection section of the organization's settings, shows each push received and the decision for each stack. Through the API:

curl -s -H "$H" "$O/git/events?stack=$ST"
Decision Meaning
run_created a run started
not_affected no file counts for this stack; the event lists the files considered
trigger_off On push is off
other_branch the stack follows another branch
duplicate this push already had a run

Events are kept for 30 days.

If On push is on and no event ever arrives, the settings and the stack say Nothing received. Check these, starting with the webhook's recent deliveries in Gitea:

  • ALLOWED_HOST_LIST, as in step 2
  • whether the secret was replaced after the webhook was created: a wrong signature gets a 401 and leaves no event
  • whether the repository belongs to the connection's account: pushes from any other are ignored and leave no event

What the run shows

A run started by a push says who pushed, the commit and, when the commit came from a pull request, a link to it. See Runs and approval for the rest of its life, which is the same as any other run.

Planned

These are not built yet:

  • Plan on pull request, with a comment and a status in Gitea
  • Commit status in Gitea for runs started by a push
  • Installing the webhook from the UI
  • A sweep every 5 minutes, to catch pushes whose webhook was lost
  • GitHub and GitLab