Gate a change in CI
The same command that an agent runs gates a change in CI: no prompts, one request, and the exit code says what happened. A check of unpushed or branch work is free and never uses credits.
Sign in without a browser
Section titled “Sign in without a browser”Store a token once, then give CI the token rather than a login:
slopcop login --token "$SLOPCOP_TOKEN" # on a machine, stores itIn CI, set SLOPCOP_TOKEN in the job’s environment from a secret; no login
step is needed. The token runs checks in, and bills, the workspace it was
approved in. Pass -w/--workspace (or set SLOPCOP_WORKSPACE) to use another
one; see Workspaces.
GitHub Actions
Section titled “GitHub Actions”name: SlopCop
on: pull_request:
permissions: contents: read security-events: write # only for the SARIF upload
jobs: check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 # the merge base must be in the clone
- name: Install slopcop run: npm install --global @brokkai/slopcop
- name: Check the change env: SLOPCOP_TOKEN: ${{ secrets.SLOPCOP_TOKEN }} run: | slopcop check --base "origin/${{ github.base_ref }}" --format sarif > slopcop.sarif echo "exit=$?" >> "$GITHUB_OUTPUT" id: slopcop continue-on-error: true
- name: Upload to code scanning if: always() uses: github/codeql-action/upload-sarif@v3 with: sarif_file: slopcop.sarif
- name: Fail on new findings or an incomplete check if: steps.slopcop.outputs.exit != '0' run: | echo "slopcop exited ${{ steps.slopcop.outputs.exit }}" exit 1Three things matter in that workflow:
fetch-depth: 0. The CLI needs the merge base with the target branch in its clone, and the service needs that commit in its own; a shallow clone gives neither.--base origin/<target branch>. A pull request’s head may have its commits pushed, and the runner’s checkout has no upstream, so name the base rather than relying on the default. Likegit diff REV...HEAD, the base is the merge base, so commits that landed on the target after the branch point are not sent as reverse edits.- Act on the exit code, not the SARIF.
1means new findings;2means some rule did not complete or the check failed, which is not a pass;3means run it again;4means a person must act. Treat anything but0as a failed gate, and read the code to know which.
The SARIF upload is optional. It puts each new finding on the pull request’s
Files changed tab as a code-scanning alert, with baselineState: new so GitHub
shows it as introduced by the change. Without security-events: write drop
that step and read the human output in the job log instead.
Other CI
Section titled “Other CI”Any runner works the same way: install from any channel,
export SLOPCOP_TOKEN, check with --base naming the target branch, and act on
the exit code.
slopcop check --base origin/main --format json > slopcop.json--timeout bounds the whole wait (default ten minutes); a check still running
then exits 3, and running the same command again picks up the same analysis
rather than starting over.
Threshold
Section titled “Threshold”By default any new finding fails the check (--fail-on finding). To fail only
on warnings and errors, pass --fail-on warning; to always exit 0 on a
completed check and read the report yourself, --fail-on never. Incomplete
checks still exit 2 whatever the threshold.
Repository rules in CI
Section titled “Repository rules in CI”Rules under .slopcop/policies/**/*.rqlp travel with the change and run in CI
like anywhere else. See Repository rules.