feat: add built-in ipfs update command#11203
Merged
Conversation
adds `ipfs update` command tree that downloads pre-built Kubo binaries from GitHub Releases, verifies SHA-512 checksums, and replaces the running binary in place. subcommands: - `ipfs update check` -- query GitHub for newer versions - `ipfs update versions` -- list available releases - `ipfs update install [version]` -- download, verify, backup, and atomically replace the current binary - `ipfs update revert` -- restore the previously backed up binary from `$IPFS_PATH/old-bin/` read-only subcommands (check, versions) work while the daemon is running. install and revert require the daemon to be stopped first. design decisions: - uses GitHub Releases API instead of dist.ipfs.tech because GitHub is harder to censor in regions that block IPFS infrastructure - honors GITHUB_TOKEN/GH_TOKEN to avoid unauthenticated rate limits - backs up the current binary before replacing, with permission-error fallback that saves to a temp dir with manual `sudo mv` instructions - `KUBO_UPDATE_GITHUB_URL` env var redirects API calls for integration testing; `IPFS_VERSION_FAKE` overrides the reported version - unit tests use mock HTTP servers and the var override; CLI tests use the env vars with a temp binary copy so the real build is never touched resolves #10937
Resolve changelog conflict by placing the update command entry after the cid inspect section.
- cap decompressed binary at 1 GB to block zip/tar bombs - propagate tar.gz/zip errors instead of swallowing them - fall back to 1h context timeout when --timeout is not set - warn on stderr when daemon lock check fails - clarify that fetch+verify+extract complete before touching binary
The test harness hardcodes the binary path as `cmd/ipfs/ipfs` without the `.exe` suffix. On Windows the built binary is `ipfs.exe`, so copyBuiltBinary needs to append the extension.
On Windows the OS locks the running executable, so atomicfile cannot rename over it. The install command falls back to saving the new binary to a temp path. Accept both outcomes in TestUpdateInstall: in-place replacement (Unix) or permission-denied fallback (Windows). Also fix stash path to include .exe suffix on Windows. - test/cli/update_test.go: branch on runtime.GOOS for install assertions - test/sharness/t0063-external.sh: remove, tested the old ExternalBinary delegation which is replaced by the built-in update command - .github/workflows/test-migrations.yml: pass GITHUB_TOKEN to avoid rate limits
da9c63c to
cd16d29
Compare
On Windows, Process.Wait() sets the handle state to "released" rather than "done", so a subsequent Signal() returns syscall.EINVAL instead of os.ErrProcessDone. This caused StopDaemon cleanup to panic on Windows CI. Treat both errors as "process already exited".
cd16d29 to
6fb1eb6
Compare
guillaumemichel
approved these changes
Apr 9, 2026
Contributor
guillaumemichel
left a comment
There was a problem hiding this comment.
Nice feature!
Maybe add command to purge stashed versions, or document they can/should be purged manually when not needed anymore to prevent them from piling up?
Drops every backed-up Kubo binary from $IPFS_PATH/old-bin/ so users can reclaim disk space without hand-deleting files. Safe with the daemon running, only touches the backup directory. - update.go: extract stashDirName const, factor out listStashes() helper, add updateCleanCmd - commands_test.go: register /update/clean - test/cli/update_test.go: TestUpdateClean covers removal, empty dir, json output, and preservation of unrelated files
Drop the marketing opener, the duplicate install example, and the revert/versions sentence; all are covered by 'ipfs update --help'. Mention the new 'clean' subcommand in the trailing pointer.
Both fuse_test.go and realworld_test.go rely on Unix-only APIs (syscall.Truncate, POSIX tools). The sibling xattr_*_test.go files were already gated, but these two compiled everywhere, so any workflow running 'go test ./test/cli/...' on Windows hit 'undefined: syscall.Truncate'. Use the same '(linux || darwin || freebsd) && !nofuse' constraint that the fuse/ packages already use so platform gating is consistent.
TestUpdateInstall and TestUpdateRevert write a copy of the ipfs binary and then exec it. When other tests run in parallel, a concurrent fork() can inherit the still-open write fd into its child, leaving the freshly written file 'text file busy' for exec until the sibling child execs. Dropping t.Parallel() on these two tests ensures no other goroutine is mid-fork while the binary is being written, which is the only reliable way to avoid the ETXTBSY race without clever fd tricks.
GitHub's macOS runners intermittently lose DNS for api.github.com, which fails the real-network subtests in TestUpdate. Point the resolver at 1.1.1.1 and 8.8.8.8 on every active network service and flush the DNS cache before running the update tests.
The previous fallback wrote to a predictable path (/tmp/ipfs-<ver>), which on shared systems lets a local attacker pre-create the path as a symlink and steer the user's subsequent 'sudo mv' anywhere. Switch to os.CreateTemp so the path is unique and exclusively owned by this process.
IPFS_VERSION_FAKE and KUBO_UPDATE_GITHUB_URL are test-only escape hatches with no production use case. The TEST_ prefix signals this clearly and reduces the chance of accidental use in production. - IPFS_VERSION_FAKE -> TEST_KUBO_VERSION - KUBO_UPDATE_GITHUB_URL -> TEST_KUBO_UPDATE_GITHUB_URL
silently skipping the daemon lock check on path-resolution failure can mask a misconfigured IPFS_PATH; print a warning so the user notices before the install proceeds.
Revert the Sync() addition in atomicfile.Close() to avoid widening the failure surface for existing migration callers that panic on Close errors (Must(out.Close()) in WithBackup). The stashBinary fsync in update.go is kept since that code path is new. - revert repo/fsrepo/migrations/atomicfile/atomicfile.go to master - use errors.Is(err, io.EOF) in extractFromTarGz
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Warning
Not finished yet, parking here until we work on 0.41
ipfs update: add built-in command, sunsetipfs-update#10937adds
ipfs updatecommand tree that downloads pre-built Kubo binaries from GitHub Releases, verifies SHA-512 checksums, and replaces the running binary in place.ipfs update: add built-in command, sunsetipfs-update#10937subcommands:
ipfs update check-- query GitHub for newer versionsipfs update versions-- list available releasesipfs update install [version]-- download, verify, backup, and atomically replace the current binaryipfs update revert-- restore the previously backed up binary from$IPFS_PATH/old-bin/read-only subcommands (check, versions) work while the daemon is running. install and revert require the daemon to be stopped first.
design decisions:
sudo mvinstructionsKUBO_UPDATE_GITHUB_URLenv var redirects API calls for integration testing;IPFS_VERSION_FAKEoverrides the reported versionReferences
Closes
ipfs update: add built-in command, sunsetipfs-update#10937Closes Test case for
ipfs update. #5195 - test coverage for ipfs update (the PR adds unit and CLI integration tests in test/cli/update_test.go and core/commands/update_github_test.go)Closes Have cli prompt for update to latest version #7381 - built-in update check and install (the "get ipfs-update bundled into go-ipfs" part; the auto-prompt part is not implemented but could be built on top)
ipfs/ipfs-update (outdated by the replacement):