Skip to content

chore: repository health check (tests, security, deps, CI) - #292

Merged
shenxianpeng merged 8 commits into
mainfrom
chore/repo-health-check
Oct 2, 2026
Merged

shenxianpeng merged 8 commits into
mainfrom
chore/repo-health-check

Conversation

@shenxianpeng

@shenxianpeng shenxianpeng commented Oct 1, 2026 •

Copy link
Copy Markdown
Member

Summary

Automated repository health check: raise test coverage, review security, refresh
dependencies, and quiet CI warnings. No production behavior changes except one
real bug fix (see below). Opened as a draft.

Commits are grouped by category:

  • test: cover the remaining hook and version-resolution paths
  • fix: match --version prefixes on whole version components
  • build: drop the unused tomli dependency and stray package data
  • build(deps): refresh uv.lock
  • chore: pre-commit autoupdate
  • chore(ci): least-privilege workflow tokens + checkout credentials
  • chore(ci): actionlint / shellcheck / path-filter / Codecov fixes

Coverage before → after

Tool: coverage (same invocation as CI: --source=tests,cpp_linter_hooks).

Scope Before After
cpp_linter_hooks/ (line) 98% (6 lines missed) 100%
cpp_linter_hooks/ (branch) not measured 100% (90/90)

Full suite: 119 → 211 tests, all passing. The new tests are offline
(PyPI, pip, and the clang-* binaries are mocked), so they add no network or
subprocess dependency and run in well under a second.

The previous [tool.coverage.report] exclude_also used bare substrings
"__name__" and "FileNotFoundError", which silently excluded every line
mentioning those tokens — including the except FileNotFoundError handlers in
both hooks. Narrowed to the if __name__ == "__main__": guards only, and the
previously-hidden paths are now tested.

No remaining gaps in the shipped source. With 100% reached, a coverage gate
(fail_under = 100) could be added; left out of this PR as a maintainer call.

Tests added

~55 cases across the existing files:

  • tests/test_clang_format.py — command construction, --Werror injection for
    --dry-run, merged stdout/stderr, missing executable, verbose diagnostics,
    main() reading sys.argv.
  • tests/test_clang_tidy.py — --jobs validation, exit-code/diagnostic
    detection, compile-DB and MSVC hint matchers, source-file splitting, --fix
    placement, compile_commands.json search order, -p=<dir>, main().
  • tests/test_util.py — numeric version ordering, the PyPI URL + timeout,
    pre-release filtering, invalid JSON, --version banner parsing, timeouts,
    pip-failure logging, verbose/offline resolution branches, and the prefix-match
    regression below.

Bug fix

--version prefix resolution compared plain strings, so a major version with no
wheel resolved to an unrelated release instead of failing as the README
documents:

  • --version=2 → installed clang-format 23.1.2
  • --version=1 → installed clang-format 19.1.7

Now the prefix matches only at a component boundary: --version=2 fails with the
list of available versions, while --version=21 still resolves to the newest
21.x and --version=19.1.0 to 19.1.0.1. Covered by a regression test that
fails on the old code.

Security hardening (workflows)

The repo's default GITHUB_TOKEN is read/write, so workflows without a
permissions: block ran over-privileged.

  • Default every workflow to permissions: {} and grant each job only what it
    uses: contents: read for test / codspeed / pre-commit; the scopes the org
    CodeQL and publish reusable workflows declare for their callers
    (security-events: write; id-token: write + attestations: write).
  • persist-credentials: false on checkouts that never push.
    (security updates are exempt).
  • Fixed the CodSpeed pin comment (#5.2.1 → # v5.2.1).

Verified with zizmor and actionlint. Remaining zizmor findings are the org
reusable workflows referenced as @main (cpp-linter/.github, out of scope
here) and secrets: inherit on publish (would need a change in that org repo).

Dependency updates

  • Removed the unused tomli runtime dependency and the
    [tool.setuptools.package-data] ../pyproject.toml entry — both left over
    from the pre-feat: dynamic PyPI version resolution  #242 pyproject-based version lookup. Nothing imports tomli or
    reads pyproject.toml at runtime now, and the package-data entry was shipping
    a stray top-level pyproject.toml into site-packages.
  • Refreshed uv.lock (dev group had drifted because Dependabot's pip
    ecosystem only bumps pip there): coverage 7.11→7.16, pre-commit 4.3→4.6,
    pytest 9.0→9.1, pytest-codspeed 4.2→5.0 (drops cffi/pycparser),
    virtualenv 20→21, pip 26.2→26.2.1. Benchmarks run clean locally on codspeed 5.
  • pre-commit autoupdate: ruff-pre-commit v0.16.3 → v0.16.10.

Pending bot PR worth merging: #291 (chore: Test and declare Python 3.15 support, community contributor, closes #286) — adds 3.15 to the CI matrix and
classifiers. Its only failing checks are setup-python not finding a 3.15 build
on the hosted runners yet and a PR-title lint; not duplicated here.

CI warning fixes

  • release-drafter.yml: grouped redirects and quoted "$GITHUB_ENV"
    (shellcheck SC2129/SC2086); generated notes + env file are byte-identical.
  • publish.yml: dropped the branches: filter from the release trigger
    (invalid for release events; actionlint).
  • codspeed.yml: path filter said cpp-linter-hooks/** but the package is
    cpp_linter_hooks/, so hook-code-only changes never triggered benchmarks.
  • test.yml: plugins: noop on the Codecov step to silence the
    xcode/gcov/pycoverage "not found" warnings (coverage.xml is passed
    explicitly).

Not fixable here: the ubuntu-latest → Ubuntu 26 migration notice and the
release-drafter categories[*].labels deprecation both originate in
cpp-linter/.github (org-level config), not this repo.

Items needing a maintainer decision

How it was verified

  • coverage run --source=tests,cpp_linter_hooks -m pytest → 211 passed,
    100% line; a separate branch run → 100% branch (90/90).
  • Offline subset re-run under Python 3.10 (oldest supported) and -W error::DeprecationWarning → green.
  • bash testing/run.sh (full pre-commit pipeline) → 5/5 passed.
  • pre-commit run --all-files, actionlint, zizmor, bandit, pip-audit
    (no known vulnerabilities), wheel/sdist build inspected.

Add offline unit tests (PyPI, pip and the clang binaries are mocked) for:

- clang-format: command construction, --Werror injection for --dry-run,
  merged stdout/stderr, a missing executable, verbose diagnostics and
  main() reading sys.argv
- clang-tidy: --jobs validation, exit-code and diagnostic detection,
  compile-database and MSVC hints, source-file splitting, --fix placement,
  compile_commands.json search order, -p=<dir>, and main()
- util: numeric version ordering, the PyPI URL and timeout, pre-release
  filtering, invalid JSON, --version banner parsing, timeouts, pip
  failure logging, and the verbose and offline resolution branches

Narrow the coverage exclusions to the `if __name__ == "__main__":`
guards. The old patterns also excluded every line mentioning
FileNotFoundError or __name__, which hid testable error handling.
The version prefix lookup compared plain strings, so a major version
without a wheel silently resolved to an unrelated release:
`--version=2` installed clang-format 23.1.2 and `--version=1` installed
19.1.7, instead of failing with the list of available versions as the
README documents. Match the prefix only at a component boundary, so
"21" still resolves to the newest 21.x and "19.1.0" to "19.1.0.1".
Both were left over from the pyproject.toml-based version lookup that
#242 replaced with dynamic PyPI resolution; nothing imports tomli or
reads pyproject.toml at runtime any more.

The `../pyproject.toml` package-data entry also installed a stray
top-level `pyproject.toml` into site-packages (outside the package),
which can clash with other distributions that do the same.
Dependabot's pip ecosystem only bumps `pip` in uv.lock, so the dev
dependency group had drifted. Upgrade every locked package to its
latest compatible release, including:

- coverage 7.11.0 -> 7.16.2
- pre-commit 4.3.0 -> 4.6.2
- pytest 9.0.3 -> 9.1.1
- pytest-codspeed 4.2.0 -> 5.0.3 (drops cffi/pycparser)
- pip 26.2 -> 26.2.1
- virtualenv 20.36.1 -> 21.14.2
ruff-pre-commit v0.16.3 -> v0.16.10; all hooks pass on the repository.
… credentials

The repository's default GITHUB_TOKEN is read/write, so workflows without
a permissions block ran with write access to contents, pull requests,
packages and more.

- Default every workflow to `permissions: {}` and grant each job only
  what it uses: `contents: read` for tests, benchmarks and pre-commit;
  the scopes the org CodeQL and publish workflows declare for those
  callers.
- Set `persist-credentials: false` on checkouts that never push.
- Fix the CodSpeed action pin comment (`#5.2.1` -> `# v5.2.1`).
- Give Dependabot a 7-day cooldown before proposing newly published
  releases (security updates are not delayed).
…cov noise

- publish.yml: drop `branches` from the `release` trigger; it is not a
  valid filter for release events and GitHub ignores it (actionlint).
- release-drafter.yml: group the redirects and quote "$GITHUB_ENV"
  (shellcheck SC2129/SC2086). The generated notes and env file are
  byte-identical.
- codspeed.yml: the path filter named `cpp-linter-hooks/**`, but the
  package lives in `cpp_linter_hooks/`, so changes to the hook code alone
  never triggered benchmarks.
- test.yml: disable the Codecov CLI plugins (xcode, gcov, pycoverage),
  which only printed "not found" warnings; coverage.xml is passed
  explicitly.
@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Oct 1, 2026
@codecov

codecov Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (85389ec) to head (66ade29).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff             @@
##             main      #292      +/-   ##
===========================================
+ Coverage   97.53%   100.00%   +2.46%     
===========================================
  Files           3         3              
  Lines         243       248       +5     
===========================================
+ Hits          237       248      +11     
+ Misses          6         0       -6     

☔ 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.

@codspeed

codspeed Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

Merging this PR will not alter performance

🎉 Hooray! pytest-codspeed just leveled up to 5.0.3!

A heads-up, this is a breaking change and it might affect your current performance baseline a bit. But here's the exciting part - it's packed with new, cool features and promises improved result stability 🥳!
Curious about what's new? Visit our releases page to delve into all the awesome details about this new version.

✅ 92 untouched benchmarks
⏩ 54 skipped benchmarks1


Comparing chore/repo-health-check (66ade29) with main (5de731b)2

Open in CodSpeed

Footnotes

  1. 54 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

  2. No successful run was found on main (85389ec) during the generation of this report, so 5de731b was used instead as the comparison base. There might be some changes unrelated to this pull request in this report. ↩

Dependabot already applies a 3-day cooldown to version updates by default, which is enough here.
@sonarqubecloud

sonarqubecloud Bot commented Oct 2, 2026

Copy link
Copy Markdown

@shenxianpeng shenxianpeng added maintenance Targets chores, refactors and cleanups and removed documentation Improvements or additions to documentation labels Oct 2, 2026
@shenxianpeng
shenxianpeng marked this pull request as ready for review October 2, 2026 20:15
@shenxianpeng
shenxianpeng merged commit 064dd3c into main Oct 2, 2026
32 checks passed
@shenxianpeng
shenxianpeng deleted the chore/repo-health-check branch October 2, 2026 20:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

maintenance Targets chores, refactors and cleanups

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support Python 3.15

1 participant