All guides

Guide

Gating a deploy from CI

Run the suite on every pull request and fail the build when a case that must never break, breaks.

Everyday12 min

A suite nobody runs is documentation. The point of wiring it into CI is that a regression stops a deploy instead of being discovered by a customer three weeks later.

What you need

  1. An agent reachable from your CI runner. A staging deployment is the usual answer.
  2. A workspace API key, from API keys in the app. It is shown once.
  3. At least one regression case, so the gate has something to gate on.

Not production

A run executes real tool calls. An agent marked Production is refused by the API with a 409, deliberately, because a pipeline pointed at production would issue real refunds on every pull request.

The workflow

- name: Run the regression suite
  env:
    ACTIONPROOF_API_KEY: ${{ secrets.ACTIONPROOF_API_KEY }}
  run: |
    curl -fsSL https://actionproof.ai/ci/actionproof.mjs -o actionproof.mjs
    node actionproof.mjs run \
      --agent my-support-agent \
      --suite regression \
      --version "${GITHUB_SHA::7}" \
      --wait

The runner exits 0 on pass or warn and 1 when the gate is blocked, so the build fails on its own. Nothing in your pipeline has to parse JSON.

The gate is decided by us, on purpose

The status response carries an explicit gate field rather than leaving CI to work it out from counts. If every customer derives the verdict themselves, every customer derives it slightly differently, and eventually a blocking regression ships because of an off-by-one in a shell script.

GateMeaningExit code
passNothing failed.0
warnSomething failed, but no case marked blocking.0
blockedA blocking regression case failed, or the run was stopped by a guard.1
pendingThe run has not finished.,

Which suite to run

Use --suite regression on pull requests. Those are the cases someone decided must never break again, they are scripted, and scripted conversations are byte-identical between runs, so a failure is the agent changing rather than the weather.

Run the full suite on a schedule instead, with generated customers. That is where the next unknown failure is, and a surprise at 3am is better than a broken build at 6pm.

Calling the API directly

If you would rather not use the runner, it is two endpoints.

# start
curl -X POST https://actionproof.ai/api/v1/runs \
  -H "Authorization: Bearer $ACTIONPROOF_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"agent":"my-support-agent","suite":"regression","version":"abc1234"}'

# poll
curl https://actionproof.ai/api/v1/runs/<ref> \
  -H "Authorization: Bearer $ACTIONPROOF_API_KEY"

Or skip polling entirely: add a webhook under Integrations and we will POST the result, signed, when the run finishes.

Keeping the gate trusted

  • Block on few things. A gate that blocks on everything gets switched off within a fortnight, and then nothing is gated.
  • Never block on `not_verified`. By definition it is not evidence of a defect. Gating on it teaches people the gate is noise.
  • Label the version. A failures list that cannot say which build produced it is an argument waiting to happen.
  • Watch the runtime. A suite that takes longer than the deploy it guards will be skipped under pressure.

Next guide

Choosing what to test first

Twenty scenarios that matter beat two hundred that do not. How to pick them.