Skip to content

feat: migrate to uv and use nu shell #306

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Aug 13, 2025
Merged

feat: migrate to uv and use nu shell #306

merged 14 commits into from
Aug 13, 2025

Conversation

2bndy5
Copy link
Collaborator

@2bndy5 2bndy5 commented Aug 12, 2025

resolves #305
closes #234

This uses dependabot's newer option to combine multiple package ecosystems into 1 group. This means that updates to uv.lock, pyproject.toml, and **/requirements.txt should be submitted in 1 PR.

uv requires pyproject.toml to specify dependency groups. The specified [project] in pyproject.toml shall be considered "virtual" because no build-backend is specified.

Install all dependencies as before with uv:

uv sync --all-groups

Summary by CodeRabbit

  • New Features

    • Added a cache-enable action input (enabled by default) and a unified, cross-platform cpp-linter workflow with caching for faster, more consistent runs.
  • Documentation

    • Docs build upgraded to a newer OS/Python and now installs docs dependencies via a dedicated install job.
    • Documented the new cache-enable input.
  • Chores

    • Consolidated dependencies into project configuration and removed corresponding entries from requirements files.
    • Removed a pre-commit requirements fixer and adjusted dependency-update configuration.

@2bndy5 2bndy5 requested a review from a team as a code owner August 12, 2025 11:03
@2bndy5 2bndy5 requested review from shenxianpeng and removed request for a team August 12, 2025 11:03
@2bndy5 2bndy5 added dependencies Pull requests that update a dependency file python Pull requests that update Python code labels Aug 12, 2025
@2bndy5
Copy link
Collaborator Author

2bndy5 commented Aug 12, 2025

Technically requirements.txt is not used by uv (in favor of pyproject.toml). I have retained the requirements.txt files because:

  1. action.yml uses requirements.txt (not uv)
  2. our mkdocs reusable workflows expect docs/requirements.txt to exist (they don't use uv yet)

2bndy5 added 2 commits August 12, 2025 04:50
reusable workflow does not use uv (yet)
@shenxianpeng
Copy link
Collaborator

We might remove requirements.txt by installing action deps by pip install --group action or uv pip install --group action

@shenxianpeng
Copy link
Collaborator

- requirements: docs/requirements.txt

https://docs.readthedocs.com/platform/stable/build-customization.html#id15

Here also support pip install --group docs

@shenxianpeng
Copy link
Collaborator

If existing requirements.txt could be replaced by pyproject.toml file, that would be great!

@2bndy5
Copy link
Collaborator Author

2bndy5 commented Aug 12, 2025

We might remove requirements.txt by installing action deps by pip install --group action or uv pip install --group action

I had no idea this was supported. I need to investigate what version of pip introduced this option.

uv pip ... doesn't actually use pip. Rather it uses uv's own implementation of pip tools.

- requirements: docs/requirements.txt

https://docs.readthedocs.com/platform/stable/build-customization.html#id15

Here also support pip install --group docs

I often forget about updating RTD config. Nice catch!

@2bndy5
Copy link
Collaborator Author

2bndy5 commented Aug 12, 2025

pip v25.1 introduced the --group option (complying with PEP735). We may have to ensure action.yml updates pip before using the --group option.

Copy link
Collaborator

@shenxianpeng shenxianpeng left a comment

Choose a reason for hiding this comment

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

@2bndy5
Copy link
Collaborator Author

2bndy5 commented Aug 12, 2025

I think I found a way to prevent adding uv to the PATH env var:

env:
  UV_NO_MODIFY_PATH: 1

Using UV in action.yml can also make caching the venv (and action deps) rather easy. This would also resolve #234 . We also wouldn't require runners to have python installed because uv venv automatically downloads a standalone binary distribution of python (as built by a astral-sh sister project).


I'm a bit distracted right now. I'll pick this up later.

@shenxianpeng
Copy link
Collaborator

💯 No rush

Copy link
Contributor

github-actions bot commented Aug 13, 2025

Cpp-Linter Report ⚠️

Some files did not pass the configured checks!

clang-tidy (v12.0.0) reports: 3 concern(s)
  • build/CMakeFiles/3.31.6/CompilerIdC/CMakeCCompilerId.c:2:3: error: [clang-diagnostic-error]

    "A C++ compiler has been selected for C."

    # error "A C++ compiler has been selected for C."
      ^
  • build/CMakeFiles/3.31.6/CompilerIdC/CMakeCCompilerId.c:776:1: warning: [modernize-avoid-c-arrays]

    do not declare C-style arrays, use std::array<> instead

    char const info_version[] = {
    ^
  • build/CMakeFiles/3.31.6/CompilerIdC/CMakeCCompilerId.c:877:5: warning: [modernize-use-trailing-return-type]

    use a trailing return type for this function

    int main(int argc, char* argv[])
    ~~~ ^
    auto                             -> int

Have any feedback or feature suggestions? Share it here.

includes doc'd `minimum-version` for the new input option
@2bndy5
Copy link
Collaborator Author

2bndy5 commented Aug 13, 2025

If existing requirements.txt could be replaced by pyproject.toml file, that would be great!

I've done what I can, but our org's reusable workflow (for mkdocs) still depends on docs/requirements.txt. Once that workflow is updated (or replaced), I can delete docs/requirements.txt.

I think I found a way to prevent adding uv to the PATH env var

I also managed to use uv in action.yml with the help of nushell. This means we don't have to write 2 copies of the steps for unix and windows. The action.yml installs nushell and uses it where cross-platform script support is needed.

Only nushell is added to the PATH (via hustcer/setup-nu), uv and everything else is kept out of the PATH. We could look at other methods of installing nushell, but I doubt this will be an actual problem for our users.

Using UV in action.yml can also make caching the venv (and action deps) rather easy

I also introduced the new cache-enable input option. Caching is enabled by default. Cached assets are kept out of the runner's workspace (and stored in runner.temp instead). So, this now closes #234 proper.

@2bndy5 2bndy5 added the minor A minor version bump label Aug 13, 2025
@2bndy5
Copy link
Collaborator Author

2bndy5 commented Aug 13, 2025

I will remove the useless docs/requirements.txt after cpp-linter/.github#38 is merged.

@2bndy5 2bndy5 changed the title build(dev): migrate to uv feat: migrate to uv Aug 13, 2025
@2bndy5 2bndy5 added the enhancement New feature or request label Aug 13, 2025
Copy link
Contributor

coderabbitai bot commented Aug 13, 2025

Walkthrough

Replaces Python venv steps with a Nu + uv-based composite action (with optional caching), adds a cache-enable input and unified outputs, updates CI/docs packaging and dependency files (pyproject, requirements), adjusts ReadTheDocs build, updates Dependabot to uv, and removes a pre-commit requirements fixer.

Changes

Cohort / File(s) Summary
Action flow & docs
action.yml, docs/action.yml
Migrate action to Nu + uv flow; add cache-enable input; consolidate cpp-linter step/outputs; compute cache key via Nu; enable actions/cache; set UV_NO_MODIFY_PATH; adjust LLVM install path handling.
CI / docs build
.readthedocs.yaml
Update ReadTheDocs build OS to ubuntu-24.04, Python to latest; add install job using pip install --group 'docs'; remove prior docs requirements install step.
Automation configs
.github/dependabot.yml
Replace pip package-ecosystem entry with uv; keep github-actions weekly; minor quoting/formatting change to patterns.
Packaging & dependencies
pyproject.toml, requirements.txt, docs/requirements.txt
Add pyproject.toml with dependency-groups (action/dev/docs); remove clang-tools & cpp-linter from requirements.txt; remove docs packages from docs/requirements.txt.
Pre-commit
.pre-commit-config.yaml
Remove requirements-txt-fixer hook; other hooks unchanged.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Runner as GitHub Runner
  participant Action as Composite Action
  participant Nu as Nu shell
  participant Cache as actions/cache
  participant uv as uv

  User->>Runner: Trigger workflow
  Runner->>Action: Run action.yml
  Action->>Action: Setup Nu shell
  Action->>Nu: Compute cache key (lock/requirements/action.yml)
  alt cache-enable == true
    Action->>Cache: Restore cache with key
    Cache-->>Action: Cache hit/miss
  end
  Action->>Nu: Install uv and sync deps (group: action)
  Nu->>uv: Resolve/install tools
  Action->>Nu: Run cpp-linter via uv
  Nu-->>Action: Returns results (checks-failed, clang-* outputs)
  Action-->>Runner: Expose unified outputs
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Assessment against linked issues

Objective Addressed Explanation
Migrate to uv (#305)
Avoid modifying PATH while migrating to uv (#305)
Python venv cache support / hashFiles workaround (#234) Cache key is computed by a Nu script and used with actions/cache, but it is unclear if the specific hashFiles/glob workaround for venv scenarios was implemented.

Out-of-scope changes

Code Change Explanation
Add pyproject.toml with dependency-groups (pyproject.toml) Packaging/metadata addition not required by the uv migration or caching objective.
Remove docs dependencies (docs/requirements.txt) Deleting docs dependency list is unrelated to uv migration or venv caching requirements.
Remove runtime deps from requirements.txt (requirements.txt) Removing clang-tools/cpp-linter from requirements is a packaging change not requested by linked issues.
Remove requirements-txt-fixer pre-commit hook (.pre-commit-config.yaml) Pre-commit hook removal is not part of the migration/caching objectives.

📜 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 3421a4e and 86d4fb5.

📒 Files selected for processing (1)
  • action.yml (3 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-13T09:26:54.549Z
Learnt from: 2bndy5
PR: cpp-linter/cpp-linter-action#306
File: pyproject.toml:7-24
Timestamp: 2025-08-13T09:26:54.549Z
Learning: In cpp-linter-action repository, the pyproject.toml file is a "virtual" project (version = "0.0.0+private_virtual") that exists solely to define dependency groups for uv, not to describe an actual installable Python package. The uv.lock file is the authoritative source for dependency resolution.

Applied to files:

  • action.yml
🔇 Additional comments (9)
action.yml (9)

219-222: LGTM! Well-designed cache control input.

The cache-enable input provides good flexibility for users to control caching behavior, with a sensible default of true for optimal performance.


226-226: LGTM! Consolidated outputs correctly reference unified step.

The outputs now consistently reference the single cpp-linter step instead of OS-specific steps, which simplifies the action architecture and improves maintainability.

Also applies to: 229-229, 232-232


244-246: LGTM! Robust path handling for LLVM script.

Using ${GITHUB_ACTION_PATH%/} properly handles potential trailing slashes in the path, making the script more robust across different environments.


251-256: Security: Pin the Nu shell action to a full commit SHA.

The action is correctly pinned to a specific commit SHA for security, which follows GitHub's security best practices.


258-273: Cache key computation logic is appropriate.

The cache key computation correctly prioritizes uv.lock (the authoritative dependency source) over action.yml as fallback. This aligns with the repository's uv migration and the "virtual" nature of pyproject.toml.


275-280: LGTM! Cache configuration follows best practices.

The cache step correctly:

  • Uses conditional execution based on the cache-enable input
  • Stores cache outside workspace in runner.temp to address hashFiles limitations
  • Uses a descriptive cache key with OS and computed hash

285-285: Good addition of continue-on-error for macOS dependencies.

Adding continue-on-error: true to the macOS clang installation step ensures the workflow doesn't fail if Homebrew installation encounters issues, which is appropriate for a dependency installation step.


291-317: LGTM! Well-implemented cross-platform uv setup.

The Nu-based setup step effectively:

  • Uses UV_NO_MODIFY_PATH: 1 to prevent PATH modifications
  • Installs uv consistently across platforms using version-specific URLs
  • Properly configures cache and project environment directories
  • Includes helpful colored output for better debugging

319-353: LGTM! Clean unified cpp-linter execution.

The consolidated Nu-based execution step successfully:

  • Replaces OS-specific steps with a single cross-platform implementation
  • Properly constructs the argument list from all action inputs
  • Uses the uv-managed environment to run cpp-linter
  • Maintains the same functionality while simplifying the workflow
✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch switch-to-uv

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

Copy link
Contributor

@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: 5

🔭 Outside diff range comments (1)
action.yml (1)

326-351: Split extra-args into individual flags & quote path inputs

To align with action.yml documentation—where extra-args is a space-separated list that should be passed as repeated --extra-arg flags—replace the single --extra-arg="${{ inputs.extra-args }}" with Nu code that splits on whitespace. Also quote any path-like inputs to guard against spaces.

Bullet-proof diff:

         let args = [
             --style="${{ inputs.style }}"
             --extensions="${{ inputs.extensions }}"
             --tidy-checks="${{ inputs.tidy-checks }}"
-            --repo-root=${{ inputs.repo-root }}
+            --repo-root="${{ inputs.repo-root }}"
             --version="${{ inputs.version }}"
             --verbosity="${{ inputs.verbosity }}"
             --lines-changed-only="${{ inputs.lines-changed-only }}"
             --files-changed-only="${{ inputs.files-changed-only }}"
             --thread-comments="${{ inputs.thread-comments }}"
             --no-lgtm="${{ inputs.no-lgtm }}"
             --step-summary="${{ inputs.step-summary }}"
             --ignore="${{ inputs.ignore }}"
             --ignore-tidy="${{ inputs.ignore-tidy }}"
             --ignore-format="${{ inputs.ignore-format }}"
-            --database=${{ inputs.database }}
+            --database="${{ inputs.database }}"
-            --file-annotations=${{ inputs.file-annotations }}
+            --file-annotations="${{ inputs.file-annotations }}"
-            --extra-arg="${{ inputs.extra-args }}"
         ]
 
+        # Split `extra-args` into individual --extra-arg flags
+        let extra_inputs = "${{ inputs.extra-args }}"
+        let extra_flags = (
+          $extra_inputs
+          | split row ' '
+          | where {|x| $x != ''}
+          | each {|e| $"--extra-arg={e}"}
+        )
+        let args = ($args | append $extra_flags)
 
        ^$'($env.UV_INSTALL_DIR)/uv' run cpp-linter ...$args
  • Verified in action.yml that the intent is one --extra-arg per token:
    clang-tidy --extra-arg=-std=c++17 --extra-arg=-Wall.
  • Quoted repo-root, database, and file-annotations to handle paths with spaces.
🧹 Nitpick comments (2)
action.yml (2)

278-284: Optional: add restore-keys for partial cache reuse.

To soften cache busts on minor edits (e.g., comments in pyproject), add a generic restore key.

       uses: actions/cache@v4
       with:
         path: ${{ runner.temp }}/cpp-linter-action-cache
         key: cpp-linter-action_${{ runner.os }}_${{ steps.compute-cache-key.outputs.key }}
+        restore-keys: |
+          cpp-linter-action_${{ runner.os }}_

236-249: Optional: consider dropping platform tool installs if clang-tools pip covers it.

Given you run “uv run clang-tools -i … -b”, the apt/brew installs may be redundant and slow. Consider making them conditional or removing them to shorten runs, unless you rely on system clang-{tidy,format} elsewhere.

I can provide a follow-up diff that skips OS package installs when clang-tools installation succeeds.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0f6d1b8 and 032cb47.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (7)
  • .github/dependabot.yml (2 hunks)
  • .pre-commit-config.yaml (0 hunks)
  • .readthedocs.yaml (1 hunks)
  • action.yml (3 hunks)
  • docs/action.yml (1 hunks)
  • pyproject.toml (1 hunks)
  • requirements.txt (0 hunks)
💤 Files with no reviewable changes (2)
  • requirements.txt
  • .pre-commit-config.yaml
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-12T08:57:29.249Z
Learnt from: 2bndy5
PR: cpp-linter/cpp-linter-action#303
File: .github/dependabot.yml:0-0
Timestamp: 2025-08-12T08:57:29.249Z
Learning: For Dependabot's github-actions ecosystem, multiple directories in the directories list are supported. When directory is "/", Dependabot scans both .github/workflows/ and root action.yml/action.yaml files. Other directory entries are treated as workflow directories and scanned for .yml/.yaml files.

Applied to files:

  • .github/dependabot.yml
🔇 Additional comments (5)
docs/action.yml (1)

52-53: Good addition: version-gating the new input.

Adding cache-enable with minimum-version '2.16.0' is consistent and keeps the docs metadata aligned with the composite action interface.

.github/dependabot.yml (1)

8-12: Dependabot multi-ecosystem-groups configuration is correct—no per-update schedules needed
The top-level key multi-ecosystem-groups is valid and group-level schedule settings apply to all member updates. No changes are required.

pyproject.toml (1)

1-5: Virtual project config looks sane for uv.

Declaring a “virtual” project with requires-python and empty dependencies is fine for uv-managed groups. Nice touch on the pre-release version tag.

action.yml (2)

219-223: New input wired correctly.

cache-enable defaulting to true is reasonable; naming and description are clear.


244-247: Minor robustness improvement looks good.

Using ${GITHUB_ACTION_PATH%/} guards against stray trailing slashes. Good catch.

@2bndy5
Copy link
Collaborator Author

2bndy5 commented Aug 13, 2025

I looked at the source for hustcer/setup-nu, and it does exactly what I would have to do manually:

  1. read the runner's architecture type and OS type
  2. match output from step 1 and the desired nushell version with nushell GitHub Release assets
  3. download the release asset to a known path (eg GTIHUB_ACTION_PATH)
  4. manually invoke the downloaded release asset wherever needed.

Fortunately, hustcer/setup-nu already does steps 1-3. It also adds the downloaded asset to somewhere in PATH, so step 4 is not really needed.

If the user's workflow already uses a version of nushell, then we may have a conflict on our hands. However, nu shell doesn't seem widely used because it is still in v0.x. I'll just have to keep updating the pinned version of nushell here:

uses: hustcer/setup-nu@985d59ec83ae3e3418f9d36471cda38b9d8b9879 # v3.20.0
with:
version: '0.106.1'

@2bndy5 2bndy5 changed the title feat: migrate to uv feat: migrate to uv and use nu shell Aug 13, 2025
@2bndy5 2bndy5 merged commit ac82521 into main Aug 13, 2025
83 checks passed
@2bndy5 2bndy5 deleted the switch-to-uv branch August 13, 2025 11:25
@2bndy5
Copy link
Collaborator Author

2bndy5 commented Aug 13, 2025

I forgot to review the README. A follow up PR is coming.

2bndy5 added a commit that referenced this pull request Aug 13, 2025
follow-up to #306
Python is no longer required to be installed on the runner anymore.
`uv sync` will automatically download the latest supported stable version of Python.
@2bndy5 2bndy5 mentioned this pull request Aug 13, 2025
2bndy5 added a commit that referenced this pull request Aug 13, 2025
follow-up to #306

Python is no longer required to be installed on the runner anymore.
`uv sync` will automatically download the latest supported stable version of Python.
@shenxianpeng shenxianpeng removed the dependencies Pull requests that update a dependency file label Aug 16, 2025
@coderabbitai coderabbitai bot mentioned this pull request Aug 17, 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 python Pull requests that update Python code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

migrate to uv
2 participants