Multi-Branch Scanning

Introduction

This document explains how to set up GitHub Actions workflows to perform CodeScan static analysis on a repository, including a baseline scan for the main branch and multi-branch scanning. Due to limitations in CodeScan/Sonar, special steps are required to manage the master/main branch creation.

YAML Files Overview

YAML
Purpose
Notes

First YAML Option 1

Baseline scan on main branch (flexible push/PR)

Uses ubuntu-latest; scans changed files only; generates SARIF.

First YAML Option 2

Baseline scan on main branch (restricted to main)

Uses ubuntu-latest; fails on red quality gate; requires secrets for login.

Second YAML

Multi-branch scan

Runs on any branch; push = standard branch analysis; PR = comparison analysis.

First YAML – Baseline Scan Options

Option 1

name: CI env: SONAR_SCANNER_VERSION: 5.0.1.3006 on: push: branches: - '*' paths-ignore: - src/test/java/** - target/** pull_request: branches: - '*' paths-ignore: - src/test/java/** - target/** jobs: build: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 - name: Cache files uses: actions/cache@v4 with: path: | ~/.sonar key: ${{ runner.os }}-sonar restore-keys: ${{ runner.os }}-sonar - name: Run Codescan On Push if: github.event_name == 'push' uses: codescan-io/[email protected] with: scanChangedFilesOnly: true organization: 'Enter organization key here' projectKey: 'Enter project key here' codeScanUrl: 'Enter your instance URL' login: ${{ secrets.codescan_token }} generateSarifFile: true - name: Run Codescan On PR if: github.event_name == 'pull_request' uses: codescan-io/[email protected] with: scanChangedFilesOnly: true organization: 'Enter organization key here' projectKey: 'Enter project key here' codeScanUrl: 'Enter your instance URL' login: ${{ secrets.codescan_token }} generateSarifFile: true args: | sonar.pullrequest.branch=${{github.head_ref}} sonar.pullrequest.base=${{github.base_ref}} sonar.pullrequest.key=${{github.event.number}} - name: Upload SARIF file uses: github/codeql-action/upload-sarif@v3 with: sarif_file: codescan.sarif - name: Archive code coverage results uses: actions/upload-artifact@v4 with: name: codescan.sarif path: codescan.sarif


Option 2

name: CI on: push: branches: [main] pull_request: branches: [main] env: SONAR_SCANNER_VERSION: 5.0.1.3006 jobs: build: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 - name: Cache files uses: actions/cache@v4 with: path: | ~/.sonar key: ${{ runner.os }}-sonar restore-keys: ${{ runner.os }}-sonar - name: Run Codescan On Push if: github.event_name == 'push' uses: codescan-io/[email protected] with: organization: 'Enter organization key here' projectKey: 'Enter project key here' codeScanUrl: 'Enter your instance URL' login: ${{ secrets.codescan_token }} generateSarifFile: true failOnRedQualityGate: true - name: Run Codescan On PR if: github.event_name == 'pull_request' uses: codescan-io/[email protected] with: organization: 'Enter organization key here' projectKey: 'Enter project key here' codeScanUrl: 'Enter your instance URL' login: ${{ secrets.codescan_token }} scanChangedFilesOnly: true generateSarifFile: true failOnRedQualityGate: true args: | sonar.pullrequest.branch=${{github.head_ref}} sonar.pullrequest.base=${{github.base_ref}} sonar.pullrequest.key=${{github.event.number}} - name: Upload SARIF file uses: github/codeql-action/upload-sarif@v3 with: sarif_file: codescan.sarif - name: Archive code coverage results uses: actions/upload-artifact@v4 with: name: codescan.sarif path: codescan.sarif


Handling Master/Main Branch Issue

  • After the first scan, a master branch may exist in CodeScan.

  • When switching to the second YAML, pushing to main may create an extra main branch.

Steps to resolve:

  1. Delete the newly created main branch in CodeScan.

  2. Rename the master branch to main.

  3. Confirm the baseline analysis is associated with the main.


Second YAML – Multi-Branch Scan

name: CI env: SONAR_SCANNER_VERSION: 5.0.1.3006 SONAR_SOURCES: force-app on: push: branches: - '*' paths-ignore: - src/test/java/** - target/** pull_request: branches: - '*' paths-ignore: - src/test/java/** - target/** jobs: build: runs-on: macos-latest steps: - name: Checkout repository uses: actions/checkout@v4 with: fetch-depth: 0 - name: Cache files uses: actions/cache@v4 with: path: | ~/.sonar key: ${{ runner.os }}-sonar restore-keys: ${{ runner.os }}-sonar - name: Run Codescan On Push if: github.event_name == 'push' uses: codescan-io/[email protected] with: scanChangedFilesOnly: true organization: 'Enter organization key here' projectKey: 'Enter project key here' codeScanUrl: 'Enter your instance URL' login: ${{ secrets.codescan_token }} generateSarifFile: true args: | sonar.branch.name=${{ github.ref_name }} sonar.sources=${{ env.SONAR_SOURCES }} sonar.exclusions=target/**,src/test/java/** - name: Run Codescan On PR if: github.event_name == 'pull_request' uses: codescan-io/[email protected] with: scanChangedFilesOnly: true organization: 'Enter organization key here' projectKey: 'Enter project key here' codeScanUrl: 'Enter your instance URL' login: ${{ secrets.codescan_token }} generateSarifFile: true args: | sonar.pullrequest.key=${{ github.event.pull_request.number }} sonar.pullrequest.branch=${{ github.head_ref }} sonar.pullrequest.base=${{ github.base_ref }} sonar.sources=${{ env.SONAR_SOURCES }} sonar.exclusions=target/**,src/test/java/** - name: Upload SARIF file uses: github/codeql-action/upload-sarif@v3 with: sarif_file: codescan.sarif - name: Archive code coverage results uses: actions/upload-artifact@v4 with: name: codescan.sarif


Step-by-Step Workflow

  1. Initial Baseline Scan

  • Add first YAML (Option 1 or 2) to scan main branch.

  • Push and verify baseline scan on CodeScan.

  1. Branch Adjustment

  • Replace YAML with second YAML

  • Delete extra main branch in CodeScan if created.

  • Rename master to main.

  1. Multi-Branch Scanning.

  • Push to other branches to enable scanning.

  • Verify SARIF upload and analysis in GitHub.


Notes & Considerations

  • Sonar/CodeScan limitations require the baseline to be on main/master first.

  • Always fetch full history for PR analysis (fetch-depth: 0).

  • SONAR_SOURCES: force-app Incase folder structure is other than DX

  • SONAR_SOURCES: src (or) .(. here represents the ROOT FOLDER)

  • Specifying Root Folder, CodeScan always scans the Root folder mentioned and files within it.

  • In scenarios where the customer has multiple root folders, using (.) will make sure every root folder in the repo is scanned.


Last updated

Was this helpful?