Conversation
Operations now communicate with the presentation layer through typed events instead of driving progress bars directly. New icp-events crate carries the task/step/output vocabulary and the Reporter handles; the new icp-cli render module owns all wording, indicatif bars, and failure replay (absorbing MultiStepProgressBar::dump_output). The Build trait and the low-level script/wasm helpers in the core crate take a StepReporter in place of Option<Sender<String>>; the sync path bridges into its legacy line channel until it is ported. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QUZHfx2ng97WM2j9XoA3rr
The Synchronize and ScriptRunner traits, and the sync-plugin runtime's run_plugin, take a StepReporter in place of Option<Sender<String>>, which removes the temporary line-channel bridges entirely — the plugin runtime's live output forwarding is now lossless (events instead of best-effort try_send). Retained plugin stderr rides on TaskOutcome::Succeeded and failure cause chains on TaskOutcome::Failed, so the renderers own printing both; sync_many drops its ProgressManager and eprintln calls. MultiStepProgressBar and its step channel are now unused and deleted from progress.rs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QUZHfx2ng97WM2j9XoA3rr
Install, settings sync, binding env vars, and the Candid compatibility check take a Reporter instead of a debug flag; their per-canister Failure structs, progress bars, and batch error! dumps move into the renderers (new TaskKinds carry the data, TaskOutcome::Skipped covers the not-an-upgrade Candid case). Deploy's create phase emits Create task events instead of driving bars, so no ProgressManager remains in deploy or the operations layer. A render::rendered() helper wraps the channel/renderer lifecycle that every phase and command was repeating. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QUZHfx2ng97WM2j9XoA3rr
The blob upload/download operations take a TaskReporter and emit the
new Progress { position } event in place of driving an indicatif bar;
TaskKind::SnapshotTransfer declares the direction, blob, and byte
total, and the interactive renderer builds the byte-bar style (moved
from create_transfer_progress_bar) for that kind. The snapshot
upload/download commands run each blob through the new rendered_task
helper. Under --debug the plain renderer shows no live transfer bar,
consistent with the rest of the CLI (the bar previously drew there).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QUZHfx2ng97WM2j9XoA3rr
Contributor
There was a problem hiding this comment.
Pull request overview
Introduces typed operation-progress events and CLI-owned renderers, decoupling core operations from terminal presentation.
Changes:
- Adds the
icp-eventsevent and reporter API. - Routes build, sync, deploy, and snapshot progress through renderers.
- Replaces output channels and operation-owned progress bars.
Reviewed changes
Copilot reviewed 36 out of 37 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
Cargo.toml |
Registers icp-events. |
Cargo.lock |
Locks new dependencies. |
crates/icp-events/Cargo.toml |
Defines the events crate. |
crates/icp-events/src/lib.rs |
Implements events and reporters. |
crates/icp/Cargo.toml |
Adds events dependency. |
crates/icp/src/canister/wasm.rs |
Reports WASM resolution events. |
crates/icp/src/canister/script.rs |
Streams script output through reporters. |
crates/icp/src/canister/build/mod.rs |
Updates the build interface. |
crates/icp/src/canister/build/script.rs |
Reports script-build output. |
crates/icp/src/canister/build/prebuilt.rs |
Reports prebuilt-WASM progress. |
crates/icp/src/canister/sync/mod.rs |
Updates the synchronization interface. |
crates/icp/src/canister/sync/script.rs |
Updates script-runner reporting. |
crates/icp/src/canister/sync/plugin.rs |
Passes reporters into plugins. |
crates/icp-sync-plugin/Cargo.toml |
Adds events dependency. |
crates/icp-sync-plugin/src/runtime.rs |
Emits typed plugin output. |
crates/icp-cli/Cargo.toml |
Adds events dependency. |
crates/icp-cli/src/main.rs |
Registers the render module. |
crates/icp-cli/src/progress.rs |
Removes migrated multi-step rendering. |
crates/icp-cli/src/render/mod.rs |
Adds renderer orchestration and logging. |
crates/icp-cli/src/render/plain.rs |
Adds debug-mode rendering. |
crates/icp-cli/src/render/interactive.rs |
Adds interactive progress rendering. |
crates/icp-cli/src/operations/build.rs |
Emits build task events. |
crates/icp-cli/src/operations/sync.rs |
Emits sync task events. |
crates/icp-cli/src/operations/install.rs |
Emits installation events. |
crates/icp-cli/src/operations/settings.rs |
Emits settings-update events. |
crates/icp-cli/src/operations/binding_env_vars.rs |
Emits environment-update events. |
crates/icp-cli/src/operations/candid_compat.rs |
Emits compatibility-check events. |
crates/icp-cli/src/operations/bundle.rs |
Uses event-driven builds. |
crates/icp-cli/src/operations/snapshot_transfer.rs |
Emits byte positions. |
crates/icp-cli/src/commands/build.rs |
Runs builds with a renderer. |
crates/icp-cli/src/commands/sync.rs |
Runs sync with a renderer. |
crates/icp-cli/src/commands/deploy.rs |
Renders deploy phases. |
crates/icp-cli/src/commands/project/bundle.rs |
Renders bundle builds. |
crates/icp-cli/src/commands/canister/snapshot/upload.rs |
Renders upload progress. |
crates/icp-cli/src/commands/canister/snapshot/download.rs |
Renders download progress. |
crates/icp-cli/tests/build_tests.rs |
Updates tracing targets. |
crates/icp-cli/tests/sync_tests.rs |
Updates tracing targets. |
Suppressed comments (1)
crates/icp-cli/src/render/interactive.rs:65
- The spinner is inserted into
MultiProgressbefore its prefix and initial message are set. This reintroduces the unlabeled first-frame race described in the superseded implementation: configure the detached bar fully, add it, and only then start the ticker.
let bar = self.multi_progress.add(
ProgressBar::new_spinner()
.with_style(make_style(TICK_EMPTY, COLOR_REGULAR)),
);
bar.set_prefix(format!("[{}]", task.canister()));
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+55
to
+58
| let bar = self.multi_progress.add(ProgressBar::new(*total_bytes)); | ||
| bar.set_style(transfer_style()); | ||
| bar.set_prefix(transfer_label(blob)); | ||
| bar |
Comment on lines
+99
to
+102
| view.header = step_header(view.log.kind(), number, total, &label); | ||
| view.window = RollingLines::new(LIVE_WINDOW_LINES); | ||
| view.log.start_step(view.header.clone()); | ||
| view.bar.set_message(view.header.clone()); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Supersedes #709, which landed the same inversion as one change. This PR reaches the same end state through four reviewable slices (one commit each), each keeping the full test suite green and pinning output parity against the existing integration tests along the way.
Why
Progress reporting is what welded the operations layer to the terminal: operations constructed
ProgressManagers, droveindicatifbars, formatted user-facing strings, and printed batch failure dumps, while theBuild/Synchronizeports incrates/icptook atokio::sync::mpsc::Sender<String>that only existed because the binary had a progress bar to feed.What
New
crates/icp-events: typed,serde::Serializeevents (TaskStarted/StepStarted/Output/Progress/StepCompleted/TaskCompleted, with typedTaskKindpayloads per operation) and cheap-clone emitter handles (Reporter→TaskReporter→StepReporter). Sends are sync and non-blocking; with no receiver they are no-ops, so tests and headless callers need no wiring. Errors stay on the operations'Resultpath —TaskOutcome::Failedcarries display data only.New
crates/icp-cli/src/render/: the presentation layer.InteractiveRendererreproduces the existing indicatif UX (spinners, step headers, rolling output window, byte bars for snapshot transfers, deferred failure dumps — absorbingMultiStepProgressBar::dump_output);PlainRenderercovers--debug. Commands drive a renderer per operation phase viarendered()/rendered_task().Push-down:
Build,Synchronize,ScriptRunner, and the sync-plugin runtime'srun_plugintake aStepReporterin place ofOption<Sender<String>>— noOption, a null reporter instead. The plugin runtime's live output forwarding becomes lossless (events instead of best-efforttry_send).Commit chain (intended to be reviewed commit by commit, merged unsquashed):
icp-eventscrate + renderers + the build pipeline end to endicpandicp-sync-plugin, temporary line-channel bridges deleted, retained plugin stderr and failure cause chains modeled as outcome datarendered()helper; noProgressManagerleft in operations or deployProgress { position }events and renderer-owned byte barsNotes for review
build_tests/sync_testsexact-format assertions; the only test edits are the tracing-target renames (icp::progress:→icp::render::plain:).--debug, snapshot transfer bars no longer draw (previously they ignored the debug flag);--debugoutput is now consistent across all commands.migrate_id's status spinner are command-owned UX and intentionally stay direct — commands are the presentation layer.--jsonrenderer (RFC: document --json output schemas in --help and/or generated docs #493) is purely additive later.🤖 Generated with Claude Code
https://claude.ai/code/session_01QUZHfx2ng97WM2j9XoA3rr