name: CodeQL

# Advanced setup replacing GitHub's CodeQL default setup. Real analysis runs on
# every push to dev, weekly and on demand: actions, JavaScript/TypeScript and
# Python without a build, Swift built directly with SwiftPM on macOS.
#
# PRs do not run analysis. The code_scanning rule on dev waits for a result in
# every language category dev has, so each PR uploads an empty result per
# category in seconds instead. New alerts are reported by the dev-push scan of
# the merged commit (see docs/codeql-results.md). Empty results are only ever
# uploaded for PRs, never for dev.
#
# Default setup must be disabled for this workflow's uploads to be accepted.
# See docs/codeql-results.md.

on:
  pull_request:
    branches:
      - dev
  push:
    branches:
      - dev
  schedule:
    - cron: "17 5 * * 1"
  workflow_dispatch:

concurrency:
  group: codeql-${{ github.event_name }}-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: ${{ github.event_name == 'pull_request' }}

permissions:
  contents: read

jobs:
  analyze:
    name: Analyze (${{ matrix.language }})
    # Swift needs macOS (AppKit); JavaScript/TypeScript, the largest analysis,
    # uses every core it gets. PR legs only upload an empty result.
    runs-on: ${{ github.event_name == 'pull_request' && 'ubuntu-latest' || matrix.language == 'swift' && 'blacksmith-12vcpu-macos-15' || matrix.language == 'javascript-typescript' && 'blacksmith-16vcpu-ubuntu-2204' || 'ubuntu-latest' }}
    timeout-minutes: ${{ matrix.language == 'swift' && 45 || 30 }}
    permissions:
      actions: read
      contents: read
      packages: read
      security-events: write
    strategy:
      fail-fast: false
      matrix:
        include:
          - language: actions
            build-mode: none
          - language: javascript-typescript
            build-mode: none
          - language: python
            build-mode: none
          - language: swift
            build-mode: manual
    env:
      RUN_ANALYSIS: ${{ github.event_name != 'pull_request' }}
    steps:
      # PRs only need the commit identity for the upload, not the sources.
      - name: Checkout repository
        uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
        with:
          persist-credentials: false
          sparse-checkout: ${{ github.event_name == 'pull_request' && '.github/codeql' || '' }}

      # PRs: an empty CodeQL result for this category satisfies the dev
      # code_scanning rule without a scan. Dev pushes run the real analysis.
      - name: Write empty PR result
        if: github.event_name == 'pull_request'
        env:
          LANGUAGE: ${{ matrix.language }}
        run: |
          mkdir -p "$RUNNER_TEMP/codeql-pr"
          cat > "$RUNNER_TEMP/codeql-pr/$LANGUAGE.sarif" <<'SARIF'
          {
            "version": "2.1.0",
            "$schema": "https://json.schemastore.org/sarif-2.1.0.json",
            "runs": [
              {
                "tool": { "driver": { "name": "CodeQL", "rules": [] } },
                "results": []
              }
            ]
          }
          SARIF

      - name: Upload empty PR result
        if: github.event_name == 'pull_request'
        uses: github/codeql-action/upload-sarif@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
        with:
          sarif_file: ${{ runner.temp }}/codeql-pr/${{ matrix.language }}.sarif
          category: /language:${{ matrix.language }}

      - name: Initialize CodeQL
        if: env.RUN_ANALYSIS == 'true'
        uses: github/codeql-action/init@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
        with:
          languages: ${{ matrix.language }}
          build-mode: ${{ matrix.build-mode }}
          config-file: ./.github/codeql/codeql-config.yml

      # CodeQL traces this compile. Building the one SwiftPM product directly
      # skips autobuild's project discovery.
      - name: Build Swift
        if: env.RUN_ANALYSIS == 'true' && matrix.language == 'swift'
        run: swift build --package-path packages/computer-use/native --product ComputerUse

      - name: Perform CodeQL Analysis
        if: env.RUN_ANALYSIS == 'true'
        uses: github/codeql-action/analyze@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
        with:
          category: /language:${{ matrix.language }}