The event file

The file a dispatcher hands your pipeline. Read Triggers first for the wiring; this page is the format, and where to find the details of the source you use.

Running as a server? You need none of this. trigger.FromRequest reads a webhook delivery straight off the wire, headers and signature included, with no file and no envelope. See Run it as a server.

Load one

func LoadEvent(path string, providers ...Provider) (*Event, error)
func ReadEvent(r io.Reader, providers ...Provider) (*Event, error)

path is a file, - for standard input, or "" for no event at all.

The empty case is not an error. A pipeline run by hand has no event, and senro.Run given a nil event gates nothing and runs, so ./pipeline builds everything, which is what the local loop wants. A dispatcher that forgets the flag therefore over-runs, which somebody notices, rather than never running, which nobody does.

The format

An envelope naming where the event came from, wrapped around the source’s own payload:

{
  "provider": "github",
  "event": "push",
  "payload": { "ref": "refs/heads/main", "before": "...", "after": "...", "commits": [] }
}

provider and event are both required. None of the four webhook bodies says which event it is (that is the X-GitHub-Event, X-Gitlab-Event, X-Event-Key or X-Gitea-Event header), and guessing from the payload’s shape is how a create gets read as a push.

A shell one-liner for a webhook receiver:

jq -n --arg e "$GITHUB_EVENT_NAME" --slurpfile p body.json \
   '{provider:"github", event:$e, payload:$p[0]}' > event.json

The sources this build reads

providerevent valuesIts own header
githubpush, pull_requestX-GitHub-Event
gitlabpush, tag_push, merge_requestX-Gitlab-Event
bitbucketrepo:push, every pullrequest:*X-Event-Key
giteapush, pull_request, createX-Gitea-Event
senroschedule, manualnone, no webhook behind it

Each page covers what that source sends, what it leaves out, and the traps worth knowing before you rely on a matcher.

None of the five is privileged: all are trigger.Provider values dispatched through the same function yours is. Every one of them translates into senro’s single vocabulary, so Branches always tests a pull request’s target branch and Actions always matches the source’s own action words, untranslated.

A provider of yours may not claim any of those five names. One that shadowed a built-in would make the same event file mean different things in two binaries.

When there is no file list

Paths filters on the changed-file list the event carries. An event whose source supplied no list is an error from Paths, not a no-match:

  • every Bitbucket payload, which never carries one;
  • a GitHub, GitLab or Gitea pull request payload, none of which carries one;
  • a GitLab push over 20 commits, or a Gitea push whose commit list was truncated.

If you fetched the list yourself, supply it through the neutral shape’s files field.

The distinction is load-bearing if you write a provider: nil means “this source did not say”, empty means “it said, and nothing changed”.

Where to go next