From 3f97e7c34f727509f16c1b9ce97b951cf8ec989d Mon Sep 17 00:00:00 2001 From: Ankit Samantaray Date: Wed, 21 Oct 2026 19:41:26 +0100 Subject: [PATCH 1/2] ci: compile Java CodeQL explicitly with JDK21 --- .github/scripts/test_release_pr_ci_gate.py | 20 ++++++ .github/workflows/codeql.yml | 72 ++++++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 .github/workflows/codeql.yml diff --git a/.github/scripts/test_release_pr_ci_gate.py b/.github/scripts/test_release_pr_ci_gate.py index 7923c85e0..2b9bd4ed6 100644 --- a/.github/scripts/test_release_pr_ci_gate.py +++ b/.github/scripts/test_release_pr_ci_gate.py @@ -7,6 +7,26 @@ class JavaReleasePRGateTests(unittest.TestCase): + def test_codeql_compiles_kotlin_with_pinned_jdk_without_caches(self): + path = ROOT / ".github/workflows/codeql.yml" + self.assertTrue(path.is_file(), "Production needs an explicit CodeQL workflow") + workflow = path.read_text(encoding="utf-8") + for contract in ( + "name: Analyze (${{ matrix.language }})", + "language: actions", "language: java-kotlin", "build-mode: manual", + "java-version: '21'", "distribution: temurin", + "./gradlew clean classes", "--no-build-cache", "--no-configuration-cache", + "--rerun-tasks", "--no-parallel", "--max-workers=1", + "-Pkotlin.compiler.execution.strategy=in-process", + "-Pkotlin.incremental=false", "persist-credentials: false", + "security-events: write", "branches: [master, next]", + ): + with self.subTest(contract=contract): + self.assertIn(contract, workflow) + self.assertNotIn("autobuild", workflow) + self.assertNotIn("cache: gradle", workflow) + self.assertNotIn("pull_request_target", workflow) + def test_classifier_owns_every_full_ci_job(self): ci = (ROOT / ".github/workflows/ci.yml").read_text(encoding="utf-8") self.assertIn("name: classify production CI", ci) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 000000000..8864467b0 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,72 @@ +name: CodeQL + +# Production-owned: staging promotion restores this file from master. +# Coordinate default-setup -> advanced-setup cutover after this workflow lands. +on: + push: + branches: [master, next] + pull_request: + branches: [master, next] + workflow_dispatch: + schedule: + - cron: '23 4 * * 2' + +permissions: + contents: read + +jobs: + analyze: + name: Analyze (${{ matrix.language }}) + runs-on: ubuntu-latest + timeout-minutes: 90 + permissions: + contents: read + security-events: write + packages: read + strategy: + fail-fast: false + matrix: + include: + - language: actions + build-mode: none + - language: java-kotlin + build-mode: manual + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + # Select the compiler runtime before CodeQL initializes tracing. Merely + # installing JDK21 leaves automatic JDK discovery free to select JDK25. + - name: Select JDK21 + if: matrix.language == 'java-kotlin' + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 + with: + distribution: temurin + java-version: '21' + + - name: Initialize CodeQL + uses: github/codeql-action/init@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4 + with: + languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} + + - name: Compile all production Kotlin and Java sources + if: matrix.language == 'java-kotlin' + run: | + java -version + ./gradlew --version + # classes selects every subproject's main source set, including the + # custom lib/websocket modules and examples. Tests/shrinkers are CI's + # responsibility. Recompile inside tracing, never restore bytecode. + # One compiler JVM avoids inheriting a second generated 12GiB heap. + ./gradlew clean classes --no-daemon --no-parallel --max-workers=1 \ + --no-build-cache --no-configuration-cache --rerun-tasks \ + -Dorg.gradle.jvmargs="-Xmx8g -XX:MaxMetaspaceSize=1g -Dfile.encoding=UTF-8" \ + -Pkotlin.compiler.execution.strategy=in-process \ + -Pkotlin.incremental=false + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4 + with: + category: '/language:${{ matrix.language }}' From 8031869abdec811ee3292b506a028822aa7c81cf Mon Sep 17 00:00:00 2001 From: Ankit Samantaray Date: Wed, 21 Oct 2026 21:06:49 +0100 Subject: [PATCH 2/2] fix(ci): align CodeQL compiler heap with proven hosted build --- .github/scripts/test_release_pr_ci_gate.py | 13 +++++++++++++ .github/workflows/codeql.yml | 4 +++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/.github/scripts/test_release_pr_ci_gate.py b/.github/scripts/test_release_pr_ci_gate.py index 2b9bd4ed6..6022553e8 100644 --- a/.github/scripts/test_release_pr_ci_gate.py +++ b/.github/scripts/test_release_pr_ci_gate.py @@ -27,6 +27,19 @@ def test_codeql_compiles_kotlin_with_pinned_jdk_without_caches(self): self.assertNotIn("cache: gradle", workflow) self.assertNotIn("pull_request_target", workflow) + def test_codeql_uses_established_hosted_compiler_memory_budget(self): + workflow = (ROOT / ".github/workflows/codeql.yml").read_text(encoding="utf-8") + ci = (ROOT / ".github/workflows/ci.yml").read_text(encoding="utf-8") + # The same source tree compiles in CI at 12GiB; 8GiB exhausts the + # Kotlin psi2ir heap even without CodeQL tracing. + budget = '-Dorg.gradle.jvmargs="-Xmx12g -XX:MaxMetaspaceSize=1g -Dfile.encoding=UTF-8"' + self.assertIn(budget, ci) + self.assertIn(budget, workflow) + self.assertIn("runs-on: ubuntu-latest", workflow) + self.assertIn("-Pkotlin.compiler.execution.strategy=in-process", workflow) + self.assertIn("--max-workers=1", workflow) + self.assertNotIn("-Xmx8g", workflow) + def test_classifier_owns_every_full_ci_job(self): ci = (ROOT / ".github/workflows/ci.yml").read_text(encoding="utf-8") self.assertIn("name: classify production CI", ci) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 8864467b0..61395d833 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -59,10 +59,12 @@ jobs: # classes selects every subproject's main source set, including the # custom lib/websocket modules and examples. Tests/shrinkers are CI's # responsibility. Recompile inside tracing, never restore bytecode. + # Match CI's proven 12GiB compiler budget: 8GiB exhausts Kotlin's + # psi2ir heap on this source tree, even without CodeQL tracing. # One compiler JVM avoids inheriting a second generated 12GiB heap. ./gradlew clean classes --no-daemon --no-parallel --max-workers=1 \ --no-build-cache --no-configuration-cache --rerun-tasks \ - -Dorg.gradle.jvmargs="-Xmx8g -XX:MaxMetaspaceSize=1g -Dfile.encoding=UTF-8" \ + -Dorg.gradle.jvmargs="-Xmx12g -XX:MaxMetaspaceSize=1g -Dfile.encoding=UTF-8" \ -Pkotlin.compiler.execution.strategy=in-process \ -Pkotlin.incremental=false