Skip to content

ci: restore C++ CodeQL analysis (dynamic workflow is python-only since 2026-08-08) #655

Open

Description

@mvillmow

Summary

Keystone C++ code is not covered by CodeQL: the GitHub-managed dynamic workflow (dynamic/github-code-scanning/codeql) runs only an Analyze (python) job. The last /language:c-cpp analysis was 2026-08-08 (commit a1b0f41).

Impact

Suggested fix

Add a fleet-standard .github/workflows/codeql.yml with the cpp language matrix (autobuild or the repo containerized build path) + paths-ignore for build/**, mirroring Argus/modular-community/Myrmidons/Odysseus (HomericIntelligence/Odysseus#455 rollout). Note Keystone C++ builds run inside the dev container (conan deps) per _required.yml, so a bare-runner autobuild may need a conan install step.

Activity

  1. added
    ciSomething isn't working
    state:needs-planIssue has no plan yet; planner should run.
    on Aug 17, 2026
  2. mvillmow commented on Aug 23, 2026

    @mvillmow
    CollaboratorAuthor

    Implementation Plan

    Objective

    Restore dedicated, committed CodeQL analysis for Keystone's C++ code in a fleet-standard .github/workflows/codeql.yml, as requested by #655. Functional C++ coverage was already re-established on main inside _required.yml by PR #657 (Analyze (c-cpp) green on main, run 32103653163, 2026-08-18), so this task moves that proven job into the fleet-standard standalone workflow file (mirroring Odysseus' .github/workflows/codeql.yml from the HomericIntelligence/Odysseus#455 rollout) rather than duplicating it — two workflows uploading SARIF under the same /language:c-cpp category on the same ref would collide. .github/codeql/codeql-config.yml already carries paths-ignore: build/** + **/_deps/** (#614), and code-scanning default setup is not-configured, so advanced-workflow SARIF uploads are accepted.

    Approach

    • Move, don't duplicate. Verified live: ruleset homeric-main-baseline (id 15556488) required contexts are lint, unit-tests, integration-tests, security/dependency-scan, security/secrets-scan, build, schema-validation, deps/version-sync, test, package, release, install — no Analyze (*) context is pinned, so relocating the analyze job out of _required.yml cannot brick the merge queue (per the pinned-contexts discipline).
    • Reuse the proven manual build path, reject autobuild. Open PR ci(codeql): restore C++ CodeQL analysis #661 drafts a codeql.yml using codeql-action/autobuild with an env: CONAN_OUTPUT_DIR hint — autobuild does not consume that variable and cannot pass -DCMAKE_TOOLCHAIN_FILE=build/codeql/conan-deps/conan_toolchain.cmake, which the Conan-generated build requires. Instead, port the exact manual-build steps already green in _required.yml:1038–1061: the ./.github/actions/install-build-deps composite (exists at .github/actions/install-build-deps/action.yml, installs clang-18/cmake/ninja/conan with cache-conan input), the FetchContent cache, conan install --output-folder=build/codeql/conan-deps, and explicit cmake -S . -B build/codeql -G Ninja -DCMAKE_TOOLCHAIN_FILE=....
    • Matrix parity: keep exactly the languages _required.yml covers today — c-cpp (build-mode manual) + python (build-mode none) — preserving current coverage without scope creep.
    • Fleet-standard shape copied from HomericIntelligence/Odysseus/.github/workflows/codeql.yml (read live): name: CodeQL, triggers push→main / pull_request→main / weekly cron 0 8 * * 1, top-level permissions: contents: read, security-events: write, actions: read, concurrency: group: codeql-${{ github.ref }}, timeout-minutes: 60, fail-fast: false.
    • Action pins: reuse the repo's existing SHAs — actions/checkout@3d3c42e… (v7.0.1) and github/codeql-action/*@5595ccaf912efad79be6eef63a5619ff05969be3 — identical to _required.yml:1027,1030,1064.
    • Suppressions hygiene: the new file must contain no || true, continue-on-error, or ::warning:: (enforced by the forbid-or-true, forbid-continue-on-error, and forbid-advisory-warnings pre-commit hooks at .pre-commit-config.yaml:103,116,126; the advisory hook excludes only _required.yml).

    Files to Create

    .github/workflows/codeql.yml

    Fleet-standard CodeQL workflow: header comment referencing #655 and the Odysseus#455 rollout; name: CodeQL; triggers push: branches: [main], pull_request: branches: [main], schedule: cron "0 8 * * 1", plus workflow_dispatch; top-level read-only permissions + security-events: write; concurrency.group: codeql-${{ github.ref }} with cancel-in-progress: true. Single analyze job (ubuntu-24.04, timeout 60) with matrix {language: c-cpp, build-mode: manual} / {language: python, build-mode: none}, containing: checkout (pinned SHA, fetch-depth: 0); codeql-action/init with languages/build-mode from the matrix, queries: security-and-quality, config-file: ./.github/codeql/codeql-config.yml; for c-cpp only: ./.github/actions/install-build-deps with cache-conan: "true", FetchContent cache (actions/cache, path build/codeql/_deps, key fetchcontent-codeql-${{ runner.os }}-${{ hashFiles('CMakeLists.txt') }}), conan install . --output-folder=build/codeql/conan-deps --build=missing -s build_type=Release -s compiler.cppstd=20, and the cmake configure+build with the toolchain file (steps lifted verbatim from _required.yml:1038–1061); finally codeql-action/analyze with category: "/language:${{ matrix.language }}".

    Files to Modify

    .github/workflows/_required.yml

    Delete the entire analyze job and its section comment banner (lines ~1000–1066, from the # 22. analyze banner through the final Perform CodeQL Analysis step). Intended behavior: CodeQL runs once, from the new standalone workflow, eliminating duplicate SARIF uploads for categories /language:c-cpp and /language:python. No other jobs reference analyze (verified: nothing needs: it).

    .github/workflows/README.md

    Update the "Current Workflows" list (~line 10) to add codeql.yml ("fleet-standard CodeQL analysis for cpp + python; weekly schedule") and drop any implication that CodeQL lives in _required.yml.

    Implementation Order

    1. Verify no required context references Analyze (re-run the ruleset query; already confirmed empty) — safety gate before removing the job.
    2. Create .github/workflows/codeql.yml per spec above.
    3. Remove the analyze job (lines ~1000–1066) from .github/workflows/_required.yml.
    4. Update .github/workflows/README.md.
    5. Run local validations (below); fix anything the hooks flag.
    6. Feature branch ci/fleet-standard-codeql-yml, conventional commit ci(codeql): move C++ analysis to fleet-standard codeql.yml, PR body Closes #655 noting supersession of draft PR ci(codeql): restore C++ CodeQL analysis #661's autobuild approach.

    Verification

    # Criterion 1: new workflow parses and passes repo YAML gates (yamllint hook)
    uv run pre-commit run yamllint --files .github/workflows/codeql.yml
    
    # Criterion 2: no forbidden suppressions enter the tree (forbid-* hooks over both files)
    uv run pre-commit run forbid-or-true --show-diff-on-failure --files .github/workflows/codeql.yml .github/workflows/_required.yml
    uv run pre-commit run forbid-continue-on-error --files .github/workflows/codeql.yml
    
    # Criterion 3: structural sanity — one analyze job, c-cpp+python matrix, init/analyze wired to codeql-config.yml
    python3 -c "
    import yaml; d=yaml.safe_load(open('.github/workflows/codeql.yml'))
    j=d['jobs']['analyze']; langs=[m['language'] for m in j['strategy']['matrix']['include']]
    assert set(langs)=={'c-cpp','python'}, langs
    s=' '.join(st.get('uses','') for st in j['steps'])
    assert 'codeql-action/init' in s and 'codeql-action/analyze' in s and 'autobuild' not in s
    print('OK', langs)"
    
    # Criterion 4: analyze job fully removed from _required.yml (no duplicate CodeQL surface)
    ! grep -n "codeql-action/init" .github/workflows/_required.yml
    
    # Criterion 5 (gated, post-merge): first scheduled/push CodeQL run green with both categories.
    # Author the command; accept only verbatim run output as evidence:
    gh run watch $(gh run list --workflow codeql.yml --limit 1 --json databaseId --jq '.[0].databaseId') --exit-status

    Skills Used

    Team knowledge base: codeql-exclude-vendored-deps-false-criticals (paths-ignore already landed via #614 — reused, not re-implemented), ci-cd-codeql-default-to-advanced-canonical-names (default-setup/SARIF sequencing facts; confirmed Keystone default setup is not-configured so no disable step needed), planning-validator-ci-gate-tasks (pinned-contexts check before touching _required.yml; tooling-presence/dead-gate discipline; forbid-suppressions constraints), repo-audit-triage-fix-and-issue-workflow (verify-issue-premise before implementing — confirmed C++ coverage already restored by #657, narrowing this task to the fleet-standard relocation).

    Changes from Review

    N/A — initial plan

  3. mvillmow commented on Aug 23, 2026

    @mvillmow
    CollaboratorAuthor

    🔍 Plan Review

    Verified against the worktree:

    • Requirements alignment: Issue asks for a fleet-standard .github/workflows/codeql.yml with cpp coverage + paths-ignore for build/** — plan delivers exactly that (Files to Create section), reusing the already-landed codeql-config.yml paths-ignore (ci(codeql): exclude vendored build/_deps from CodeQL analysis #614) rather than re-implementing.
    • Accuracy of claims: _required.yml:1001-1066 contains the analyze job exactly as described (c-cpp manual build + python matrix, pinned SHAs, config-file wiring); .github/actions/install-build-deps/action.yml and .github/codeql/codeql-config.yml both exist. Line-number and step citations match on disk.
    • Concreteness: names exact files, line ranges, action pins, conan/cmake invocations, branch/commit convention, PR supersession of ci(codeql): restore C++ CodeQL analysis #661's autobuild approach with a technical rationale (autobuild can't pass the Conan toolchain file).
    • Risk surface: ruleset required-contexts checked before deleting the pinned-file job (no Analyze (*) pinned); no needs: dependencies; forbid-suppressions hooks enumerated with file:line in .pre-commit-config.yaml.
    • Verification: 5 concrete criteria including a structural Python assertion and a post-merge gated run watch; each maps to an acceptance criterion.
    • P1/P2: move-not-duplicate rationale (SARIF category collision) justifies the deletion; no scope creep.

    Minor (non-blocking): plan says "lines ~1000–1066" while the job body actually ends at ~1066 incl. final step — off-by-a-couple, harmless since the deletion is described by banner-to-final-step boundaries. Criterion 5 is inherently post-merge and properly gated as such.

    state:plan-go

  4. added
    state:plan-goPlan approved by reviewer; implementer may proceed.
    and removed
    state:needs-planIssue has no plan yet; planner should run.
    on Aug 23, 2026
  5. added a commit that references this issue on Aug 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    ciSomething isn't workingstate:plan-goPlan approved by reviewer; implementer may proceed.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions