Githome
Actions: Events that trigger workflows
Docs / Actions

Events that trigger workflows

Every event that can start a Githome workflow, its activity types and filters, the commit and ref it runs on, and its github.event payload.

Note: The forge CI of git.pkgforge.dev is dormant. githome reads and validates workflow files, but an event starts no run, and a dispatch is refused with "CI is off on this deployment". This page is the reference for a deployment that turns the CI on.

The on: section of a workflow says which events start it. Githome supports the GitHub Actions events that matter for CI and automation: pushes, pull requests, merge queue groups, manual dispatch, schedules, other workflows' runs, published releases, external repository_dispatch events, reusable workflow calls, and the activity of the repository: issues and their comments, reviews and review comments, branches and tags created or deleted, labels, stars, commit statuses, deployments and check runs. This page lists each one with its activity types, filters, the GITHUB_SHA and GITHUB_REF its runs get, and its github.event payload.

Supported events

EventFires whenActivity typesFilters
pushA branch or tag is created or updatedbranches, branches-ignore, tags, tags-ignore, paths, paths-ignore
pull_requestA pull request is opened, updated, edited, reopened, closed, marked ready for review or converted to a draftopened, synchronize, reopened, closed, edited, ready_for_review, converted_to_drafttypes, branches, branches-ignore, paths, paths-ignore
pull_request_targetSame as pull_request, but runs the base branch's workflowSame as pull_requestSame as pull_request
merge_groupThe merge queue builds a merge groupchecks_requestedtypes, branches, branches-ignore
workflow_dispatchSomeone starts the workflow from the UI, CLI, API or MCPinputs
scheduleA cron schedule is duecron
workflow_runA run of another named workflow is requested or completesrequested, completedworkflows, types, branches, branches-ignore
releaseA release is published, unpublished, edited or deletedpublished, unpublished, created, edited, deleted, prereleased, releasedtypes
repository_dispatchSomeone calls POST /repos/{owner}/{repo}/dispatchesAny event_type you choosetypes
workflow_callAnother workflow calls this one as a reusable workflowinputs, outputs, secrets
issuesAn issue is opened, edited, closed, reopened, assigned, labeled, locked or given a milestoneopened, edited, closed, reopened, assigned, unassigned, labeled, unlabeled, locked, unlocked, milestoned, demilestonedtypes
issue_commentA comment on an issue or a pull request is created, edited or deletedcreated, edited, deletedtypes
pull_request_reviewA review is submitted or dismissedsubmitted, dismissedtypes
pull_request_review_commentA comment on the diff of a pull request is created, edited or deletedcreated, edited, deletedtypes
createA branch or tag is created
deleteA branch or tag is deleted
labelA label of the repository is created, edited or deletedcreated, edited, deletedtypes
watchSomeone stars the repositorystartedtypes
statusA commit status is created
deploymentA deployment is created
deployment_statusA deployment status is created
check_runA check run is created or completed over the APIcreated, completedtypes
check_suiteEvery check run of an app on a commit has completedcompletedtypes

Without types, a workflow runs for every activity type that Githome sends for its event (pull_request, pull_request_target and merge_group have their own defaults, given in their sections).

Other GitHub events

The other GitHub event names (discussion, discussion_comment, fork, gollum, milestone, page_build, project, project_card, project_column, public, registry_package and branch_protection_rule) are accepted in on: without an error or warning, so workflows that list them still parse, but Githome never starts a run for them. A name that isn't a GitHub event at all gives the warning unknown event '<name>' in githome workflow validate.

Writing on

on: push                          # one event, no configuration
on: [push, pull_request]          # several events, no configuration
on:                               # events with configuration
  push:
    branches: [main]
    tags: ["v*"]
  pull_request:
    types: [opened, synchronize, reopened, closed]
    paths: ["src/**"]
  workflow_dispatch:

An event's configuration must be a mapping (on.<event> must be a mapping), except schedule, which is a list. Each workflow file whose on: matches an event gets one run for it.

Filter patterns

Branch, tag and path filters use GitHub's filter pattern syntax:

PatternMatches
*Any characters except /. feature/* matches feature/login but not feature/a/b.
**Any characters, including /. feature/** matches feature/a/b.
**/ at the startAny directories, or none. **/README.md matches README.md and docs/README.md.
?Zero or one of the preceding character. v1? matches v and v1.
+One or more of the preceding character. v1+ matches v1 and v111.
[abc], [0-9]One character from the set or range.
\Escapes the next character, for example \* for a literal *.
!patternIn a list, excludes what earlier patterns matched.

Patterns match the whole name: a branch name without refs/heads/, a tag name without refs/tags/, or a file path relative to the repository root. Quote patterns that start with *, ! or [ in YAML.

A list is read in order, and the last pattern that matches decides: a value is included when it matches a positive pattern and no later ! pattern excludes it. A ! pattern can only exclude what an earlier pattern included, so a list of only ! patterns matches nothing.

on:
  push:
    branches:
      - "releases/**"
      - "!releases/**-alpha"

This runs for releases/10 and releases/beta/mona, but not releases/10-alpha.

Include and ignore filters

  • branches runs the workflow only for matching branches; branches-ignore runs it for every branch except matching ones. The same goes for tags and tags-ignore, and paths and paths-ignore.
  • You can't use a filter and its -ignore form for the same event. The file fails with 'branches' and 'branches-ignore' cannot be used together for the same event (or the same message for tags or paths). Use ! patterns in the positive form instead.

Path filters

  • With paths, the workflow runs when at least one changed file matches the list.
  • With paths-ignore, the workflow runs unless every changed file matches the list.
  • For a push, the changed files are the difference between the commit before the push and the pushed commit. When the push creates a new branch, or the previous commit isn't known, Githome can't compute the change and path filters pass. (GitHub compares a new branch with the default branch instead.)
  • For a pull request, the changed files are those the pull request changes, compared with the merge base of the head and the base branch. When a merged pull request is closed, path filters pass.
  • Path filters are never evaluated for tag pushes.
  • When branch or tag filters and path filters are both set, both must pass.

push

Runs when you push to a branch or tag, including pushes that create a branch or tag, force pushes, pushes by agents, and merges made through the web UI, CLI, API or merge queue. Deleting a branch or tag doesn't start push runs; it sends delete.

on:
  push:
    branches: [main, "release/**"]
    tags: ["v*.*.*"]
    paths-ignore: ["docs/**", "**.md"]

How branches and tags combine, as on GitHub:

Filters setBranch pushesTag pushes
NoneRunRun
Only branches or branches-ignoreRun when the branch matchesDon't run
Only tags or tags-ignoreDon't runRun when the tag matches
Both kindsRun when the branch matchesRun when the tag matches
Only paths or paths-ignoreRun when the paths matchRun (paths aren't checked for tags)

The workflow file is read from the pushed commit, so a push that changes a workflow runs the new version.

When a merge queue builds a merge group, it pushes a branch named gh-readonly-queue/<base>/pr-<n>-<head sha>, and push workflows run on it as on GitHub. Add branches-ignore: ["gh-readonly-queue/**"] (or list only the branches you want) to avoid running twice.

VariableValue
GITHUB_SHAThe pushed commit
GITHUB_REFThe pushed ref, refs/heads/<branch> or refs/tags/<tag>

Payload (github.event):

FieldValue
refThe pushed ref
beforeThe commit the ref pointed to before the push (0000000000000000000000000000000000000000 for a new ref)
afterThe pushed commit
created, deleted, forcedWhether the push created the ref, deleted it (always false for runs) or was a force push
head_commitid, message, timestamp (committer time) and author (name, email) of the pushed commit
commitsA list with the pushed commit only (id, message). GitHub lists up to 20 commits.
pushername: the login of the account that pushed, and email: null
senderSee The sender object
repositorySee The repository object

pull_request

Runs for activity on a pull request, using the workflow and code of the pull request's test merge commit: the head branch merged into the current base branch, as on GitHub.

on:
  pull_request:
    types: [opened, synchronize, reopened]
    branches: [main]
    paths: ["src/**", "package.json"]
TypeFires when
openedA pull request is created (drafts included)
synchronizeNew commits are pushed to the head branch
reopenedA closed pull request is reopened
closedA pull request is closed or merged. Check github.event.pull_request.merged to tell them apart.
editedThe title or description changed. Not for label changes, and not when the text saved is the same.
ready_for_reviewA draft is marked ready for review: Ready for review in the web UI, githome pr ready, or PATCH /repos/{owner}/{repo}/pulls/{number} with "draft": false
converted_to_draftAn open pull request is turned back into a draft: githome pr ready --undo, or PATCH with "draft": true

Without types, the workflow runs for opened, synchronize and reopened, as on GitHub. GitHub's other types (labeled, assigned, review_requested, locked and so on) are accepted in types but never fire on Githome.

A common use is to skip expensive jobs while a pull request is a draft and run them once it's ready:

on:
  pull_request:
    types: [opened, synchronize, reopened, ready_for_review]
jobs:
  e2e:
    if: ${{ !github.event.pull_request.draft }}
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npm run e2e

For edited, the payload has no changes object with the old title or body (GitHub sends one).

branches and branches-ignore filter on the pull request's base branch.

  • The run checks out and runs refs/pull/<n>/merge. You can fetch that ref and refs/pull/<n>/head with git, but not push to them.
  • While a pull request conflicts with its base, there is no test merge commit and its pull_request workflows don't run. pull_request_target workflows still do.
  • For closed on a merged pull request, the run uses the merge commit instead.
  • The run's checks are reported on the pull request's head commit, so they appear on the pull request.
  • Every pull request comes from a branch of the same repository, so pull_request runs get the repository's secrets, like push runs.
VariableValue
GITHUB_SHAThe test merge commit (for a merged pull request's closed event, the merge commit)
GITHUB_REFrefs/pull/<n>/merge
GITHUB_REF_NAME<n>/merge
GITHUB_HEAD_REFThe head branch
GITHUB_BASE_REFThe base branch

Payload (github.event):

FieldValue
actionThe activity type
numberThe pull request number
pull_request.number, pull_request.idThe pull request number (both)
pull_request.node_idAn opaque ID
pull_request.stateopen or closed
pull_request.lockedfalse
pull_request.title, pull_request.bodyTitle and description
pull_request.draft, pull_request.mergedBooleans
pull_request.merged_atWhen it merged, or null
pull_request.merged_by{ "login": ... } or null
pull_request.merge_commit_shaThe merge commit once merged, otherwise the test merge commit (or null while it conflicts)
pull_request.userThe author, as a user object (see The sender object)
pull_request.labels[{ "name": ... }]
pull_request.assignees[{ "login": ... }]
pull_request.requested_reviewers[]
pull_request.author_associationMEMBER
pull_request.headlabel (<owner>:<branch>), ref (branch), sha (head commit), user (the repository owner) and repo (a repository object)
pull_request.baseThe same fields for the base branch
pull_request.html_urlhttps://git.pkgforge.dev/acme/website/pull/<n>
pull_request.urlhttps://git.pkgforge.dev/api/v3/repos/acme/website/pulls/<n>
pull_request.diff_url, pull_request.patch_urlhttps://git.pkgforge.dev/acme/website/pull/<n>.diff and .patch
pull_request.issue_url, pull_request.commits_url, pull_request.review_comments_url, pull_request.comments_urlAPI URLs, as on GitHub
repositorySee The repository object
organizationFor repositories owned by an organization; see The repository object
senderWhoever caused the event; see The sender object

pull_request_target

Same activity types, filters and payload as pull_request, but the run uses the base branch's own workflow file and code: the base branch's current commit. A pull request therefore can't change what runs with the repository's secrets. Check out the pull request's code (for example with ref: ${{ github.event.pull_request.head.sha }}) only if you trust it.

on:
  pull_request_target:
    types: [opened, reopened]
jobs:
  welcome:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Thanks for pull request #${{ github.event.number }}, ${{ github.event.pull_request.user.login }}"

Unlike pull_request, it also runs while the pull request conflicts with its base. Checks are reported on the pull request's head commit.

VariableValue
GITHUB_SHAThe base branch's current commit
GITHUB_REFrefs/heads/<base branch>
GITHUB_HEAD_REF, GITHUB_BASE_REFThe head and base branches

merge_group

Runs when the merge queue builds a merge group for a pull request: a commit holding the base branch, every pull request ahead in the queue, and this pull request's changes. The queue merges the pull request once the group's required checks pass. See Merge queue.

on:
  pull_request:
  merge_group:
    types: [checks_requested]
    branches: [main]
  • The only activity type is checks_requested, which is also the default.
  • branches and branches-ignore filter on the queue's base branch.
  • The queue reads the required checks from the merge group commit, so the workflows that produce them must run on it: list merge_group next to pull_request. (A push workflow without branch filters also runs there.) If a required check never reports, the pull request leaves the queue when the queue's check timeout expires.
  • push workflows also run on the merge group branch; see push.
  • A merge group commit with an invalid workflow file gets an Invalid workflow file run, like a push.
VariableValue
GITHUB_SHAThe merge group commit
GITHUB_REFrefs/heads/gh-readonly-queue/<base>/pr-<n>-<head sha>

Payload (github.event):

FieldValue
actionchecks_requested
merge_group.head_shaThe merge group commit
merge_group.head_refThe merge group ref
merge_group.base_shaThe commit the group was built on
merge_group.base_refrefs/heads/<base>
merge_group.head_commitid, tree_id, message, timestamp, author and committer (name, email)
repository, senderAs for other events

The run's title is Merge group for #<n>: <pull request title>.

workflow_dispatch

Lets people and agents with write access start the workflow on demand, on a branch or tag they choose, with typed inputs. How to start a run from the web UI, the CLI, the API and MCP is in Actions overview.

on:
  workflow_dispatch:
    inputs:
      environment:
        description: Target environment
        type: choice
        options: [staging, production]
        default: staging
      version:
        description: Version to deploy
        required: true
      replicas:
        type: number
        default: 2
      dry-run:
        type: boolean
        default: false
      target:
        type: environment

Each input can have:

KeyMeaning
descriptionLabel in the Run workflow form (the input's name is shown under it).
requiredtrue makes the input mandatory: an empty or missing value without a default is rejected with input '<name>' is required. Must be a boolean.
defaultUsed when no value is given.
typestring (the default), boolean, number, choice or environment. Another value fails with input '<name>': invalid type '<type>' (expected one of string, boolean, number, choice, environment).
optionsFor choice: the allowed values. A choice input without options fails with input '<name>' of type 'choice' must define 'options'. A value outside the list is rejected with input '<name>' must be one of <options>.
deprecationMessageAccepted and ignored.

Values are converted by type: boolean inputs become true when the value is true or "true" and false otherwise; number inputs become numbers; string, choice and environment inputs stay as given. Values for inputs the workflow doesn't declare are dropped. An environment input is a plain text field in the Run workflow form, and its value isn't checked against the repository's environments.

Read inputs with the inputs context (${{ inputs.version }}). github.event.inputs holds the same values with the same types; on GitHub, github.event.inputs values are always strings.

The workflow must exist and have a workflow_dispatch trigger at the chosen ref. A ref given without refs/ is a branch if a branch with that name exists, and a tag otherwise.

VariableValue
GITHUB_SHAThe latest commit of the chosen ref
GITHUB_REFrefs/heads/<branch> or refs/tags/<tag>

Payload (github.event): inputs, ref (the full ref), workflow (the workflow file's path), repository and sender.

Each accepted dispatch also sends a workflow_dispatch webhook event with the same ref, workflow and inputs, to webhooks subscribed to it.

schedule

Runs the workflow on a schedule, in UTC.

on:
  schedule:
    - cron: "30 5 * * 1-5"    # 05:30 UTC, Monday to Friday
    - cron: "0 */6 * * *"     # every 6 hours

schedule is a list of entries with a cron string. Each cron has 5 fields:

FieldValues
Minute0-59
Hour0-23
Day of month1-31
Month1-12 or JAN-DEC
Day of week0-6 (Sunday is 0; 7 also means Sunday) or SUN-SAT

Each field accepts *, a value, a range (1-5), a list (1,15,30) and a step (*/15, 0-30/10, or 5/15 meaning from 5 to the end every 15). Names are case-insensitive. As in standard cron, when both day of month and day of week are restricted, a day matches if either one matches.

How schedules run:

  • Granularity is 5 minutes. Githome checks schedules every 5 minutes and starts every schedule that was due at any minute since the last check. A schedule for 2 * * * * starts a few minutes after :02, and one for * * * * * runs once per check, not every minute. GitHub's minimum interval is also 5 minutes. A check that comes late is caught up by the next one (up to an hour back), and a schedule starts once however many of its minutes it covers.
  • Only the default branch counts. Schedules are read from the workflow files on the default branch, and refreshed on every push to it. A schedule in a workflow on another branch does nothing.
  • Each run uses the workflow file on the default branch at that moment, and only if it still has that exact cron string.
  • Schedules of archived repositories don't run.
  • The run's actor is githome-scheduler. Notifications for scheduled runs go to the repository's watchers.

Invalid crons fail the file with Invalid cron: <detail>, for example Invalid cron: Cron '0 3 * *' must have exactly 5 fields (minute hour day-of-month month day-of-week), minute value 60 out of range 0-59 in cron '<cron>' or Invalid step '0' in minute field of cron '<cron>'. schedule must be a list (on.schedule must be a list of { cron: '...' } entries) and each entry needs a cron string (on.schedule entries must have a 'cron' string).

VariableValue
GITHUB_SHAThe latest commit on the default branch
GITHUB_REFrefs/heads/<default branch>

Payload (github.event): schedule (the cron string) and repository.

workflow_run

Runs after a run of another workflow is requested or completes. Use it to post-process another workflow's results with access to secrets, or to chain workflows.

name: Report
on:
  workflow_run:
    workflows: [CI]
    types: [completed]
    branches: [main]
jobs:
  report:
    if: ${{ github.event.workflow_run.conclusion == 'failure' }}
    runs-on: ubuntu-latest
    steps:
      - run: echo "CI failed on ${{ github.event.workflow_run.head_branch }}: ${{ github.event.workflow_run.html_url }}"
  • workflows is required: a list of workflow names (each workflow's name, or its path when it has none). A workflow_run trigger without workflows never fires.
  • types can be requested (when the other run is created, including re-runs) and completed. Without types, both fire. GitHub's in_progress type never fires on Githome.
  • branches and branches-ignore filter on the other run's head branch: the pushed branch, or the pull request's head branch for pull request runs.
  • Like on GitHub, the triggered workflow is read from the default branch and runs there, whatever branch the other run was on.
  • Chains stop after three levels: if A triggers B, B triggers C and C triggers D, D's runs don't trigger anything.
  • If the run it follows came from an agent (for example CI on a branch an agent pushed), the workflow_run run counts as agent code too, although it runs on the default branch: its GITHUB_TOKEN acts as an agent and environment secrets follow the agent rules. A follower acts on what the other run produced (artifacts, outputs), so it can't be used to carry agent-written results past the agent guardrails. See GITHUB_TOKEN permissions.
VariableValue
GITHUB_SHAThe latest commit on the default branch
GITHUB_REFrefs/heads/<default branch>

Payload (github.event):

FieldValue
actionrequested or completed
workflow_run.idThe other run's number, which is also its github.run_id and what download-artifact's run-id takes
workflow_run.name, workflow_run.pathThe other workflow's name and file path
workflow_run.display_titleThe other run's title
workflow_run.run_number, workflow_run.run_attemptIts number and attempt
workflow_run.eventThe event that started it
workflow_run.status, workflow_run.conclusionqueued and null for requested; completed and the conclusion for completed
workflow_run.head_branch, workflow_run.head_shaThe branch and the commit it reported checks on
workflow_run.actor, workflow_run.triggering_actor{ "login": ... }
workflow_run.pull_requests[{ "number": ... }] for pull request runs, otherwise empty
workflow_run.created_at, workflow_run.updated_atTimestamps
workflow_run.html_urlLink to the other run
workflowname and path of the other workflow
repository, senderAs for other events

release

Runs when a release changes: when it's published, unpublished, edited or deleted. Use it to build and attach binaries, publish packages or deploy when you publish a release. Releases are managed on the repository's Releases page (https://git.pkgforge.dev/acme/website/releases), with POST /api/v3/repos/{owner}/{repo}/releases and PATCH /api/v3/repos/{owner}/{repo}/releases/{release_id}, or with the create_release and update_release MCP tools. All of them need write access. See Releases.

name: Release
on:
  release:
    types: [published]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: make dist VERSION="${{ github.event.release.tag_name }}"

Each change sends one or more activity types, and a workflow with on: release and no types runs once for each of them. Creating a published release sends three (created, published and released), so you get three runs. Set types to the ones you need; types: [published] is the usual choice.

ChangeActivity types sent to workflows
Create a release that isn't a draft (Publish release on a new release)created, published, then released (or prereleased for a pre-release)
Publish a draft (Publish release on a draft)published, then released or prereleased
Turn a published release back into a draft ("draft": true in the API)unpublished
Edit a published release (Update release)edited, plus released or prereleased when the pre-release setting changed
Delete a published releasedeleted
Create, edit or delete a draftNone. Webhooks still get created, edited and deleted for drafts, but workflows don't run for draft releases, as on GitHub.

How a release run is set up:

  • The run uses the commit the release's tag points to (the commit, for an annotated tag), and the workflow file at that commit. If the tag doesn't exist (for example it was deleted after the release was published), no run starts.
  • Publishing a release whose tag doesn't exist yet creates the tag at target_commitish (the default branch when it's not set). Creating the tag is a push of that tag, so push workflows that match the tag run too, as on GitHub. Use either on: push: tags or on: release for the same job, not both.
  • The run's title is the release's name, or its tag name when the release has no name.
  • The run's actor is whoever made the change. Its checks are reported on the tagged commit.
  • types is the only filter. branches, tags and paths aren't applied to release; check github.event.release.tag_name or github.ref_name in an if: instead.
  • Invalid workflow files are skipped without an Invalid workflow file run.
VariableValue
GITHUB_SHAThe commit the release's tag points to
GITHUB_REFrefs/tags/<tag>
GITHUB_REF_NAMEThe tag name
GITHUB_REF_TYPEtag

Payload (github.event):

FieldValue
actionThe activity type
release.idThe release's ID, a number
release.tag_nameThe tag, for example v1.2.0
release.target_commitishThe branch or commit the tag was created from
release.name, release.bodyTitle and release notes, or null when empty
release.draft, release.prereleaseBooleans
release.latestWhether this is the repository's latest release (a Githome field)
release.immutableAlways false
release.created_at, release.updated_at, release.published_atTimestamps (published_at is null for drafts)
release.authorThe user object of whoever created the release (login, id, type and URLs)
release.assetsThe release's assets, each with id, name, label, content_type, size, download_count, browser_download_url and url
release.html_urlhttps://git.pkgforge.dev/acme/website/releases/tag/<tag>
release.url, release.assets_url, release.upload_urlAPI URLs. Upload assets to upload_url (with the {?name,label} template removed).
release.tarball_url, release.zipball_urlSource archives of the tag
release.node_id, release.reactionsAs on GitHub
repositorySee The repository object
senderSee The sender object

Uploading an asset needs contents: write. Give the job that permission and use its GITHUB_TOKEN, or use a personal or agent token stored as a secret (see GITHUB_TOKEN permissions):

on:
  release:
    types: [published]
jobs:
  upload:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: tar czf dist.tar.gz src
      - name: Attach dist.tar.gz to the release
        env:
          TOKEN: ${{ secrets.RELEASE_TOKEN }}
          UPLOAD_URL: ${{ github.event.release.upload_url }}
        run: |
          curl -fsS -X POST "${UPLOAD_URL%\{*}?name=dist.tar.gz" \
            -H "Authorization: Bearer $TOKEN" \
            -H "Content-Type: application/gzip" \
            --data-binary @dist.tar.gz

repository_dispatch

Runs when someone calls the dispatches endpoint of the repository with an event type. Use it to start workflows from outside Githome: another system's CI, a deployment tool, a chat bot or an agent.

on:
  repository_dispatch:
    types: [deploy, rollback]
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: ./deploy.sh "${{ github.event.action }}" "${{ github.event.client_payload.version }}"
  • types lists the event_type values that start the workflow. Without types, every event_type does.
  • Like on GitHub, the workflow is read from the default branch's latest commit and runs there.
  • The run's title is the event_type, and its actor is the account whose token sent the request.
  • Invalid workflow files are skipped without an Invalid workflow file run.

Send a repository_dispatch event

You need write access to the repository, with a token that has the write scope (see Tokens). People and agents can both send events.

curl -X POST https://git.pkgforge.dev/api/v3/repos/acme/website/dispatches \
  -H "Authorization: Bearer ghome_..." \
  -H "Content-Type: application/json" \
  -d '{"event_type": "deploy", "client_payload": {"version": "1.4.2", "environment": "staging"}}'
FieldRequiredMeaning
event_typeYesA name for the event, 1 to 100 characters. Workflows match it against types, and it becomes github.event.action.
client_payloadNoA JSON object with at most 10 top-level properties and at most 64 KB as JSON. Becomes github.event.client_payload. Default: {}.

The answer is 204 No Content, as on GitHub, also when no workflow listens for the event type. The request doesn't return the runs it started; find them with GET /api/v3/repos/acme/website/actions/runs?event=repository_dispatch or githome run list -R acme/website -e repository_dispatch. Webhooks subscribed to repository_dispatch also get the event.

StatusMessageCause
403write access requiredYour role or token scope is below write.
403repository is archived (read-only)Archived repositories don't accept events.
422event_type is required (at most 100 characters)event_type is missing, empty, not a string or too long.
422client_payload must be an objectclient_payload is an array or a scalar.
422client_payload can have at most 10 top-level propertiesNest the values in fewer top-level properties.
422client_payload is too largeThe payload is over 64 KB as JSON.
422the repository is emptyThe default branch has no commits yet.
VariableValue
GITHUB_SHAThe latest commit on the default branch
GITHUB_REFrefs/heads/<default branch>

Payload (github.event):

FieldValue
actionThe event_type
branchThe default branch
client_payloadThe client_payload you sent
repositorySee The repository object
senderThe account whose token sent the event; see The sender object

workflow_call

Makes the workflow reusable: other workflows call it from a job with uses:. It never starts a run on its own.

on:
  workflow_call:
    inputs:
      node-version:
        type: string
        default: "22"
    secrets:
      npm-token:
        required: true
    outputs:
      version:
        value: ${{ jobs.build.outputs.version }}

inputs take type (required: string, boolean or number), description, required and default. secrets take description and required. outputs each need a value. Runs of a called workflow use the caller's event, ref, commit and github context. The full reference is in Reusable workflows.

Repository activity events

The events of this section come from what people, agents and apps do in the repository, through the web UI, the CLI, the API or MCP.

  • Most of them run the workflow file of the default branch's latest commit, on the default branch. create, deployment, deployment_status, pull_request_review and pull_request_review_comment run where their table says.
  • Without types, a workflow runs for every activity type that Githome sends for the event. types: [opened] keeps out the others.
  • An invalid workflow file is skipped without an Invalid workflow file run.
  • The run's actor is whoever made the change. The payload has the fields listed in each section: issue, comment, review, pull_request, label and milestone as the REST API returns them, and repository, sender and (for an organization's repository) organization.
  • What a job does with its own GITHUB_TOKEN starts no run (see Runs started from inside a workflow). Neither does what Githome writes by itself: the comment of auto-merge when it turns off, the comment of the merge queue when it removes a pull request, the check of agent review, and the branches of a merge group. A job's write can cause each of them, and GitHub writes no such comment.
  • While the CI of the deployment is off, these events start nothing and read nothing: no workflow file, no payload and no test merge.
  • An event that no workflow of its commit listens to builds no payload. Githome parses the workflow files of a commit once for a burst of events on it.

Some changes send many events, as on GitHub, and each listening workflow runs once for each of them, on the repository owner's minutes: adding many labels to an issue sends one labeled for each label (and one label created for each new name), a review with many comments sends one pull_request_review and one pull_request_review_comment for each comment, and starring a repository again after removing the star sends watch again. Filter with types and if: where a workflow only needs some of them.

issues

on:
  issues:
    types: [opened, labeled]
jobs:
  triage:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Issue #${{ github.event.issue.number }}: ${{ github.event.issue.title }}"
TypeFires when
openedAn issue is created
editedIts title or description changes. The payload's changes has the old title or body ({ "from": ... }).
closed, reopenedIt is closed (also by a merged pull request that says fixes #<n>) or reopened
assigned, unassignedA person is added to or removed from its assignees. One event for each person, with assignee.
labeled, unlabeledA label is added or removed. One event for each label, with label.
locked, unlockedIts conversation is locked or unlocked
milestoned, demilestonedIt is given a milestone or taken out of one, with milestone. Moving it to another milestone sends demilestoned, then milestoned.

A pull request sends pull_request instead, as on GitHub. GitHub's other types (deleted, transferred, pinned, unpinned, typed, untyped) are accepted in types but never fire on Githome, which has none of these operations. An issue opened with labels or assignees sends opened only, not a labeled or assigned for each.

Payload: action, issue (with number, title, body, state, user, labels, assignees, locked and the URLs of the REST API), and changes, assignee, label or milestone for the types above.

issue_comment

Runs when a comment on an issue, or on the conversation of a pull request, is created, edited or deleted. A comment on a pull request has github.event.issue.pull_request, as on GitHub; check it to tell the two apart.

Payload: action, issue, comment (id, body, user, created_at, updated_at, html_url and url), and for edited, changes.body.from.

pull_request_review

Runs when a review of a pull request is submitted (an approval, a request for changes or a comment, and a pending review once it is submitted) or dismissed. GitHub's edited type never fires on Githome.

Like pull_request, the run uses the workflow and code of the pull request's test merge commit, and its checks are reported on the pull request's head commit. While the pull request conflicts with its base, no run starts. A review of a pull request from a fork runs as that fork's pull_request runs do: a read-only GITHUB_TOKEN and no secrets.

Payload: action, review (id, body, state in lower case, such as approved, user, commit_id, submitted_at) and pull_request.

pull_request_review_comment

Runs when a comment on the diff of a pull request is created (each comment of a submitted review, and a single comment or reply), edited or deleted. A single comment or reply is a review of one comment, so it also sends pull_request_review submitted. The comments of a pending review send nothing until the review is submitted. It runs where pull_request_review runs, and a review and its comments share one test merge commit.

Payload: action, comment (id, body, path, line, side, commit_id, user, pull_request_review_id), pull_request, and for edited, changes.body.from.

create

Runs when a branch or tag is created: by a push, POST /repos/{owner}/{repo}/git/refs, a new branch from the web UI, or a published release whose tag didn't exist. A push that creates more than three tags sends no create event for them. The branch of a merge group (gh-readonly-queue/...) sends none: the merge queue creates it.

Payload: ref (the short name), ref_type (branch or tag), master_branch, description (null) and pusher_type (user).

delete

Runs when a branch or tag is deleted, also when a merged pull request's branch is deleted. A push that deletes more than three tags sends no delete event for them, and the merge queue's deletion of a merge group's branch sends none.

Payload: ref (the short name), ref_type and pusher_type.

label

Runs when a label of the repository is created (also when adding a label that doesn't exist to an issue creates it), edited (changes has the old name, color or description) or deleted. Renaming or deleting a label sends no event for each issue that has it.

Payload: action, label (id, name, color, description, url) and, for edited, changes.

watch

Runs when someone stars the repository (PUT /user/starred/{owner}/{repo}). The only type is started. A second star by the same person, and a star of an archived repository, start nothing.

Payload: action (started).

status

Runs when a commit status is created (POST /repos/{owner}/{repo}/statuses/{sha}).

Payload: id, sha, name, state, context, description, target_url, commit.sha, created_at and updated_at.

deployment

Runs when a deployment is created with POST /repos/{owner}/{repo}/deployments. The deployments that a job with environment: records start no run, as on GitHub, so a workflow can't trigger itself through them.

Payload: action (created) and deployment (id, sha, ref, task, environment, description, payload, created_at).

deployment_status

Runs when a deployment status is created for a deployment of the API. As on GitHub, a status inactive starts no run, and neither do the statuses of a job's own deployment.

Payload: action (created), deployment_status (id, state, description, environment, environment_url, log_url, created_at) and deployment (id, sha, ref, task, environment).

check_run

Runs when a check run that an app or a person reports over the API is created, and when an update completed it. GitHub's rerequested and requested_action types never fire on Githome. The check runs of Githome Actions jobs and the check of agent review send no event, by any door.

Payload: action and check_run (id, name, head_sha, status, conclusion, started_at, completed_at, output, app, check_suite.id).

check_suite

Runs when the last unfinished check run of an app on a commit completes, so the app's suite on that commit is completed. Githome sends completed only: GitHub's requested and rerequested types never fire on Githome. The suites of Githome Actions runs and of agent review send no event.

Payload: action (completed) and check_suite (id, head_sha, status, conclusion, app, latest_check_runs_count).

GITHUB_SHA and GITHUB_REF by event

EventGITHUB_SHAGITHUB_REFWorkflow file read from
pushPushed commitPushed branch or tagPushed commit
pull_requestTest merge commit (merge commit once merged)refs/pull/<n>/mergeTest merge commit
pull_request_targetBase branch's latest commitrefs/heads/<base>Base branch's latest commit
merge_groupMerge group commitrefs/heads/gh-readonly-queue/<base>/pr-<n>-<head sha>Merge group commit
workflow_dispatchLatest commit of the chosen refChosen branch or tagChosen ref
scheduleDefault branch's latest commitDefault branchDefault branch
workflow_runDefault branch's latest commitDefault branchDefault branch
releaseThe commit the release's tag points torefs/tags/<tag>The tagged commit
repository_dispatchDefault branch's latest commitDefault branchDefault branch
issues, issue_comment, label, watch, delete, status, check_run, check_suiteDefault branch's latest commitDefault branchDefault branch
createThe commit the created branch or tag points toThe created branch or tagThat commit
deployment, deployment_statusThe deployed commitThe deployed branch or tag, or empty when the deployment names a commit SHAThe deployed commit
pull_request_review, pull_request_review_commentTest merge commit (merge commit once merged)refs/pull/<n>/mergeTest merge commit

A re-run keeps the original run's commit, ref, event and payload.

The repository object

Every payload has a repository field with GitHub's full repository object, the same one the REST API returns for GET /repos/{owner}/{repo}. The fields workflows read most:

FieldValue
idThe repository's ID, a number
node_idAn opaque ID
namewebsite
full_nameacme/website
privatetrue for a private repository, false for a public one
visibilitypublic or private
ownerA user object for the owner (login, a numeric id, type: User or Organization, and URLs)
default_branchmain
archivedWhether the repository is archived
topicsThe repository's topics
html_urlhttps://git.pkgforge.dev/acme/website
clone_urlhttps://git.pkgforge.dev/acme/website.git
url and the *_url templatesAPI URLs under https://git.pkgforge.dev/api/v3/repos/acme/website
created_at, updated_at, pushed_atTimestamps

For a repository owned by an organization, payloads also have an organization field with login, id (a number), node_id, url, repos_url, avatar_url and description.

The payload is also written to the file at GITHUB_EVENT_PATH for tools that read it from disk, such as @actions/github's context.payload in actions/github-script.

The sender object

sender is the account that caused the event, as a GitHub user object:

FieldValue
loginThe account's login
idA number derived from the account's ID, like GitHub's numeric user IDs
node_idAn opaque ID
typeUser for people, Bot for agents and Githome itself (for example githome-scheduler)
site_adminfalse
avatar_url, html_url, urlThe avatar, the profile page and the API URL

Runs started from inside a workflow

As on GitHub, an event caused by a job's own GITHUB_TOKEN doesn't start new workflow runs, so workflows can't trigger themselves in a loop with it. A push, a pull request, a release, an issue, a comment, a review, a label, a milestone, a commit status, a deployment or a check run made with a job token starts nothing, and neither does what Githome writes by itself because of it (auto-merge turned off by the job's push, a pull request that the merge queue removes, agent review's check). The two exceptions, as on GitHub, are workflow_dispatch (a job with permissions: actions: write can start another workflow with POST /repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches) and repository_dispatch (a job with contents: write can send POST /repos/{owner}/{repo}/dispatches).

Events caused by a personal or agent token stored as a secret, or by an app's installation token, are treated like any other event from that account or app and do start workflows: a push starts push workflows, a published release starts release workflows, a comment starts issue_comment workflows, and a dispatch starts repository_dispatch workflows. Two workflows that use such tokens can start each other without end. As on GitHub, nothing but the workflows themselves stops that: Githome only caps the runs of a repository that haven't finished (500 at a time, then new events start nothing until some finish) and the requests of each token (see Limits).

- name: Ask the deploy workflow to run
  env:
    TOKEN: ${{ secrets.DISPATCH_TOKEN }}
  run: |
    curl -fsS -X POST "${{ github.api_url }}/repos/${{ github.repository }}/dispatches" \
      -H "Authorization: Bearer $TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"event_type": "deploy", "client_payload": {"sha": "${{ github.sha }}"}}'

Guard against loops, for example with paths-ignore, types, or an if: that checks github.actor or the commit message.

Differences from GitHub

  • Only the events in Supported events start runs. Other GitHub event names parse but never fire.
  • pull_request and pull_request_target fire for opened, synchronize, reopened, closed, edited, ready_for_review and converted_to_draft only, and the edited payload has no changes object.
  • workflow_run fires for requested and completed, not in_progress, and requires workflows.
  • release workflows get no branches, tags or paths filtering, and a published release whose tag doesn't exist any more starts no runs.
  • issues, pull_request_review, check_run and check_suite never send the types of an operation Githome doesn't have, listed in their sections, and an issue opened with labels or assignees sends opened only.
  • The deployments and statuses that a job with environment: records go to webhooks but start no run, as on GitHub, where Actions records them.
  • push payloads list only the pushed commit in commits.
  • Path filters pass when a push creates a branch.
  • github.event.inputs keeps input types.
  • schedule is checked every 5 minutes; a schedule runs within about 5 minutes after it is due.