Recipe: Add Travsr to CI
Run Travsr in your CI pipeline to catch blast-radius regressions, enforce dependency rules, or generate change impact reports on every PR.
GitHub Actions example
# .github/workflows/travsr.yml
name: Travsr graph check
on:
pull_request:
jobs:
blast-radius:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2 # need HEAD~1 for delta index
- name: Install Travsr
run: npm install -g @travsr.com/travsr
- name: Index repository
# --semantic runs Phase B (call edges) before returning so the graph is
# query-ready immediately. The git hook is installed but never fires in CI.
run: travsr init --semantic
- name: Check blast radius of changed files
run: |
CHANGED=$(git diff --name-only HEAD~1 HEAD | grep -E '\.(ts|rs|py|go)$' || true)
if [ -z "$CHANGED" ]; then
echo "No source files changed."
exit 0
fi
for FILE in $CHANGED; do
echo "=== Blast radius: $FILE ==="
# --direction callers follows incoming edges: everything that depends on this file.
travsr graph "$FILE" --direction callers --format json \
| jq -r '.nodes | length as $n | "\($n) affected nodes"'
done
- name: Fail if a change affects more than 50 nodes
run: |
for FILE in $(git diff --name-only HEAD~1 HEAD | grep -E '\.(ts|rs)$'); do
COUNT=$(travsr graph "$FILE" --direction callers --format json | jq '.nodes | length')
if [ "$COUNT" -gt 50 ]; then
echo "HIGH BLAST RADIUS: $FILE affects $COUNT nodes (> 50)"
exit 1
fi
done
Caching the graph between runs
For large repositories, cache .travsr/graph.db between CI runs to avoid re-indexing from scratch:
- uses: actions/cache@v4
with:
path: .travsr/graph.db
key: travsr-${{ runner.os }}-${{ hashFiles('**/*.ts', '**/*.rs') }}
restore-keys: travsr-${{ runner.os }}-
- name: Index repository
# travsr init is idempotent: it refreshes an existing graph or builds one
# from scratch. With a cached .travsr/graph.db only changed files are re-parsed.
run: travsr init --semantic
Dependency rule enforcement
Enforce architectural rules (e.g. "controllers must not import db directly"):
# --direction deps follows outgoing edges: what this file imports / depends on.
travsr graph "src/controllers/UserController.ts" --direction deps --format json \
| jq -e '.nodes[] | select(.path | startswith("src/db/"))' >/dev/null \
&& { echo "VIOLATION: Controller imports db directly"; exit 1; } \
|| echo "OK: no direct db import"