From 6f19305dee2bb3e7f04b42888e359891b4ce1e02 Mon Sep 17 00:00:00 2001 From: StringKE Date: Tue, 11 Aug 2026 17:50:54 +0400 Subject: [PATCH 1/2] ci(codeql): path-gate native language analysis on pull requests Only run go/python/ruby/java/csharp/swift CodeQL jobs when matching sdk paths change. Docs and i18n PRs keep actions plus javascript-typescript without spinning macos Swift builds. Full matrix remains on main, schedule, and workflow_dispatch. Signed-off-by: StringKE --- .github/workflows/codeql.yml | 113 ++++++++++++++++++++++++++++++++++- 1 file changed, 112 insertions(+), 1 deletion(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index aac8e7a7..61ea05d9 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -15,10 +15,120 @@ concurrency: permissions: contents: read +# Language matrix is path-gated on pull_request so a docs/i18n-only change does not spin up +# macos Swift builds or other native SDK scanners. push to main, weekly schedule, and manual +# dispatch still analyze every configured language. jobs: + changes: + name: Detect languages + runs-on: ubuntu-latest + timeout-minutes: 5 + outputs: + actions: ${{ steps.select.outputs.actions }} + javascript-typescript: ${{ steps.select.outputs.javascript-typescript }} + go: ${{ steps.select.outputs.go }} + python: ${{ steps.select.outputs.python }} + ruby: ${{ steps.select.outputs.ruby }} + java-kotlin: ${{ steps.select.outputs.java-kotlin }} + csharp: ${{ steps.select.outputs.csharp }} + swift: ${{ steps.select.outputs.swift }} + steps: + # actions/checkout v7.0.1 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 + with: + fetch-depth: 0 + + - name: Select languages to analyze + id: select + shell: bash + run: | + set -euo pipefail + + enable_all() { + { + echo 'actions=true' + echo 'javascript-typescript=true' + echo 'go=true' + echo 'python=true' + echo 'ruby=true' + echo 'java-kotlin=true' + echo 'csharp=true' + echo 'swift=true' + } >> "$GITHUB_OUTPUT" + } + + # Full matrix outside pull requests (main, schedule, workflow_dispatch). + if [[ "${{ github.event_name }}" != 'pull_request' ]]; then + enable_all + exit 0 + fi + + # PRs always scan workflow YAML and the TypeScript/JavaScript surface. + { + echo 'actions=true' + echo 'javascript-typescript=true' + } >> "$GITHUB_OUTPUT" + + base='${{ github.event.pull_request.base.sha }}' + head='${{ github.event.pull_request.head.sha }}' + mapfile -t files < <(git diff --name-only "$base" "$head") + + match() { + local re="$1" + local f + for f in "${files[@]}"; do + if [[ "$f" =~ $re ]]; then + return 0 + fi + done + return 1 + } + + if match '^sdk/go/'; then echo 'go=true'; else echo 'go=false'; fi >> "$GITHUB_OUTPUT" + if match '^sdk/python/'; then echo 'python=true'; else echo 'python=false'; fi >> "$GITHUB_OUTPUT" + if match '^sdk/ruby/'; then echo 'ruby=true'; else echo 'ruby=false'; fi >> "$GITHUB_OUTPUT" + if match '^sdk/(java|android)/'; then + echo 'java-kotlin=true' + else + echo 'java-kotlin=false' + fi >> "$GITHUB_OUTPUT" + if match '^sdk/(dotnet|windows)/'; then + echo 'csharp=true' + else + echo 'csharp=false' + fi >> "$GITHUB_OUTPUT" + if match '^sdk/(ios|macos)/'; then + echo 'swift=true' + else + echo 'swift=false' + fi >> "$GITHUB_OUTPUT" + + { + echo 'Selected CodeQL languages for this pull request:' + echo " actions=true" + echo " javascript-typescript=true" + echo " go=$(grep '^go=' "$GITHUB_OUTPUT" | tail -1 | cut -d= -f2)" + echo " python=$(grep '^python=' "$GITHUB_OUTPUT" | tail -1 | cut -d= -f2)" + echo " ruby=$(grep '^ruby=' "$GITHUB_OUTPUT" | tail -1 | cut -d= -f2)" + echo " java-kotlin=$(grep '^java-kotlin=' "$GITHUB_OUTPUT" | tail -1 | cut -d= -f2)" + echo " csharp=$(grep '^csharp=' "$GITHUB_OUTPUT" | tail -1 | cut -d= -f2)" + echo " swift=$(grep '^swift=' "$GITHUB_OUTPUT" | tail -1 | cut -d= -f2)" + } + analyze: name: Analyze ${{ matrix.language }} - if: github.event.repository.visibility == 'public' + needs: changes + if: | + github.event.repository.visibility == 'public' && ( + (matrix.language == 'actions' && needs.changes.outputs.actions == 'true') || + (matrix.language == 'javascript-typescript' && needs.changes.outputs.javascript-typescript == 'true') || + (matrix.language == 'go' && needs.changes.outputs.go == 'true') || + (matrix.language == 'python' && needs.changes.outputs.python == 'true') || + (matrix.language == 'ruby' && needs.changes.outputs.ruby == 'true') || + (matrix.language == 'java-kotlin' && needs.changes.outputs.java-kotlin == 'true') || + (matrix.language == 'csharp' && needs.changes.outputs.csharp == 'true') || + (matrix.language == 'swift' && needs.changes.outputs.swift == 'true') + ) runs-on: ${{ matrix.runner }} timeout-minutes: 60 permissions: @@ -54,6 +164,7 @@ jobs: build-mode: manual runner: macos-latest steps: + # actions/checkout v7.0.1 - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 - name: Initialize CodeQL From 3f4a37b107635e1b26aeafc4f5fecf2cf7d5f942 Mon Sep 17 00:00:00 2001 From: StringKE Date: Tue, 11 Aug 2026 17:54:21 +0400 Subject: [PATCH 2/2] ci(codeql): emit dynamic matrix instead of matrix if with needs Job-level if cannot use the matrix context when the job has needs. Detect languages now outputs matrix JSON; analyze consumes it via fromJSON so path gating validates and runs. Signed-off-by: StringKE --- .github/workflows/codeql.yml | 203 +++++++++++++++++------------------ 1 file changed, 97 insertions(+), 106 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 61ea05d9..28fedf77 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -18,20 +18,18 @@ permissions: # Language matrix is path-gated on pull_request so a docs/i18n-only change does not spin up # macos Swift builds or other native SDK scanners. push to main, weekly schedule, and manual # dispatch still analyze every configured language. +# +# Important: job-level `if` with `needs` cannot use the `matrix` context. The detect job therefore +# emits the concrete matrix JSON and analyze consumes it with fromJSON. jobs: changes: name: Detect languages + if: github.event.repository.visibility == 'public' runs-on: ubuntu-latest timeout-minutes: 5 outputs: - actions: ${{ steps.select.outputs.actions }} - javascript-typescript: ${{ steps.select.outputs.javascript-typescript }} - go: ${{ steps.select.outputs.go }} - python: ${{ steps.select.outputs.python }} - ruby: ${{ steps.select.outputs.ruby }} - java-kotlin: ${{ steps.select.outputs.java-kotlin }} - csharp: ${{ steps.select.outputs.csharp }} - swift: ${{ steps.select.outputs.swift }} + matrix: ${{ steps.select.outputs.matrix }} + has_work: ${{ steps.select.outputs.has_work }} steps: # actions/checkout v7.0.1 - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 @@ -44,91 +42,109 @@ jobs: run: | set -euo pipefail - enable_all() { - { - echo 'actions=true' - echo 'javascript-typescript=true' - echo 'go=true' - echo 'python=true' - echo 'ruby=true' - echo 'java-kotlin=true' - echo 'csharp=true' - echo 'swift=true' - } >> "$GITHUB_OUTPUT" + # language|build_mode|runner + all_rows=( + 'actions|none|ubuntu-latest' + 'javascript-typescript|none|ubuntu-latest' + 'go|autobuild|ubuntu-latest' + 'python|none|ubuntu-latest' + 'ruby|none|ubuntu-latest' + 'java-kotlin|none|ubuntu-latest' + 'csharp|none|ubuntu-latest' + 'swift|manual|macos-latest' + ) + + selected=() + + append_row() { + local row="$1" + selected+=("$row") + } + + append_all() { + local row + for row in "${all_rows[@]}"; do + append_row "$row" + done } # Full matrix outside pull requests (main, schedule, workflow_dispatch). if [[ "${{ github.event_name }}" != 'pull_request' ]]; then - enable_all + append_all + else + # PRs always scan workflow YAML and the TypeScript/JavaScript surface. + append_row 'actions|none|ubuntu-latest' + append_row 'javascript-typescript|none|ubuntu-latest' + + base='${{ github.event.pull_request.base.sha }}' + head='${{ github.event.pull_request.head.sha }}' + mapfile -t files < <(git diff --name-only "$base" "$head") + + match() { + local re="$1" + local f + for f in "${files[@]}"; do + if [[ "$f" =~ $re ]]; then + return 0 + fi + done + return 1 + } + + if match '^sdk/go/'; then + append_row 'go|autobuild|ubuntu-latest' + fi + if match '^sdk/python/'; then + append_row 'python|none|ubuntu-latest' + fi + if match '^sdk/ruby/'; then + append_row 'ruby|none|ubuntu-latest' + fi + if match '^sdk/(java|android)/'; then + append_row 'java-kotlin|none|ubuntu-latest' + fi + if match '^sdk/(dotnet|windows)/'; then + append_row 'csharp|none|ubuntu-latest' + fi + if match '^sdk/(ios|macos)/'; then + append_row 'swift|manual|macos-latest' + fi + fi + + if [[ ${#selected[@]} -eq 0 ]]; then + echo 'has_work=false' >> "$GITHUB_OUTPUT" + echo 'matrix={"include":[]}' >> "$GITHUB_OUTPUT" + echo 'No CodeQL languages selected.' exit 0 fi - # PRs always scan workflow YAML and the TypeScript/JavaScript surface. + include_json='[' + first=1 + for row in "${selected[@]}"; do + IFS='|' read -r language build_mode runner <<<"$row" + if [[ $first -eq 0 ]]; then + include_json+=',' + fi + first=0 + include_json+=$(printf '{"language":"%s","build_mode":"%s","runner":"%s"}' \ + "$language" "$build_mode" "$runner") + done + include_json+=']' + + matrix_json=$(printf '{"include":%s}' "$include_json") { - echo 'actions=true' - echo 'javascript-typescript=true' + echo "has_work=true" + echo "matrix=$matrix_json" } >> "$GITHUB_OUTPUT" - base='${{ github.event.pull_request.base.sha }}' - head='${{ github.event.pull_request.head.sha }}' - mapfile -t files < <(git diff --name-only "$base" "$head") - - match() { - local re="$1" - local f - for f in "${files[@]}"; do - if [[ "$f" =~ $re ]]; then - return 0 - fi - done - return 1 - } - - if match '^sdk/go/'; then echo 'go=true'; else echo 'go=false'; fi >> "$GITHUB_OUTPUT" - if match '^sdk/python/'; then echo 'python=true'; else echo 'python=false'; fi >> "$GITHUB_OUTPUT" - if match '^sdk/ruby/'; then echo 'ruby=true'; else echo 'ruby=false'; fi >> "$GITHUB_OUTPUT" - if match '^sdk/(java|android)/'; then - echo 'java-kotlin=true' - else - echo 'java-kotlin=false' - fi >> "$GITHUB_OUTPUT" - if match '^sdk/(dotnet|windows)/'; then - echo 'csharp=true' - else - echo 'csharp=false' - fi >> "$GITHUB_OUTPUT" - if match '^sdk/(ios|macos)/'; then - echo 'swift=true' - else - echo 'swift=false' - fi >> "$GITHUB_OUTPUT" - - { - echo 'Selected CodeQL languages for this pull request:' - echo " actions=true" - echo " javascript-typescript=true" - echo " go=$(grep '^go=' "$GITHUB_OUTPUT" | tail -1 | cut -d= -f2)" - echo " python=$(grep '^python=' "$GITHUB_OUTPUT" | tail -1 | cut -d= -f2)" - echo " ruby=$(grep '^ruby=' "$GITHUB_OUTPUT" | tail -1 | cut -d= -f2)" - echo " java-kotlin=$(grep '^java-kotlin=' "$GITHUB_OUTPUT" | tail -1 | cut -d= -f2)" - echo " csharp=$(grep '^csharp=' "$GITHUB_OUTPUT" | tail -1 | cut -d= -f2)" - echo " swift=$(grep '^swift=' "$GITHUB_OUTPUT" | tail -1 | cut -d= -f2)" - } + echo "Selected CodeQL matrix: $matrix_json" analyze: name: Analyze ${{ matrix.language }} needs: changes if: | - github.event.repository.visibility == 'public' && ( - (matrix.language == 'actions' && needs.changes.outputs.actions == 'true') || - (matrix.language == 'javascript-typescript' && needs.changes.outputs.javascript-typescript == 'true') || - (matrix.language == 'go' && needs.changes.outputs.go == 'true') || - (matrix.language == 'python' && needs.changes.outputs.python == 'true') || - (matrix.language == 'ruby' && needs.changes.outputs.ruby == 'true') || - (matrix.language == 'java-kotlin' && needs.changes.outputs.java-kotlin == 'true') || - (matrix.language == 'csharp' && needs.changes.outputs.csharp == 'true') || - (matrix.language == 'swift' && needs.changes.outputs.swift == 'true') - ) + github.event.repository.visibility == 'public' && + needs.changes.outputs.has_work == 'true' runs-on: ${{ matrix.runner }} timeout-minutes: 60 permissions: @@ -137,32 +153,7 @@ jobs: security-events: write strategy: fail-fast: false - matrix: - include: - - language: actions - build-mode: none - runner: ubuntu-latest - - language: javascript-typescript - build-mode: none - runner: ubuntu-latest - - language: go - build-mode: autobuild - runner: ubuntu-latest - - language: python - build-mode: none - runner: ubuntu-latest - - language: ruby - build-mode: none - runner: ubuntu-latest - - language: java-kotlin - build-mode: none - runner: ubuntu-latest - - language: csharp - build-mode: none - runner: ubuntu-latest - - language: swift - build-mode: manual - runner: macos-latest + matrix: ${{ fromJSON(needs.changes.outputs.matrix) }} steps: # actions/checkout v7.0.1 - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 @@ -171,10 +162,10 @@ jobs: uses: github/codeql-action/init@5595ccaf912efad79be6eef63a5619ff05969be3 with: languages: ${{ matrix.language }} - build-mode: ${{ matrix.build-mode }} + build-mode: ${{ matrix.build_mode }} - name: Build Swift packages - if: matrix.build-mode == 'manual' && matrix.language == 'swift' + if: matrix.language == 'swift' run: | swift build --package-path sdk/ios swift build --package-path sdk/macos