guide
ci-cd
automation
Adding CKB to Your CI Pipeline
By CKB Team
CKB isn't just for interactive AI sessions. Its analysis tools integrate directly into CI pipelines, catching issues before they reach production.
This guide covers GitHub Actions, GitLab CI, and general CI integration patterns.
What CKB Checks in CI
- Dead code - Unused functions and types
- Coupling violations - Modules that shouldn't depend on each other
- Ownership drift - Code areas losing their maintainers
- Impact assessment - PRs that touch high-risk areas
- Test coverage gaps - Changes without corresponding tests
GitHub Actions
Basic Setup
# .github/workflows/ckb-analysis.yml
name: CKB Analysis
on:
pull_request:
branches: [main]
jobs:
analyze:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history for ownership analysis
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install CKB
run: npm install -g @tastehub/ckb
- name: Initialize and index
run: |
ckb init
ckb index
- name: Run analysis
run: ckb analyze --format=github
Dead Code Check
Fail the build if new dead code is introduced:
- name: Check for dead code
run: |
ckb findDeadCode --format=json > dead-code.json
NEW_DEAD=$(jq '[.[] | select(.confidence == "high")] | length' dead-code.json)
if [ "$NEW_DEAD" -gt 0 ]; then
echo "::error::Found $NEW_DEAD new dead code items"
jq -r '.[] | select(.confidence == "high") | "::warning file=\(.file),line=\(.line)::\(.name) appears to be unused"' dead-code.json
exit 1
fi
Impact Analysis on PRs
Add impact summary as a PR comment:
- name: Analyze PR impact
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Get changed files
CHANGED=$(gh pr view ${{ github.event.pull_request.number }} --json files -q '.files[].path')
# Run impact analysis
ckb analyze-changes --files="$CHANGED" --format=markdown > impact.md
# Post as comment
gh pr comment ${{ github.event.pull_request.number }} --body-file impact.md
Ownership Validation
Ensure PRs have appropriate reviewers:
- name: Check ownership
run: |
# Get files in PR
FILES=$(git diff --name-only origin/main...HEAD)
# Get suggested reviewers
REVIEWERS=$(ckb getReviewers --files="$FILES" --format=json | jq -r '.suggested[]')
# Check if any owner is assigned
ASSIGNED=$(gh pr view ${{ github.event.pull_request.number }} --json reviewRequests -q '.reviewRequests[].login')
for reviewer in $REVIEWERS; do
if echo "$ASSIGNED" | grep -q "$reviewer"; then
echo "✓ Owner $reviewer is assigned"
exit 0
fi
done
echo "::warning::None of the suggested owners ($REVIEWERS) are assigned as reviewers"
GitLab CI
Basic Setup
# .gitlab-ci.yml
ckb-analysis:
image: node:20
stage: test
before_script:
- npm install -g @tastehub/ckb
- ckb init
- ckb index
script:
- ckb analyze --format=gitlab
artifacts:
reports:
codequality: ckb-report.json
Merge Request Analysis
ckb-mr-analysis:
image: node:20
stage: test
only:
- merge_requests
script:
- npm install -g @tastehub/ckb
- ckb init && ckb index
# Analyze changed files
- |
CHANGED=$(git diff --name-only $CI_MERGE_REQUEST_DIFF_BASE_SHA...HEAD)
ckb analyze-changes --files="$CHANGED" --format=gitlab-note > note.md
# Post to MR (requires GITLAB_TOKEN)
- |
curl --request POST \
--header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
--data-urlencode "body@note.md" \
"$CI_API_V4_URL/projects/$CI_PROJECT_ID/merge_requests/$CI_MERGE_REQUEST_IID/notes"
General CI Integration
JSON Output
All CKB commands support JSON output for easy parsing:
# Dead code as JSON
ckb findDeadCode --format=json
# Impact analysis as JSON
ckb prepareChange --target=src/auth --format=json
# Architecture as JSON
ckb getArchitecture --format=json
Exit Codes
CKB uses standard exit codes:
0- Success, no issues1- Analysis found issues (dead code, coupling, etc.)2- CKB error (missing index, invalid config)
Caching the Index
Speed up CI by caching the CKB index:
GitHub Actions:
- uses: actions/cache@v4
with:
path: .ckb/
key: ckb-index-${{ hashFiles('**/*.go', '**/*.ts', '**/*.py') }}
restore-keys: |
ckb-index-
GitLab CI:
cache:
key: ckb-index
paths:
- .ckb/
Workflow Examples
Quality Gate
Block merges if quality degrades:
quality-gate:
script:
- ckb init && ckb index
# Check coupling score
- |
COUPLING=$(ckb analyzeCoupling --format=json | jq '.score')
if [ "$COUPLING" -gt 70 ]; then
echo "Coupling score $COUPLING exceeds threshold (70)"
exit 1
fi
# Check dead code
- |
DEAD=$(ckb findDeadCode --format=json | jq 'length')
BASELINE=$(cat .ckb/baselines/dead-code-count || echo 0)
if [ "$DEAD" -gt "$BASELINE" ]; then
echo "Dead code increased from $BASELINE to $DEAD"
exit 1
fi
Nightly Analysis
Run comprehensive analysis on a schedule:
# .github/workflows/nightly-analysis.yml
name: Nightly Code Analysis
on:
schedule:
- cron: '0 2 * * *' # 2 AM daily
jobs:
analyze:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Full analysis
run: |
npm install -g @tastehub/ckb
ckb init && ckb index
# Generate comprehensive report
ckb report --full --format=html > report.html
# Upload as artifact
echo "Report generated"
- uses: actions/upload-artifact@v4
with:
name: ckb-report
path: report.html
PR Size Warning
Warn on large PRs that skip analysis:
- name: Check PR size
run: |
CHANGED=$(git diff --name-only origin/main...HEAD | wc -l)
if [ "$CHANGED" -gt 50 ]; then
echo "::warning::Large PR ($CHANGED files). Consider breaking into smaller changes."
# Run extra thorough analysis
ckb analyze --depth=deep --format=github
fi
Metrics and Tracking
Export Metrics
Send CKB metrics to your observability platform:
- name: Export metrics
run: |
METRICS=$(ckb status --format=json)
# Send to Datadog
curl -X POST "https://api.datadoghq.com/api/v1/series" \
-H "DD-API-KEY: $DATADOG_API_KEY" \
-d @- << EOF
{
"series": [{
"metric": "ckb.dead_code_count",
"points": [$(date +%s), $(echo $METRICS | jq '.deadCode')](/docs/$(date-+%s),-$(echo-$METRICS-|-jq-'.deadCode')),
"type": "gauge"
}, {
"metric": "ckb.coupling_score",
"points": [$(date +%s), $(echo $METRICS | jq '.couplingScore')](/docs/$(date-+%s),-$(echo-$METRICS-|-jq-'.couplingScore')),
"type": "gauge"
}]
}
EOF
Trend Tracking
Store baselines to track trends:
- name: Update baselines
if: github.ref == 'refs/heads/main'
run: |
mkdir -p .ckb/baselines
ckb findDeadCode --format=json | jq 'length' > .ckb/baselines/dead-code-count
ckb analyzeCoupling --format=json | jq '.score' > .ckb/baselines/coupling-score
# Commit baselines
git config user.name "CKB Bot"
git config user.email "ckb@example.com"
git add .ckb/baselines
git commit -m "Update CKB baselines" || true
git push
Best Practices
- Cache the index - Rebuilding on every commit is slow
- Run incrementally on PRs - Full analysis nightly, targeted analysis on PRs
- Set reasonable thresholds - Start permissive, tighten over time
- Don't block on warnings - Use annotations, not failures, for advisory issues
- Track trends - Metrics over time matter more than absolute values
Links: