Skip to content

ci(lint): detect TAP groups that no workflow can select - #5992

Merged
renecannao merged 1 commit into
v3.0from
ci/lint-group-workflow-coverage
Aug 8, 2026
Merged

ci(lint): detect TAP groups that no workflow can select#5992
renecannao merged 1 commit into
v3.0from
ci/lint-group-workflow-coverage

Conversation

@renecannao

@renecannao renecannao commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Adds the check you asked for — except a linter for this already existed, so this widens it rather than adding a second one.

Why it didn't catch anything

test/tap/groups/lint_group_coverage.py already ran in CI-lint-groups-json and already asked "does this group have a workflow". Two narrowing assumptions made it blind to a whole class of gap:

1. Infra-less groups were exempt by construction.

concrete = read_infra_names(group) or []
if concrete and not missing and not workflow_exists(group):   # <- `concrete and`

A group with an empty or absent infras.lst could never be flagged. But needing no backend doesn't mean needing no workflow.

2. Only the filename CI-<group>.yml on this branch counted.

That misses groups selected by an env/matrix entry inside a larger workflow (TAP_GROUP: mysqlx-tsan-g1), and it cannot see the reusable half of a pair, which lives on GH-Actions.

Together these hid no-infra-g1 — created in ffb610f4b (2026-03-19), empty infras.lst, no wiring on either branch. Its 5 tests have never run in CI, and the linter meant to catch exactly this stayed quiet for five months.

What changed

A group is wired if any of:

  1. .github/workflows/CI-<group>.yml exists
  2. its name appears in a workflow on this branch
  3. its name appears in a workflow on origin/GH-Actions
  4. it belongs to a dynamically discovered family

(4) matters and was easy to get wrong: CI-cluster-simulator.yml builds its matrix from cluster-simulator-ci.bash discover, which selects every groups.json entry starting with cluster_sim_. Those 6 groups have no static reference anywhere and are genuinely wired — a naive check reports them as gaps. I verified this by reading discover_groups_json() rather than assuming.

When origin/GH-Actions is unavailable the workflow check skips with an explicit NOTE instead of reporting gaps it can't verify. actions/checkout fetches a single branch, so CI-lint-groups-json.yml now fetches that ref at --depth=1 — without it the check would silently no-op in CI, which is the same failure mode this PR exists to fix.

Result

group coverage lint: 94 groups | phantom-infra=0 | missing-workflow NEW=1 known=41

WARN [missing-workflow:NEW]  group 'no-infra-g1' is not selectable by any workflow
on this branch or on origin/GH-Actions -- tests registered in it never run in CI.

Widening the check surfaced 21 further pre-existing unwired groups (the mysql-<variant>-g* families, mysql91-gr, mysql92-gr, mysqlx-e2e, pgsql-repl, todo). Those are allowlisted as tracked debt so the signal stays clean and only genuinely NEW gaps appear. no-infra-g1 is deliberately not allowlisted — it's real and actionable, and is now the single NEW finding.

Still warn-only (exit 0). --strict exits 1, for a future enforcement step.

Verification

  • adding a temporary CI-no-infra-g1.yml drops NEW from 1 → 0, then removed
  • --depth=1 fetch confirmed sufficient: git ls-tree -r origin/GH-Actions .github/workflows returns all 67 files
  • --strict exits 1; default exits 0
  • YAML validates; the other two lint steps still pass

Follow-up, not in this PR

no-infra-g1 still needs its actual wiring — CI-no-infra-g1.yml here plus ci-no-infra-g1.yml on GH-Actions. It's cheap to run (the whole group is ~73s with no backend), and it currently gates reg_test_5363_admin_monitor_caching_sha2-t from #5991.

Summary by CodeRabbit

  • Bug Fixes
    • Improved validation of workflow coverage across local and remote workflow configurations.
    • Added clearer reporting for groups missing infrastructure or selectable workflows.
    • Preserved warnings for known, allowlisted coverage gaps.
    • Added graceful handling when remote workflow information is unavailable.

lint_group_coverage.py already answered "does this group have a CI
workflow", but two narrowing assumptions meant it could not see a whole
class of gap:

1. classify_group() only considered infra-backed groups:

       if concrete and not missing and not workflow_exists(group):

   A group whose infras.lst is empty or absent was exempt by construction.
   But needing no backend does not mean needing no workflow -- such a group
   still needs one to ever run in CI.

2. workflow_exists() only looked for a .github/workflows/CI-<group>.yml
   filename on this branch. That misses groups selected by an env or matrix
   entry inside a larger workflow (e.g. 'TAP_GROUP: mysqlx-tsan-g1'), and it
   cannot see the reusable half of a workflow pair, which lives on
   GH-Actions.

Together these hid no-infra-g1: created in ffb610f (2026-03-19), it has an
empty infras.lst and no wiring on either branch, so its 5 tests have never
run in CI -- and the linter meant to catch exactly this stayed silent.

A group is now considered wired if any of: a CI-<group>.yml caller exists;
its name appears in a workflow on this branch; its name appears in a workflow
on origin/GH-Actions; or it belongs to a dynamically discovered family.
cluster_sim_* is the one such family today -- CI-cluster-simulator.yml builds
its matrix from `cluster-simulator-ci.bash discover`, which selects every
groups.json entry with that prefix, so those groups are wired without any
static reference.

When origin/GH-Actions is unavailable (shallow clone, no remote), the
workflow check is skipped with an explicit NOTE rather than reporting gaps it
cannot verify. CI-lint-groups-json.yml now fetches that ref at --depth=1,
since actions/checkout fetches a single branch and the check would otherwise
skip itself silently.

Widening the check surfaced 21 further pre-existing unwired groups. They are
allowlisted as tracked debt so the linter reports only genuinely NEW gaps.
no-infra-g1 is deliberately NOT allowlisted: it is real and actionable, and
is now the single NEW finding.

Still warn-only (exit 0); --strict exits 1 for a future enforcement step.
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 89447304-29b9-446f-a6fd-79f11f4b2c89

📥 Commits

Reviewing files that changed from the base of the PR and between 89a29ec and e1146e1.

📒 Files selected for processing (2)
  • .github/workflows/CI-lint-groups-json.yml
  • test/tap/groups/lint_group_coverage.py
📜 Recent review details
🧰 Additional context used
🪛 ast-grep (0.45.0)
test/tap/groups/lint_group_coverage.py

[warning] 135-135: File path is request-/variable-derived; validate and normalize to prevent path traversal.
Context: open(os.path.join(root, name), encoding="utf-8", errors="replace")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').

(open-filename-from-request)


[error] 151-154: Command coming from incoming request
Context: subprocess.run(
["git", "ls-tree", "-r", "--name-only", "origin/GH-Actions", ".github/workflows"],
cwd=REPO_ROOT, capture_output=True, text=True, timeout=60, check=False,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(subprocess-from-request)


[error] 162-165: Command coming from incoming request
Context: subprocess.run(
["git", "show", f"origin/GH-Actions:{path}"],
cwd=REPO_ROOT, capture_output=True, text=True, timeout=60, check=False,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(subprocess-from-request)

🪛 Ruff (0.16.1)
test/tap/groups/lint_group_coverage.py

[error] 153-153: Starting a process with a partial executable path

(S607)


[error] 163-163: subprocess call: check for execution of untrusted input

(S603)


[error] 164-164: Starting a process with a partial executable path

(S607)

🔇 Additional comments (4)
.github/workflows/CI-lint-groups-json.yml (1)

13-22: LGTM!

Also applies to: 27-32

test/tap/groups/lint_group_coverage.py (3)

12-44: LGTM!

Also applies to: 66-140


174-223: LGTM!

Also applies to: 251-284


163-169: 🩺 Stability & Availability

No change needed for git show encoding.

subprocess.run() already uses text=True, so blob.stdout is text and parts.append(blob.stdout) is safe.


📝 Walkthrough

Walkthrough

The CI workflow fetches origin/GH-Actions before coverage validation. The linter now scans local and remote workflows, supports dynamic group discovery, checks groups without infrastructure, and reports missing workflow wiring with allowlist and unavailable-ref handling.

Changes

Workflow coverage validation

Layer / File(s) Summary
Workflow source collection
.github/workflows/CI-lint-groups-json.yml, test/tap/groups/lint_group_coverage.py
The CI workflow fetches origin/GH-Actions. The linter defines local and remote workflow inspection, dynamic discovery, and known workflow gaps.
Coverage classification and diagnostics
test/tap/groups/lint_group_coverage.py
lint_coverage passes workflow data to classify_group. Classification checks filenames, workflow contents, dynamic prefixes, groups without infrastructure, and unavailable remote refs. Diagnostics identify missing callers and reusable workflows.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CIWorkflow
  participant GitOriginGHActions
  participant lint_coverage
  participant classify_group
  CIWorkflow->>GitOriginGHActions: shallow fetch GH-Actions
  lint_coverage->>GitOriginGHActions: inspect workflow files
  lint_coverage->>classify_group: pass local and remote workflow data
  classify_group-->>lint_coverage: return coverage diagnostics
Loading

Poem

A rabbit checks the branch at dawn,
Finds workflow trails from dusk till morn.
Local paths and remote threads,
Guide each group where testing treads.
Missing wires now leave a note,
While known gaps stay in the boat.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: detecting TAP groups that no workflow can select.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/lint-group-workflow-coverage

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sonarqubecloud

sonarqubecloud Bot commented Aug 7, 2026

Copy link
Copy Markdown

@codecov

codecov Bot commented Aug 7, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 52.42%. Comparing base (89a29ec) to head (e1146e1).

Additional details and impacted files
@@            Coverage Diff             @@
##             v3.0    #5992      +/-   ##
==========================================
- Coverage   52.42%   52.42%   -0.01%     
==========================================
  Files         472      472              
  Lines      143105   143105              
  Branches    36164    36164              
==========================================
- Hits        75022    75020       -2     
- Misses      51237    51254      +17     
+ Partials    16846    16831      -15     
Flag Coverage Δ
integration-tests 48.86% <ø> (-0.01%) ⬇️
unit-tests 13.85% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant