| # Licensed to the Apache Software Foundation (ASF) under one | |
| # or more contributor license agreements. See the NOTICE file | |
| # distributed with this work for additional information | |
| # regarding copyright ownership. The ASF licenses this file | |
| # to you under the Apache License, Version 2.0 (the | |
| # "License"); you may not use this file except in compliance | |
| # with the License. You may obtain a copy of the License at | |
| # | |
| # http://www.apache.org/licenses/LICENSE-2.0 | |
| # | |
| # Unless required by applicable law or agreed to in writing, | |
| # software distributed under the License is distributed on an | |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
| # KIND, either express or implied. See the License for the | |
| # specific language governing permissions and limitations | |
| # under the License. | |
| # | |
| --- | |
| name: "CodeQL" | |
| on: # yamllint disable-line rule:truthy | |
| pull_request: | |
| branches: | |
| - main | |
| - v[0-9]+-[0-9]+-test | |
| - v[0-9]+-[0-9]+-stable | |
| - chart/v[0-9]+-[0-9]+x-test | |
| - chart/v[0-9]+-[0-9]+x-stable | |
| - airflow-ctl/v[0-9]+-[0-9]+-test | |
| - airflow-ctl/v[0-9]+-[0-9]+-stable | |
| push: | |
| branches: | |
| - main | |
| - v[0-9]+-[0-9]+-test | |
| - v[0-9]+-[0-9]+-stable | |
| - chart/v[0-9]+-[0-9]+x-test | |
| - chart/v[0-9]+-[0-9]+x-stable | |
| - airflow-ctl/v[0-9]+-[0-9]+-test | |
| - airflow-ctl/v[0-9]+-[0-9]+-stable | |
| schedule: | |
| - cron: '0 2 * * *' | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: codeql-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| detect-languages: | |
| name: Detect languages to scan | |
| runs-on: ["ubuntu-slim"] | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| outputs: | |
| languages: ${{ steps.set-languages.outputs.languages }} | |
| steps: | |
| - name: Compute CodeQL language matrix | |
| id: set-languages | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| EVENT_NAME: ${{ github.event_name }} | |
| PR_NUMBER: ${{ github.event.pull_request.number }} | |
| BEFORE_SHA: ${{ github.event.before }} | |
| AFTER_SHA: ${{ github.event.after }} | |
| REPOSITORY: ${{ github.repository }} | |
| # On `pull_request` and `push` we only scan the languages whose files actually changed. | |
| # On `schedule` we always scan every language to keep full periodic coverage. | |
| run: | | |
| set -euo pipefail | |
| all_languages='["python","javascript","actions","go","java"]' | |
| if [[ "${EVENT_NAME}" == "schedule" ]]; then | |
| echo "languages=${all_languages}" >> "${GITHUB_OUTPUT}" | |
| exit 0 | |
| fi | |
| if [[ "${EVENT_NAME}" == "push" ]]; then | |
| changed_files="$(gh api "repos/${REPOSITORY}/compare/${BEFORE_SHA}...${AFTER_SHA}" \ | |
| --jq '.files[].filename')" || true | |
| num_files="$(printf '%s\n' "${changed_files}" | grep -c . || true)" | |
| # Fall back to a full scan if the compare call failed, returned nothing, or hit the | |
| # API's 300-file cap. The compare API does not paginate files (only commits), so a | |
| # merge of >300 files truncates the list and could under-detect a changed language; | |
| # release branches have no daily schedule full-scan to back them up. Empty also covers | |
| # a force-push or a newly created branch whose before SHA is all zeros (no base commit). | |
| if [[ -z "${changed_files}" || "${num_files}" -ge 300 ]]; then | |
| echo "languages=${all_languages}" >> "${GITHUB_OUTPUT}" | |
| exit 0 | |
| fi | |
| else | |
| # pull_request | |
| changed_files="$(gh api --paginate \ | |
| "repos/${REPOSITORY}/pulls/${PR_NUMBER}/files" --jq '.[].filename')" | |
| fi | |
| languages=() | |
| grep -Eiq '\.(py|pyi)$' <<< "${changed_files}" && languages+=("python") | |
| grep -Eiq '\.(js|jsx|mjs|cjs|ts|tsx|vue)$' <<< "${changed_files}" && languages+=("javascript") | |
| grep -Eiq '^\.github/(workflows|actions)/' <<< "${changed_files}" && languages+=("actions") | |
| grep -Eiq '(\.go$|/go\.(mod|sum)$)' <<< "${changed_files}" && languages+=("go") | |
| grep -Eiq '(\.java$|\.gradle(\.kts)?$|\.kts$)' <<< "${changed_files}" && languages+=("java") | |
| if [[ ${#languages[@]} -eq 0 ]]; then | |
| echo "languages=[]" >> "${GITHUB_OUTPUT}" | |
| else | |
| json_languages="$(printf '%s\n' "${languages[@]}" \ | |
| | jq -Rsc 'split("\n") | map(select(length > 0))')" | |
| echo "languages=${json_languages}" >> "${GITHUB_OUTPUT}" | |
| fi | |
| analyze: | |
| name: Analyze | |
| needs: detect-languages | |
| # Skip entirely when no scannable language changed (e.g. docs-only PRs). | |
| if: needs.detect-languages.outputs.languages != '[]' | |
| runs-on: ["ubuntu-22.04"] | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| language: ${{ fromJSON(needs.detect-languages.outputs.languages) }} | |
| permissions: | |
| actions: read | |
| contents: read | |
| pull-requests: read | |
| security-events: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| - name: Setup Java | |
| if: matrix.language == 'java' | |
| uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1 | |
| with: | |
| distribution: 'temurin' | |
| java-version: '11' | |
| - name: Initialize CodeQL | |
| uses: github/codeql-action/init@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3 | |
| with: | |
| languages: ${{ matrix.language }} | |
| - name: Autobuild | |
| if: matrix.language != 'java' | |
| uses: github/codeql-action/autobuild@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3 | |
| - name: Build Java SDK | |
| if: matrix.language == 'java' | |
| working-directory: java-sdk | |
| run: ./gradlew classes testClasses | |
| - name: Perform CodeQL Analysis | |
| uses: github/codeql-action/analyze@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3 | |
| with: | |
| # Provide more context to the SARIF output (shows up in run.automationDetails.id field) | |
| category: "/language:${{matrix.language}}" |