CI
GitHub Action
Re-check your app every time a migration lands on your default branch. The action starts a PatchLabs check, waits for the lab result, prints it in the job summary, and fails the build if strangers can read personal data.
Set up in three steps
-
Add and verify the app
Sign in, add the repo as an app and commit its verification file. See monitoring. Copy the app’s ID from its page.
-
Create an API key
In Settings → API keys, create a key named, say, “GitHub Actions”. It’s shown once. In your repo, open Settings → Secrets and variables → Actions and add it as the secret
PATCHLABS_API_KEY. Add the app ID as the variablePATCHLABS_APP_ID. -
Add the workflow
Save this as
.github/workflows/patchlabs.yml:name: PatchLabs on: push: branches: [main] paths: ['supabase/migrations/**'] workflow_dispatch: concurrency: patchlabs jobs: leak-check: runs-on: ubuntu-latest steps: - uses: manra399/patchlabs/action@main with: api-key: ${{ secrets.PATCHLABS_API_KEY }} app-id: ${{ vars.PATCHLABS_APP_ID }} wait: true fail-on-leak: true
No checkout step is needed: PatchLabs reads the repo from GitHub. concurrency stops two runs from overlapping, since an app can only have one check open at a time.
What you see
PatchLabs check started: 7c1e2f0a-… Status: queued Status: running PatchLabs · you/shop-app result Leaks found; a lab-proven fix is ready tables leaking profiles lab proof passed report https://patchlabs.dev/check?id=… Error: Leaks found … Apply the fix, then re-run.
The same result goes into the job summary as a small table with a link to the report. After you apply the fix, re-run the job: it passes once the check reads no_leaks.
Inputs
| Input | Default | What it does |
|---|---|---|
api-key | required | Workspace API key (pl_live_…). Pass it from a secret. |
app-id | required | The monitored app’s ID. |
wait | true | Wait for the result. false starts the check and ends the step straight away. |
fail-on-leak | true | Fail the step when the finished check (done or needs_review) has leaking tables your team hasn’t marked as intended. |
timeout-minutes | 30 | How long to wait for a result. |
fail-on-timeout | false | Fail instead of warn when no result arrives in time. |
poll-seconds | 15 | Seconds between status requests (minimum 5). |
api-url | https://api.patchlabs.dev | API base URL. |
Outputs
| Output | Value |
|---|---|
check-id | The check this run started |
status | done, no_leaks, needs_review or failed; queued/running if not waited for or timed out; busy or limit if no check could start |
url | Link to the report |
leaks-found | true or false |
tables-leaking | Comma-separated table names |
suppressed-tables | Leaking tables your team marked as intended (not counted by fail-on-leak) |
lab-proof-passed | true when the fix passed the lab proof |
Use them in later steps, for example to post the report link somewhere:
- id: patchlabs
uses: manra399/patchlabs/action@main
with:
api-key: ${{ secrets.PATCHLABS_API_KEY }}
app-id: ${{ vars.PATCHLABS_APP_ID }}
fail-on-leak: false
- if: steps.patchlabs.outputs.leaks-found == 'true'
run: echo "Leaking tables: ${{ steps.patchlabs.outputs.tables-leaking }} → ${{ steps.patchlabs.outputs.url }}"How each result is handled
| Situation | Step result |
|---|---|
no_leaks | passes |
done or needs_review | fails with fail-on-leak: true, otherwise warns |
| Only tables marked as intended are leaking | Passes with a notice |
failed (the check couldn’t finish) | Warns. We’re alerted and follow up |
| A check is already open for the app | Warns and passes; no new check is started |
| Monthly run limit reached | Warns and passes |
| App not verified, bad key, wrong app ID | Fails with the reason |
No result within timeout-minutes | Warns, or fails with fail-on-timeout: true |
On a schedule
Monitoring already re-checks your app weekly or monthly. If you’d rather see results in GitHub, add a cron trigger:
on:
schedule:
- cron: '0 6 * * 1' # Mondays at 06:00 UTC
workflow_dispatch:How it works
The action is a small shell script that uses curl and jq (both preinstalled on GitHub-hosted Linux and macOS runners). It calls two endpoints with your key:
POST /v1/apps/{app_id}/checksto start a check;GET /v1/checks/{id}everypoll-secondsuntilfinishedis true.
The source is in the action/ folder of the manra399/patchlabs repo. Read it before you use it; it’s about 130 lines. For a fixed version, pin a commit SHA instead of @main.
Good to know
A check reads your default branch as it is on GitHub, not the branch of a pull request. Run the action after changes land on your default branch; on a pull_request trigger it would report on the default branch, not the PR. Each run uses one of your plan’s monthly manual runs (Free 4, Maker 30, Agency 200). Tables your team marked as intended don’t count for fail-on-leak: the step fails only while other leaking tables remain, and lists the intended ones separately.