CI/CD Setup
Complete guide to integrating Technical Debt Radar into your CI/CD pipeline with GitHub Actions, GitLab CI, environment variables, and branch protection.
CI/CD Setup
Technical Debt Radar runs in CI to gate every pull request. This guide covers GitHub Actions and GitLab CI setup, including environment variables, secrets management, monorepo configuration, and branch protection rules.
GitHub Action
The official GitHub Action runs Radar on every pull request and posts results as a PR comment and status check.
Basic Setup
Create .github/workflows/radar.yml:
name: Technical Debt Radar
on:
pull_request:
branches: [main, develop]
permissions:
contents: read
pull-requests: write
statuses: write
jobs:
radar:
name: Debt Scan
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history needed for base branch comparison
- uses: actions/setup-node@v4
with:
node-version: 20
- name: Install dependencies
run: npm ci
- name: Run Technical Debt Radar
uses: technical-debt-radar/action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
radar-api-key: ${{ secrets.RADAR_API_KEY }}
All Inputs
| Input | Required | Default | Description |
|---|---|---|---|
github-token | Yes | --- | GitHub token for posting PR comments and status checks |
radar-api-key | Yes | --- | Your Radar API key (from dashboard settings) |
fail-on-violations | No | true | Set to false to report without blocking |
format | No | github | Output format: github, json, markdown, ai-prompt |
include-ai | No | false | Enable AI cross-file analysis (requires Anthropic API key) |
working-directory | No | . | Path to the project root (for monorepos) |
config | No | radar.yml | Path to the radar.yml config file |
rules | No | rules.yml | Path to the rules.yml file |
anthropic-api-key | No | --- | Anthropic API key (required when include-ai: true) |
base-branch | No | auto-detected | Base branch for comparison |
All Outputs
| Output | Description |
|---|---|
score | The computed debt_delta_score |
violations | Total number of violations found |
gate-result | pass or fail |
report-url | URL to the full report on the Radar dashboard |
Using Outputs in Downstream Steps
- name: Run Technical Debt Radar
id: radar
uses: technical-debt-radar/action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
radar-api-key: ${{ secrets.RADAR_API_KEY }}
- name: Post summary to Slack
if: steps.radar.outputs.gate-result == 'fail'
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "Radar gate failed on PR #${{ github.event.pull_request.number }}: score ${{ steps.radar.outputs.score }}, ${{ steps.radar.outputs.violations }} violations"
}
Full Configuration with AI
name: Technical Debt Radar (Full)
on:
pull_request:
branches: [main, develop]
permissions:
contents: read
pull-requests: write
statuses: write
jobs:
radar:
name: Debt Scan
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- name: Install dependencies
run: npm ci
- name: Run Technical Debt Radar
id: radar
uses: technical-debt-radar/action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
radar-api-key: ${{ secrets.RADAR_API_KEY }}
include-ai: true
anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}
fail-on-violations: true
format: github
- name: Upload report artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: radar-report
path: .radar/report.json
retention-days: 30
GitLab CI
Basic Setup
Add to your .gitlab-ci.yml:
stages:
- test
- quality
radar:
stage: quality
image: node:20
variables:
RADAR_API_KEY: $RADAR_API_KEY
before_script:
- npm ci
- npm i -g @radar/cli
script:
- radar run . --format gitlab
rules:
- if: $CI_MERGE_REQUEST_IID
allow_failure: false
artifacts:
when: always
paths:
- .radar/report.json
expire_in: 30 days
With AI Analysis
radar:
stage: quality
image: node:20
variables:
RADAR_API_KEY: $RADAR_API_KEY
ANTHROPIC_API_KEY: $ANTHROPIC_API_KEY
before_script:
- npm ci
- npm i -g @radar/cli
script:
- radar run . --format gitlab --include-ai
rules:
- if: $CI_MERGE_REQUEST_IID
allow_failure: false
Shared Pipeline (Include in Multiple Projects)
Create a shared CI template at https://gitlab.com/your-org/ci-templates/-/raw/main/radar.yml:
.radar:
stage: quality
image: node:20
before_script:
- npm ci
- npm i -g @radar/cli
script:
- radar run . --format gitlab
rules:
- if: $CI_MERGE_REQUEST_IID
artifacts:
when: always
paths:
- .radar/report.json
expire_in: 30 days
Include in your project's .gitlab-ci.yml:
include:
- remote: 'https://gitlab.com/your-org/ci-templates/-/raw/main/radar.yml'
radar:
extends: .radar
variables:
RADAR_API_KEY: $RADAR_API_KEY
GitLab Merge Request Approval Rules
Configure GitLab to require the Radar job to pass before merging:
- Go to Settings > Merge Requests.
- Under Merge checks, enable Pipelines must succeed.
- The
radarjob will prevent merging when it exits with code 1.
Environment Variables
Both GitHub Actions and GitLab CI need the following variables configured:
| Variable | Required | Where to Set | Description |
|---|---|---|---|
RADAR_API_KEY | Yes | Repository secrets | API key from your Radar dashboard |
ANTHROPIC_API_KEY | AI only | Repository secrets | Anthropic API key for AI features |
GITHUB_TOKEN | GitHub only | Automatic | Provided by GitHub Actions automatically |
GitHub: Setting Secrets
- Go to your repository on GitHub.
- Navigate to Settings > Secrets and variables > Actions.
- Click New repository secret.
- Add
RADAR_API_KEYwith your API key from the Radar dashboard. - If using AI features, add
ANTHROPIC_API_KEY.
GitLab: Setting Variables
- Go to your project on GitLab.
- Navigate to Settings > CI/CD > Variables.
- Add
RADAR_API_KEYwith your API key. Check Mask variable. - If using AI features, add
ANTHROPIC_API_KEY. Check Mask variable.
Warning: Never commit API keys to your repository. Always use CI/CD secrets or environment variables.
Monorepo Configuration
For monorepos with multiple projects, run Radar on each project separately using the working-directory input.
GitHub Actions (Monorepo)
name: Technical Debt Radar
on:
pull_request:
branches: [main]
permissions:
contents: read
pull-requests: write
statuses: write
jobs:
radar-api:
name: Radar — API
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- uses: technical-debt-radar/action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
radar-api-key: ${{ secrets.RADAR_API_KEY }}
working-directory: apps/api
radar-web:
name: Radar — Web
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- uses: technical-debt-radar/action@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
radar-api-key: ${{ secrets.RADAR_API_KEY }}
working-directory: apps/web
GitLab CI (Monorepo)
.radar-base:
stage: quality
image: node:20
before_script:
- npm ci
- npm i -g @radar/cli
rules:
- if: $CI_MERGE_REQUEST_IID
artifacts:
when: always
paths:
- .radar/report.json
radar-api:
extends: .radar-base
script:
- cd apps/api && radar run . --format gitlab
variables:
RADAR_API_KEY: $RADAR_API_KEY
radar-web:
extends: .radar-base
script:
- cd apps/web && radar run . --format gitlab
variables:
RADAR_API_KEY: $RADAR_API_KEY
Branch Protection Rules
Configure your repository to require the Radar check before merging.
GitHub Branch Protection
- Go to Settings > Branches > Branch protection rules.
- Click Add rule for
main(or your default branch). - Enable Require status checks to pass before merging.
- Search for and select the Debt Scan check (or whatever you named the job).
- Enable Require branches to be up to date before merging to ensure the check runs against the latest base branch.
GitHub Rulesets (Recommended for Organizations)
For organizations using the newer GitHub Rulesets:
- Go to Settings > Rules > Rulesets.
- Create a new ruleset targeting
main. - Add Require status checks and select the Radar check.
- Apply to the organization or specific repositories.
GitLab Protected Branches
- Go to Settings > Repository > Protected branches.
- For the
mainbranch, set Allowed to merge to Maintainers. - Under Settings > Merge Requests, enable Pipelines must succeed.
Troubleshooting
"Permission denied" on PR Comment
Ensure your workflow has the correct permissions:
permissions:
contents: read
pull-requests: write
statuses: write
If using a fine-grained personal access token instead of GITHUB_TOKEN, it needs pull_requests: write and statuses: write scopes.
"No radar.yml found"
Verify the working-directory input points to the directory containing your radar.yml. For monorepos, each app needs its own config file.
Scan Takes Too Long
For large PRs (100+ changed files), consider:
- Set
timeout-minutes: 15on the job. - Disable AI analysis in CI (
include-ai: false) to reduce time. - Use
--changed-onlyto analyze only files changed in the PR, not the entire project.
GitLab: Job Succeeds When It Should Fail
Ensure allow_failure: false is set on the job. Check that the script uses radar run (which exits with code 1 on violations) rather than radar scan (which always exits with code 0).