a checkout with no node_modules does not run, so cloning without installing left
something that looked finished and was not.
run after an update too, and UNCONDITIONALLY — including when the pull changed
nothing. skipping it on "already up to date" is the shortcut that is right until
the one time it is not, and an install on an unchanged tree is close to free.
`process.execPath`, NEVER the string "bun". verified on fofos today: PM2 started
officer with PATH=/usr/local/sbin:…:/snap/bin and bun lives in ~/.bun/bin, so
looking it up by name fails inside the process and works perfectly when you run the
same command by hand — the worst version of this bug, because it cannot be
reproduced the obvious way. execPath is the bun already running us.
bun's directory is also prepended to PATH for the child, which execPath alone does
not cover: a postinstall script calling `bun` would not find it, and that reads as
a broken package rather than a missing PATH entry.
the two commands report as ONE, each prefixed with the line that produced it, so
the panel reads like the terminal somebody would otherwise have opened. it stops at
the first failure — installing into a clone that did not happen produces a second,
more confusing error about a directory that is not there — and a clone that worked
followed by an install that did not is legible as exactly that.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`<root>/website` is now checked, and the block says which of three things it is:
not there, there but not a checkout, or a checkout with its branch and its head
commit. the middle one is the state worth being loud about — cloning will refuse,
and the reason is something already sitting in the way.
SSH, hardcoded. the repo is private, so https asks for a username with nobody at a
terminal to answer, and the SSH remote is already authenticated by the owner's key.
hardcoded because this plugin administers exactly one website: a field for it would
be a setting nobody changes and one more thing that can point somewhere wrong. when
the checkout's origin is NOT that URL, the block says so — shown always it is noise,
shown on a mismatch it answers why an update pulled something unexpected.
NOTHING HERE MAY HANG. these run inside an HTTP request, so git gets
GIT_TERMINAL_PROMPT=0 and ssh gets BatchMode=yes. without them a key that lost
access does not fail, it BLOCKS forever waiting for a password at a terminal that
does not exist, and the panel spins until somebody restarts the server. there is a
five-minute kill on top for everything else that can wedge.
update is `--ff-only`, never a merge. a merge commit made by a button in a checkout
nobody is watching is a thing somebody finds days later; refusing is recoverable
and legible. it also refuses on a dirty tree rather than failing halfway — and
dirty is `--untracked-files=no`, because a build artefact or an uncommitted .env is
not a reason to make Update permanently unavailable.
clone takes FULL history, not --depth 1. this is a working checkout somebody will
pull into and read the log of, and shallow turns both into a support question.
it sits inside Root location rather than in a block of its own: the path and the
thing at the path are one question, and split apart somebody could change the root
in one place and read a status about the old one in the other, both looking equally
current. hidden while editing, because it describes what is SAVED.
git's own output is shown verbatim on failure. "Permission denied (publickey)" says
exactly what is wrong; anything written in its place would be a guess at which of a
dozen causes it was.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>