Skip to content

Commit 60d68b2

Browse files
committed
nox manage cargo-binstall
1 parent 4481ab3 commit 60d68b2

File tree

5 files changed

+197
-14
lines changed

5 files changed

+197
-14
lines changed

.github/workflows/run-dev-tests.yml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ jobs:
3131
steps:
3232
- uses: actions/checkout@v4
3333

34+
- run: rustup update --no-self-update
3435
- run: rustup component add llvm-tools-preview
3536

3637
# https://docs.rs/openssl/latest/openssl/#automatic
@@ -44,13 +45,13 @@ jobs:
4445
# if: runner.os == 'Windows'
4546
# run: vcpkg install openssl
4647

47-
- name: Install third-party binaries
48-
uses: taiki-e/install-action@v2
49-
with:
50-
tool: cargo-nextest,cargo-llvm-cov,cargo-binstall,just
48+
- uses: cargo-bins/cargo-binstall@main
5149

52-
- name: Install llvm-cov-pretty (HTML report generator)
53-
run: cargo binstall -y llvm-cov-pretty
50+
- name: Install third-party binaries
51+
run: |-
52+
cargo binstall -y cargo-nextest
53+
cargo binstall -y cargo-llvm-cov
54+
cargo binstall -y llvm-cov-pretty
5455
5556
- uses: actions/setup-python@v5
5657
with:

docs/README.md

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,11 @@ This folder is only for generating the documentation about CLI and runtime permi
44
Please [visit our website][gh-pages] to see generated documentation.
55

66
[gh-pages]: https://cpp-linter.github.io/cpp-linter-rs
7-
[uv]: https://docs.astral.sh/uv/
87

98
## Build and inspect locally
109

1110
To view the documentation locally, some software needs to be installed.
12-
This project's dependencies are managed with a tool called [`uv`][uv].
13-
So, [`uv`][uv] is the only software that needs to be manually installed beforehand.
1411

15-
After [`uv`][uv] is installed, building (and viewing) the docs is as simple as
16-
17-
```shell
18-
uvx nox -s docs -- --open
19-
```
12+
> [!IMPORTANT]
13+
> Please review of [Contributing doc](docs/getting-started.md)
14+
> which contains instruction about building and inspecting docs.

docs/docs/getting-started.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Contributing
2+
3+
This project requires the following tools installed:
4+
5+
- :simple-rust: [rust](https://rustup.rs/)
6+
- :simple-uv: [`uv` (Python Project management tool)](https://docs.astral.sh/uv/)
7+
8+
## Getting started
9+
10+
After checking out the repo locally, use
11+
12+
```sh
13+
uv sync
14+
```
15+
16+
This creates a venv at ".venv/" in repo root (if it doesn't exist).
17+
It also installs dev dependencies like `pre-commit`, `nox`, `ruff`, and `mypy`.
18+
19+
See [`uv sync` docs](https://docs.astral.sh/uv/reference/cli/#uv-sync)
20+
for more detailed usage.
21+
22+
> [!TIP]
23+
> To register the pre-commit hooks, use:
24+
>
25+
> ```shell
26+
> uv run pre-commit install
27+
> ```
28+
29+
### Cargo-managed binaries
30+
31+
The tasks run with `nox` will ensure cargo-managed binaries are installed as needed.
32+
33+
### Running tests
34+
35+
Use nox to run tests:
36+
37+
```sh
38+
uv run nox -s test
39+
```
40+
41+
Different test profiles are still defined in .config/nextest.toml.
42+
The above command uses the "default" profile, but to mimic the CI, use:
43+
44+
```sh
45+
uv run nox -s test -- --profile ci
46+
```
47+
48+
To generate a coverage report:
49+
50+
```sh
51+
uv run nox -s llvm-cov -- --open
52+
```
53+
54+
The `-- --open` part is optional. It opens the built coverage report in your default browser.
55+
56+
The uploaded codecov report is generated with
57+
58+
```sh
59+
uv run nox -s lcov
60+
```
61+
62+
### Generating docs
63+
64+
To view the docs locally, use
65+
66+
```sh
67+
uv run nox -s docs -- --open
68+
```
69+
70+
The `-- --open` part is optional. It opens the built docs in your default browser.
71+
72+
In CI, docs are built using
73+
74+
```sh
75+
uv run nox -s docs-build
76+
```

docs/mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ nav:
1212
- python.md
1313
- node.md
1414
- changelog.md
15+
- getting-started.md
1516
- other-licenses.md
1617

1718
theme:

noxfile.py

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
import logging
2+
from os import environ
3+
from shutil import which
4+
import platform
5+
import re
26
import sys
37
import nox
48

@@ -10,6 +14,86 @@
1014

1115
nox.options.default_venv_backend = "uv"
1216

17+
BIN_STALL_CARGO = re.compile(r"^([^\s]+)\s([^:]+):")
18+
CARGO_BINSTALL = "cargo-binstall"
19+
IS_CI = "CI" in environ
20+
21+
22+
class CargoInstaller:
23+
def __init__(self, session: nox.Session):
24+
cargo_installed: str | None = session.run(
25+
"cargo", "install", "--list", external=True, silent=True
26+
)
27+
assert cargo_installed is not None, "Is rust cargo installed?"
28+
cargo_bins: dict[str, str] = {}
29+
for line in cargo_installed.splitlines():
30+
found = BIN_STALL_CARGO.match(line)
31+
if found is not None:
32+
name, version = found.groups()
33+
cargo_bins.setdefault(name, version)
34+
self.cargo_bins = cargo_bins
35+
if IS_CI:
36+
for dep, ver in cargo_bins.items():
37+
ci_logger.info("cargo installed %s: %s" % (dep, ver))
38+
self.cargo_install_cmd: tuple[str, ...] = ("cargo", "install")
39+
40+
path = which(CARGO_BINSTALL)
41+
42+
if CARGO_BINSTALL in cargo_bins:
43+
ci_logger.info(
44+
"Found %s: %s" % (CARGO_BINSTALL, cargo_bins[CARGO_BINSTALL])
45+
)
46+
elif path is not None:
47+
ci_logger.info("Found: %s in %s" % (CARGO_BINSTALL, path))
48+
elif not IS_CI:
49+
ci_logger.info("Installing %s" % CARGO_BINSTALL)
50+
match platform.system():
51+
case "Windows":
52+
one_liner = """Set-ExecutionPolicy Unrestricted -Scope Process; iex (iwr "https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.ps1").Content"""
53+
session.run(*one_liner.split(), external=True)
54+
case "Linux" | "Darwin":
55+
one_liner = "curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash"
56+
session.run(*one_liner.split(), external=True)
57+
case _:
58+
session.run(
59+
*self.cargo_install_cmd,
60+
CARGO_BINSTALL,
61+
"--locked",
62+
external=True,
63+
)
64+
self.cargo_install_cmd = ("cargo", "binstall", "-y")
65+
66+
def check_install(self, req: str, session: nox.Session):
67+
"""Use cargo to ensure `req` is installed.
68+
69+
Parameters:
70+
req: The package name (on crates.io) to check and install.
71+
Supports explicit version in the form
72+
73+
Typically this is the project's name as published on crates.io.
74+
"""
75+
76+
ver = None
77+
if "@" in req:
78+
req, ver = req.split("@", 1)[:2]
79+
80+
def install():
81+
ci_logger.info("Installing %s" % req)
82+
dep = req if not ver else f"{req}@{ver}"
83+
session.run(*self.cargo_install_cmd, dep, "--locked", external=True)
84+
85+
path = which(req)
86+
87+
installed = False
88+
if req in self.cargo_bins:
89+
ci_logger.info("Found %s %s" % (req, self.cargo_bins[req]))
90+
installed = True
91+
elif path is not None:
92+
ci_logger.info("Found: %s in %s" % (req, path))
93+
installed = True
94+
if ver or not installed:
95+
install()
96+
1397

1498
def uv_sync(session: nox.Session, *args: str):
1599
session.run_install(
@@ -79,6 +163,13 @@ def test(session: nox.Session):
79163
Otherwise, the default profile is used.
80164
"""
81165
uv_sync(session, "--group", "test")
166+
installer = CargoInstaller(session)
167+
for req in [
168+
"cargo-llvm-cov",
169+
"cargo-nextest",
170+
]:
171+
installer.check_install(req, session)
172+
82173
session.run(
83174
"cargo",
84175
"llvm-cov",
@@ -102,6 +193,8 @@ def test_clean(session: nox.Session):
102193
This is useful if coverage data needs to be
103194
completely refreshed.
104195
"""
196+
installer = CargoInstaller(session)
197+
installer.check_install("cargo-llvm-cov", session)
105198
session.run("cargo", "llvm-cov", "clean", external=True)
106199

107200

@@ -114,6 +207,8 @@ def llvm_cov(session: nox.Session):
114207
115208
Otherwise, the default profile is used.
116209
"""
210+
installer = CargoInstaller(session)
211+
installer.check_install("cargo-llvm-cov", session)
117212
session.run(
118213
"cargo",
119214
"llvm-cov",
@@ -135,6 +230,9 @@ def pretty_cov(session: nox.Session):
135230
136231
Otherwise, the default profile is used.
137232
"""
233+
installer = CargoInstaller(session)
234+
for req in ["cargo-llvm-cov", "llvm-cov-pretty"]:
235+
installer.check_install(req, session)
138236
session.run(
139237
"cargo",
140238
"llvm-cov",
@@ -156,6 +254,8 @@ def lcov(session: nox.Session):
156254
Useful for codecov uploads and VSCode extensions
157255
like "Coverage Gutters".
158256
"""
257+
installer = CargoInstaller(session)
258+
installer.check_install("cargo-llvm-cov", session)
159259
session.run(
160260
"cargo",
161261
"llvm-cov",
@@ -177,3 +277,13 @@ def lint(session: nox.Session):
177277
"cargo", "clippy", "--allow-staged", "--allow-dirty", "--fix", external=True
178278
)
179279
session.run("cargo", "fmt", external=True)
280+
281+
282+
@nox.session(python=False)
283+
def install(session: nox.Session):
284+
"""Install necessary software in global env"""
285+
286+
installer = CargoInstaller(session)
287+
288+
for req in session.posargs:
289+
installer.check_install(req, session)

0 commit comments

Comments
 (0)