Skip to content

fix(update): compare versions as semver and replace the binary safely - #22

Merged
nabil1440 merged 1 commit into
blockers/5-docker-availabilityfrom
blockers/8-self-update
Sep 22, 2026
Merged

nabil1440 merged 1 commit into
blockers/5-docker-availabilityfrom
blockers/8-self-update

Conversation

@nabil1440

@nabil1440 nabil1440 commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Change

  • golang.org/x/mod/semver compares the versions. Thus v0.1.10 is newer than v0.1.9.
  • A git describe version (v0.1.1-2-gabc, -dirty) counts as its tag.
  • fly cannot compare a build that is not from a release tag (dev). fly update tells this and asks before it installs the latest release.
  • fly reads the release information one time, with a 60 s timeout, a User-Agent header and a status check.
  • A GitHub rate limit gives a clear error. Before this change, it gave "You are already running the latest version."
  • archive/tar and compress/gzip extract the binary. The code does not start the tar command.
  • The new binary goes to a temporary file in the directory of the executable. Then a rename replaces the executable. Thus the rename cannot cross filesystems (EXDEV).
  • If the update fails, the old binary does not change.
  • The asset names and the archive layout do not change.

Tests

  • Unit tests:
    • a table of version comparisons
    • GitHub API responses (httptest): 200, 403 rate limit, 500, and a response without a tag
    • asset selection
    • binary replacement, and no change to the old binary when the archive is bad
  • An end-to-end test in a Linux container, as root. /tmp is on tmpfs. A local server replaces GitHub:
    • v0.1.9 updates to v0.1.10.
    • A second run shows "You are already running the latest version."
    • No temporary files stay in /usr/local/bin.
    • A user who is not root gets exit status 1.
  • golangci-lint shows 0 issues on the full repository. govulncheck finds no vulnerabilities.

Closes #8

@nabil1440
nabil1440 added this pull request to stack #24 September 21, 2026 10:41
- Compare versions with golang.org/x/mod/semver (v0.1.10 is newer
  than v0.1.9). A git describe build (v0.1.1-2-gabc) counts as its
  tag. A build that is not from a release tag (dev) cannot be
  compared: fly update says so and asks before it installs.
- Get the release one time, with a 60 s timeout, a User-Agent and a
  status check. A GitHub rate limit gives a clear error instead of
  'already running the latest version'.
- Extract the binary with archive/tar and compress/gzip instead of
  the tar command.
- Write the new binary to a temporary file next to the executable and
  rename it, so the rename cannot cross filesystems (EXDEV). The old
  binary stays unchanged when the update fails.
- Release asset names and archive layout are unchanged.

Closes #8
@nabil1440
nabil1440 force-pushed the blockers/8-self-update branch from c106f5c to 062e0a7 Compare September 22, 2026 06:36
@nabil1440
nabil1440 merged commit 901f57c into develop Sep 22, 2026
@nabil1440
nabil1440 deleted the blockers/8-self-update branch September 22, 2026 06:51
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.

bug(self-update): correct the version comparison, the HTTP errors and the binary replacement

1 participant