Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ members = [

[package]
name = "retch-cli"
version = "0.6.20"
version = "0.6.21"
edition = "2021"
authors = ["Ken Tobias"]
description = "A fast, feature-rich system information fetcher written in Rust (similar to fastfetch or neofetch)"
Expand Down
44 changes: 42 additions & 2 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -382,8 +382,32 @@ pr:
echo " [ ] GitHub wiki cloned and updated (Configuration-and-Theming.md, Workspace-Architecture.md)"
echo " [ ] Upstream tldr page updated / docs/retch.md synced (if CLI flags changed)"
echo ""
echo -n "All manual items confirmed? [y/N] "
read -r CONFIRM
# A bare `read` makes this gate unanswerable by anything that is not a human at a
# terminal: a script, CI job or agent either blocks on a stdin that will never answer or
# dies without saying why -- and that failure reads as the gate refusing the change rather
# than asking a question nobody could hear. Three sources of an answer, in order:
#
# 1. PR_CONFIRM in the environment -- the explicit answer for a non-interactive caller.
# It is NOT a bypass: setting it is the same act of confirmation as typing y, just
# recorded where a script can supply it. Answer it AFTER checking each item.
# 2. An interactive stdin -- a human, prompted exactly as before.
# 3. Neither, so read whatever was piped in, bounded by a timeout. `echo y | just pr`
# keeps working, and a stdin that never answers costs ten seconds rather than hanging.
#
# The failure names PR_CONFIRM, because a gate that cannot be satisfied from the context it
# failed in is a wall rather than a gate.
if [ -n "${PR_CONFIRM:-}" ]; then
CONFIRM="$PR_CONFIRM"
echo "All manual items confirmed? [y/N] $CONFIRM (answered by PR_CONFIRM)"
elif [ -t 0 ]; then
echo -n "All manual items confirmed? [y/N] "
read -r CONFIRM
else
echo -n "All manual items confirmed? [y/N] "
read -r -t 10 CONFIRM || CONFIRM=""
echo "$CONFIRM"
[ -n "$CONFIRM" ] || { echo -e "${RED}Aborted.${NC} No terminal to confirm the checklist on, and nothing on stdin. Re-run with PR_CONFIRM=y once each item above is actually checked."; exit 1; }
fi
[ "$CONFIRM" = "y" ] || [ "$CONFIRM" = "Y" ] \
|| { echo -e "${RED}Aborted.${NC} Complete the checklist first."; exit 1; }

Expand All @@ -395,6 +419,22 @@ open-pr *ARGS:
#!/usr/bin/env bash
set -euo pipefail
just pr

# Push the branch if it has no upstream yet. Without this, on a never-pushed branch
# `gh pr create` has no remote branch to open a PR from and fails non-interactively --
# AFTER the gate has printed "Gate passed", which reads as the gate refusing a change it
# had just approved.
#
# Deliberately ONLY when there is no upstream. Pushing unconditionally would make this
# recipe silently publish existing commits on a branch that already has one -- a different
# and more surprising act than "put this branch where gh can see it".
if ! git rev-parse --abbrev-ref --symbolic-full-name '@{upstream}' >/dev/null 2>&1; then
BRANCH="$(git rev-parse --abbrev-ref HEAD)"
[ "$BRANCH" != HEAD ] || { echo "detached HEAD -- check out a branch first" >&2; exit 1; }
echo "no upstream for $BRANCH -- pushing it so gh has a remote branch to open from"
# pre-push runs `just check`, so this cannot publish a branch the gate would refuse.
git push -u origin "$BRANCH"
fi
gh pr create "$@"

# Generate a flamegraph for execution profiling (requires perf on Linux or dtrace on macOS)
Expand Down
29 changes: 28 additions & 1 deletion NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,34 @@ The `retch-sysinfo` crate can be used independently as a library for cross-platf

---

## Current State (v0.6.20)
## Current State (v0.6.21)
- **v0.6.21 — two gates that could not be satisfied from the situation they failed in**
(tooling only; no runtime change, `retch-sysinfo` unchanged at `0.1.53`). Both were hit by hand
while landing v0.6.20, and both are fixes `rusticprofile` already had.
- **`just pr` ended in a bare `read`, so nothing but a human at a terminal could answer it.** A
script, CI job or agent either blocked on a stdin that would never answer or died without
saying why — and that failure reads as *the gate refusing the change*, not as a question
nobody could hear. It now takes its answer from `PR_CONFIRM`, from an interactive stdin, or
from piped input under a ten-second bound, and the failure message **names `PR_CONFIRM`**.
It is not a bypass: all four paths still require an explicit `y`, so this widens *who can
answer*, not *what counts as an answer* — and the checklist must still be answered after
each item is actually checked.
- **`just open-pr` did not push, so on a never-pushed branch it printed "Gate passed" and then
failed.** `gh pr create` had no remote branch to open from. The observable result was a
command that announced the gate passing and then exited non-zero, which reads as the gate
rejecting work it had just approved. It now pushes **only when there is no upstream** —
pushing unconditionally would silently publish existing commits on a branch that already has
one, a different and more surprising act. `pre-push` still runs `just check`, so this cannot
publish a branch the gate would refuse; the push is inside the gate, not around it.
- **Both were verified on this PR itself**, which is the only honest test for the second one:
the branch had no upstream when `open-pr` ran, and that condition cannot be reproduced after
the fact.
- *Why these existed at all:* they are `rusticprofile`'s `0.0.21` and `0.2.12`, which retch
never received — the same cross-repo staleness that left the nushell completion path wrong
here for months and that v0.6.20's `standard-check` now guards for the install family. The
`pr`/`open-pr` triad is **not** yet covered by that standard; `templates/justfile-common.just`
records it as out of scope, because these recipes legitimately differ per repo.
- `retch-cli` → 0.6.21. Patch bump.
- **v0.6.20 — nushell completions went where Windows nushell never looks; the install helpers
become a checked cross-repo standard** (tooling only; no runtime behavior change,
`retch-sysinfo` unchanged at `0.1.53`).
Expand Down
2 changes: 1 addition & 1 deletion docs/retch.1
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.TH "RETCH" "1" "August 2026" "retch 0.6.20" "System Information Fetcher"
.TH "RETCH" "1" "August 2026" "retch 0.6.21" "System Information Fetcher"

.SH "NAME"
.PP
Expand Down