Conversation
Fixes #1671. ## What `pull`, `restart`, `stop`, `start`, `kill`, `pause`, `unpause`, `rm` and `run` open the live board over the resources they will touch and close it on every exit, the way `up` does; in a pipe the plain lines stay. Each container action gets a working verb before the call (`Stopping`, `Restarting`, `Killing`, `Pausing`, `Unpausing`, `Removing`), so the row carries the spinner and the clock while Podman works, and a skipped container ends its row with `Skipped` instead of silence. ## Measured (pseudo-terminal, `script`, local Podman 5.7.0) | command | board before | board after | last row | |---|---|---|---| | pull | 0 | 1 | `✔ Image alpine:3.20 Pulled 0.0s` | | restart, stop, start, pause, unpause, kill, rm | 0 | 1 | `✔ Container ux-web-1 Restarted` and so on | | run --rm | 0 | 1 | network rows, then the command's output on stdout | | stop with `stop_grace_period: 3s` on a container that ignores SIGTERM | frozen `Pending` | `⠋ Stopping 0.0s` for 35 frames, then `✔ Stopped 3.2s` | Piped `pull` prints `Pulling` and `Pulled` as before (test `a_piped_pull_keeps_the_plain_lines`). ## How it was built MiniMax wrote the wiring and nine tests under a brief; I added the working verbs, the `Skipped` final and its test after the captures showed rows jumping from `Pending` to the final verb with no activity in between. Unit: 1824 pass. Clippy and fmt clean. Note for the merge order: #1672/#1673/#1675 (in review next) make the plain sink print only final verbs; whichever lands second adapts the piped-pull expectation. Signed-off-by: Jaro-c <75870284+Jaro-c@users.noreply.github.com> Signed-off-by: Jaro-c <75870284+Jaro-c@users.noreply.github.com>
…lain sink never contradicts itself (#1677) Fixes #1672, #1673 and #1675. ## What - The live sink is chosen by the terminal alone; `NO_COLOR` and `--ansi never` remove the styling and keep the spinner, the repaint and the markers. Measured: `NO_COLOR=1 up -d` now hides the cursor and repaints with zero SGR sequences. - Rows and the summary line are cut to the measured width with `…` on the name. Measured at `stty rows 24 cols 30`: longest row 29 columns, cursor moves unchanged. - The plain sink never contradicts itself: a transitional verb is held until the final one; both lines are printed when work happened (`Pulling` then `Pulled`, so a log still shows when it started), only the final when nothing was done (`Exists`, `Running`, `Absent`, `Skipped`); the held line is flushed at `end` and at the error exit. Piped `up -d` on an existing network prints `Network ux_default Exists` and nothing else for it. - A failed `up` printed its `Failed` row twice; once now. Interactive `exec` wrote a stray byte before the output (`^@hi` under `script`); the first bytes are `hi`. Empty `volumes`, `images`, `ps` and `ls` print `no volumes` / `no images` / `no containers` / `no projects` on stderr and nothing on stdout. ## How it was built MiniMax wrote the fixes and the eight named tests under a brief. Two things I changed on review: its plain sink dropped every transitional line, which broke four contract tests in `tests/reporting_contract.rs` that hold `Pulling` then `Pulled` in a pipe (the rule above keeps them and drops only the contradiction); and it had rewritten every pre-existing em dash in `docs/commands.md` into broken punctuation, so the docs diff was rebuilt from `HEAD` plus its five new paragraphs. Unit: 1824 pass; the 14 contract tests pass. Signed-off-by: Jaro-c <75870284+Jaro-c@users.noreply.github.com> --------- Signed-off-by: Jaro-c <75870284+Jaro-c@users.noreply.github.com>
Fixes #1674. Podman 5.7.0 sends no byte counts on the pull API (measured: `Copying blob` lines in libpod mode, `Pulling fs layer`/`Download complete` with an empty `progressDetail` in compat mode), so the row counts layers: `Pulling 1 layer`, `Pulling 4 layers` as digests appear, `Pulling 4/4` once every copy is reported, then `Pulled`. In a pipe, `Pulling` and `Pulled` as before. Measured on a real pull of `python:3.12-alpine` after `podman rmi`: the row moved through `Pulling 1 layer`, `2 layers`, `3 layers`, 20 frames at `4 layers`, `4/4`, `Pulled`. MiniMax wrote it under a brief; I fixed the plural and one comment. Unit: 1827 pass, the 15 contract tests pass. Signed-off-by: Jaro-c <75870284+Jaro-c@users.noreply.github.com> Signed-off-by: Jaro-c <75870284+Jaro-c@users.noreply.github.com>
… it (#1683) Fixes #1680. A pull-request job (`windows-arm64.yml`, same shape as `linux-hardening.yml`) builds `aarch64-pc-windows-msvc` on `windows-11-arm` and runs `--version`. Its run on this pull request is the measurement that the label exists for this organization and that the binary runs. The release matrix moves the `podup-windows-arm64.exe` leg to that runner and the smoke skip from #1649 goes away; the threat-model row no longer names an exception. What this pull request must show: the `aarch64-pc-windows-msvc on windows-11-arm` job green. If the label is not available, that job is the only red and this pull request waits. MiniMax wrote it under a brief. Signed-off-by: Jaro-c <75870284+Jaro-c@users.noreply.github.com> Signed-off-by: Jaro-c <75870284+Jaro-c@users.noreply.github.com>
…fore signing (#1682) Fixes #1679. ## Measured first An independent parser over the 5.8.0 assets: both Windows binaries have `DllCharacteristics 0x8160` (`DYNAMIC_BASE`, `HIGH_ENTROPY_VA`, `NX_COMPAT`, no `GUARD_CF`); `podup-darwin-arm64` is `PIE`. Control Flow Guard is opt-in on rustc for MSVC. ## What - `.cargo/config.toml`: `-C control-flow-guard` for both MSVC targets. - `.github/scripts/check-hardening.ps1` parses the PE header itself (no Visual Studio tooling) and requires the four `DllCharacteristics` bits; its test builds a minimal PE32+ and one control per bit. - `.github/scripts/check-hardening-macos.sh` requires `MH_PIE` in `otool -h` and no local symbols in `nm -p`; its test builds controls with `clang` where the tools exist and says `SKIP` elsewhere; it runs on the macOS legs. - `release.yml`: both scripts run in the legs that can read the file, before signing. - `lint-powershell.yml`: a `windows-latest` job runs the PE fixture, then builds the release binary with the pinned toolchain and reads it, so the rustflag is proven on a pull request and not at tag time. Paths include `.cargo/**` and `Cargo.toml`. - Threat model rows and the supply-chain sentence. ## What this pull request must show The `check-hardening.ps1 tests` job green with the built binary passing all four bits: that is the measurement that `control-flow-guard` reaches the linker. Nothing macOS could be executed on this Linux machine; the macOS legs run at release time and the shell test skips here with a printed reason. MiniMax wrote it under a brief; I added the build-and-read step and the exec bits on the two shell files. Signed-off-by: Jaro-c <75870284+Jaro-c@users.noreply.github.com> --------- Signed-off-by: Jaro-c <75870284+Jaro-c@users.noreply.github.com>
…olded under it (#1684) Closes #1681. ## What changes `podup build`, and the build `up` runs when a service's image is missing, draw one row per image on the board every other verb command already uses. The row reads `Building`, then `Building n/m` as each `STEP n/m` line arrives, then `Built` or `Failed` with the elapsed time. On a terminal the buildah stream is folded under the row: the last four lines sit dimmed below it while it builds and vanish when the row finishes. A failed build replays its whole stream once, above the error, so the reason is on screen. In a pipe every stream line goes to stderr prefixed with the image tag, the way `logs` prefixes container output, and the verb lines are written in plain form with no escape sequence. The image id goes to stdout only when stdout is not a terminal, so `podup build | awk '{print $1}'` still reads it; on a terminal the row is the record. Buildah emits the id as a bare 64-hex line after `Successfully tagged` (measured on Podman 5.7 today); the reader matches that line and falls back to asking libpod for the tag's id. `up --build` runs the build board first and the `up` board after it, because `up` resolves images concurrently and a forced build inside that stage would build services in parallel, which `build` does not do. `docs/commands.md` says so. ## Measured under a pseudo-terminal (`script -qfc`) Fresh build, deduplicated frames: ``` [+] Running 0/1 ⠙ Image localhost/ux-talker:1 Building 1/3 0.0s STEP 1/3: FROM docker.io/library/alpine:3.20 ⠸ Image localhost/ux-talker:1 Building 2/3 0.2s --> 8e66f4345325 ⠼ Image localhost/ux-talker:1 Building 3/3 0.3s COMMIT localhost/ux-talker:1 ✔ Image localhost/ux-talker:1 Built 0.3s ``` Failed build: ``` ✘ Image localhost/ux-bad:1 Failed 0.4s localhost/ux-bad:1 | STEP 1/3: FROM docker.io/library/alpine:3.20 localhost/ux-bad:1 | STEP 2/3: RUN echo one localhost/ux-bad:1 | one localhost/ux-bad:1 | --> a8f9c8f333e8 localhost/ux-bad:1 | STEP 3/3: RUN false podup: error: build error: building at STEP "RUN false": while running runtime: exit status 1 ``` Piped build: stdout is the single line `3ec8da61bf44…882b`; stderr carries ` Image localhost/ux-talker:1 Building`, the prefixed stream, and ` Image localhost/ux-talker:1 Built`, with zero escape sequences. `up -d --build` shows the build board, then the network and container board. A cached rebuild reads the same rows in 0.1s. ## Tests - `build_draws_a_row_per_image_and_counts_steps`, `a_failed_build_prints_its_stream_once_before_the_error`, `build_stream_progress_parses_a_three_step_dockerfile`, `parse_image_id_line_only_matches_the_bare_full_id` (unit, against the fake Podman). - `up_with_a_missing_image_builds_on_the_same_board` (unit). - `a_piped_build_prefixes_every_stream_line_with_the_service` and `build_writes_the_image_id_to_stdout` (contract, against real Podman). - `notes_keep_the_last_four_lines_per_row` (unit). The three plain-sink tests in the progress module share one process-wide buffer and failed 3 runs in 20 under the parallel harness; they now hold a lock, 0 in 20 after. Suite, clippy and fmt clean locally. Signed-off-by: Jaro-c <75870284+Jaro-c@users.noreply.github.com> --------- Signed-off-by: Jaro-c <75870284+Jaro-c@users.noreply.github.com>
Bump for the minor release carrying the live board on every verb command, the build and pull rows, and the hardening gates for the Windows and macOS binaries with Control Flow Guard newly enabled. Nothing existing changes what it does; the output is what changed. ## Verified The three version comparisons of release.yml run locally: crate=5.9.0 lock=5.9.0 deb=5.9.0, GATE OK; cargo metadata --locked accepts the lockfile. Signed-off-by: Jaro-c <75870284+Jaro-c@users.noreply.github.com> Signed-off-by: Jaro-c <75870284+Jaro-c@users.noreply.github.com> Signed-off-by: Jaro-c <75870284+Jaro-c@users.noreply.github.com>
… and a missing named compose file fails ps and events (#1689) Closes #1686, #1687 and #1688, the three findings of the pseudo-terminal pass over develop at 91d7260 (every command, in a terminal, in a pipe, with NO_COLOR and at 30 columns). ## rm and scale-down (#1686) Both called the final line without opening the row, so `Removed` had no elapsed time and the scale-down stop said nothing for its whole grace. Measured after: ``` ⠙ Container tfix-talker-2 Stopping 10.0s ⠙ Container tfix-talker-2 Removing 10.1s ✔ Container tfix-talker-2 Removed 10.1s ``` Every arm now closes the row (`Absent` on 404, `Skipped` on a running container without `-f`, `Failed` otherwise), so the plain sink never flushes a row left at `Removing`. Tests: `stop_and_remove_opens_the_row_before_the_stop_and_closes_it_removed` pins the verb sequence against the fake Podman; the rm board test now asserts `Removing` precedes `Removed` for each container. ## rm --stop (#1688) It ran the whole `unpause` command first, which drew a board over every container, closed each unpaused one as `Skipped` and noted `no containers to unpause`. `unpause_paused` takes one project listing, keeps the paused containers, and draws nothing when there are none. Measured after, nothing paused: the board opens at `Stopped`; one paused container: `Unpausing`, `Unpaused`, then the stop and the removal, for that container only. Test: `unpause_paused_touches_only_the_paused_containers` covers both cases, including that no `/unpause` request is sent when nothing is paused. ## ps and events with a missing named file (#1687) `podup -f /nonexistent.yml ps` printed `no containers` and exited 0. A file named with `-f` or `COMPOSE_FILE` that does not exist now fails with `compose file not found: /nonexistent.yml`, exit 1, for both label-only commands; a directory with no compose file and no `-f` still answers by label (measured: `no containers`, exit 0, from `/tmp`). Test: `a_named_compose_file_that_is_missing_fails_ps_and_events`. Suite, clippy and fmt clean locally. Signed-off-by: Jaro-c <75870284+Jaro-c@users.noreply.github.com> --------- Signed-off-by: Jaro-c <75870284+Jaro-c@users.noreply.github.com>
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.
Release
develop→mainfor 5.9.0. Merge commit, not squash:mainis the released state.What ships
The live board on every command that acts (#1671 to #1675, PRs #1676, #1677, #1678).
up,down,start,stop,restart,kill,pause,unpause,create,rm,scale,pullandpushdraw the same boarduphad: a working verb while a row is in flight, a final verb with the elapsed time, one row per resource. The board keeps animating underNO_COLOR, cuts rows to the terminal width, and in a pipe prints plain lines that never contradict each other.pullcounts the layers as they copy.buildon the board (#1681, PR #1684). One row per image,Building n/mfrom the builder's STEP lines, the builder stream folded under the row on a terminal and replayed above the error when a build fails; in a pipe every line is prefixed with the image tag and the image id goes to stdout.rm, scale-down andpsread right (#1686, #1687, #1688, PR #1689).rmand a scale-down open their rows before stopping and removing, soRemovedcarries the time;rm --stopresumes only what is paused and draws nothing otherwise;psandeventsfail on a compose file named with-fthat does not exist instead of answering by label.The release itself changes
Every binary is read before it is signed (#1679, PR #1682). Windows:
DllCharacteristicsmust carryDYNAMIC_BASE,HIGH_ENTROPY_VA,NX_COMPATandGUARD_CF; Control Flow Guard is newly enabled for both MSVC targets, and the 5.8.0 executables measured without it. macOS:MH_PIEand a stripped symbol table. Linux keeps the gate from 5.7.1. Each script has a fixture with one control per property, and the Windows gate ran on apodup.exebuilt in a pull request before this release.The windows-arm64 asset is built and run on an arm64 runner (#1680, PR #1683). Until now it cross-compiled on x86_64 and its smoke test was skipped.
This run is the first release that exercises the Windows and macOS gates on the assets that ship. If one fails, the release stops before signing, which is the point.
Verified before opening this
release.ymllocally:crate=5.9.0 lock=5.9.0 deb=5.9.0, GATE OK;cargo metadata --lockedaccepts the lockfile.NO_COLOR, 30 columns) found the three issues PR fix(cli): rm and scale-down rows, rm --stop only unpauses the paused, and a missing named compose file fails ps and events #1689 fixed and nothing else.Signed-off-by: Jaro-c 75870284+Jaro-c@users.noreply.github.com