-
-
Notifications
You must be signed in to change notification settings - Fork 11
CI CD Integration
CKB becomes your single source of truth for change risk in CI/CD pipelines. Instead of treating code review as a human-only process, CKB provides precomputed analysis that travels with every PR:
- Blast radius — Know exactly what breaks before merging
- Suggested reviewers — Based on actual code ownership, not guesswork
- Boundary detection — Flag when "local" changes cross API contracts
- Risk scoring — Quantified risk based on hotspots, module spread, and history
The pattern: start CKB as a local server, call it with curl, parse JSON responses.
When you call POST /pr/summary, CKB:
- Diffs the branches using git (base vs head)
- Maps files to modules based on path structure
- Checks each file against hotspot data — flags files with score > 0.5
- Queries ownership for each changed file (CODEOWNERS + git-blame)
- Calculates risk based on: file count, lines changed, hotspots touched, module spread
- Returns structured JSON with everything a PR comment needs
Example response shape:
{
"summary": {
"totalFiles": 12,
"totalAdditions": 450,
"totalDeletions": 120,
"totalModules": 3,
"hotspotsTouched": 2
},
"riskAssessment": {
"level": "medium",
"score": 0.45,
"factors": ["Touches 2 hotspot(s)", "Spans 3 modules"],
"suggestions": ["Extra review recommended for hotspot files"]
},
"suggestedReviewers": [
{"owner": "@api-team", "reason": "Owns 8 of 12 changed files", "coverage": 0.67}
],
"modulesAffected": [
{"moduleId": "internal/api", "filesChanged": 8, "riskLevel": "medium"}
]
}CKB runs as a local HTTP server inside the runner. The workflow:
- Checkout with full history (
fetch-depth: 0) - Install CKB
- Start server:
ckb serve --port 8080 & - Call endpoints with
curl - Parse JSON, post PR comment
npm (Recommended):
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install CKB
run: npm install -g @tastehub/ckbOr use npx (no install):
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Initialize CKB
run: npx @tastehub/ckb initOr download pre-built binary:
- run: |
curl -sSL https://github.com/SimplyLiz/CodeMCP/releases/latest/download/ckb_linux_amd64.tar.gz | tar xz
sudo mv ckb /usr/local/bin/Or build from source:
- uses: actions/setup-go@v5
with:
go-version: '1.21'
- name: Install CKB
run: |
git clone https://github.com/SimplyLiz/CodeMCP.git /tmp/codemcp
cd /tmp/codemcp
go build -o /usr/local/bin/ckb ./cmd/ckbCKB needs git history for ownership analysis. Without it, suggested reviewers will be empty.
- uses: actions/checkout@v4
with:
fetch-depth: 0 # RequiredBefore running CKB analysis, validate that your CI environment has the required tooling installed. The ckb doctor --tier command checks for language-specific tools and outputs JSON for scripting.
- name: Validate CKB Environment
run: |
# Check if required tools are installed for standard tier
RESULT=$(ckb doctor --tier=standard --format json)
# Check for missing tools
MISSING=$(echo "$RESULT" | jq '[.languages[] | select(.status == "missing")] | length')
if [ "$MISSING" -gt 0 ]; then
echo "::warning::Missing $MISSING language tools"
echo "$RESULT" | jq '.languages[] | select(.status == "missing") | "\(.name): \(.installCmd)"'
fiDifferent tiers require different tools:
| Tier | Tools Required | Use Case |
|---|---|---|
fast |
None (tree-sitter built-in) | Quick PR checks |
standard |
SCIP indexers (scip-go, scip-typescript, etc.) | Full code intelligence |
full |
Standard + LSP servers | Maximum accuracy |
- name: Check Standard Tier Readiness
run: |
# Fail if standard tier tools aren't available
ckb doctor --tier=standard --format json | jq -e '.ready == true' || {
echo "::error::CI environment missing required tools for standard tier"
ckb doctor --tier=standard
exit 1
}- name: Setup Go Indexer
run: |
# Check if scip-go is needed and missing
if ckb doctor --tier=standard --format json | jq -e '.languages[] | select(.name == "go" and .status == "missing")' > /dev/null 2>&1; then
go install github.com/sourcegraph/scip-go/cmd/scip-go@latest
fi# .github/workflows/pr-analysis.yml
name: CKB PR Analysis
on:
pull_request:
types: [opened, synchronize, reopened]
permissions:
contents: read
pull-requests: write
jobs:
analyze:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install CKB
run: npm install -g @tastehub/ckb
- name: Initialize CKB
run: |
ckb init
ckb doctor --fix
- name: Start CKB Server
run: |
ckb serve --port 8080 &
sleep 2 # Wait for server to start
- name: Run PR Summary
id: summary
run: |
RESULT=$(curl -s -X POST http://localhost:8080/pr/summary \
-H "Content-Type: application/json" \
-d '{"baseBranch": "${{ github.base_ref }}"}')
RISK=$(echo "$RESULT" | jq -r '.riskAssessment.level // "unknown"')
echo "risk=$RISK" >> $GITHUB_OUTPUT
echo "result<<EOF" >> $GITHUB_OUTPUT
echo "$RESULT" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Post Comment
uses: actions/github-script@v7
with:
script: |
const data = JSON.parse(`${{ steps.summary.outputs.result }}`);
let emoji = data.riskAssessment?.level === 'high' ? '🔴' :
data.riskAssessment?.level === 'medium' ? '🟡' : '🟢';
let body = `## CKB Analysis ${emoji}\n\n`;
body += `**Risk:** ${data.riskAssessment?.level || 'unknown'}\n`;
body += `**Files:** ${data.summary?.totalFiles || 0}\n`;
body += `**Hotspots touched:** ${data.summary?.hotspotsTouched || 0}\n\n`;
if (data.suggestedReviewers?.length) {
body += `### Suggested Reviewers\n`;
data.suggestedReviewers.slice(0,3).forEach(r => {
body += `- ${r.owner}\n`;
});
}
github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: body
});For Go projects, CKB supports incremental indexing that only processes changed files. This can dramatically speed up CI pipelines.
| Scenario | Full Index | Incremental |
|---|---|---|
| Large Go project (10k files) | ~60s | ~2-5s |
| Typical PR (5-10 files changed) | ~60s | ~1-2s |
| Single file hotfix | ~60s | <1s |
The key insight: PR pipelines typically change a small fraction of files. Incremental indexing is O(changed files), not O(total files).
- name: Restore CKB Cache
uses: actions/cache@v4
with:
path: .ckb/
key: ckb-${{ runner.os }}-${{ hashFiles('go.sum') }}
restore-keys: |
ckb-${{ runner.os }}-
- name: Index (Incremental)
run: |
ckb init
ckb index # Incremental by default for Go
# Show what was updated
echo "Index complete"Use full reindexing (--force) in these scenarios:
# Nightly: Full reindex for maximum accuracy
- name: Nightly Full Index
if: github.event_name == 'schedule'
run: ckb index --force
# PR: Incremental for speed
- name: PR Incremental Index
if: github.event_name == 'pull_request'
run: ckb indexUse --force when:
- Running nightly/scheduled builds (accuracy matters more than speed)
- After major refactoring (many files changed)
- When you need accurate "callers" information (who calls this function?)
- After CKB version upgrades (schema may have changed)
Use incremental when:
- Running on every PR (speed matters)
- Running on every push (CI cost matters)
- You only need "callees" information (what does this function call?)
After incremental indexing:
| Query | Accuracy | Notes |
|---|---|---|
| Go to definition | Always accurate | |
| Find refs FROM changed files | Always accurate | |
| Find refs TO changed symbols | May be stale | Other files weren't re-scanned |
| Callees (outgoing calls) | Always accurate | v7.3+ |
| Callers (incoming calls) | May be stale | Other files weren't re-scanned |
For PR analysis, this is usually fine—you care about what the changed code does, not what calls it.
CKB automatically skips reindexing when the index is already up-to-date:
- name: Smart Index
run: |
ckb index
# Output: "Index is fresh (matches HEAD abc1234). Skipping."This is useful when:
- Running multiple CKB commands in sequence
- Cache restored an up-to-date index
- Re-running a failed job
For incremental indexing to work across CI runs, you must cache the .ckb/ directory:
- name: Restore CKB Cache
uses: actions/cache@v4
with:
path: .ckb/
key: ckb-${{ runner.os }}-${{ github.ref }}-${{ github.sha }}
restore-keys: |
ckb-${{ runner.os }}-${{ github.ref }}-
ckb-${{ runner.os }}-
- name: Index
run: |
ckb init
ckb index
- name: Save CKB Cache
uses: actions/cache/save@v4
if: always()
with:
path: .ckb/
key: ckb-${{ runner.os }}-${{ github.ref }}-${{ github.sha }}Cache key strategy:
- Include
github.shafor exact match on re-runs - Include
github.refto separate branch caches - Use
restore-keysto fall back to older caches
# .github/workflows/ckb-incremental.yml
name: CKB Analysis (Incremental)
on:
pull_request:
push:
branches: [main]
jobs:
analyze:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: '20'
- uses: actions/setup-go@v5
with:
go-version: '1.21'
- name: Install Tools
run: |
npm install -g @tastehub/ckb
go install github.com/sourcegraph/scip-go/cmd/scip-go@latest
- name: Restore Cache
uses: actions/cache@v4
with:
path: .ckb/
key: ckb-${{ runner.os }}-${{ github.ref }}-${{ github.sha }}
restore-keys: |
ckb-${{ runner.os }}-${{ github.ref }}-
ckb-${{ runner.os }}-
- name: Index
run: |
ckb init
# Use --force on main branch pushes for accuracy
if [ "${{ github.event_name }}" = "push" ] && [ "${{ github.ref }}" = "refs/heads/main" ]; then
ckb index --force
else
ckb index
fi
- name: Analyze
run: |
ckb serve --port 8080 &
sleep 2
curl -s http://localhost:8080/status | jq .
- name: Save Cache
uses: actions/cache/save@v4
if: always()
with:
path: .ckb/
key: ckb-${{ runner.os }}-${{ github.ref }}-${{ github.sha }}CKB uses a lock file (.ckb/index.lock) to prevent concurrent indexing. In CI:
- If a previous step is still indexing, subsequent
ckb indexcalls will wait - Lock is automatically released on process exit
- Stale locks (from crashed processes) are detected and removed
This is safe for parallel jobs as long as they don't share the same .ckb/ directory.
Run daily to keep architectural data fresh:
# .github/workflows/ckb-refresh.yml
name: CKB Architecture Refresh
on:
schedule:
- cron: '0 2 * * *' # Daily at 2 AM UTC
workflow_dispatch:
inputs:
force:
description: 'Force full refresh'
type: boolean
default: false
permissions:
contents: write
jobs:
refresh:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install CKB
run: npm install -g @tastehub/ckb
- name: Initialize and Start Server
run: |
ckb init
ckb serve --port 8080 &
sleep 2
- name: Refresh Architecture
run: |
curl -s -X POST http://localhost:8080/architecture/refresh \
-H "Content-Type: application/json" \
-d '{"scope": "all", "force": ${{ inputs.force || false }}}'
- name: Generate Reports
run: |
curl -s "http://localhost:8080/hotspots?limit=20" > hotspots.json
curl -s "http://localhost:8080/ownership/drift?threshold=0.3" > drift.json
- name: Upload Reports
uses: actions/upload-artifact@v4
with:
name: ckb-reports
path: '*.json'
retention-days: 30
- name: Cache CKB Database
run: |
git config user.email "github-actions[bot]@users.noreply.github.com"
git config user.name "github-actions[bot]"
git add .ckb/
git diff --staged --quiet || git commit -m "chore: update CKB cache [skip ci]"
git pushFor large repositories, use async mode to avoid timeouts:
- name: Start CKB Server
run: |
ckb init
ckb serve --port 8080 &
sleep 2
- name: Start Async Refresh
id: refresh
run: |
RESULT=$(curl -s -X POST http://localhost:8080/architecture/refresh \
-H "Content-Type: application/json" \
-d '{"scope": "all", "async": true}')
JOB_ID=$(echo "$RESULT" | jq -r '.jobId')
echo "job_id=$JOB_ID" >> $GITHUB_OUTPUT
- name: Wait for Completion
run: |
JOB_ID="${{ steps.refresh.outputs.job_id }}"
while true; do
STATUS=$(curl -s "http://localhost:8080/jobs/$JOB_ID")
STATE=$(echo "$STATUS" | jq -r '.status')
PROGRESS=$(echo "$STATUS" | jq -r '.progress')
echo "Job $JOB_ID: $STATE ($PROGRESS%)"
if [ "$STATE" = "completed" ]; then
echo "$STATUS" | jq .result
break
elif [ "$STATE" = "failed" ]; then
echo "Job failed: $(echo $STATUS | jq -r '.error')"
exit 1
fi
sleep 5
donePOST /pr/summary — The main CI endpoint
Request:
{"baseBranch": "main", "headBranch": "HEAD"}Returns: File counts, module impacts, hotspots touched, risk assessment (low/medium/high), suggested reviewers with coverage percentages.
Risk is calculated from:
- File count (>20 files = +0.3 risk)
- Lines changed (>1000 = +0.3 risk)
- Hotspots touched (+0.1 per hotspot, max 0.3)
- Module spread (>5 modules = +0.2 risk)
GET /ownership/drift — CODEOWNERS accuracy check
curl "http://localhost:8080/ownership/drift?threshold=0.3&limit=10"Compares declared owners (CODEOWNERS) vs actual contributors (git-blame). Returns files where ownership has drifted, with drift scores.
GET /hotspots — High-churn files
curl "http://localhost:8080/hotspots?limit=20"Returns files ranked by volatility (commit frequency, author count, complexity).
POST /architecture/refresh — Rebuild cached analysis
curl -X POST http://localhost:8080/architecture/refresh \
-H "Content-Type: application/json" \
-d '{"scope": "all", "async": true}'With async: true, returns a jobId immediately. Poll /jobs/:id for completion.
GET /jobs/:id — Check async job status
curl "http://localhost:8080/jobs/job-abc123"Returns: status (queued/running/completed/failed), progress (0-100), result (when done).
When changes touch API contracts (protobuf, OpenAPI), CKB can detect cross-boundary impact that simple file diffs miss.
A "local" change to user.proto might break consumers in three other repositories. Without contract analysis, this surfaces as production incidents, not PR warnings.
- name: Check Contract Impact
run: |
# Find changed contract files
CONTRACTS=$(git diff --name-only ${{ github.base_ref }}...HEAD | grep -E '\.(proto|yaml|json)$' | grep -E '(proto/|openapi/|api/)' || true)
if [ -n "$CONTRACTS" ]; then
echo "⚠️ Contract files changed:"
echo "$CONTRACTS"
for CONTRACT in $CONTRACTS; do
echo "Analyzing impact of $CONTRACT..."
curl -s "http://localhost:8080/contracts/impact?path=$CONTRACT" | jq .
done
fi{
"contract": "proto/api/v1/user.proto",
"visibility": "public",
"consumers": [
{"repo": "frontend", "confidence": "high", "files": ["src/api/user.ts"]},
{"repo": "mobile-app", "confidence": "medium", "files": ["lib/api/user.dart"]}
],
"riskLevel": "high",
"riskFactors": [
"Public contract with 2 known consumers",
"Breaking field removal detected"
],
"suggestion": "Coordinate with frontend and mobile-app teams before merging"
}- name: Contract Safety Check
run: |
CONTRACTS=$(git diff --name-only ${{ github.base_ref }}...HEAD | grep -E '\.proto$' || true)
for CONTRACT in $CONTRACTS; do
RESULT=$(curl -s "http://localhost:8080/contracts/impact?path=$CONTRACT")
RISK=$(echo "$RESULT" | jq -r '.riskLevel')
CONSUMERS=$(echo "$RESULT" | jq -r '.consumers | length')
if [ "$RISK" = "high" ] && [ "$CONSUMERS" -gt 0 ]; then
echo "::error::Contract $CONTRACT has $CONSUMERS consumers and is high risk"
echo "$RESULT" | jq .
exit 1
fi
doneWhen CKB detects a risky change, you can generate a checklist for the PR:
- name: Generate Refactor Checklist
if: steps.summary.outputs.risk == 'high'
uses: actions/github-script@v7
with:
script: |
const data = JSON.parse(`${{ steps.summary.outputs.result }}`);
let checklist = `## Safe Refactor Checklist\n\n`;
checklist += `This PR was flagged as **high risk**. Please verify:\n\n`;
// Add affected modules
if (data.modulesAffected?.length) {
checklist += `### Modules Affected\n`;
data.modulesAffected.forEach(m => {
checklist += `- [ ] Reviewed changes in \`${m.moduleId}\` (${m.filesChanged} files)\n`;
});
checklist += `\n`;
}
// Add reviewers to notify
if (data.suggestedReviewers?.length) {
checklist += `### Required Sign-offs\n`;
data.suggestedReviewers.forEach(r => {
checklist += `- [ ] ${r.owner} approved (owns ${Math.round(r.coverage * 100)}% of changes)\n`;
});
checklist += `\n`;
}
// Add hotspot warnings
if (data.summary?.hotspotsTouched > 0) {
checklist += `### Hotspot Review\n`;
checklist += `- [ ] Verified ${data.summary.hotspotsTouched} hotspot file(s) have adequate test coverage\n`;
checklist += `- [ ] Confirmed changes don't increase complexity\n\n`;
}
checklist += `### Before Merge\n`;
checklist += `- [ ] All tests passing\n`;
checklist += `- [ ] No unintended breaking changes\n`;
checklist += `- [ ] Documentation updated if needed\n`;
github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: checklist
});CKB can enforce documentation coverage thresholds and detect stale symbol references in CI.
Documentation that references deleted or renamed symbols becomes misleading. A function signature change can leave docs describing behavior that no longer exists.
Fail the build if documentation coverage drops below a threshold:
- name: Check Doc Coverage
run: |
# Initialize and index docs
ckb init
ckb docs index
# Fail if coverage below 80%
ckb docs coverage --fail-under=80Exit codes:
-
0: Coverage meets or exceeds threshold -
1: Coverage below threshold
Check for broken symbol references:
- name: Check Stale Docs
run: |
ckb docs index
STALE=$(ckb docs stale --all --format json | jq '.totalStale')
if [ "$STALE" -gt 0 ]; then
echo "::warning::Found $STALE stale symbol references in documentation"
ckb docs stale --all
fiFind what docs will break before you rename:
- name: Check Docs Impact
run: |
SYMBOL="UserService.Authenticate"
# Find docs referencing this symbol
DOCS=$(ckb docs symbol "$SYMBOL" --format json | jq '.docs | length')
if [ "$DOCS" -gt 0 ]; then
echo "::warning::$DOCS docs reference $SYMBOL - update after rename"
ckb docs symbol "$SYMBOL"
fi# .github/workflows/doc-check.yml
name: Documentation Quality
on:
pull_request:
paths:
- '**/*.md'
- '**/*.go'
- '**/*.ts'
jobs:
check-docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install CKB
run: npm install -g @tastehub/ckb
- name: Initialize
run: |
ckb init
ckb index
ckb docs index
- name: Check Coverage
run: ckb docs coverage --fail-under=70
- name: Check Staleness
run: |
RESULT=$(ckb docs stale --all --format json)
STALE=$(echo "$RESULT" | jq '.totalStale')
if [ "$STALE" -gt 0 ]; then
echo "## Stale Documentation References" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "$RESULT" | jq -r '.reports[] | .stale[] | "- \(.docPath):\(.line): \(.rawText) (\(.reason))"' >> $GITHUB_STEP_SUMMARY
exit 1
fiThis is: A way to get structured JSON about PR changes that you can parse and post as comments. It combines git diff data with CKB's hotspot/ownership/contract analysis to surface risk before merge.
This is not:
- A CLI command you can run directly (
ckb summarize-prdoesn't exist yet) - Enforcement — it posts warnings, doesn't block merges by default
- Magic — if you don't have CODEOWNERS, reviewers come from git-blame heuristics
- Real-time — hotspot data comes from the last
refreshArchitecturerun
The awkward part: You have to start a server (ckb serve &) and call it with curl. This is because v6.1 implemented the logic as HTTP handlers, not CLI commands. It works, but it's not as clean as ckb summarize-pr --base=main.
Recommended rollout:
- Start with just the PR comment (informational)
- Add hotspot warnings after you trust the data
- Add contract boundary detection for API changes (v6.3)
- Consider ownership drift on a schedule, not every PR
- Only add enforcement (failing builds) after the team trusts the signals
| Variable | Description | Default |
|---|---|---|
CKB_REPO_ROOT |
Repository root path | Current directory |
CKB_LOG_LEVEL |
Log verbosity (debug/info/warn/error) | info |
CKB_CONFIG_PATH |
Config file location | .ckb/config.json |
CKB_TIER |
Analysis tier: fast, standard, or full
|
Auto-detected |
-
Cache the
.ckb/directory — Enables incremental indexing across runs -
Use
fetch-depth: 0— Required for git-blame analysis and incremental indexing - Run refresh on schedule — Keep data fresh without blocking PRs
- Set appropriate timeouts — Large repos may need longer timeouts
- Use async for big repos — Avoid CI timeout issues
- Use incremental indexing for PRs — O(changed files) instead of O(total files)
-
Use
--forcefor nightly builds — Ensures maximum accuracy -
Validate with
ckb doctor --tier— Catch missing tools early -
Set
CKB_TIERenvironment variable — Control analysis depth explicitly
- name: Check Risk Level
run: |
RISK="${{ steps.summary.outputs.risk }}"
if [ "$RISK" = "high" ]; then
echo "::error::PR flagged as HIGH RISK. Manual review required."
exit 1
fi- name: Request Reviewers
uses: actions/github-script@v7
with:
script: |
const data = JSON.parse(`${{ steps.summary.outputs.result }}`);
const reviewers = data.suggestedReviewers
?.filter(r => !r.owner.startsWith('@')) // Filter out teams
.map(r => r.owner)
.slice(0, 2);
if (reviewers?.length) {
await github.rest.pulls.requestReviewers({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number,
reviewers: reviewers
});
}For organizations using a central CKB index server, publish indexes from CI:
# .github/workflows/publish-index.yml
name: Publish Index to CKB Server
on:
push:
branches: [main]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: '1.21'
- name: Install SCIP indexer
run: go install github.com/sourcegraph/scip-go/cmd/scip-go@latest
- name: Generate SCIP index
run: scip-go
- name: Upload to CKB server
env:
CKB_TOKEN: ${{ secrets.CKB_TOKEN }}
run: |
curl -X POST "${{ vars.CKB_SERVER_URL }}/index/repos/${{ github.repository }}/upload" \
-H "Authorization: Bearer $CKB_TOKEN" \
-H "Content-Type: application/octet-stream" \
-H "Content-Encoding: gzip" \
-H "X-CKB-Commit: ${{ github.sha }}" \
-H "X-CKB-Language: go" \
--data-binary @<(gzip -c index.scip)With compression (recommended for large indexes):
# gzip (widely available)
gzip -c index.scip | curl -X POST "$URL/upload" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Encoding: gzip" \
--data-binary @-
# zstd (faster, better compression)
zstd -c index.scip | curl -X POST "$URL/upload" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Encoding: zstd" \
--data-binary @-Setting up tokens:
# On the server, create a write-scoped token for CI
ckb token create --name "GitHub CI" --scopes write --repos "myorg/*"
# Add the returned token as CKB_TOKEN secret in GitHubSee Federation#authentication--api-keys-v74-phase-4 for token configuration.
Full example workflows are available in the repository:
-
examples/github-actions/pr-analysis.yml— PR analysis with comments -
examples/github-actions/scheduled-refresh.yml— Daily architecture refresh -
examples/github-actions/publish-index.yml— Publish to central index server