Skip to content

Conversation

@2bndy5
Copy link
Contributor

@2bndy5 2bndy5 commented Sep 4, 2025

This new _version.py file is gitignored and generated at build time. It will be distributed to pypi though.

The generated code is used as

  1. a part of the custom User-Agent request header (cpp-linter/<version>). This should help identify REST API requests as unique requests from this software. The requests lib default user-agent value is set similarly but specific to the requests library (python-requests/X.Y.Z).
  2. the output of the new CLI subcommand cpp-linter version. This is meant to differentiate between the global --version arg used to specify a clang version.

Other changes


All of this is already implemented in the cpp-linter-rs port. So, this patch aligns with the future v2, disregarding the difference in --help output.

Summary by CodeRabbit

  • New Features

    • Added a CLI "version" subcommand and a versioned User-Agent header for API requests.
  • Documentation

    • CLI docs now list subcommands with version badges.
  • Chores

    • Updated pre-commit hooks and Dependabot schedules.
    • Enabled setuptools_scm version_file and ignored generated version output.
    • Pinned GitHub Actions to SHAs; added a new release workflow and removed the prior PyPI publish workflow.
  • Tests

    • Added tests for the version subcommand and updated API tests for the User-Agent.

This new `_version.py` file is gitignored and generated at build time. It will be distributed to pypi though.

The generated code is used as
1. a part of the custom `User-Agent` request header (`cpp-linter/<version>`).
   This should help identify REST API requests as unique requests from this software. The `requests` lib default user-agent value is set similarly but specific to the requests library (`python-requests/X.Y.Z`).
2. the output of the new CLI subcommand `cpp-linter version`.
   This is meant to differentiate between the global `--version` arg used to specify a clang version.

### Other changes
- ran `uv sync --all-groups -U` to upgrade locked dependencies
- update pre-commit hooks and ran them
- updated the test about listing changed files to ensure the user-agent is set accordingly.
- updated test about CLI parsing to ensure the new subcommand is respected (when used)
- updated CLI docs about new subcommand

---
All of this is already implemented in the cpp-linter-rs port.
So, this patch aligns with the future v2, disregarding the difference in `--help` output.
@2bndy5 2bndy5 added enhancement New feature or request minor A minor version bump labels Sep 4, 2025
and switch back to ubuntu-latest
@coderabbitai
Copy link

coderabbitai bot commented Sep 4, 2025

Walkthrough

Adds a top-level "version" CLI subcommand and exposes package version via a generated _version.py; standardizes REST API requests to include a versioned User-Agent; extends docs generation to render CLI subcommands with badges; updates tests, packaging, pre-commit, and multiple CI workflows.

Changes

Cohort / File(s) Summary
Version export & CLI
cpp_linter/__init__.py, cpp_linter/cli.py
Exposes version from ._version; adds Args.command and a top-level version subcommand; main() supports early exit when command == "version".
REST API headers
cpp_linter/rest_api/__init__.py, cpp_linter/rest_api/github_api.py
Adds USER_AGENT = f"cpp-linter/{version}"; make_headers now always includes User-Agent alongside existing headers.
Docs generation
docs/conf.py
Detects CLI subcommands when generating docs and emits a Subcommands section using SUBCOMMAND_VERSIONS badges and subcommand descriptions.
Tests
tests/list_changes/test_get_file_changes.py, tests/test_cli_args.py
Tests updated to expect the versioned User-Agent; added assertions for args.command default and for the "version" subcommand parsing.
Packaging & tooling config
pyproject.toml, .pre-commit-config.yaml, .gitignore
Sets version_file = "cpp_linter/_version.py" for setuptools_scm; bumps pre-commit hook revisions and renames ruff hook to ruff-check; removes [tool.codespell]; adds ignores for generated cpp_linter/_version.py.
CI/CD workflows
.github/workflows/release.yml, .github/workflows/docs.yml, .github/workflows/tests.yml, .github/workflows/publish-pypi.yml (deleted), .github/workflows/codeql.yml, .github/workflows/labeler.yml, .github/workflows/docs.yml
Adds release.yml (build/check/publish flow) and deletes legacy publish-pypi.yml; pins external action references to SHAs in multiple workflows; updates test matrix/conditionals; adds permissions blocks to CodeQL and labeler workflows.
Repo config
.github/dependabot.yml
Changes selected Dependabot update intervals to monthly.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant CLI as cpp_linter.__init__.main
  participant Parser as cli.parse_args
  note over CLI: New top-level "version" subcommand
  User->>CLI: run cpp-linter [args]
  CLI->>Parser: parse_args()
  Parser-->>CLI: Args(command="version" | None, …)
  alt command == "version"
    CLI-->>User: print(version)
    note right of CLI: early exit
  else
    CLI->>CLI: continue existing flow (file/PR handling)
    CLI-->>User: normal execution result
  end
Loading
sequenceDiagram
  autonumber
  participant Client as RestApiClient
  participant GHAPI as github_api.make_headers
  participant GitHub as api.github.com
  note over GHAPI: Adds standardized User-Agent header
  Client->>GHAPI: make_headers(token, accept)
  GHAPI-->>Client: {"Authorization": "...", "Accept": "...", "User-Agent":"cpp-linter/{version}"}
  Client->>GitHub: HTTP request with headers
  GitHub-->>Client: Response
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch generated-version-info

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

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

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

change dependabot updates to monthly check
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/conf.py (1)

307-326: Help-slicing bug truncates text when “Defaults to” is absent

Using str.find returns -1 when not found, which slices off the last character. Rename the variable to avoid shadowing built-in and guard the index.

-            assert arg.help is not None
-            help = arg.help[: arg.help.find("Defaults to")]
+            assert arg.help is not None
+            idx = arg.help.find("Defaults to")
+            help_text = arg.help if idx == -1 else arg.help[:idx]
...
-            doc.write("\n\n    ")
-            doc.write("\n    ".join(help.splitlines()) + "\n")
+            doc.write("\n\n    ")
+            doc.write("\n    ".join(help_text.splitlines()) + "\n")
🧹 Nitpick comments (10)
cpp_linter/cli.py (1)

400-405: Subcommand wiring — consider minor help UX tweaks.

Add a title/metavar so --help shows a clearer “Subcommands” section.

Apply within this block:

-    sub_parser = cli_parser.add_subparsers(
-        description="Subcommands for special behavior", dest="command"
-    )
+    sub_parser = cli_parser.add_subparsers(
+        description="Subcommands for special behavior",
+        dest="command",
+        title="Subcommands",
+        metavar="command",
+    )
.github/workflows/run-dev-tests.yml (1)

28-29: Matrix updates OK; two quick nits/checks.

  • Quote consistency nit:
-        os: ['windows-latest', ubuntu-latest]
+        os: ['windows-latest', 'ubuntu-latest']
  • Intent check: Only the clang=20 job runs tests that aren’t marked no_clang (see Lines 98–101). With clang 21 added, do you still want 20 to be the “full” run, or should that switch to 21?
docs/conf.py (4)

292-299: Avoid runtime asserts in non-test code (ruff S101)

Replace asserts with explicit errors for clearer failures in docs builds.

-            assert arg.dest is not None
+            if arg.dest is None:
+                raise ValueError("arg.dest is None; CLI parser misconfigured")
...
-                assert arg.help is not None
+                if arg.help is None:
+                    raise ValueError(f"Missing help for positional argument '{arg.dest}'")

If you prefer keeping asserts, add “# noqa: S101” with justification.


284-299: Subparser detection may be brittle; add a robust fallback

Relying on encountering a “command” positional within parser._optionals can miss subparsers depending on how the parser is structured. Add a post-loop fallback that scans all actions for _SubParsersAction.

         for arg in args:
             if arg.option_strings:
                 continue
             if arg.dest is None:
                 raise ValueError("arg.dest is None; CLI parser misconfigured")
             if arg.dest != "command":
                 doc.write(f"\n.. std:option:: {arg.dest.lower()}\n\n")
                 if arg.help is None:
                     raise ValueError(f"Missing help for positional argument '{arg.dest}'")
                 idx = arg.help.find("Defaults to")
                 help_text = arg.help if idx == -1 else arg.help[:idx]
                 doc.write("\n    ".join(help_text.splitlines()))
             else:
                 sub_commands = arg
+
+        # Fallback: ensure we found subparsers even if grouping differs
+        if sub_commands is None:
+            for a in parser._actions:
+                if isinstance(a, argparse._SubParsersAction):
+                    sub_commands = a
+                    break

327-338: Make subcommand section resilient and drop redundant assert

  • Accessing SUBCOMMAND_VERSIONS with [] will KeyError on new subcommands.
  • The assert at Line 328 is redundant due to the guard.
  • Description may be None; prefer a safe default.
-        if sub_commands is not None:
-            assert sub_commands is not None
+        if sub_commands is not None:
             choices = cast(Dict[str, argparse.ArgumentParser], sub_commands.choices)
             doc.write("\n\nSubcommands\n")
             doc.write("-----------\n")
             for sub_cmd in choices:
                 doc.write(f"\n.. std:option:: {sub_cmd}\n")
-                version = SUBCOMMAND_VERSIONS[sub_cmd]
+                version = SUBCOMMAND_VERSIONS.get(sub_cmd, release)
                 doc.write(f"\n    :badge-version:`{version}`\n\n    ")
                 sub_cmd_action = choices[sub_cmd]
-                assert sub_cmd_action.description is not None
-                doc.write("\n    ".join(sub_cmd_action.description.splitlines()) + "\n")
+                desc = sub_cmd_action.description or ""
+                doc.write("\n    ".join(desc.splitlines()) + "\n")

242-242: Centralize and document SUBCOMMAND_VERSIONS maintenance

Mapping looks good. Consider a brief comment or test that fails if a new subcommand lacks a version entry, to keep docs consistent.

tests/test_cli_args.py (1)

54-59: LGTM: “version” subcommand parsing

Test clearly verifies the new subcommand path. Consider also asserting no unintended args are set.

tests/list_changes/test_get_file_changes.py (3)

8-8: Avoid private import; use the public constant instead.

Importing from a private module (_version) couples the test to build-time artifacts. Prefer the exported USER_AGENT for a stable expectation that tracks production behavior.

Apply:

-from cpp_linter._version import version
+from cpp_linter.rest_api import USER_AGENT

118-126: Align expected header with production constant.

Use USER_AGENT to prevent drift if the format changes (e.g., metadata added).

         mock.get(
             endpoint,
             request_headers={
                 "Authorization": "token 123456",
                 "Accept": "application/vnd.github.diff",
-                "User-Agent": f"cpp-linter/{version}",
+                "User-Agent": USER_AGENT,
             },

136-146: Same here—match the standardized User-Agent.

                 mock.get(
                     mock_endpoint + ("" if pg == 1 else "?page=2"),
                     request_headers={
                         "Authorization": "token 123456",
                         "Accept": "application/vnd.github.raw+json",
-                        "User-Agent": f"cpp-linter/{version}",
+                        "User-Agent": USER_AGENT,
                     },
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 105ced2 and 599be8a.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (11)
  • .github/workflows/run-dev-tests.yml (1 hunks)
  • .gitignore (1 hunks)
  • .pre-commit-config.yaml (3 hunks)
  • cpp_linter/__init__.py (1 hunks)
  • cpp_linter/cli.py (2 hunks)
  • cpp_linter/rest_api/__init__.py (1 hunks)
  • cpp_linter/rest_api/github_api.py (2 hunks)
  • docs/conf.py (4 hunks)
  • pyproject.toml (1 hunks)
  • tests/list_changes/test_get_file_changes.py (3 hunks)
  • tests/test_cli_args.py (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-05-31T03:53:32.334Z
Learnt from: 2bndy5
PR: cpp-linter/cpp-linter#143
File: noxfile.py:10-10
Timestamp: 2025-05-31T03:53:32.334Z
Learning: In cpp-linter project, dev dependencies including `nox`, `mypy`, `ruff`, `pre-commit`, `rich`, and `types-requests` are properly configured in pyproject.toml under the `[dependency-groups]` dev section. Running `uv sync` installs all necessary dev requirements.

Applied to files:

  • pyproject.toml
🪛 Ruff (0.12.2)
tests/test_cli_args.py

51-51: Use of assert detected

(S101)


58-58: Use of assert detected

(S101)

docs/conf.py

292-292: Use of assert detected

(S101)


295-295: Use of assert detected

(S101)


328-328: Use of assert detected

(S101)


337-337: Use of assert detected

(S101)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: codeql / Analyze (python)
  • GitHub Check: test (ubuntu-latest, 20)
  • GitHub Check: test (windows-latest, 11)
  • GitHub Check: test (windows-latest, 10)
  • GitHub Check: test (windows-latest, 15)
  • GitHub Check: test (windows-latest, 16)
  • GitHub Check: test (windows-latest, 14)
  • GitHub Check: test (windows-latest, 18)
🔇 Additional comments (10)
pyproject.toml (1)

61-61: Setuptools_scm version file configuration added — verify dev/test import path.

version_file = "cpp_linter/_version.py" looks right. Please confirm that local dev and CI test runs (without building a wheel/sdist first) still succeed when importing cpp_linter._version. If not, consider a fallback import (e.g., get version via importlib.metadata.version("cpp-linter")) in cpp_linter/__init__.py when _version.py is absent.

Would you like a small patch that adds a safe fallback import?

.gitignore (1)

182-184: Ignore generated _version.py — good call.

This matches the build-time generation via setuptools_scm and avoids accidental check-ins.

.pre-commit-config.yaml (1)

6-6: Pre-commit bumps look good; ruff hook id is correct for this rev.

Upgrades are reasonable. Using id: ruff-check with rev: v0.12.11 matches the current Ruff docs. (docs.astral.sh)

Also applies to: 21-21, 24-24, 28-28, 39-39

cpp_linter/cli.py (1)

72-74: New Args.command attribute — LGTM.

Keeps parsing state explicit without impacting existing flags.

docs/conf.py (1)

6-10: Imports look good

Argparse and typing additions are appropriate for the subcommand docs logic.

cpp_linter/rest_api/__init__.py (1)

23-24: LGTM: Centralized User-Agent

Exposing USER_AGENT at package level is clean and keeps headers consistent across clients.

tests/test_cli_args.py (1)

51-52: LGTM: default subcommand state

Asserting args.command is None for bare parser usage matches the intended CLI.

cpp_linter/__init__.py (1)

19-23: Version subcommand flow looks good.

cpp_linter/rest_api/github_api.py (2)

32-32: Good: centralizing User-Agent via constant.

Keeps headers consistent across requests.


199-207: Header construction LGTM.

User-Agent inclusion is correct; Authorization remains conditional.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
.github/dependabot.yml (2)

11-11: Monthly is fine; consider a faster cadence for Actions due to frequent security fixes.

Optional: switch Actions to weekly or keep monthly but enable/confirm Dependabot security updates so CVE PRs aren’t delayed by the schedule. You can also add time/timezone to batch PRs predictably.


19-19: uv updates monthly: OK; add scheduling hygiene if noise becomes an issue.

If you later want tighter control without increasing volume, set schedule.time/timezone and keep grouping. uv is now a supported ecosystem, so this config is valid.

.github/workflows/build-docs.yml (1)

15-15: Good pin on setup-uv to a commit.

LGTM. As a follow-up, consider pinning other third‑party actions (e.g., actions-gh-pages) to SHAs for supply‑chain hardening.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 599be8a and bafc097.

📒 Files selected for processing (3)
  • .github/dependabot.yml (1 hunks)
  • .github/workflows/build-docs.yml (1 hunks)
  • .github/workflows/run-dev-tests.yml (3 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-05-31T02:10:01.595Z
Learnt from: 2bndy5
PR: cpp-linter/cpp-linter#143
File: .github/dependabot.yml:16-23
Timestamp: 2025-05-31T02:10:01.595Z
Learning: As of March 13, 2025, Dependabot officially supports `uv` as a package-ecosystem in general availability. Prior to this date, `uv` was not supported by Dependabot. The configuration `package-ecosystem: uv` is now valid and will enable automated dependency updates for uv.lock files.

Applied to files:

  • .github/dependabot.yml
  • .github/workflows/build-docs.yml
  • .github/workflows/run-dev-tests.yml
📚 Learning: 2025-05-31T02:10:01.595Z
Learnt from: 2bndy5
PR: cpp-linter/cpp-linter#143
File: .github/dependabot.yml:16-23
Timestamp: 2025-05-31T02:10:01.595Z
Learning: Dependabot now supports `uv` as a package-ecosystem in general availability, though `uv` is still in beta stage (major version 0). This is documented in GitHub issue https://github.com/dependabot/dependabot-core/issues/10478 and related threads tracking uv maturity features.

Applied to files:

  • .github/dependabot.yml
  • .github/workflows/build-docs.yml
  • .github/workflows/run-dev-tests.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: test (ubuntu-latest, 18)
  • GitHub Check: test (ubuntu-latest, 21)
  • GitHub Check: test (windows-latest, 15)
  • GitHub Check: test (windows-latest, 10)
  • GitHub Check: test (windows-latest, 11)
  • GitHub Check: test (windows-latest, 12)
  • GitHub Check: test (windows-latest, 14)
  • GitHub Check: test (windows-latest, 19)
  • GitHub Check: test (windows-latest, 20)
  • GitHub Check: test (windows-latest, 16)
  • GitHub Check: test (windows-latest, 21)
🔇 Additional comments (2)
.github/workflows/run-dev-tests.yml (2)

59-59: Pinning setup-uv by commit: thumbs up.

Consistent with the docs workflow; reduces supply‑chain risk.


135-135: Coverage job also pins setup-uv: consistent and good.

No further changes needed here.

@codecov
Copy link

codecov bot commented Sep 4, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.26%. Comparing base (105ced2) to head (a7a1503).
⚠️ Report is 17 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #150      +/-   ##
==========================================
+ Coverage   98.25%   98.26%   +0.01%     
==========================================
  Files          23       23              
  Lines        1886     1899      +13     
==========================================
+ Hits         1853     1866      +13     
  Misses         33       33              

☔ View full report in Codecov by Sentry.
📢 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.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/tests.yml (1)

72-86: Fail fast if both clang installation attempts miss.

As written, if the first apt install fails and the LLVM script fails, the step won’t error (commands run inside if conditions don’t trip set -e). Add a post-check to ensure tools exist.

Apply:

           fi
         fi
+
+        # Verify clang-tidy for the requested version is available, or fail fast
+        if ! command -v "clang-tidy-${{ matrix.version }}" >/dev/null 2>&1; then
+          echo "clang-tidy-${{ matrix.version }} not found after installation attempts" >&2
+          exit 1
+        fi
🧹 Nitpick comments (12)
.github/workflows/docs.yml (2)

24-24: Pin looks good; consider artifact retention to save storage.

Add a short retention for doc artifacts (they’re ephemeral).

       - name: Upload docs build as artifact
-        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+        uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
         with:
           name: ${{ github.event.repository.name }}_docs
           path: ${{ github.workspace }}/${{ env.path_to_doc }}
+          retention-days: 7

32-32: Pin is solid; ensure GITHUB_TOKEN has write perms for gh-pages push.

If repo defaults are read-only, this step will fail. Recommend explicit permissions.

 jobs:
   build-docs:
     runs-on: ubuntu-latest
+    permissions:
+      contents: write  # required by peaceiris/actions-gh-pages to push to gh-pages
     env:
       path_to_doc: docs/_build/html

Optional: add concurrency to avoid overlapping publishes.

   build-docs:
+    concurrency:
+      group: docs-${{ github.ref }}
+      cancel-in-progress: true

If you prefer least-privilege, split deploy into a second job with permissions: contents: write and keep build as contents: read.

.github/workflows/release.yml (7)

21-25: Be explicit about fetching tags for setuptools_scm.

fetch-depth: 0 usually brings full history, but being explicit about tags avoids edge cases where tags aren’t present and setuptools_scm can't compute a version.

       - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 #v5.0.0
         # use fetch --all for setuptools_scm to work
         with:
           fetch-depth: 0
+          fetch-tags: true

29-35: Avoid relying on pipx availability on runners.

pipx is not guaranteed across all runners. Prefer python -m build and install tools explicitly for stability.

-      - name: Build distributions
-        run: pipx run build -o dist
+      - name: Install build tooling
+        run: python -m pip install --upgrade build
+      - name: Build distributions
+        run: python -m build -o dist

31-36: Artifact name is misleading.

You’re uploading both sdists and wheels, but naming the artifact “wheels”. Rename to “dist” for clarity.

-      - name: Upload builds as artifacts
+      - name: Upload distributions as artifacts
         uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
         with:
           path: dist
-          name: wheels
+          name: dist

Note: Update the download step accordingly (see next comment).


41-46: Keep artifact name consistent with the upload step.

If you rename the artifact to “dist”, update the consumer step.

       - name: Download distributions
         uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
         with:
-          name: wheels
+          name: dist
           path: dist

51-56: Preflight twine check on tag builds and make re-runs idempotent.

Running twine check for tag refs helps catch metadata issues before publish. Also consider skip-existing: true to allow safe re-runs on the same tag.

       - name: Check distributions
-        if: ${{ !startsWith(github.ref, 'refs/tags/') }}
+        if: ${{ !startsWith(github.ref, 'refs/tags/') }}
         run: pipx run twine check dist/*
+      - name: Check distributions (tag)
+        if: startsWith(github.ref, 'refs/tags/')
+        run: pipx run twine check dist/*
       - name: Deploy to PyPI
         if: startsWith(github.ref, 'refs/tags/')
-        uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
+        uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
+        with:
+          skip-existing: true

If you adopt the earlier “no pipx” change, replace the twine check invocations with python -m twine check and add python -m pip install --upgrade twine alongside build tooling.


1-2: Header comment is out of sync with triggers.

Comment says “when a release is created,” but the workflow runs on pushes (branches and tags) and manual dispatch. Update to avoid confusion.

-# This workflow will upload a Python Package using Twine when a release is created
+# This workflow builds on every push (main and v* tags); tag pushes publish to PyPI.

55-56: Confirm publishing method (OIDC vs token).

If you’re not using PyPI Trusted Publishing, pass the API token instead of OIDC. Otherwise, the earlier permissions change is sufficient.

Option for token-based publishing:

       - name: Deploy to PyPI
         if: startsWith(github.ref, 'refs/tags/')
         uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
+        with:
+          password: ${{ secrets.PYPI_API_TOKEN }}

Would you like me to open a follow-up PR snippet with either OIDC (preferred) or token wiring based on your PyPI setup?

.github/workflows/tests.yml (3)

28-29: Matrix bump to clang 21: verify toolchain availability across runners.

LLVM 21 may not be present on all GitHub-hosted images yet. Please verify that:

  • apt.llvm.org (for Ubuntu 24.04 behind ubuntu-latest) provides clang-format-21/clang-tidy-21
  • clang-tools --install 21 succeeds on both Linux and Windows runners

If 21 is still rolling out, consider temporarily allowing it to be “experimental” to avoid blocking PRs.

Proposed tweak (make 21 non-blocking until confirmed stable):

   strategy:
     fail-fast: false
     matrix:
       os: ['windows-latest', ubuntu-latest]
-      version: ['21', '20', '19', '18', '17', '16', '15', '14', '13', '12', '11', '10', '9']
+      version: ['21', '20', '19', '18', '17', '16', '15', '14', '13', '12', '11', '10', '9']
+      experimental: [false]
+      include:
+        - version: '21'
+          experimental: true
+  continue-on-error: ${{ matrix.experimental }}

For consistency, also quote ubuntu-latest:

-        os: ['windows-latest', ubuntu-latest]
+        os: ['windows-latest', 'ubuntu-latest']

98-101: Avoid mixing expression interpolation inside Python.

Using ${{ matrix.version }} inside Python produces generated code like “if 21 == 21:” which is brittle. A small bash step is simpler and safer.

Apply:

-      - name: Is clang-only tests?
-        id: clang-dep
-        shell: python
-        run: |-
-          from os import environ
-          with open(environ["GITHUB_OUTPUT"], mode="a") as gh_out:
-            if ${{ matrix.version }} == 21:
-                gh_out.write("args=\n")
-            else:
-                gh_out.write("args=-m \"not no_clang\"\n")
+      - name: Is clang-only tests?
+        id: clang-dep
+        shell: bash
+        run: |
+          if [ "${{ matrix.version }}" = "21" ]; then
+            echo "args=" >> "$GITHUB_OUTPUT"
+          else
+            echo 'args=-m "not no_clang"' >> "$GITHUB_OUTPUT"
+          fi

1-3: Optional: lock down default token permissions and job timeouts.

Reduce blast radius and prevent hangs.

Apply near the top:

 name: Build and Test
+
+permissions:
+  contents: read

And per job:

 jobs:
   test:
+    timeout-minutes: 45
   coverage-report:
+    timeout-minutes: 20
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between bafc097 and a47da57.

📒 Files selected for processing (4)
  • .github/workflows/docs.yml (2 hunks)
  • .github/workflows/publish-pypi.yml (0 hunks)
  • .github/workflows/release.yml (1 hunks)
  • .github/workflows/tests.yml (7 hunks)
💤 Files with no reviewable changes (1)
  • .github/workflows/publish-pypi.yml
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-05-31T02:10:01.595Z
Learnt from: 2bndy5
PR: cpp-linter/cpp-linter#143
File: .github/dependabot.yml:16-23
Timestamp: 2025-05-31T02:10:01.595Z
Learning: Dependabot now supports `uv` as a package-ecosystem in general availability, though `uv` is still in beta stage (major version 0). This is documented in GitHub issue https://github.com/dependabot/dependabot-core/issues/10478 and related threads tracking uv maturity features.

Applied to files:

  • .github/workflows/tests.yml
📚 Learning: 2025-05-31T02:10:01.595Z
Learnt from: 2bndy5
PR: cpp-linter/cpp-linter#143
File: .github/dependabot.yml:16-23
Timestamp: 2025-05-31T02:10:01.595Z
Learning: As of March 13, 2025, Dependabot officially supports `uv` as a package-ecosystem in general availability. Prior to this date, `uv` was not supported by Dependabot. The configuration `package-ecosystem: uv` is now valid and will enable automated dependency updates for uv.lock files.

Applied to files:

  • .github/workflows/tests.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (21)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: test (ubuntu-latest, 13)
  • GitHub Check: test (windows-latest, 19)
  • GitHub Check: test (ubuntu-latest, 12)
  • GitHub Check: test (ubuntu-latest, 11)
  • GitHub Check: test (ubuntu-latest, 10)
  • GitHub Check: test (windows-latest, 9)
  • GitHub Check: test (windows-latest, 13)
  • GitHub Check: test (ubuntu-latest, 19)
  • GitHub Check: test (ubuntu-latest, 21)
  • GitHub Check: test (windows-latest, 14)
  • GitHub Check: test (windows-latest, 18)
  • GitHub Check: test (ubuntu-latest, 20)
  • GitHub Check: test (windows-latest, 10)
  • GitHub Check: test (windows-latest, 11)
  • GitHub Check: test (windows-latest, 12)
  • GitHub Check: test (windows-latest, 15)
  • GitHub Check: test (windows-latest, 17)
  • GitHub Check: test (windows-latest, 16)
  • GitHub Check: test (windows-latest, 20)
  • GitHub Check: test (windows-latest, 21)
🔇 Additional comments (5)
.github/workflows/docs.yml (2)

12-12: **Pin verified **The pinned SHA 08c6903cd8c0fde910a37f88322edcfb5dd907a8 correctly matches tag v5.0.0.


15-15: Setup-uv v6.6.1 SHA verified
Tag v6.6.1 matches commit 557e51de59eb14aaaba2ed9621916900a91d50c6.

.github/workflows/tests.yml (3)

58-63: LGTM: uv setup pinned and cached.

Pinned SHA with dependency glob is solid. No changes requested.


109-115: LGTM: artifact upload pinned.

Good pin and includes hidden files for coverage artifacts.


120-156: LGTM: coverage job pinned actions and Codecov.

Checkout/download/setup-python/setup-uv/upload-artifact/codecov all pinned—nice hardening. No changes requested.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
.github/workflows/tests.yml (1)

37-37: Resolved: checkout pinned in test job.

This addresses the earlier supply‑chain hardening comment. Thanks for pinning.

🧹 Nitpick comments (3)
.github/workflows/tests.yml (3)

28-29: Matrix tweaks look fine; minor consistency nit.

Mixing quoted and unquoted values in the same list is valid YAML but a bit noisy. Consider quoting both OS entries for consistency.

-        os: ['windows-latest', ubuntu-latest]
+        os: ['windows-latest', 'ubuntu-latest']

98-101: Prefer shell-based output over Python interpolation for simplicity and robustness.

Embedding ${{ matrix.version }} inside Python is a bit brittle. Bash keeps it simpler and avoids type/quoting surprises while writing to $GITHUB_OUTPUT.

-      - name: Is clang-only tests?
-        id: clang-dep
-        shell: python
-        run: |-
-          from os import environ
-          with open(environ["GITHUB_OUTPUT"], mode="a") as gh_out:
-            if ${{ matrix.version }} == 21:
-                gh_out.write("args=\n")
-            else:
-                gh_out.write("args=-m \"not no_clang\"\n")
+      - name: Is clang-only tests?
+        id: clang-dep
+        shell: bash
+        run: |
+          if [[ "${{ matrix.version }}" == "21" ]]; then
+            echo "args=" >> "$GITHUB_OUTPUT"
+          else
+            echo 'args=-m "not no_clang"' >> "$GITHUB_OUTPUT"
+          fi

118-118: Optional: pin Ubuntu runner to an LTS for stability.

ubuntu-latest can shift images and break toolchains unexpectedly. If you value determinism, consider ubuntu-22.04 (or 24.04) here and in the matrix.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a47da57 and c273e18.

📒 Files selected for processing (2)
  • .github/workflows/release.yml (1 hunks)
  • .github/workflows/tests.yml (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/release.yml
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-05-31T02:10:01.595Z
Learnt from: 2bndy5
PR: cpp-linter/cpp-linter#143
File: .github/dependabot.yml:16-23
Timestamp: 2025-05-31T02:10:01.595Z
Learning: Dependabot now supports `uv` as a package-ecosystem in general availability, though `uv` is still in beta stage (major version 0). This is documented in GitHub issue https://github.com/dependabot/dependabot-core/issues/10478 and related threads tracking uv maturity features.

Applied to files:

  • .github/workflows/tests.yml
📚 Learning: 2025-05-31T02:10:01.595Z
Learnt from: 2bndy5
PR: cpp-linter/cpp-linter#143
File: .github/dependabot.yml:16-23
Timestamp: 2025-05-31T02:10:01.595Z
Learning: As of March 13, 2025, Dependabot officially supports `uv` as a package-ecosystem in general availability. Prior to this date, `uv` was not supported by Dependabot. The configuration `package-ecosystem: uv` is now valid and will enable automated dependency updates for uv.lock files.

Applied to files:

  • .github/workflows/tests.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (21)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: test (ubuntu-latest, 9)
  • GitHub Check: test (ubuntu-latest, 14)
  • GitHub Check: test (ubuntu-latest, 12)
  • GitHub Check: test (ubuntu-latest, 16)
  • GitHub Check: test (ubuntu-latest, 20)
  • GitHub Check: test (windows-latest, 10)
  • GitHub Check: test (ubuntu-latest, 13)
  • GitHub Check: test (ubuntu-latest, 17)
  • GitHub Check: test (windows-latest, 12)
  • GitHub Check: test (ubuntu-latest, 18)
  • GitHub Check: test (windows-latest, 21)
  • GitHub Check: test (windows-latest, 13)
  • GitHub Check: test (windows-latest, 15)
  • GitHub Check: test (ubuntu-latest, 21)
  • GitHub Check: test (windows-latest, 9)
  • GitHub Check: test (windows-latest, 20)
  • GitHub Check: test (windows-latest, 18)
  • GitHub Check: test (windows-latest, 16)
  • GitHub Check: test (windows-latest, 17)
  • GitHub Check: test (windows-latest, 14)
🔇 Additional comments (2)
.github/workflows/tests.yml (2)

39-39: Good hardening: actions pinned to SHAs.

Pinning setup-python, setup-uv, upload/download-artifact, checkout, and codecov is solid. No issues spotted.

Also applies to: 58-63, 110-110, 121-121, 124-124, 130-130, 135-135, 144-144, 149-149


107-107: Verify lone -- usage in CI
Sandbox lacked uvx, so please confirm in your CI environment that running

uvx nox -s test-all --

with an empty steps.clang-dep.outputs.args doesn’t produce a parse error. If it does, gate the -- on non-empty args as shown in the original diff.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
.github/workflows/labeler.yml (1)

9-13: Minor naming nit: job id “draft-release” under “PR Autolabeler” can confuse.

Consider renaming the job to reflect its PR-labeling purpose (e.g., autolabel) for clarity.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c273e18 and 91115db.

📒 Files selected for processing (3)
  • .github/workflows/codeql.yml (1 hunks)
  • .github/workflows/labeler.yml (1 hunks)
  • .github/workflows/tests.yml (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/tests.yml
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-04T03:33:27.553Z
Learnt from: 2bndy5
PR: cpp-linter/cpp-linter#150
File: .github/workflows/release.yml:0-0
Timestamp: 2025-09-04T03:33:27.553Z
Learning: In GitHub workflows, `contents: read` permissions can be controlled via repository settings for `github.token` access rather than explicitly defining it in the workflow permissions block, as preferred by user 2bndy5.

Applied to files:

  • .github/workflows/labeler.yml
  • .github/workflows/codeql.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (21)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: test (ubuntu-latest, 12)
  • GitHub Check: test (ubuntu-latest, 9)
  • GitHub Check: test (ubuntu-latest, 19)
  • GitHub Check: test (ubuntu-latest, 20)
  • GitHub Check: test (windows-latest, 10)
  • GitHub Check: test (ubuntu-latest, 14)
  • GitHub Check: test (ubuntu-latest, 15)
  • GitHub Check: test (ubuntu-latest, 18)
  • GitHub Check: test (windows-latest, 18)
  • GitHub Check: test (windows-latest, 9)
  • GitHub Check: test (ubuntu-latest, 17)
  • GitHub Check: test (ubuntu-latest, 21)
  • GitHub Check: test (windows-latest, 15)
  • GitHub Check: test (windows-latest, 17)
  • GitHub Check: test (windows-latest, 14)
  • GitHub Check: test (windows-latest, 13)
  • GitHub Check: test (windows-latest, 16)
  • GitHub Check: test (windows-latest, 21)
  • GitHub Check: test (windows-latest, 19)
  • GitHub Check: test (windows-latest, 20)
🔇 Additional comments (2)
.github/workflows/codeql.yml (1)

12-14: Remove redundant contents: read suggestion
Repository-level permissions already grant contents: read for the GITHUB_TOKEN, so explicitly adding it here is unnecessary. Ignore this change.

Likely an incorrect or invalid review comment.

.github/workflows/labeler.yml (1)

10-12: Incorrect suggestion: this is the labeler workflow, not a release-drafter job, and removing contents: write without replacing it with contents: read (when you override permissions) would break config loading. Ignore this comment.

Likely an incorrect or invalid review comment.

After restricting the GITHUB_TOKEN to read only permissions (in contents and packages scopes).
@2bndy5 2bndy5 force-pushed the generated-version-info branch from 91115db to a7a1503 Compare September 4, 2025 04:56
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
.github/workflows/labeler.yml (2)

10-12: Reduce to least-privilege permissions

Autolabeling needs pull-requests: write; contents: write is unnecessary. Prefer contents: read to limit the GITHUB_TOKEN scope. If the reusable workflow doesn’t require repo writes, this is safer.

Apply:

 permissions:
-  contents: write
+  contents: read
   pull-requests: write

Note: Per your stated preference to manage token scopes via repo settings, you could also drop this block entirely if the repo default grants pull-requests: write to workflows (verify first).


9-9: Nit: rename job for clarity

Job id draft-release is misleading in an autolabeler workflow. Consider autolabel or similar.

-jobs:
-  draft-release:
+jobs:
+  autolabel:
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 91115db and a7a1503.

📒 Files selected for processing (2)
  • .github/workflows/codeql.yml (1 hunks)
  • .github/workflows/labeler.yml (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/codeql.yml
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-09-04T03:33:27.553Z
Learnt from: 2bndy5
PR: cpp-linter/cpp-linter#150
File: .github/workflows/release.yml:0-0
Timestamp: 2025-09-04T03:33:27.553Z
Learning: In GitHub workflows, `contents: read` permissions can be controlled via repository settings for `github.token` access rather than explicitly defining it in the workflow permissions block, as preferred by user 2bndy5.

Applied to files:

  • .github/workflows/labeler.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (21)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: test (ubuntu-latest, 17)
  • GitHub Check: test (ubuntu-latest, 10)
  • GitHub Check: test (windows-latest, 9)
  • GitHub Check: test (windows-latest, 12)
  • GitHub Check: test (windows-latest, 16)
  • GitHub Check: test (windows-latest, 15)
  • GitHub Check: test (windows-latest, 13)
  • GitHub Check: test (ubuntu-latest, 13)
  • GitHub Check: test (ubuntu-latest, 21)
  • GitHub Check: test (ubuntu-latest, 18)
  • GitHub Check: test (windows-latest, 14)
  • GitHub Check: test (ubuntu-latest, 19)
  • GitHub Check: test (windows-latest, 11)
  • GitHub Check: test (windows-latest, 10)
  • GitHub Check: test (ubuntu-latest, 16)
  • GitHub Check: test (ubuntu-latest, 20)
  • GitHub Check: test (windows-latest, 17)
  • GitHub Check: test (windows-latest, 20)
  • GitHub Check: test (windows-latest, 21)
  • GitHub Check: test (windows-latest, 19)
🔇 Additional comments (1)
.github/workflows/labeler.yml (1)

3-6: Fork PRs won’t be labeled with pull_request trigger

For PRs from forks, pull_request runs with a read-only token; write perms (even if requested) won’t apply, so labels may not be added. If you want labels on forked PRs, switch to pull_request_target and ensure the called workflow does not check out or execute untrusted PR code.

If you decide to switch:

 on:
-  pull_request:
+  pull_request_target:
     types: [opened, reopened, synchronize]

Confirm the reusable workflow only reads PR metadata and does not run PR code.

@2bndy5 2bndy5 marked this pull request as draft September 4, 2025 06:29
@2bndy5
Copy link
Contributor Author

2bndy5 commented Sep 4, 2025

I'm resetting this branch and splitting out the CI changes to a new branch (see #151).
I'll rebase and open a new PR once #151 is merged.

@2bndy5 2bndy5 closed this Sep 4, 2025
@2bndy5 2bndy5 mentioned this pull request Sep 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request minor A minor version bump

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants