Skip to content

Fix the updater, which upgraded the wrong directory and then stopped - #10

Merged
Slicit merged 2 commits into
mainfrom
fix-the-updater
Sep 11, 2026
Merged

Slicit merged 2 commits into
mainfrom
fix-the-updater

Conversation

@Slicit

@Slicit Slicit commented Sep 11, 2026 •

Copy link
Copy Markdown
Owner

Three faults, all in v0.1.0, all found by installing it and running update.sh the way somebody would.

update.sh upgraded the wrong directory. It never told install.sh where it lived, so install.sh fell back to its default of /opt/componium. An install anywhere else upgraded a directory it had nothing to do with, created it if it was not there, and reported success while leaving the install it belongs to on the old image. The default directory is the common case and worked, which is exactly why this survived being tested by hand.

confirm ... || return ends the installer. A bare return carries the exit status of the last command, which is the confirm that just answered no, so configure returned 1 and set -e stopped everything. That is every upgrade that keeps its settings, which is what --yes always does.

[ -n "$previous" ] && PORT="$previous" is the same shape one level down: the statement returns 1 when the test is false, and each of those lines is "keep the old value if there was one". An upgrade of an install that never turned the show profile on stopped there.

A fourth, quieter one: download_bundle set an EXIT trap naming a local variable, so every run that actually downloaded ended with tmp: unbound variable from a trap firing in a scope where the local was gone.

The test that should have existed

hack/check-install.sh installs into a temporary directory and updates it, with no Docker and no network, and asserts what those faults broke:

  • the update upgrades its own directory, and creates nothing in /opt
  • every answer survives it
  • the database password does not change, so an upgrade cannot invalidate the database it is upgrading
  • the films are untouched

It runs in check-edits.sh. Both of the first two faults were put back to watch it fail.

The installer had no compiler and no test runner, and was checked by running it. Three of these only happen on the second run.

One more, unrelated and mine

The test added yesterday to hold the README's score to the parser contained a literal markdown fence, which is two adjacent backticks, which is the exact pattern check-edits.sh greps for as evidence that a shell ate a raw string. It broke that check on main for every edit after it. CI never saw it, because CI runs the language suites and the line-ending job and not that script.

🤖 Generated with Claude Code

Slicit and others added 2 commits September 11, 2026 13:05
Three faults, all in v0.1.0, all found by installing it and running update.sh
the way somebody would.

update.sh did not tell install.sh where it lived, so install.sh fell back to
its default of /opt/componium. An install anywhere else upgraded a directory
it had nothing to do with, created it if it was not there, and reported
success while leaving the install it belongs to on the old image. The default
directory is the common case and worked, which is exactly why this survived
being tested by hand.

`confirm "Review the settings again?" "no" || return` ends the installer. A
bare return carries the exit status of the last command, which is the confirm
that just answered no, so configure returned 1 and `set -e` stopped
everything. That is every upgrade that keeps its settings, which is what --yes
always does.

`[ -n "$previous" ] && PORT="$previous"` is the same shape one level down: the
statement returns 1 when the test is false, and each of those lines is "keep
the old value if there was one". An upgrade of an install that never turned
the show profile on stopped there.

A fourth, quieter one: download_bundle set an EXIT trap naming a local
variable, so every run that actually downloaded ended with "tmp: unbound
variable" from a trap firing in a scope where the local was gone.

hack/check-install.sh installs into a temporary directory and updates it,
without Docker and without a network, and asserts what the three faults broke:
that the update upgrades its own directory and creates nothing in /opt, that
every answer survives it, that the database password does not change, and that
the films are untouched. It runs in check-edits.sh. Both of the first two
faults were put back to watch it fail.

The installer had no compiler and no test runner and was checked by running
it, which is how three things that only happen on the second run reached a
release.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
check-edits.sh greps Go files for two adjacent backticks, because that is what
a shell leaves behind when it has eaten the contents of a raw string or a
struct tag, and both of those have shipped here.

A markdown fence written literally is exactly that pattern, so the test added
yesterday to hold the README's score to the parser broke the tool on the day
it landed: a test about the README made check-edits.sh report a mangled file,
on main, for every edit anybody made after it.

Written as escapes instead. CI never saw it, because CI runs the language
suites and the line-ending job and not this script, which is its own small
lesson about a check that only runs where somebody remembers to run it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Slicit
Slicit merged commit 72632f1 into main Sep 11, 2026
9 checks passed
@Slicit
Slicit deleted the fix-the-updater branch September 11, 2026 17:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant