Skip to content

Commit e9b5a7f

Browse files
feat: colorized output + progress bars for HN launch (#18)
1 parent c618d7e commit e9b5a7f

38 files changed

Lines changed: 1019 additions & 552 deletions

File tree

.github/workflows/ci.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ jobs:
3737
run: cargo clippy --all-targets -p harmont-cli -- -D warnings
3838

3939
python-lint:
40-
name: harmont-py (pytest + ruff + mypy)
40+
name: harmont-py (pytest + ruff + ty)
4141
runs-on: ubuntu-latest
4242
strategy:
4343
fail-fast: false
@@ -59,9 +59,9 @@ jobs:
5959
working-directory: dsls/harmont-py
6060
run: ruff check .
6161

62-
- name: mypy
62+
- name: ty
6363
working-directory: dsls/harmont-py
64-
run: mypy harmont
64+
run: ty check harmont
6565

6666
- name: pytest
6767
working-directory: dsls/harmont-py
@@ -97,7 +97,7 @@ jobs:
9797
dogfood:
9898
name: dogfood (hm run ci)
9999
runs-on: ubuntu-latest
100-
timeout-minutes: 30
100+
timeout-minutes: 45
101101
steps:
102102
- uses: actions/checkout@v4
103103

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ __pycache__/
33
*.py[codz]
44
*$py.class
55

6+
# Node
7+
node_modules/
8+
69
# C extensions
710
*.so
811

.harmont/ci.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ def shared_base() -> hm.Step:
2121
def rust_project(shared_base: hm.Target[hm.Step]) -> tuple[hm.Step, ...]:
2222
project = hm.rust.project(path=".", base=shared_base)
2323
return hm.group([
24-
project.test(flags=("--lib",)),
24+
project.test(flags=("--lib",), packages=("harmont-cli",)),
2525
project.clippy(),
2626
project.fmt(),
2727
])

.harmont/ci.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const pipelines: PipelineDefinition[] = [
2727
slug: "ci",
2828
triggers: [push({ branch: "main" }), pullRequest({ branches: ["main"] })],
2929
pipeline: pipeline(
30-
rustProject.test({ flags: ["--lib"] }),
30+
rustProject.test({ flags: ["--lib"], packages: ["harmont-cli"] }),
3131
rustProject.clippy(),
3232
rustProject.fmt(),
3333
pyProject.lint(),

Cargo.lock

Lines changed: 49 additions & 46 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/hm-plugin-protocol/src/events.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ pub enum BuildEvent {
4040
step_id: Uuid,
4141
key: String,
4242
chain_idx: usize,
43+
/// Key of this step's `BuildsIn` parent, if any. Lets renderers
44+
/// nest progress bars to reflect the pipeline's DAG structure.
45+
parent_key: Option<String>,
46+
/// Human-readable name for display. Falls back to a truncated
47+
/// command when no explicit label was set in the pipeline DSL.
48+
display_name: String,
4349
},
4450
StepStart {
4551
step_id: Uuid,

crates/hm-plugin-protocol/tests/round_trip.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ fn build_event_round_trip_all_variants() {
6464
step_id: Uuid::nil(),
6565
key: "a".into(),
6666
chain_idx: 0,
67+
parent_key: None,
68+
display_name: "a".into(),
6769
},
6870
BuildEvent::StepStart {
6971
step_id: Uuid::nil(),

crates/hm/Cargo.toml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,13 @@ reqwest = { version = "0.13", default-features = false, features = ["rustls", "h
3030
serde = { version = "1", features = ["derive"] }
3131
serde_json = "1"
3232
toml = "0.8"
33-
owo-colors = { version = "4", features = ["supports-colors"] }
3433
dialoguer = { version = "0.11", features = ["fuzzy-select"] }
35-
indicatif = "0.17"
34+
owo-colors = "4"
35+
console = "0.16"
36+
indicatif = "0.18"
37+
tracing-indicatif = "0.3"
3638
comfy-table = { version = "7", features = ["custom_styling"] }
37-
console = "0.15"
39+
terminal_size = "0.4"
3840
tar = "0.4"
3941
flate2 = "1"
4042
fs2 = "0.4"
@@ -70,6 +72,7 @@ semver = { workspace = true }
7072
smart-default = { workspace = true }
7173
once_cell = "1"
7274
hex = "0.4"
75+
is_ci = "1.2.0"
7376

7477
[features]
7578
default = []

crates/hm/src/cli/run.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,9 @@ pub struct RunArgs {
3737
/// `name`). Built-ins: `human`, `json`. Default: `human`.
3838
#[arg(long, value_name = "NAME", default_value = "human", global = false)]
3939
pub format: String,
40+
41+
/// Stream full build logs instead of showing progress bars.
42+
/// Has no effect with `--format json`.
43+
#[arg(long)]
44+
pub logs: bool,
4045
}

crates/hm/src/commands/run/local.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ fn decode_plan_to_wire(bytes: &[u8]) -> anyhow::Result<hm_pipeline_ir::PipelineG
2222
/// the resulting plan does not decode, the Docker daemon is unreachable,
2323
/// or the orchestrator surfaces an internal scheduler error. Non-zero
2424
/// step exit codes are returned as the `i32`, not as an Err.
25-
pub async fn handle(args: RunArgs, _ctx: RunContext) -> Result<i32> {
25+
pub async fn handle(args: RunArgs, ctx: RunContext) -> Result<i32> {
2626
let repo_root = match args.dir.clone() {
2727
Some(p) => p,
2828
None => std::env::current_dir().context("cannot determine current directory")?,
@@ -68,9 +68,19 @@ pub async fn handle(args: RunArgs, _ctx: RunContext) -> Result<i32> {
6868
runner_registry.register(Arc::new(DockerRunner), true);
6969
let runner_registry = Arc::new(runner_registry);
7070

71+
let use_logs = args.logs || std::env::var_os("CI").is_some_and(|v| !v.is_empty());
72+
7173
let renderer: Box<dyn crate::runner::OutputRenderer> = match args.format.as_str() {
7274
"json" => Box::new(crate::output::json::JsonRenderer::new(std::io::stdout())),
73-
_ => Box::new(crate::output::human::HumanRenderer::new(std::io::stderr())),
75+
"human" if use_logs => Box::new(crate::output::human::HumanRenderer::new(
76+
std::io::stderr(),
77+
ctx.output.color_enabled(),
78+
)),
79+
"human" => Box::new(crate::output::progress::ProgressRenderer::new(
80+
std::io::stderr(),
81+
ctx.output.color_enabled(),
82+
)),
83+
other => anyhow::bail!("unknown --format '{other}'\n available: human, json"),
7484
};
7585

7686
let exit_code =

0 commit comments

Comments
 (0)