Skip to content

Consider tuning Code QL checks to be content-specific #1443

Description

@edburns

Consider this run:

#1437

I happen to know that this work only dealt with Java.

Is there a way to make it so only the Java Code QL checks happen in such cases?

I can see the problem — the PR triggered CodeQL Analyze jobs for all 7 languages (python, go, javascript-typescript, csharp, java-kotlin, rust, actions) even though only Java files changed. Let me look at the CodeQL workflow:

CodeQL is running via GitHub's default setup (no .github/workflows/codeql.yml file exists in the repo). The default setup always analyzes all configured languages on every PR — it has no path-based filtering.

To get per-language filtering, you'd need to switch to advanced setup by creating a workflow file. Here's what that would look like:

# .github/workflows/codeql.yml
name: "CodeQL"
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  changes:
    runs-on: ubuntu-latest
    outputs:
      java: ${{ steps.filter.outputs.java }}
      js: ${{ steps.filter.outputs.js }}
      python: ${{ steps.filter.outputs.python }}
      go: ${{ steps.filter.outputs.go }}
      csharp: ${{ steps.filter.outputs.csharp }}
      rust: ${{ steps.filter.outputs.rust }}
    steps:
      - uses: dorny/paths-filter@v3
        id: filter
        with:
          filters: |
            java:   ['java/**']
            js:     ['nodejs/**', 'scripts/**']
            python: ['python/**']
            go:     ['go/**']
            csharp: ['dotnet/**']
            rust:   ['rust/**']

  analyze:
    needs: changes
    strategy:
      matrix:
        include:
          - language: java-kotlin
            gate: java
          - language: javascript-typescript
            gate: js
          - language: python
            gate: python
          - language: go
            gate: go
          - language: csharp
            gate: csharp
          # rust not natively supported by CodeQL
    if: always()
    runs-on: ubuntu-latest
    steps:
      - if: needs.changes.outputs[matrix.gate] == 'true'
        uses: actions/checkout@v4
      - if: needs.changes.outputs[matrix.gate] == 'true'
        uses: github/codeql-action/init@v3
        with:
          languages: ${{ matrix.language }}
      - if: needs.changes.outputs[matrix.gate] == 'true'
        uses: github/codeql-action/autobuild@v3
      - if: needs.changes.outputs[matrix.gate] == 'true'
        uses: github/codeql-action/analyze@v3

However, this change requires repo admin action:

  1. Go to Settings → Code security → Code scanning → CodeQL analysis and switch from "Default" to "Advanced" (this disables the default setup)
  2. Commit the new workflow file
  3. If CodeQL is a required status check, the check names may change and branch protection rules need updating

This isn't something I can do via code alone — it requires a repo admin to toggle the setting in GitHub. I'd recommend filing an issue or discussing with the team, since switching setups affects all languages and their required checks.

Completed: Update documentation to reflect package changes. (3/4)

Activity

  1. edburns commented on May 29, 2026

    @edburns
    CollaboratorAuthor

    Disable default setup first, but do it in a way that keeps coverage continuous enough for your risk tolerance.

    Best practical approach

    Use this sequence:

    1. Temporarily make the CodeQL check non-blocking for this PR
      • If branch protection currently requires this CodeQL status check, temporarily remove that requirement or allow an admin bypass for this one PR.
    2. Disable default setup
      • This immediately removes the conflict that is causing SARIF processing to fail.
    3. Re-run the PR
      • Confirm .github/workflows/codeql.yml now uploads successfully.
    4. Merge the PR
    5. Re-enable required-status enforcement for the advanced CodeQL check if needed

    That avoids the “merged but broken” state and gives you a validated advanced setup before merge.

    Why this is the safest option

    If you merge first and disable default setup later, you create a window where:

    • the PR is blocked by the failing advanced CodeQL job, or
    • you merge with a knowingly failing required check, which is worse operationally

    If you disable default setup first, there may be a short transition window, but it can be minimized to just:

    • disable default setup
    • immediately re-run this PR’s CodeQL job
    • verify success
    • merge

    That is usually the cleanest cutover.

    What I would not do

    I would not merge the workflow first while it is still guaranteed to fail due to the repo setting conflict. That leaves the repo in an intentionally broken state and complicates branch protection.

    If you want near-zero scanning gap

    The cleanest operational plan is:

    • temporarily relax the required check
    • disable default setup
    • re-run this PR and verify advanced CodeQL passes
    • merge immediately

    That makes the “gap” effectively just the few minutes between disabling default setup and the advanced workflow succeeding.

    If branch protection is strict

    If CodeQL is required on main, the most practical answer is:

    • use an admin merge/bypass or temporary branch protection adjustment for this migration PR only

    Recommendation

    My recommendation: disable default setup before merge, then re-run and validate this PR before merging.
    That is the least risky migration path.

  2. edburns commented on May 29, 2026

    @edburns
    CollaboratorAuthor

    Do one of these two things:

    Option 1: Temporarily remove the required CodeQL check

    If the PR is blocked because Analyze (actions) is a required status check on the protected branch:

    1. Go to the repository Settings.
    2. Open Branches.
    3. Edit the branch protection rule for main
      • or edit the applicable ruleset if your repo uses rulesets instead of classic branch protection.
    4. Find Require status checks to pass before merging.
    5. Remove the specific CodeQL check from the required list, or temporarily disable required status checks entirely.
    6. Disable CodeQL default setup.
    7. Re-run the PR checks.
    8. Once the advanced CodeQL workflow passes, add the check back if you still want it required. About protected branches

    Option 2: Use an admin bypass for this one PR

    This is cleaner if you only want a one-time exception.

    You can bypass branch protection only if:

    • you have admin or a custom role with bypass permissions, and
    • the rule does not enforce Do not allow bypassing the above settings.
      GitHub docs note that by default branch protection restrictions do not apply to admins or roles with bypass permissions, unless that stricter setting is enabled. About protected branches

    So for a one-PR migration:

    1. Check whether the target branch rule allows admin bypass.
    2. If yes, merge this PR with admin/bypass privileges.
    3. Immediately disable CodeQL default setup.
    4. Re-run or verify the advanced CodeQL workflow on the merged/default branch.
    5. Keep the advanced workflow as the required check going forward. About protected branches

    Which I recommend

    For this migration, I’d use admin bypass for this one PR if your repository policy allows it. That avoids editing branch protection rules twice.

    If bypass is not allowed, then temporarily remove the required CodeQL check, merge the PR, disable default setup immediately, and then restore the required check. GitHub documents that required status checks must be successful, skipped, or neutral before merge when that rule is enabled. About protected branches

    One important thing to verify

    Make sure your protected branch is using a uniquely named check. GitHub warns that non-unique job names across workflows can create ambiguous status checks and block merges. About protected branches

    If you want, I can next help you determine whether this repo is likely using a branch protection rule or a ruleset, and tell you exactly where in the UI to click for each.

  3. edburns commented on May 29, 2026

    @edburns
    CollaboratorAuthor

    Your codeql.yml is working perfectly. Here's the breakdown:

    Your workflow (run 26666608987) — working as intended

    26666608987

    Job Result Why
    Analyze (java-kotlin) ✅ Full analysis (~2.5 min) Java files changed
    Analyze (actions) ✅ Full analysis (~1 min) .github/workflows/** changed
    Skip (python) ✅ Empty SARIF (~12s) No python changes
    Skip (javascript-typescript) ✅ Empty SARIF (~10s) No JS changes
    Skip (csharp) ✅ Empty SARIF (~11s) No C# changes
    Skip (go) ✅ Empty SARIF (~10s) No Go changes
    Skip (rust) ✅ Empty SARIF (~12s) No Rust changes

    The problem: dynamic code scanning (run 26666607864)

    26666607864

    Job Duration Source
    Analyze (csharp) ~2 min dynamic/github-code-scanning/codeql
    Analyze (python) ~2 min same
    Analyze (go) ~1 min same
    Analyze (javascript-typescript) ~1 min same
    Analyze (java-kotlin) ~1.5 min same

    This second run ("event": "dynamic", "path": "dynamic/github-code-scanning/codeql") is not controlled by any workflow file. It's GitHub's automatic code scanning feature running at the repo level, completely ignoring your path filters.

    Found it. The repo has an org-level property "CodeQL-Block": "true". This is what triggers the dynamic code scanning runs — it's enforced at the GitHub org level, not at the repo level.

    Summary of what's happening on PR #1509

    Your workflow (run 26666608987, codeql.yml) — 9 jobs, working correctly:

    • Detect changed paths
    • Analyze (java-kotlin) — full scan (java changed)
    • Analyze (actions) — full scan (workflow files changed)
    • Skip (python|js|csharp|go|rust) — 5 empty SARIF uploads (~10s each)

    Org-mandated dynamic scanning (run 26666607864, dynamic/github-code-scanning/codeql) — 5 jobs, redundant:

    • Analyze (java-kotlin|python|go|javascript-typescript|csharp) — full scan of all 5, ignoring path changes

    The dynamic scanning is triggered by the org property CodeQL-Block=true. It's not something you can control at the repo level — it requires an org admin to either:

    1. Remove this repo from the CodeQL-Block policy, or
    2. Configure the org-level scanning to respect your custom workflow

    Your options

    1. Ask an org admin to exempt copilot-sdk from CodeQL-Block since you already have a custom codeql.yml that covers all 7 languages (including rust and actions which the dynamic scanning doesn't even cover). This is the ideal fix — it removes the 5 redundant full-analysis jobs.

    2. Do nothing — your workflow is correct and the dynamic scanning is harmless (just redundant). The dynamic runs add ~2 min of CI time but don't block anything.

    3. Remove your custom codeql.yml entirely and rely solely on the org-level scanning — but then you lose language-specific targeting and rust/actions coverage.

    Option 1 is what I'd recommend. The argument is straightforward: you already have a more comprehensive custom CodeQL workflow (7 languages vs. 5) with path-based filtering, so the org-level dynamic scanning is purely redundant.

    Created 8 todos

  4. added a commit that references this issue on May 29, 2026
    5522793
  5. added 2 commits that reference this issue on Aug 4, 2026
    5f5e347
    4f31a58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions