Commit Graph

3 Commits

Author SHA1 Message Date
bcherb2 53022b8146 fix: a wrong password no longer costs an entire reinstall
The endpoint credentials are asked for at the very end of a run, after every
package is installed -- correct, because a password typed at picker time would
sit in memory through ten minutes of downloads. But any non-200 was fatal, so
one mistyped character meant repeating the whole install to get back to a
three-line prompt.

Now it retries, up to five attempts. URL and username persist across them and
blank keeps them, shown as `Bootstrap URL [https://...]:`, so only the password
is retyped -- retyping an address that was already pasted correctly is its own
source of error. `q` at the URL prompt leaves the machine public-only.

The message also names the fault. Every failure used to print "endpoint refused
the credentials", including a 404 and an unreachable host -- which is precisely
how a URL-shape bug reads as a password problem. The status is now captured
alongside the body rather than relying on --fail:

  401  wrong username or password
  404  reached the host, but no bootstrap.env is there -- check the route
  000  could not reach that address (DNS, TLS, or the host is down)

The body is used only when the code is 200, so an error page is still never
parsed as a blob; that was --fail's job and an explicit check is stronger.

`dotup private` already re-ran only this step, leaving installed packages
alone -- it was simply missing from --help, so the cheap way back in was
undiscoverable. Documented, and the failure path now points at it.

The end-to-end sends a wrong password first on purpose and asserts both the
message and that blank-blank-correct works, which is the only way to test a
recovery path. Note that harness clones the PUBLISHED repo, so it validates
what a user gets, not the working tree -- these invariants are covered in the
unit suite, which reads the tree directly. 105 -> 113.
2026-08-17 22:57:08 -04:00
bcherb2 2a93bfd5b1 test: assert dotup's absolute path before touching PATH
The check was `export PATH="$HOME/.local/bin:$PATH"` followed by
`command -v dotup`, which proves the export worked and nothing else. It passed
on every run while a real operator on a fresh box hit
`dotup: command not found`.

~/.local/bin is put on PATH only by the .zshrc this tier ships, for a zsh that
dotup itself installs. So on any new machine the first invocation must be
~/.local/bin/dotup -- which the README already documents -- and bare `dotup`
cannot work until zsh is installed and logged into.

Assert `-x ~/.local/bin/dotup` first, then export for the rest of the script's
convenience. Reproduced the original failure in a clean root container before
changing anything, and re-ran the end-to-end after: PASS.
2026-08-17 22:30:55 -04:00
bcherb2 cebb38b97a test: move the end-to-end here, and fix the race that made it flaky
The e2e harness and its mock endpoint were living in the private repo, justified
by "they name the endpoint host". That was true when written and false two
commits later, once the hardcoded URL came out of the wrapper so the route would
live only in Bitwarden. Rechecked: all three name the endpoint zero times -- the
URL, username and password are supplied at runtime -- and the only host they
mention is this repo. They belong next to the dotup they exercise and the unit
suite that covers the rest of it.

The move surfaced a worse problem than the misplacement. The harness was flaky,
and an earlier PASS was partly luck.

chezmoi writes "git user.email?" with the tty still in cooked mode and only then
switches to raw mode -- with TCSAFLUSH, which discards whatever is already
buffered. Answering on the prompt TEXT races that switch. One run answered all
seven prompts; the next lost the Enter after user.email, leaving the field
unsubmitted. Every later expect then waited out its own timeout and the whole
thing surfaced at the 600s ceiling as an unattributed "a prompt went
unanswered".

Two fixes:

  - each answer now waits for \033[?2004h, bracketed-paste-on, which the TUI
    emits only AFTER raw mode is established. "Probably ready" becomes
    "demonstrably ready", and each prompt emits its own, so it is per-answer.
  - a bare `expect -re {pat} {...}` treats timeout as "carry on", which is what
    turned one lost keystroke into a ten-minute mystery. Prompts now fail
    immediately naming which one was missed, and distinguish EOF (dotup exited
    early) from timeout.

Also moved red(), the redactor, above the run. It was defined below the new
early-abort path that calls it, so the one branch that most needs redaction
would have hit an undefined function.

Verified by running it twice end to end against a mock endpoint, both passing
identically, including the three assertions the argv fix exists for.

README: the suite is 101 assertions, not 81, and the end-to-end is documented.
2026-08-17 22:14:35 -04:00