CI/CD Integration

SqC is designed for CI/CD pipelines with exit codes, severity thresholds, diff-only analysis, and SARIF output for code scanning integrations.

General Strategy

A typical CI setup uses two modes:

  1. PR analysis (diff-only): fast feedback on changed files only

  2. Push/merge analysis (full scan): comprehensive scan on the main branch

Both modes export SARIF for integration with code scanning dashboards.

# PR mode: fast, only changed files, fail on High+
sqc . --diff --min-severity Medium --fail-on-severity High --export results.sarif

# Full scan: entire repo with cross-file context
sqc . -d . --min-severity Medium --fail-on-severity High --export results.sarif

GitHub Actions

The repository includes a ready-to-use workflow at .github/workflows/sqc-analysis.yml:

name: SqC CERT C Analysis

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  build:
    name: Build SqC
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Cache Cargo
        uses: actions/cache@v4
        with:
          path: |
            ~/.cargo/registry
            ~/.cargo/git
            target
          key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}

      - name: Build SqC
        run: cargo build --release

      - name: Upload binary
        uses: actions/upload-artifact@v4
        with:
          name: sqc-binary
          path: target/release/sqc

  analyze-pr:
    name: Analyze PR (diff only)
    if: github.event_name == 'pull_request'
    needs: build
    runs-on: ubuntu-latest
    permissions:
      security-events: write
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0  # Full history for --diff mode

      - name: Download SqC
        uses: actions/download-artifact@v4
        with:
          name: sqc-binary

      - run: chmod +x sqc

      - name: Run SqC (diff mode)
        run: |
          ./sqc . --diff \
            --min-severity Medium \
            --fail-on-severity High \
            --export results.sarif

      - name: Upload SARIF
        uses: github/codeql-action/upload-sarif@v3
        if: always()
        with:
          sarif_file: results.sarif

  analyze-full:
    name: Full Analysis
    if: github.event_name == 'push'
    needs: build
    runs-on: ubuntu-latest
    permissions:
      security-events: write
    steps:
      - uses: actions/checkout@v4

      - name: Download SqC
        uses: actions/download-artifact@v4
        with:
          name: sqc-binary

      - run: chmod +x sqc

      - name: Run SqC (full scan)
        run: |
          ./sqc . -d . \
            --min-severity Medium \
            --fail-on-severity High \
            --export results.sarif

      - name: Upload SARIF
        uses: github/codeql-action/upload-sarif@v3
        if: always()
        with:
          sarif_file: results.sarif

Azure DevOps

A ready-to-use Azure Pipelines configuration is provided at docs/azure-pipelines.yml:

# SqC Static Analysis - Azure DevOps Example Pipeline
#
# This pipeline runs SqC CERT C analysis on your C/C++ codebase.
# - On PRs: analyzes only changed files (--diff mode)
# - On push to main: full repository scan
# - Publishes SARIF results as a build artifact
#
# Prerequisites:
#   - Rust toolchain installed on the agent (or use a Rust container)
#   - A sqc-rules.toml manifest (or use built-in defaults)

trigger:
  branches:
    include:
      - main

pr:
  branches:
    include:
      - main

pool:
  vmImage: 'ubuntu-latest'

variables:
  CARGO_TERM_COLOR: always

stages:
  - stage: Build
    displayName: Build SqC
    jobs:
      - job: BuildSqC
        displayName: Build SqC binary
        steps:
          - task: Cache@2
            inputs:
              key: 'cargo | "$(Agent.OS)" | Cargo.lock'
              restoreKeys: |
                cargo | "$(Agent.OS)"
              path: $(Pipeline.Workspace)/.cargo
            displayName: Cache Cargo

          - script: |
              cargo build --release
            displayName: Build SqC

          - task: PublishPipelineArtifact@1
            inputs:
              targetPath: target/release/sqc
              artifactName: sqc-binary
            displayName: Publish SqC binary

  - stage: Analyze
    displayName: Run Analysis
    dependsOn: Build
    jobs:
      - job: AnalyzePR
        displayName: Analyze PR (diff only)
        condition: eq(variables['Build.Reason'], 'PullRequest')
        steps:
          - checkout: self
            fetchDepth: 0  # Full history for --diff mode

          - task: DownloadPipelineArtifact@2
            inputs:
              artifactName: sqc-binary
              targetPath: $(Build.SourcesDirectory)
            displayName: Download SqC binary

          - script: |
              chmod +x sqc
              ./sqc . --diff \
                --min-severity Medium \
                --fail-on-severity High \
                --export results.sarif
            displayName: Run SqC (diff mode)

          - task: PublishBuildArtifacts@1
            inputs:
              pathToPublish: results.sarif
              artifactName: sarif-results
            displayName: Publish SARIF results
            condition: always()

      - job: AnalyzeFull
        displayName: Full Analysis
        condition: ne(variables['Build.Reason'], 'PullRequest')
        steps:
          - checkout: self

          - task: DownloadPipelineArtifact@2
            inputs:
              artifactName: sqc-binary
              targetPath: $(Build.SourcesDirectory)
            displayName: Download SqC binary

          - script: |
              chmod +x sqc
              ./sqc . -d . \
                --min-severity Medium \
                --fail-on-severity High \
                --export results.sarif
            displayName: Run SqC (full scan)

          - task: PublishBuildArtifacts@1
            inputs:
              pathToPublish: results.sarif
              artifactName: sarif-results
            displayName: Publish SARIF results
            condition: always()

SARIF Integration Tips

  • GitHub Code Scanning: Use github/codeql-action/upload-sarif@v3 to surface SqC violations as code scanning alerts on PRs and the Security tab.

  • Azure DevOps: Publish SARIF as a build artifact. Third-party extensions (e.g., SARIF SAST Scans Tab) can render results inline.

  • VS Code: Open .sarif files with the SARIF Viewer extension for inline annotations.

  • IDE Integration: Any tool that consumes SARIF 2.1.0 can display SqC results.

CI/CD Readiness

Component

Status

Readiness

Output Formats

CSV, XLSX, JSON, SARIF 2.1.0

100%

Exit Codes

--fail-on-violation, --fail-on-severity

100%

Severity Filtering

--min-severity, --fail-on-severity

100%

Rule Filtering

--rules ARR30-C,MEM30-C

100%

Incremental

--diff (git modified files)

90%

CI Workflows

GitHub Actions + Azure DevOps templates

100%

Suppressions

SHA-256 code-location

70%

Docker

No image published

0%

Remaining gaps:

  1. No baseline-aware suppression — can’t report “only new violations since last run”

  2. No Docker image for containerized CI/CD

  3. Unclassified real-world violation density — no ground truth to split TP vs FP on production code