Guides

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

InputRequiredDefaultDescription
github-tokenYes---GitHub token for posting PR comments and status checks
radar-api-keyYes---Your Radar API key (from dashboard settings)
fail-on-violationsNotrueSet to false to report without blocking
formatNogithubOutput format: github, json, markdown, ai-prompt
include-aiNofalseEnable AI cross-file analysis (requires Anthropic API key)
working-directoryNo.Path to the project root (for monorepos)
configNoradar.ymlPath to the radar.yml config file
rulesNorules.ymlPath to the rules.yml file
anthropic-api-keyNo---Anthropic API key (required when include-ai: true)
base-branchNoauto-detectedBase branch for comparison

All Outputs

OutputDescription
scoreThe computed debt_delta_score
violationsTotal number of violations found
gate-resultpass or fail
report-urlURL 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:

  1. Go to Settings > Merge Requests.
  2. Under Merge checks, enable Pipelines must succeed.
  3. The radar job will prevent merging when it exits with code 1.

Environment Variables

Both GitHub Actions and GitLab CI need the following variables configured:

VariableRequiredWhere to SetDescription
RADAR_API_KEYYesRepository secretsAPI key from your Radar dashboard
ANTHROPIC_API_KEYAI onlyRepository secretsAnthropic API key for AI features
GITHUB_TOKENGitHub onlyAutomaticProvided by GitHub Actions automatically

GitHub: Setting Secrets

  1. Go to your repository on GitHub.
  2. Navigate to Settings > Secrets and variables > Actions.
  3. Click New repository secret.
  4. Add RADAR_API_KEY with your API key from the Radar dashboard.
  5. If using AI features, add ANTHROPIC_API_KEY.

GitLab: Setting Variables

  1. Go to your project on GitLab.
  2. Navigate to Settings > CI/CD > Variables.
  3. Add RADAR_API_KEY with your API key. Check Mask variable.
  4. 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

  1. Go to Settings > Branches > Branch protection rules.
  2. Click Add rule for main (or your default branch).
  3. Enable Require status checks to pass before merging.
  4. Search for and select the Debt Scan check (or whatever you named the job).
  5. Enable Require branches to be up to date before merging to ensure the check runs against the latest base branch.

For organizations using the newer GitHub Rulesets:

  1. Go to Settings > Rules > Rulesets.
  2. Create a new ruleset targeting main.
  3. Add Require status checks and select the Radar check.
  4. Apply to the organization or specific repositories.

GitLab Protected Branches

  1. Go to Settings > Repository > Protected branches.
  2. For the main branch, set Allowed to merge to Maintainers.
  3. 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: 15 on the job.
  • Disable AI analysis in CI (include-ai: false) to reduce time.
  • Use --changed-only to 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).

Technical Debt Radar Documentation