Skip to content

Run in CI

The CLI sends the PR to your backend, streams the investigation and prints the report. Its exit code is the CI contract:

Exit Meaning
0 analysis finished, risk below HIGH
1 HIGH risk — fail the check
2 no validated report (backend unreachable, license problem, or the model never produced a report). Fails closed: a check is never green without a verdict

The CI job must reach the backend, and the backend lives inside your network. That works with:

  • Self-hosted runners inside your network (GitHub Actions, GitLab, …) — they pull jobs outbound, no inbound firewall holes.
  • On-prem CI — Jenkins, GitLab self-managed, TeamCity, Buildkite agents.
  • GitHub-hosted runners only with a network bridge you already operate: GitHub’s Azure private networking for hosted runners, or a VPN / tunnel the job joins (WireGuard, Tailscale, a cloud VPN gateway).

Plain GitHub-hosted runners (runs-on: ubuntu-latest) cannot reach a private backend — don’t expose the backend to the internet to make them work.

.github/workflows/cotracer.yml in the repo to analyze:

name: cotracer
on: pull_request
permissions:
contents: read
pull-requests: write # post the report as a PR comment
jobs:
impact-analysis:
runs-on: self-hosted # must reach the backend — see Network requirement
steps:
# The CLI detects the repo from this checkout and reads the diff from it.
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Cotracer impact analysis
env:
COTRACER_URL: ${{ secrets.COTRACER_URL }}
COTRACER_API_KEY: ${{ secrets.COTRACER_API_KEY }}
run: cotracer analyze pr ${{ github.event.pull_request.number }} --report-file cotracer-report.md
- name: Post report as PR comment
if: always()
env:
GH_TOKEN: ${{ github.token }}
run: |
[ -f cotracer-report.md ] || { echo "No Cotracer verdict — see the step log." >> "$GITHUB_STEP_SUMMARY"; exit 0; }
cat cotracer-report.md >> "$GITHUB_STEP_SUMMARY"
cid=$(gh api "repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments" \
--jq '[.[] | select(.body | startswith("<!-- cotracer-report -->"))][0].id // empty')
if [ -n "$cid" ]; then
gh api -X PATCH "repos/${{ github.repository }}/issues/comments/$cid" -F body=@cotracer-report.md
else
gh api "repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments" -F body=@cotracer-report.md
fi

Secrets: COTRACER_URL (e.g. https://cotracer.internal.example.com) and COTRACER_API_KEY (the backend’s key). Install the CLI on the runner image once (Install → CLI). Make the check required in branch protection to block HIGH-risk merges. The report is posted as one comment per PR, edited in place on every push.

Three requirements: a git checkout of the PR head, the CLI, and network access to the backend.

Terminal window
export COTRACER_URL=https://cotracer.internal.example.com
export COTRACER_API_KEY=...
cotracer analyze pr "$PR_NUMBER" --report-file cotracer-report.md
# exit 1 → fail the build; post cotracer-report.md wherever your team reads reviews

--json prints {report, risk, text, events} instead, for custom integrations.

From inside a git checkout:

Terminal window
export COTRACER_URL=http://cotracer.internal:8420 COTRACER_API_KEY=...
cotracer analyze # analyze your uncommitted changes
cotracer analyze pr 123 # analyze a PR
cotracer # interactive mode: ask follow-up questions

Uncommitted changes never leave your machine except as the diff and the files the backend asks for — the CLI serves a fixed set of read-only git operations, no shell access.