# Since we have multiple build targets, and the makefile that CodeQL would use in its autobuild
# step doesn't build everything, we need to manually add run the Go (and C++) build commands
#
# See:
# https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning
# https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
#
# Additionally, see example CodeQL pipeline (in CodeQL repo):
# https://github.com/github/codeql/blob/0342b3eba242476cea815e601942021092d0bc10/.github/workflows/codeql-analysis.yml

name: "CodeQL"

on:
  push:
    branches: ["main", "release/*"]
  pull_request:
    branches: ["main", "release/*"]
    paths-ignore:
      - "**/*.md"
      - "**/*.txt"
      - "hack/**"
      - "scripts/**"
      - ".github/**"
      - "!.github/workflows/codeql.yml"
  schedule:
    # run weekly, at midnight on Sunday
    # minute, hour, day of month, month, day of week
    - cron: "0 0 * * 0"

jobs:
  analyze:
    name: Analyze (${{ matrix.language }} - ${{ matrix.goos }})
    runs-on: ubuntu-latest

    permissions:
      # required for all workflows
      security-events: write

      # required to fetch internal or private CodeQL packs
      packages: read

      # only required for workflows in private repositories
      actions: read
      contents: read

    strategy:
      fail-fast: false
      matrix:
        # we want a matrix across the two GOOS options, not the product of all options
        # ! update `targets` field if more binaries are added
        include:
          - goos: windows
            language: go
            targets: >-
              cmd/containerd-shim-runhcs-v1,
              cmd/device-util,
              cmd/jobobject-util,
              cmd/ncproxy,
              cmd/runhcs,
              cmd/shimdiag,
              cmd/tar2ext4,
              cmd/wclayer,
              internal/tools/extendedtask,
              internal/tools/grantvmgroupaccess,
              internal/tools/networkagent,
              internal/tools/securitypolicy,
              internal/tools/uvmboot,
              internal/tools/zapdir,

          - goos: linux
            language: go, c-cpp
            targets: >-
              cmd/gcs,
              cmd/gcstools,
              cmd/hooks/wait-paths,
              cmd/tar2ext4,
              internal/tools/policyenginesimulator,
              internal/tools/securitypolicy,
              internal/tools/snp-report,

    steps:
      # setup runner before initializing & running CodeQL

      - name: Checkout
        uses: actions/checkout@v4
        with:
          show-progress: false

      - name: Install Go
        uses: ./.github/actions/setup-go
        with:
          fill-module-cache: true

      - name: CodeQL Initialize
        uses: github/codeql-action/init@v3
        with:
          build-mode: manual
          languages: ${{matrix.language}}

      # build binaries
      - name: Build go binaries
        shell: pwsh
        run: |
          $targets = "${{ matrix.targets }}" -split ',' |
            foreach { $_.Trim() } |
            where { -not [string]::IsNullOrWhiteSpace($_) }
          Write-Output "Targets: $targets"

          foreach ( $t in $targets ) {
            Write-Output "Build: $t"
            go build "./$t" 2>&1
          }
        env:
          GOOS: ${{ matrix.goos }}

      - name: Build init and vsockexec
        if: ${{ matrix.goos == 'linux' }}
        run: make bin/vsockexec bin/init

      # only upload results if the analysis fails
      # otherwise, save the output and use `advanced-security/filter-sarif` to filter paths
      - name: CodeQL Analyze
        uses: github/codeql-action/analyze@v3
        with:
          category: "/language:${{matrix.language}}"
          output: sarif-results
          upload: failure-only

      - name: Filter Go SARIF Results
        uses: advanced-security/filter-sarif@v1
        with:
          patterns: |
            +**/*.go
            -**/*_test.go
            -test/**/*.go
            -vendor/**/*.go
          input: sarif-results/go.sarif
          output: sarif-results/go.sarif

      - name: Filter C/C++ SARIF Results
        uses: advanced-security/filter-sarif@v1
        if: ${{ matrix.goos == 'linux' }}
        with:
          patterns: |
            +**/*
            -vendor/**/*
          input: sarif-results/cpp.sarif
          output: sarif-results/cpp.sarif

      - name: Upload SARIF
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: sarif-results

      - name: Upload SARIF Results as Build Artifact
        uses: actions/upload-artifact@v4
        with:
          name: sarif-results-${{ matrix.goos }}
          path: sarif-results
          retention-days: 1
