Skip to content

Commit f43fd7d

Browse files
committed
refactor: RustProject methods with flags= instead of frozen attributes
Move test/clippy/fmt from frozen Step attributes to methods with flags= parameter for per-call customization. Add hm.group() and hm.pr() alias. Dogfood targets now self-contained.
1 parent e3cbd2d commit f43fd7d

8 files changed

Lines changed: 134 additions & 149 deletions

File tree

.harmont/ci.py

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
from __future__ import annotations
33

44
import harmont as hm
5-
from harmont.py.uv import UvProject
6-
from harmont.rust import RustProject
75

86

97
@hm.target()
@@ -20,13 +18,29 @@ def shared_base() -> hm.Step:
2018

2119

2220
@hm.target()
23-
def rust_project(shared_base: hm.Target[hm.Step]) -> RustProject:
24-
return hm.rust.project(path=".", base=shared_base, test_flags=("--lib",))
21+
def rust_project(shared_base: hm.Target[hm.Step]) -> tuple[hm.Step, ...]:
22+
project = hm.rust.project(path=".", base=shared_base)
23+
return hm.group([
24+
project.test(flags=("--lib",)),
25+
project.clippy(),
26+
project.fmt(),
27+
])
2528

2629

2730
@hm.target()
28-
def py_project(shared_base: hm.Target[hm.Step]) -> UvProject:
29-
return hm.py.uv(path="dsls/harmont-py", base=shared_base)
31+
def py_project(shared_base: hm.Target[hm.Step]) -> tuple[hm.Step, ...]:
32+
project = hm.py.uv(path="dsls/harmont-py", base=shared_base)
33+
return hm.group([
34+
project.lint(),
35+
project.fmt(),
36+
project.typecheck(paths="harmont"),
37+
project.run(
38+
"pytest -v"
39+
" --deselect tests/test_gradle.py"
40+
" --deselect tests/test_haskell.py",
41+
label=":python: test",
42+
),
43+
])
3044

3145

3246
@hm.pipeline(
@@ -35,24 +49,11 @@ def py_project(shared_base: hm.Target[hm.Step]) -> UvProject:
3549
default_image="ubuntu:24.04",
3650
triggers=[
3751
hm.push(branch="main"),
38-
hm.pull_request(branches="main"),
52+
hm.pr(branches="main"),
3953
],
4054
)
4155
def ci(
42-
rust_project: hm.Target[RustProject],
43-
py_project: hm.Target[UvProject],
44-
) -> tuple[hm.Step, ...]:
45-
return (
46-
rust_project.test,
47-
rust_project.clippy,
48-
rust_project.fmt,
49-
py_project.lint(),
50-
py_project.fmt(),
51-
py_project.typecheck(paths="harmont"),
52-
py_project.run(
53-
"pytest -v"
54-
" --deselect tests/test_gradle.py"
55-
" --deselect tests/test_haskell.py",
56-
label=":python: test",
57-
),
58-
)
56+
rust_project: hm.Target[tuple[hm.Step, ...]],
57+
py_project: hm.Target[tuple[hm.Step, ...]],
58+
) -> list:
59+
return [rust_project, py_project]

.harmont/ci.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,17 @@ const base = aptBase({
1919
],
2020
});
2121

22-
const rustProject = rust.project({ path: ".", base, testFlags: ["--lib"] });
22+
const rustProject = rust.project({ path: ".", base });
2323
const pyProject = py.uv({ path: "dsls/harmont-py", base });
2424

2525
const pipelines: PipelineDefinition[] = [
2626
{
2727
slug: "ci",
2828
triggers: [push({ branch: "main" }), pullRequest({ branches: ["main"] })],
2929
pipeline: pipeline(
30-
rustProject.test,
31-
rustProject.clippy,
32-
rustProject.fmt,
30+
rustProject.test({ flags: ["--lib"] }),
31+
rustProject.clippy(),
32+
rustProject.fmt(),
3333
pyProject.lint(),
3434
pyProject.fmt(),
3535
pyProject.typecheck({ paths: "harmont" }),

dsls/harmont-py/harmont/__init__.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
from .python import python
6060
from .ruby import ruby
6161
from .rust import RustProject, rust
62-
from .triggers import pull_request, push, schedule
62+
from .triggers import pull_request, pull_request as pr, push, schedule
6363
from .types import Pipeline
6464
from .zig import zig
6565

@@ -128,6 +128,11 @@ def sh(
128128
)
129129

130130

131+
def group(steps: list[Step] | tuple[Step, ...]) -> tuple[Step, ...]:
132+
"""Combine steps into a group for use as a target return value."""
133+
return tuple(steps)
134+
135+
131136
__all__ = [
132137
"BaseImage",
133138
"CacheCompose",
@@ -154,13 +159,15 @@ def sh(
154159
"forever",
155160
"go",
156161
"gradle",
162+
"group",
157163
"haskell",
158164
"npm",
159165
"ocaml",
160166
"on_change",
161167
"perl",
162168
"pipeline",
163169
"pipeline_to_json",
170+
"pr",
164171
"pull_request",
165172
"push",
166173
"py",

dsls/harmont-py/harmont/_unwrap.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def _one(obj: object) -> tuple[Step, ...]:
2626
if isinstance(obj, Step):
2727
return (obj,)
2828
if isinstance(obj, RustProject):
29-
return (obj.test, obj.clippy, obj.fmt)
29+
return (obj.test(), obj.clippy(), obj.fmt())
3030
if isinstance(obj, HaskellPackage):
3131
return (obj.build(),)
3232
if isinstance(obj, RustToolchain):

dsls/harmont-py/harmont/rust.py

Lines changed: 25 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,30 @@ class RustProject:
9090

9191
toolchain: RustToolchain
9292
warmup: Step
93-
test: Step
94-
clippy: Step
95-
fmt: Step
93+
94+
def test(self, *, flags: tuple[str, ...] = (), **kw: Any) -> Step:
95+
extra = (" " + " ".join(flags)) if flags else ""
96+
return self.warmup.sh(
97+
self.toolchain._wrap(f"cargo test --workspace --locked{extra}"),
98+
label=kw.pop("label", ":rust: test"),
99+
**kw,
100+
)
101+
102+
def clippy(self, *, flags: tuple[str, ...] = (), **kw: Any) -> Step:
103+
extra = (" " + " ".join(flags)) if flags else ""
104+
return self.warmup.sh(
105+
self.toolchain._wrap(
106+
f"cargo clippy --workspace --tests --locked{extra} -- -D warnings"
107+
),
108+
label=kw.pop("label", ":rust: clippy"),
109+
**kw,
110+
)
111+
112+
def fmt(self, *, flags: tuple[str, ...] = (), **kw: Any) -> Step:
113+
extra = (" " + " ".join(flags)) if flags else ""
114+
return self.toolchain._emit(
115+
f"cargo fmt --check{extra}", ":rust: fmt", **kw
116+
)
96117

97118

98119
def _make_rust(
@@ -130,9 +151,6 @@ def _make_rust_project(
130151
components: tuple[str, ...] = ("clippy", "rustfmt"),
131152
base: Step | None = None,
132153
cache: CachePolicy | None = None,
133-
test_flags: tuple[str, ...] = (),
134-
clippy_flags: tuple[str, ...] = (),
135-
fmt_flags: tuple[str, ...] = (),
136154
) -> RustProject:
137155
tc = _make_rust(
138156
path=path,
@@ -151,30 +169,7 @@ def _make_rust_project(
151169
cache=warmup_cache,
152170
)
153171

154-
test_extra = (" " + " ".join(test_flags)) if test_flags else ""
155-
test_step = warm.sh(
156-
tc._wrap(f"cargo test --workspace --locked{test_extra}"),
157-
label=":rust: test",
158-
)
159-
160-
clippy_extra = (" " + " ".join(clippy_flags)) if clippy_flags else ""
161-
clippy_step = warm.sh(
162-
tc._wrap(
163-
f"cargo clippy --workspace --tests --locked{clippy_extra} -- -D warnings"
164-
),
165-
label=":rust: clippy",
166-
)
167-
168-
fmt_extra = (" " + " ".join(fmt_flags)) if fmt_flags else ""
169-
fmt_step = tc._emit(f"cargo fmt --check{fmt_extra}", ":rust: fmt")
170-
171-
return RustProject(
172-
toolchain=tc,
173-
warmup=warm,
174-
test=test_step,
175-
clippy=clippy_step,
176-
fmt=fmt_step,
177-
)
172+
return RustProject(toolchain=tc, warmup=warm)
178173

179174

180175
class _RustEntry:
@@ -206,9 +201,6 @@ def project(
206201
components: tuple[str, ...] = ("clippy", "rustfmt"),
207202
base: Step | None = None,
208203
cache: CachePolicy | None = None,
209-
test_flags: tuple[str, ...] = (),
210-
clippy_flags: tuple[str, ...] = (),
211-
fmt_flags: tuple[str, ...] = (),
212204
) -> RustProject:
213205
return _make_rust_project(
214206
path=path,
@@ -217,9 +209,6 @@ def project(
217209
components=components,
218210
base=base,
219211
cache=cache,
220-
test_flags=test_flags,
221-
clippy_flags=clippy_flags,
222-
fmt_flags=fmt_flags,
223212
)
224213

225214

dsls/harmont-py/tests/test_rust.py

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -164,12 +164,12 @@ def test_warmup_in_pipeline(self):
164164

165165

166166
class TestRustProject:
167-
def test_project_has_all_steps(self):
167+
def test_project_has_all_methods(self):
168168
proj = hm.rust.project(path="cli")
169169
assert proj.warmup.cmd is not None
170-
assert proj.test.cmd is not None
171-
assert proj.clippy.cmd is not None
172-
assert proj.fmt.cmd is not None
170+
assert proj.test().cmd is not None
171+
assert proj.clippy().cmd is not None
172+
assert proj.fmt().cmd is not None
173173

174174
def test_warmup_implicit_cache_on_change(self):
175175
proj = hm.rust.project(path="cli")
@@ -186,39 +186,39 @@ def test_warmup_cache_override(self):
186186

187187
def test_test_command(self):
188188
proj = hm.rust.project(path="cli")
189-
assert "cargo test --workspace --locked" in proj.test.cmd
189+
assert "cargo test --workspace --locked" in proj.test().cmd
190190

191191
def test_test_flags(self):
192-
proj = hm.rust.project(path=".", test_flags=("--lib", "--no-fail-fast"))
193-
assert "cargo test --workspace --locked --lib --no-fail-fast" in proj.test.cmd
192+
proj = hm.rust.project(path=".")
193+
assert "cargo test --workspace --locked --lib --no-fail-fast" in proj.test(flags=("--lib", "--no-fail-fast")).cmd
194194

195195
def test_clippy_command(self):
196196
proj = hm.rust.project(path="cli")
197-
assert "cargo clippy --workspace --tests --locked -- -D warnings" in proj.clippy.cmd
197+
assert "cargo clippy --workspace --tests --locked -- -D warnings" in proj.clippy().cmd
198198

199199
def test_clippy_flags(self):
200-
proj = hm.rust.project(path=".", clippy_flags=("--fix",))
201-
assert "cargo clippy --workspace --tests --locked --fix -- -D warnings" in proj.clippy.cmd
200+
proj = hm.rust.project(path=".")
201+
assert "cargo clippy --workspace --tests --locked --fix -- -D warnings" in proj.clippy(flags=("--fix",)).cmd
202202

203203
def test_fmt_command(self):
204204
proj = hm.rust.project(path="cli")
205-
assert "cargo fmt --check" in proj.fmt.cmd
205+
assert "cargo fmt --check" in proj.fmt().cmd
206206

207207
def test_fmt_flags(self):
208-
proj = hm.rust.project(path=".", fmt_flags=("--all",))
209-
assert "cargo fmt --check --all" in proj.fmt.cmd
208+
proj = hm.rust.project(path=".")
209+
assert "cargo fmt --check --all" in proj.fmt(flags=("--all",)).cmd
210210

211211
def test_test_chains_off_warmup(self):
212212
proj = hm.rust.project(path=".")
213-
assert proj.test.parent is proj.warmup
213+
assert proj.test().parent is proj.warmup
214214

215215
def test_clippy_chains_off_warmup(self):
216216
proj = hm.rust.project(path=".")
217-
assert proj.clippy.parent is proj.warmup
217+
assert proj.clippy().parent is proj.warmup
218218

219219
def test_fmt_chains_off_install(self):
220220
proj = hm.rust.project(path=".")
221-
assert proj.fmt.parent is proj.toolchain.installed
221+
assert proj.fmt().parent is proj.toolchain.installed
222222

223223
def test_toolchain_escape_hatch(self):
224224
proj = hm.rust.project(path="cli")
@@ -228,21 +228,21 @@ def test_toolchain_escape_hatch(self):
228228
def test_with_base_skips_apt(self):
229229
base = hm.scratch().sh("custom base", label="base")
230230
proj = hm.rust.project(path="cli", base=base)
231-
p = hm.pipeline(proj.test, proj.clippy, proj.fmt, default_image="ubuntu:24.04")
231+
p = hm.pipeline(proj.test(), proj.clippy(), proj.fmt(), default_image="ubuntu:24.04")
232232
cmds = _cmds(p)
233233
assert not any("apt-get install" in c for c in cmds)
234234
assert any("custom base" in c for c in cmds)
235235

236236
def test_labels(self):
237237
proj = hm.rust.project(path=".")
238238
assert proj.warmup.label == ":rust: warmup"
239-
assert proj.test.label == ":rust: test"
240-
assert proj.clippy.label == ":rust: clippy"
241-
assert proj.fmt.label == ":rust: fmt"
239+
assert proj.test().label == ":rust: test"
240+
assert proj.clippy().label == ":rust: clippy"
241+
assert proj.fmt().label == ":rust: fmt"
242242

243243
def test_pipeline_ir(self):
244244
proj = hm.rust.project(path="cli")
245-
p = hm.pipeline(proj.test, proj.clippy, proj.fmt, default_image="ubuntu:24.04")
245+
p = hm.pipeline(proj.test(), proj.clippy(), proj.fmt(), default_image="ubuntu:24.04")
246246
cmds = _cmds(p)
247247
assert any("cargo build --workspace --tests --locked" in c for c in cmds)
248248
assert any("cargo test --workspace --locked" in c for c in cmds)
@@ -253,6 +253,6 @@ def test_pipeline_ir(self):
253253

254254
def test_version_forwarded(self):
255255
proj = hm.rust.project(path=".", version="1.81.0")
256-
p = hm.pipeline(proj.test)
256+
p = hm.pipeline(proj.test())
257257
rustup = _step_by_substring(p, "sh.rustup.rs")
258258
assert "--default-toolchain 1.81.0" in rustup["cmd"]

0 commit comments

Comments
 (0)