Skip to content

fix(cloud): correct watch URL host/path, taxonomy, and archive size guard#132

Merged
markovejnovic merged 1 commit into
mainfrom
relprep/5-fix-cloud-watch-url-and-archive-guard
Jun 10, 2026
Merged

fix(cloud): correct watch URL host/path, taxonomy, and archive size guard#132
markovejnovic merged 1 commit into
mainfrom
relprep/5-fix-cloud-watch-url-and-archive-guard

Conversation

@markovejnovic

Copy link
Copy Markdown
Contributor

Summary

Four cloud-path fixes for hm run --backend cloud, consolidated into one commit on top of main:

  • Watch URL host/path — the printed build link pointed at the API host with the wrong path shape, landing on raw JSON / a 404 instead of the dashboard. The api.app. heuristic is lifted out of hm-plugin-cloud's login flow into a shared hm_config::app_url helper, the resolved dashboard base is plumbed into CloudBackend, and the link is built as {app}/{org}/pipelines/{slug}/builds/{n} to match the SPA route.
  • Canceled taxonomy — a server-side canceled build was reported as a failure (exit 1). watch_build now maps the terminal state via exit_code_for_state (passed→0, canceled→130, else→1), the backend maps that to BuildStatus::Canceled (mirroring the local scheduler), and the BuildEnd event carries 130.
  • Archive size guard — the worktree archive uploaded silently with no size guard. Added an "uploading N.N MB" notice before the POST, a soft warning naming the largest top-level paths, and a hard cap (6 MiB, aligned with the backend's ~8 MB JSON body limit after base64) that fails fast with a §5-doctrine source_too_large error (observed vs cap, biggest paths, the .gitignore fix, stable code + doc URL).
  • Log-token expiry — a log token minted once was silently dropped on mid-build expiry. Re-mint before spawning a stream when within a 5-minute safety margin of expiry; on 401 Unauthorized surface a one-line notice on the step instead of dropping it.

Findings addressed

  • cloud-watch-url-host-1
  • cloud-canceled-as-failed-1
  • cloud-archive-no-size-guard-1
  • cloud-logtoken-expiry-silent-loss-1

Verification

Targeted checks on the touched crates (hm-config, hm-exec, hm-plugin-cloud, harmont-cli). No full-suite or DB-touching runs (shared-machine guardrails).

$ cargo check -p hm-config -p hm-exec -p hm-plugin-cloud -p harmont-cli
    Finished `dev` profile [unoptimized + debuginfo] target(s)

$ cargo test -p hm-exec --test backend_contract
running 3 tests
test result: ok. 3 passed; 0 failed; 0 ignored

$ cargo test -p hm-config -p hm-exec --lib
hm-config: test result: ok. 13 passed; 0 failed
hm-exec:   test result: ok. 29 passed; 0 failed

Fix-specific tests that passed:

  • cloud::backend::tests::watch_url_uses_app_host_and_pipelines_path
  • cloud::watch::tests::passed_is_zero_canceled_is_130_else_is_one
  • cloud::backend::tests::archive_over_cap_fails_with_source_too_large
  • cloud::backend::tests::archive_under_warn_passes
  • cloud::backend::tests::human_mb_formats_one_decimal
  • error::tests::unauthorized_is_matchable_and_displayed
  • local::source::tests::build_archive_emits_nonempty_gzip_for_simple_tree
  • local::source::tests::build_archive_skips_dot_git

Judge verdict

Approved. No blocking issues. Implementer verification passed.


Generated by the Harmont release-readiness workflow (automated; needs human review before merge). 🤖

…uard

Four cloud-path fixes for `hm run --backend cloud`:

- Watch URL pointed at the API host with the wrong path shape, so the
  printed link landed on raw JSON / a 404 instead of the dashboard. Lift
  the `api.` -> `app.` heuristic out of `hm-plugin-cloud`'s login flow
  into a shared `hm_config::app_url` helper, plumb the resolved dashboard
  base into `CloudBackend`, and build the link as
  `{app}/{org}/pipelines/{slug}/builds/{n}` to match the SPA route.
  (cloud-watch-url-host-1)

- A server-side canceled build was reported to the user as a failure
  (exit 1). `watch_build` now maps the terminal state via
  `exit_code_for_state` (passed->0, canceled->130, else->1) and the
  backend maps that to `BuildStatus::Canceled`, mirroring the local
  scheduler; the `BuildEnd` event carries 130 too.
  (cloud-canceled-as-failed-1)

- The worktree archive had no size guard and uploaded silently. Add an
  "uploading N.N MB" notice before the POST, a soft warning that names
  the largest top-level paths, and a hard cap (6 MiB, aligned with the
  backend's ~8 MB JSON body limit after base64) that fails fast with a
  §5 doctrine error (`source_too_large`: observed vs cap, biggest paths,
  the .gitignore fix, stable code + doc URL). (cloud-archive-no-size-guard-1)

- A log token was minted once; on expiry mid-build the remaining logs
  were silently dropped. Re-mint before spawning a stream when within a
  5-minute safety margin of expiry, and on a `401 Unauthorized` surface a
  one-line notice on the step instead of dropping it.
  (cloud-logtoken-expiry-silent-loss-1)

Co-Authored-By: Claude <noreply@anthropic.com>
@markovejnovic markovejnovic merged commit 50a951b into main Jun 10, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant