Skip to content

Latest commit

 

History

History
243 lines (193 loc) · 8.45 KB

File metadata and controls

243 lines (193 loc) · 8.45 KB

CI Integration

Cognitive Code Analysis is designed to run in continuous integration pipelines. You can analyse only the PHP files changed in a pull or merge request, publish the results as a comment, and upload reports as build artifacts.

This guide includes workflow examples originally shared in GitHub issue #29.

Overview

A typical CI integration follows these steps:

  1. Check out the repository with full git history (fetch-depth: 0)
  2. Determine which PHP files changed compared to the target branch
  3. Run bin/phpcca analyse on those files only
  4. Publish the report (Markdown comment, SARIF upload, or quality gate)

When phpcca.yaml exists in the project root, analyse loads it automatically. Use --config=path/to/config.yaml to override.

Report formats for CI

Format --report-type Use case
Markdown markdown Human-readable PR/MR comments
GitHub Actions github-actions Inline annotations in Actions logs
SARIF sarif GitHub Code Scanning
GitLab Code Quality gitlab-codequality GitLab merge request widget
Checkstyle XML checkstyle Jenkins, Maven Checkstyle Plugin
JUnit XML junit Jenkins JUnit plugin, build failure gates

Example:

bin/phpcca analyse src/ChangedFile.php --report-type=sarif --report-file=results.sarif

See Baseline Analysis to compare metrics against a previous run using --baseline or --generate-baseline.

GitHub Actions

The workflow below runs on pull requests, analyses changed PHP files, posts a Markdown report as a PR comment, and uploads the report as an artifact.

Add --config=phpcca.yaml if your config file is not named phpcca.yaml or not in the working directory.

name: Code Metrics

on:
  pull_request:
    paths:
      - '**/*.php'
    branches:
      - '*'

permissions:
  pull-requests: write
  contents: read

jobs:
  code-metrics:
    name: Cognitive Code Analysis
    runs-on: ubuntu-24.04
    if: github.event_name == 'pull_request'

    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Fetch base branch
        run: |
          git fetch origin ${{ github.base_ref }}:${{ github.base_ref }}

      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.4'
          extensions: json, fileinfo
          tools: composer

      - name: Install dependencies
        run: composer install --prefer-dist --no-ansi --no-interaction --no-progress --no-scripts

      - name: Analyze changed PHP files
        id: analyze
        run: |
          BASE_SHA="${{ github.event.pull_request.base.sha }}"
          HEAD_SHA="${{ github.sha }}"

          CHANGED_FILES=$(git diff --name-only --diff-filter=ACMR $BASE_SHA...$HEAD_SHA | grep '\.php$' | tr '\n' ' ' || echo "")

          if [ -n "$CHANGED_FILES" ]; then
            echo "Analyzing files: $CHANGED_FILES"
            bin/phpcca analyse $CHANGED_FILES --report-type=markdown --report-file=cca-report.md || true

            if [ -f "cca-report.md" ] && [ -s "cca-report.md" ]; then
              echo "has_report=true" >> $GITHUB_OUTPUT
              echo "Report generated successfully"
            else
              echo "has_report=false" >> $GITHUB_OUTPUT
              echo "No report generated"
            fi
          else
            echo "has_report=false" >> $GITHUB_OUTPUT
            echo "No PHP files changed, skipping analysis"
          fi

      - name: Post comment to PR
        if: steps.analyze.outputs.has_report == 'true'
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            const report = fs.readFileSync('cca-report.md', 'utf8');

            await github.rest.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: context.issue.number,
              body: report
            });

      - name: Upload report artifact
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: cca-report
          path: cca-report.md
          if-no-files-found: ignore

GitHub Code Scanning with SARIF

Replace the Markdown report step with:

bin/phpcca analyse $CHANGED_FILES --report-type=sarif --report-file=results.sarif

Then upload results.sarif using the GitHub Code Scanning upload action.

GitLab CI

The job below runs on merge requests, analyses changed PHP files, posts a Markdown report as an MR note, and stores the report as an artifact.

Use --config=phpcca.yaml when your config file is not auto-discovered from the project root.

Code-Metrics:
  interruptible: true
  extends: .setup_composer_install
  image: registry.gitlab.com/clipmyhorsetv/infrastructure/php_docker_images:8.4-nginx-php-dev
  stage: tests
  dependencies:
    - PHP-Unit
  variables:
    GIT_DEPTH: 0
  before_script:
    - git config --global --add safe.directory $CI_PROJECT_DIR
    - git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME:$CI_MERGE_REQUEST_TARGET_BRANCH_NAME
  script:
    - composer install --prefer-dist --no-ansi --no-interaction --no-progress --no-scripts
    - |
      if [ "$CI_PIPELINE_SOURCE" = "merge_request_event" ] && [ -n "$CI_MERGE_REQUEST_DIFF_BASE_SHA" ]; then
        CHANGED_FILES=$(git diff --name-only --diff-filter=ACMR $CI_MERGE_REQUEST_DIFF_BASE_SHA...$CI_COMMIT_SHA | grep '\.php$' | tr '\n' ' ')
      else
        CHANGED_FILES=$(find src/ -name "*.php" | tr '\n' ' ')
      fi
      if [ -n "$CHANGED_FILES" ]; then
        bin/phpcca analyse $CHANGED_FILES --report-type=markdown --report-file=cca-report.md --config=phpcca.yaml
        if [ -f "cca-report.md" ] && [ -s "cca-report.md" ]; then
          # Try with CI_JOB_TOKEN first, fallback to CI/CD variables
          if [ -n "$VALIDATOR" ]; then
            TOKEN="$VALIDATOR"
          else
            TOKEN="$CI_JOB_TOKEN"
          fi

          echo "Posting comment to merge request $CI_MERGE_REQUEST_IID..."
          echo "Report content preview:"
          head -5 cca-report.md

          # Use POST with body as query parameter as per GitLab API documentation
          RESPONSE=$(curl -s -w "\n%{http_code}" --request POST --header "PRIVATE-TOKEN: $TOKEN" \
            --data-urlencode "body=$(cat cca-report.md)" \
            "https://gitlab.com/api/v4/projects/$CI_PROJECT_ID/merge_requests/$CI_MERGE_REQUEST_IID/notes")

          HTTP_CODE=$(echo "$RESPONSE" | tail -1)
          RESPONSE_BODY=$(echo "$RESPONSE" | head -n -1)

          echo "HTTP Response Code: $HTTP_CODE"
          echo "Response Body: $RESPONSE_BODY"

          if [ "$HTTP_CODE" = "201" ]; then
            echo "Comment posted successfully"
          else
            echo "Failed to post comment. HTTP Code: $HTTP_CODE"
          fi
        fi
      else
        echo "No PHP files changed, skipping analysis"
        echo "[]" > cca-report.md
      fi
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
      changes:
        compare_to: "refs/heads/$CI_DEFAULT_BRANCH"
        paths:
          - '**/*.php'
    - when: never
  artifacts:
    when: always
    paths:
      - cca-report.md

GitLab Code Quality widget

Replace the Markdown report with:

bin/phpcca analyse $CHANGED_FILES --report-type=gitlab-codequality --report-file=gl-code-quality.json

GitLab picks up the Code Quality report automatically when configured in your pipeline.

Tips

  • Analyse only changed files in PR/MR pipelines to keep feedback fast and relevant.
  • Use baselines to show deltas between runs; see Baseline Analysis.
  • Disable cache in CI if you want a fresh analysis every run:
    cognitive:
      cache:
        enabled: false
  • Fail the build on complexity regressions using --report-type=junit or --report-type=checkstyle with your CI platform's quality gate support.

Related