feat: Switch clang tools from static binaries to wheels
closes #364
Summary by CodeRabbit
-
Documentation
- Expanded installation guidance with ordered, platform-specific fallbacks; added direct wheel URLs and removed the old static-binaries link; updated license wording to reference the MIT License.
-
Chores
- Installer now uses build-platform detection, robustly validates versions/paths, emits warnings/errors for invalid or empty inputs, and performs per-tool, version-aware sequential installs with clearer logging and outputs.
Walkthrough
Updated README to prefer clang wheels with ordered fallback sequences per OS and adjusted links/licensing wording. Reworked action.yml to validate/coerce version, build a per-tool install list from inputs, and perform tool-by-tool installation choosing between wheel and legacy installers.
Changes
| Cohort / File(s) | Change Summary |
|---|---|
Documentation README.md |
Replaced references to clang-tools-static-binaries with explicit wheel URLs for clang-tidy and clang-format; removed static-binaries link; introduced ordered, OS-specific fallback install sequences (Linux, macOS, Windows); updated license wording to reference the MIT License; minor wording adjustments. |
Action manifest / install logic action.yml |
Replaced Windows detection with build_os-based check; added robust version handling (empty -> platform-default exit; attempt integer coercion; handle invalid string vs valid path with distinct outcomes); construct dynamic per-tool list from inputs.tidy-checks and inputs.style; replace single installer invocation with per-tool loop selecting clang-tools or clang-tools-wheel based on tool/version rules and invoking installs per-tool with appropriate logging and exit paths. |
Estimated code review effort
π― 4 (Complex) | β±οΈ ~45 minutes
- Review
action.ymlversion coercion/error paths and how path-valuedversionis treated. - Verify per-tool install selection logic (when to use wheels vs legacy installer) and platform-specific branching.
- Confirm logging, runner invocation, and exit status behavior preserved across the new loop.
Possibly related PRs
- cpp-linter/cpp-linter-action#299 β Overlapping changes to
action.ymlversion handling and validation logic. - cpp-linter/cpp-linter-action#314 β Related migration discussions and installer invocation changes between static binaries and wheels.
Suggested reviewers
- shenxianpeng
Pre-merge checks and finishing touches
β Passed checks (5 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | β Passed | Check skipped - CodeRabbitβs high-level summary is enabled. |
| Title check | β Passed | The PR title accurately describes the main objective: switching clang tools installation from static binaries to Python wheels, which aligns with the primary changes in both README.md and action.yml. |
| Linked Issues check | β Passed | The PR successfully implements the core objective from issue #364: switching clang tools installation from static-binaries to Python wheels by updating documentation and modifying the installation workflow to use clang-tools-wheel. |
| Out of Scope Changes check | β Passed | All changes in README.md and action.yml are directly scoped to implementing the wheels-based installation approach from issue #364; no unrelated modifications detected. |
| Docstring Coverage | β Passed | No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. |
β¨ Finishing touches
π§ͺ Generate unit tests (beta)
- [ ] Create PR with unit tests
- [ ] Post copyable unit tests in a comment
- [ ] Commit unit tests in branch
fix-364
π Recent review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
π₯ Commits
Reviewing files that changed from the base of the PR and between b72d11b82df50ee1739b4c668448d87e01f4723a and 454ad2755e5e0241c5ade59c07caa25e876038c6.
π Files selected for processing (2)
README.md(2 hunks)action.yml(2 hunks)
π§ Files skipped from review as they are similar to previous changes (1)
- README.md
π§° Additional context used
π§ Learnings (5)
π Learning: 2025-08-17T12:34:25.463Z
Learnt from: 2bndy5
Repo: cpp-linter/cpp-linter-action PR: 314
File: action.yml:394-416
Timestamp: 2025-08-17T12:34:25.463Z
Learning: In the cpp-linter-action project, technical improvements can be deferred to separate PRs when they're not critical to the current changes, especially when the current implementation is known to work correctly.
Applied to files:
action.yml
π Learning: 2025-08-17T12:50:57.038Z
Learnt from: 2bndy5
Repo: cpp-linter/cpp-linter-action PR: 314
File: action.yml:273-321
Timestamp: 2025-08-17T12:50:57.038Z
Learning: In Nu shell, `$in` is shorthand for a closure that takes 1 argument, so `(...) | complete | $in.exit_code == 0` is equivalent to `(...) | complete | {|in| $in.exit_code == 0}`.
Applied to files:
action.yml
π Learning: 2025-08-17T12:31:25.319Z
Learnt from: 2bndy5
Repo: cpp-linter/cpp-linter-action PR: 314
File: action.yml:273-321
Timestamp: 2025-08-17T12:31:25.319Z
Learning: In Nu shell, the pattern `(...) | complete | $in.exit_code == 0` is valid syntax for checking command exit codes, where `complete` captures the command result and `$in` refers to the piped input.
Applied to files:
action.yml
π Learning: 2025-08-17T13:20:51.048Z
Learnt from: 2bndy5
Repo: cpp-linter/cpp-linter-action PR: 314
File: README.md:206-211
Timestamp: 2025-08-17T13:20:51.048Z
Learning: For GitHub Actions documentation references in cpp-linter-action, prefer stable workflow syntax documentation links over "canonical" specialized pages that may redirect, as the comprehensive workflow syntax page provides better context and examples for container configuration.
Applied to files:
action.yml
π Learning: 2025-08-17T12:34:25.463Z
Learnt from: 2bndy5
Repo: cpp-linter/cpp-linter-action PR: 314
File: action.yml:394-416
Timestamp: 2025-08-17T12:34:25.463Z
Learning: The cpp-linter/cpp-linter-action repository manages the downstream parsing of command-line arguments through their own cpp-linter/cpp-linter project, so passing empty string values for flags like --extra-arg="" is acceptable and known to work in their implementation.
Applied to files:
action.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). (8)
- GitHub Check: test (windows-latest, 17)
- GitHub Check: test (windows-latest, 13)
- GitHub Check: test (windows-latest, 12)
- GitHub Check: test (macos-latest, 20)
- GitHub Check: test (macos-latest, 21)
- GitHub Check: test (ubuntu-latest, 21)
- GitHub Check: test (macos-latest, 12)
- GitHub Check: test (macos-latest, 11)
π Additional comments (3)
action.yml (3)
351-351: Platform detection refactored correctly for consistency.Line 351 now uses
(version | get "build_os") | str starts-with "windows"for Windows detection, aligning with the suggestion from past reviews. This approach is more robust than previous alternatives and consistent with the platform check at line 420. Build_os returns values like "windows-x86_64", "macos-aarch64", and "linux-x86_64", making the string prefix check reliable across all GitHub Actions runners.
402-428: Per-tool installation with correct version-based fallback logic.The implementation properly:
- Builds a dynamic tool list (lines 402-410) based on actual usage: clang-tidy is included only if
tidy-checks != "-*"(not disabled), and clang-format only ifstyleis not empty- Iterates per-tool (lines 413-428) to install only what's needed, avoiding unnecessary installations
- Applies version-aware fallback logic (lines 415-426):
- Clang-tidy < v13: uses
clang-tools(static binaries) for compatibility- Clang-format β€ v9 on non-Linux: uses
clang-tools(addresses issue #364 regarding wheel platform tag availability)- All other cases: uses
clang-tools-wheelfor the modern wheels approach- Platform detection at line 420 correctly uses
(version | get "build_os") | str starts-with "linux"for robust Linux identificationThe fallback strategy directly addresses the PR objective to switch to wheels while maintaining backward compatibility for older clang-tidy versions and the wheel availability constraints documented in issue #364.
379-395: Based on my research, I found that the patternlet result = try { ... } catch { ... }was explicitly requested as a feature in Nushell issue #10452, but the implementation status remains unclear from the available documentation. While production code from March 2025 uses similar try-catch assignment patterns successfully, I cannot definitively verify the variable scoping behavior you requested since the Nushell interpreter is not available in the sandbox environment.The code in action.yml (lines 379-395) follows a pattern where:
- On successful
tryblock execution,$version_str | into intresult should assign to$result- On error, the
catchblock handles itHowever, without direct execution capability or explicit Nushell version documentation confirming try-catch expression support, I cannot conclusively verify whether the variable
versionproperly scopes after the try-catch block succeeds.
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.
Comment @coderabbitai help to get the list of available commands and usage tips.
Cpp-Linter Report :warning:
Some files did not pass the configured checks!
clang-format (v16.0.6) reports: 2 file(s) not formatted
- docs/examples/demo/demo.hpp
- docs/examples/demo/demo.cpp
clang-tidy (v16.0.6) reports: 7 concern(s)
-
docs/examples/demo/demo.hpp:6:11: warning: [modernize-use-default-member-init]
use default member initializer for 'useless'
char* useless; ^ {"\0"} -
docs/examples/demo/demo.hpp:7:9: warning: [modernize-use-default-member-init]
use default member initializer for 'numb'
int numb; ^ {0} -
docs/examples/demo/demo.hpp:11:11: warning: [modernize-use-trailing-return-type]
use a trailing return type for this function
void *not_useful(char *str){useless = str;} ~~~~~~^ auto -> void * -
docs/examples/demo/demo.cpp:3:10: warning: [modernize-deprecated-headers]
inclusion of deprecated C++ header 'stdio.h'; consider using 'cstdio' instead
#include <stdio.h> ^~~~~~~~~ <cstdio> -
docs/examples/demo/demo.cpp:8:5: warning: [modernize-use-trailing-return-type]
use a trailing return type for this function
int main(){ ~~~ ^ auto -> int -
docs/examples/demo/demo.cpp:10:13: warning: [readability-braces-around-statements]
statement should be inside braces
for (;;) break; ^ { -
docs/examples/demo/demo.cpp:13:5: warning: [cppcoreguidelines-pro-type-vararg]
do not call c-style vararg functions
printf("Hello world!\n"); ^
Have any feedback or feature suggestions? Share it here.
I think there's a bug in clang-tools-pip. It does not seem to match v9.0.0. Probably a logical error (>= vs >).
uv pip install clang-format==9 Γ No solution found when resolving dependencies: β°ββΆ Because clang-format==9.0.0 has no wheels with a matching platform tag (e.g., `win_amd64`) and you require clang-format==9, we can conclude that your requirements are unsatisfiable. hint: Wheels are available for `clang-format` (v9.0.0) on the following platform: `manylinux1_x86_64`
Apparently, there are only wheels for linux from clang-format v9 (or older) PyPI package:
JSON API response snippet
"6.0.1": [
{
"comment_text": "",
"digests": {
"blake2b_256": "e371db01cf5d188d0669af9cfd9f5cf8cfb47898df6ad5c86bc008ab3b73d327",
"md5": "fe41668bfa155409944fc6e7dc060b42",
"sha256": "1b71b62346e281f96aa9d45a8892427ce1eae7783c24ac0e1efbab1d5340748d"
},
"downloads": -1,
"filename": "clang_format-6.0.1-py2-none-manylinux1_x86_64.whl",
"has_sig": false,
"md5_digest": "fe41668bfa155409944fc6e7dc060b42",
"packagetype": "bdist_wheel",
"python_version": "py2",
"requires_python": null,
"size": 1285495,
"upload_time": "2019-11-04T14:55:48",
"upload_time_iso_8601": "2019-11-04T14:55:48.150563Z",
"url": "https://files.pythonhosted.org/packages/e3/71/db01cf5d188d0669af9cfd9f5cf8cfb47898df6ad5c86bc008ab3b73d327/clang_format-6.0.1-py2-none-manylinux1_x86_64.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "166065c642879f290c4233ac75d7f91038509750347271cd135a62cf0b86019c",
"md5": "cd777571cebf4190bc04ed4638d68bfd",
"sha256": "8028c358d0838e83ea85254bedba846f2106348406c9cdc4f2724779704eedca"
},
"downloads": -1,
"filename": "clang_format-6.0.1-py2.py3-none-manylinux1_x86_64.whl",
"has_sig": false,
"md5_digest": "cd777571cebf4190bc04ed4638d68bfd",
"packagetype": "bdist_wheel",
"python_version": "py2.py3",
"requires_python": null,
"size": 1295165,
"upload_time": "2019-11-09T15:05:57",
"upload_time_iso_8601": "2019-11-09T15:05:57.500683Z",
"url": "https://files.pythonhosted.org/packages/16/60/65c642879f290c4233ac75d7f91038509750347271cd135a62cf0b86019c/clang_format-6.0.1-py2.py3-none-manylinux1_x86_64.whl",
"yanked": false,
"yanked_reason": null
}
],
"7.1.0": [
{
"comment_text": "",
"digests": {
"blake2b_256": "1728feeb87d11c17d4734763db4c0a1a6939448f0c11a1713fac142e8dd2f107",
"md5": "ca817583469776c6b76aee6e8d058e8d",
"sha256": "32629996956b3e34494a926a76835e3371f10c2823c3078f5fbef08bfebbaae7"
},
"downloads": -1,
"filename": "clang_format-7.1.0-py2.py3-none-manylinux1_x86_64.whl",
"has_sig": false,
"md5_digest": "ca817583469776c6b76aee6e8d058e8d",
"packagetype": "bdist_wheel",
"python_version": "py2.py3",
"requires_python": null,
"size": 1330841,
"upload_time": "2019-11-09T16:17:01",
"upload_time_iso_8601": "2019-11-09T16:17:01.797915Z",
"url": "https://files.pythonhosted.org/packages/17/28/feeb87d11c17d4734763db4c0a1a6939448f0c11a1713fac142e8dd2f107/clang_format-7.1.0-py2.py3-none-manylinux1_x86_64.whl",
"yanked": false,
"yanked_reason": null
}
],
"8.0.1": [
{
"comment_text": "",
"digests": {
"blake2b_256": "376675e3c14f22c8a7a02c7e337547e29d42bed516ba8067fdef87d3d9346e52",
"md5": "2053ad2ea07c26dd5ad62cb7999722d7",
"sha256": "d3d0d62281ace883bc6e4188f949308b8f2e4f6de8fac463e5abd1ae02c03db6"
},
"downloads": -1,
"filename": "clang_format-8.0.1-py2.py3-none-manylinux1_x86_64.whl",
"has_sig": false,
"md5_digest": "2053ad2ea07c26dd5ad62cb7999722d7",
"packagetype": "bdist_wheel",
"python_version": "py2.py3",
"requires_python": null,
"size": 1377569,
"upload_time": "2019-11-20T18:37:41",
"upload_time_iso_8601": "2019-11-20T18:37:41.956369Z",
"url": "https://files.pythonhosted.org/packages/37/66/75e3c14f22c8a7a02c7e337547e29d42bed516ba8067fdef87d3d9346e52/clang_format-8.0.1-py2.py3-none-manylinux1_x86_64.whl",
"yanked": false,
"yanked_reason": null
}
],
"9.0.0": [
{
"comment_text": "",
"digests": {
"blake2b_256": "25f2d989afaf8a91385f18fd06e6202644be0bc3a1d14548c18a8ece4911e005",
"md5": "7b0f1d7a2785a5c2c4e9d695dfdf4583",
"sha256": "085342f9e238c9b03a019e20ec23f242f8795a3cca9296ab2427b1dea45e7014"
},
"downloads": -1,
"filename": "clang_format-9.0.0-py2.py3-none-manylinux1_x86_64.whl",
"has_sig": false,
"md5_digest": "7b0f1d7a2785a5c2c4e9d695dfdf4583",
"packagetype": "bdist_wheel",
"python_version": "py2.py3",
"requires_python": null,
"size": 1375189,
"upload_time": "2019-11-20T19:37:14",
"upload_time_iso_8601": "2019-11-20T19:37:14.542044Z",
"url": "https://files.pythonhosted.org/packages/25/f2/d989afaf8a91385f18fd06e6202644be0bc3a1d14548c18a8ece4911e005/clang_format-9.0.0-py2.py3-none-manylinux1_x86_64.whl",
"yanked": false,
"yanked_reason": null
}
]