CodeQL #240
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CodeQL | |
| on: | |
| push: | |
| branches: [main, develop] | |
| pull_request: | |
| branches: [main, develop] | |
| schedule: | |
| # Weekly schedule catches new CodeQL queries / CVE rules disclosed since | |
| # the last PR landed. Wednesday 06:00 UTC — deliberately offset from | |
| # security.yml's Monday slot so dependency-CVE forensics and source-code | |
| # findings don't pile into the same morning's GitHub-Actions queue. | |
| - cron: '0 6 * * 3' | |
| concurrency: | |
| group: codeql-${{ github.ref }} | |
| # Don't cancel in-progress runs: CodeQL uploads SARIF on cancel, and a | |
| # partial run lands as an empty-results SARIF (rules_count: 0, | |
| # results_count: 0) that GitHub flags as "Code scanning configuration | |
| # error" in the Code Scanning UI. During PR-merge cascades on develop | |
| # (e.g. 5 PRs in 15 min on 2026-05-28, #154→#156→#155→#157→#159), this | |
| # produced 3 empty SARIFs that needed manual cleanup. Better to queue | |
| # the second and later runs — small runner-time cost during cascades, | |
| # no UI banners, and every commit gets a full CodeQL analysis (matters | |
| # for the Scorecard SAST coverage metric). See #160 for full reasoning. | |
| cancel-in-progress: false | |
| # Default to read-only at the workflow level; the analyze job below opts | |
| # in to the narrow extra scopes it actually needs. Matches the OpenSSF | |
| # Scorecard Token-Permissions recommendation that workflows declare the | |
| # minimum at top level and elevate only at the job that uses it (SR-137). | |
| permissions: | |
| contents: read | |
| jobs: | |
| analyze: | |
| name: Analyze (${{ matrix.language }}) | |
| runs-on: ubuntu-latest | |
| permissions: | |
| # `actions: read` lets the CodeQL action introspect the workflow file | |
| # for the matrix expansion and language detection. | |
| actions: read | |
| # `contents: read` is REQUIRED here because job-level `permissions:` | |
| # REPLACES (not merges with) the workflow-level block — omitting it | |
| # would deny content access in this job and break the checkout step. | |
| # Also useful for grep-ability. | |
| contents: read | |
| # `security-events: write` is what CodeQL needs to upload SARIF | |
| # results to GitHub Code Scanning. Held at job level (not top level) | |
| # so no other job in this workflow inherits the write scope. | |
| security-events: write | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| # CodeQL's combined language for the JVM ecosystem. A single | |
| # `java-kotlin` database covers both languages — listing them | |
| # separately is a deprecated configuration. | |
| language: [java-kotlin] | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5.6.0 | |
| with: | |
| distribution: temurin | |
| java-version: '21' | |
| - uses: gradle/actions/setup-gradle@3f131e8634966bd73d06cc69884922b02e6faf92 # v6.2.0 | |
| - name: Initialize CodeQL | |
| uses: github/codeql-action/init@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3 | |
| with: | |
| languages: ${{ matrix.language }} | |
| # security-and-quality bundles the security-extended queries plus | |
| # maintainability/quality lints — broader than the default suite, | |
| # appropriate for a small app where we want maximum signal. | |
| queries: security-and-quality | |
| config-file: ./.github/codeql/codeql-config.yml | |
| # Build choice: manual `:app:assembleDebug` rather than `autobuild`, | |
| # with the Kotlin compiler forced in-process AND the Gradle build | |
| # cache disabled — both are required for CodeQL to see Kotlin code. | |
| # | |
| # Why not `autobuild`: it routinely fails to discover the AGP variant | |
| # model on Android projects, producing an empty CodeQL DB. | |
| # | |
| # Why not `build-mode: none`: for the `java-kotlin` combined language, | |
| # `none` only does dependency-graph analysis on the Java side and is | |
| # not a Kotlin source extractor — on a 100% Kotlin codebase (this | |
| # repo has zero `.java` sources) the finalize step fails with "no | |
| # source code seen during build" because Kotlin extraction always | |
| # requires a traced build. | |
| # | |
| # Why `kotlin.compiler.execution.strategy=in-process`: by default the | |
| # Kotlin Gradle plugin spawns an out-of-process Kotlin compiler daemon | |
| # for every build. That daemon JVM is started *outside* CodeQL's | |
| # `LD_PRELOAD` tracer scope, so even though the Android Gradle build | |
| # succeeds, the Kotlin compilation never gets traced. | |
| # | |
| # Why `--no-build-cache` AND `clean`: `gradle/actions/setup-gradle` | |
| # restores Gradle's local build cache from previous workflow runs | |
| # (including ci.yml). On a cache hit, `compileDebugKotlin` is served | |
| # `FROM-CACHE` and no compiler process runs — leaving CodeQL's tracer | |
| # with nothing to capture. Disabling the build cache + cleaning the | |
| # task outputs forces a fresh in-process Kotlin compilation that the | |
| # tracer can actually see. Canonical fix for the | |
| # https://gh.io/troubleshooting-code-scanning/no-source-code-seen-during-build | |
| # symptom on Kotlin Gradle projects where compileDebugKotlin shows | |
| # `FROM-CACHE` in the build log. | |
| - name: Build (Android debug, Kotlin compiler in-process, no cache) | |
| run: | | |
| chmod +x gradlew | |
| ./gradlew clean :app:assembleDebug --no-daemon --no-build-cache \ | |
| -Pkotlin.compiler.execution.strategy=in-process | |
| - name: Perform CodeQL Analysis | |
| uses: github/codeql-action/analyze@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4.37.3 | |
| with: | |
| category: "/language:${{ matrix.language }}" |