Skip to content

Latest commit

 

History

History
201 lines (173 loc) · 7.88 KB

File metadata and controls

201 lines (173 loc) · 7.88 KB

ZERO GitHub Action

Run ZERO headlessly inside a GitHub workflow. The action is a thin wrapper around zero exec: it installs a pinned ZERO release, runs your prompt in the checked-out repository, surfaces ZERO's exit code as the step status, captures the output as a file, and can optionally post a summary to the triggering pull request or to Slack.

ZERO is model- and provider-agnostic, and so is this action: you choose the provider and supply the API key. Nothing is hardcoded to any single provider.

Quick start

# .github/workflows/zero.yml
name: ZERO
on:
  workflow_dispatch:
    inputs:
      task:
        description: What should ZERO do?
        required: true

permissions:
  contents: write

jobs:
  run:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: Gitlawb/zero@v1
        with:
          prompt: ${{ inputs.task }}
          provider: openai
          api-key-env: OPENAI_API_KEY
          api-key: ${{ secrets.OPENAI_API_KEY }}
          model: gpt-4.1

The provider, api-key-env, and api-key trio is how you stay provider-neutral: api-key-env is the environment variable name the chosen provider reads its key from (for example ANTHROPIC_API_KEY, GEMINI_API_KEY, OPENROUTER_API_KEY), and api-key is the secret value. The action exports that variable for the run and never prints it. If your repository already commits a .zero/config.json with an active provider, you can omit provider.

Inputs

Input Required Default Description
prompt one of prompt/prompt-file "" The instruction for ZERO to execute.
prompt-file one of prompt/prompt-file "" Path (relative to working-directory) to a file whose contents are the prompt.
provider no "" Provider id to activate (e.g. openai, anthropic, gemini, ollama, or any compatible endpoint).
api-key no "" The provider API key. Pass from a secret; never logged.
api-key-env no "" Env var name the provider reads its key from (e.g. OPENAI_API_KEY). Exported with api-key.
model no "" Model id. Defaults to the resolved provider's default.
mode no "" Run mode (zero exec --mode), e.g. smart, deep, fast.
auto no low Autonomy ceiling (zero exec --auto): low, medium, or high. Conservative by default.
self-correct no false Allow mid-run model escalation (zero exec --allow-escalation).
add-dir no "" Newline-/comma-separated extra write roots (zero exec --add-dir).
worktree no false Run in an isolated git worktree (zero exec --worktree).
output-format no stream-json text, json, or stream-json. Captured to a file.
post-to no none pr-comment, slack, or none. Where to post a summary after the run.
slack-webhook-url no "" Slack incoming-webhook (or generic webhook) URL for post-to: slack. Pass from a secret.
github-token no ${{ github.token }} Token used to post a PR comment. Requires pull-requests: write.
working-directory no ${{ github.workspace }} Directory to run ZERO in.
zero-version no (action ref → latest) ZERO release version/tag to install, e.g. v1.2.3 or latest.
zero-repo no Gitlawb/zero Repository to install the ZERO release from.

Outputs

Output Description
exit-code ZERO's exit code (0 success, 2 usage, 3 provider, non-zero otherwise).
output-file Path to the captured ZERO stdout (the raw output-format stream).
summary A short, single-line summary parsed from the run, when available.

The step fails when ZERO returns a non-zero exit code, so a failed run fails the job by default. Use continue-on-error: true on the step (and read exit-code) if you want to handle failures yourself.

Examples

Run ZERO on every issue labeled zero

name: ZERO issue triage
on:
  issues:
    types: [labeled]

permissions:
  contents: write
  issues: write
  pull-requests: write

jobs:
  triage:
    if: github.event.label.name == 'zero'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: Gitlawb/zero@v1
        with:
          prompt: |
            Investigate this issue and propose a fix.

            Title: ${{ github.event.issue.title }}

            ${{ github.event.issue.body }}
          provider: anthropic
          api-key-env: ANTHROPIC_API_KEY
          api-key: ${{ secrets.ANTHROPIC_API_KEY }}
          auto: low
          post-to: slack
          slack-webhook-url: ${{ secrets.ZERO_SLACK_WEBHOOK_URL }}

Nightly dependency-upgrade PR

name: ZERO nightly deps
on:
  schedule:
    - cron: "0 6 * * 1" # Mondays 06:00 UTC

permissions:
  contents: write
  pull-requests: write

jobs:
  deps:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: Gitlawb/zero@v1
        id: zero
        with:
          prompt-file: .github/zero/upgrade-deps.md
          provider: openai
          api-key-env: OPENAI_API_KEY
          api-key: ${{ secrets.OPENAI_API_KEY }}
          worktree: true
          auto: medium
      - name: Open pull request
        run: |
          git checkout -b zero/deps-$(date +%Y%m%d)
          git commit -am "chore(deps): nightly upgrade via ZERO" || exit 0
          git push -u origin HEAD
          gh pr create --fill --label dependencies
        env:
          GH_TOKEN: ${{ github.token }}
      - name: Upload ZERO output
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: zero-output
          path: ${{ steps.zero.outputs.output-file }}
          if-no-files-found: warn

Security notes

  • Secrets are passed as Action secrets and never logged. The action exports api-key (under api-key-env) and slack-webhook-url into the step environment only. They are never echoed, and ZERO redacts secret-shaped strings from its own output.
  • The sandbox is always active. This action never passes --skip-permissions-unsafe, so writes stay inside the checked-out repository (plus any roots you grant with add-dir). Unsafe mode is never enabled implicitly.
  • Autonomy defaults to low. Raise it deliberately (auto: medium/high) only for tasks you trust to run unattended.
  • Least-privilege tokens. Grant only the permissions the workflow needs (contents: write to edit files, pull-requests: write to comment). The default GITHUB_TOKEN is scoped to the repository.
  • Pin the action. Reference a tag (Gitlawb/zero@v1) or a commit SHA so a workflow run uses a known ZERO version. zero-version lets you pin the installed binary independently of the action ref.
  • Linux and macOS runners are supported; Windows runners are rejected with a clear error.

Slack / webhook notifier

The action's post-to: slack step sends a one-line summary to a Slack incoming webhook after the run. ZERO also has a built-in webhook notifier sink (internal/notify) that an unattended run can use to report "finished / needs input / verify failed after N retries" to Slack or any generic webhook:

  • Configure the destination with the ZERO_SLACK_WEBHOOK_URL environment variable (or settings). A blank URL disables the sink.
  • The sink POSTs a JSON body { "text", "type", "message", "summary?", "links?" }. The text field is what Slack renders; the structured fields carry the machine-readable detail.
  • Fail-soft: a non-2xx response or a transport error is logged (redacted) and swallowed — a webhook problem never crashes the run.
  • Redaction: the message, summary, links, and the webhook URL itself are run through ZERO's redaction before being sent or logged, so tokens never leak.
  • Egress/proxy: the notifier uses the default HTTP transport, which honors HTTP_PROXY/HTTPS_PROXY when a proxy is configured.