diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 0a7aa09530a8..7922f7b2e857 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -27,8 +27,94 @@ on: - cron: '25 10 * * 6' jobs: + detect-changes: + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: read + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + steps: + - name: Checkout repository history + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Generate Matrix + id: set-matrix + run: | + # Full matrix of all CodeQL supported languages and their build modes in Apache Beam. + ALL_MATRIX='[ + {"language": "actions", "build-mode": "none"}, + {"language": "go", "build-mode": "manual"}, + {"language": "java-kotlin", "build-mode": "autobuild"}, + {"language": "javascript-typescript", "build-mode": "none"}, + {"language": "python", "build-mode": "none"}, + {"language": "rust", "build-mode": "none"} + ]' + + # On periodic scheduled runs (cron) or manual dispatches, scan all languages. + if [[ "${{ github.event_name }}" == "schedule" || "${{ github.event_name }}" == "workflow_dispatch" ]]; then + echo "matrix=$ALL_MATRIX" >> $GITHUB_OUTPUT + exit 0 + fi + + # Determine the commit range to compare for changed files. + if [ "${{ github.event_name }}" = "pull_request" ]; then + BASE_SHA="${{ github.event.pull_request.base.sha }}" + HEAD_SHA="${{ github.event.pull_request.head.sha }}" + else + BASE_SHA="${{ github.event.before }}" + HEAD_SHA="${{ github.event.after }}" + fi + + # Fall back to comparing against HEAD~1 if base SHA is empty or zeroed. + if [ -z "$BASE_SHA" ] || [ "$BASE_SHA" = "0000000000000000000000000000000000000000" ]; then + CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD 2>/dev/null || echo "") + else + CHANGED_FILES=$(git diff --name-only "$BASE_SHA" "$HEAD_SHA" 2>/dev/null || echo "") + fi + + # Helper function to check if any changed file matches a given regex pattern. + check_path() { + local pattern="$1" + if echo "$CHANGED_FILES" | grep -q -E "$pattern"; then + echo "true" + else + echo "false" + fi + } + + # Check path changes for each language/module context. + ACTIONS_CHANGED=$(check_path "^\.github/") + GO_CHANGED=$(check_path "^sdks/go/|^playground/backend/|^learning/katas/go/|^learning/tour-of-beam/backend/") + JAVA_CHANGED=$(check_path "^sdks/java/|^runners/|^examples/java/|^examples/kotlin/|\.java$") + JS_CHANGED=$(check_path "^sdks/typescript/|\.js$|\.ts$") + PYTHON_CHANGED=$(check_path "^sdks/python/|\.py$") + RUST_CHANGED=$(check_path "\.rs$") + + # Filter ALL_MATRIX entries using jq, keeping only entries for languages with path changes. + FILTERED=$(echo "$ALL_MATRIX" | jq -c --arg actions "$ACTIONS_CHANGED" \ + --arg go "$GO_CHANGED" \ + --arg java "$JAVA_CHANGED" \ + --arg js "$JS_CHANGED" \ + --arg python "$PYTHON_CHANGED" \ + --arg rust "$RUST_CHANGED" \ + '[.[] | select( + (.language == "actions" and $actions == "true") or + (.language == "go" and $go == "true") or + (.language == "java-kotlin" and $java == "true") or + (.language == "javascript-typescript" and $js == "true") or + (.language == "python" and $python == "true") or + (.language == "rust" and $rust == "true") + )]') + + echo "matrix=$FILTERED" >> $GITHUB_OUTPUT + analyze: name: Analyze (${{ matrix.language }}) + needs: detect-changes + if: needs.detect-changes.outputs.matrix != '[]' # Runner size impacts CodeQL analysis time. To learn more, please see: # - https://gh.io/recommended-hardware-resources-for-running-codeql # - https://gh.io/supported-runners-and-hardware-resources @@ -49,21 +135,7 @@ jobs: strategy: fail-fast: false matrix: - include: - - language: actions - build-mode: none - # - language: c-cpp - # build-mode: autobuild - - language: go - build-mode: manual - - language: java-kotlin - build-mode: autobuild - - language: javascript-typescript - build-mode: none - - language: python - build-mode: none - - language: rust - build-mode: none + include: ${{ fromJSON(needs.detect-changes.outputs.matrix) }} # CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift' # Use `c-cpp` to analyze code written in C, C++ or both # Use 'java-kotlin' to analyze code written in Java, Kotlin or both