Skip to content

Write an action

This guide shows you how to create an automated action that modifies repositories — creating commits, PRs, or running maintenance tasks.

Create the action file

Actions are YAML files stored in data/actions/. The filename becomes the action's slug.

Create data/actions/update-copyright.yaml:

name: Update Copyright Year
description: Updates the copyright year in LICENSE files

targets:
  regex: "myorg/.*"

script: |
  sed -i "s/Copyright (c) [0-9]*/Copyright (c) $(date +%Y)/" LICENSE
  git add LICENSE
  git commit -m "chore: update copyright year"
  git push

Understand the structure

Field Required Description
name Yes Display name on the dashboard
description Yes What the action does
targets No Which repos to run against; null = global action (runs once, no per-repo iteration)
script Yes Bash script to execute
schedule No Cron expression; omit for manual-only
enabled No true (default) or false

Targeting

Targeting works the same as for checks — use list, regex, or script.

If you omit targets entirely, the action is global — it runs once without iterating over repos. Useful for cross-repo tasks or infrastructure automation.

Global actions (no targets)

name: Sync templates
description: Copies shared templates to all repos
# No targets field — runs once in the workspace root

script: |
  ./scripts/sync-templates.sh

Script environment

Action scripts execute inside the cloned repository directory. Available environment variables:

Variable Description
REPO_OWNER Repository owner
REPO_NAME Repository name
REPO_FULL_NAME owner/name
BRANCH Current branch
GH_TOKEN GitHub token (for gh CLI)

The gh CLI is available inside the Docker container.

Scripts have a 10-minute timeout and output is capped at 64 KB.

Git identity

For actions that commit, configure the git section in config.yaml:

git:
  user:
    name: "Grimoire Bot"
    email: "grimoire@example.com"
  signing:
    key_path: "/keys/id_ed25519"
    format: "ssh"

See the git configuration reference for details.

Concurrency

Only one instance of a given action can run at a time. Attempting to trigger an already-running action returns HTTP 409 Conflict.

Trigger manually

# Run against all targeted repos
curl -X POST http://localhost:8000/api/actions/update-copyright/run

# Run against a specific repo
curl -X POST "http://localhost:8000/api/actions/update-copyright/run?repo=owner/repo"

View run history

# List all runs
curl http://localhost:8000/api/actions/update-copyright/runs

# Get details for a specific run
curl http://localhost:8000/api/actions/update-copyright/runs/1

Schedule an action

schedule: "0 0 1 1 *"   # midnight on Jan 1st

Omit schedule for manual-only actions.

Differences from checks

Checks Actions
Purpose Validate / detect Fix / automate
Side effects Read-only Can modify repos
Exit codes 0 = pass, non-zero = fail 0 = success, non-zero = failure
Severity error or warning N/A
Git identity Not needed Required for commits
Timeout 5 minutes 10 minutes
Targets Required Optional (null = global)