feat: allow binaryDestination to accept a full path to the CLI binary#879
Merged
feat: allow binaryDestination to accept a full path to the CLI binary#879
Conversation
d8f1641 to
59f545c
Compare
jeremyruppel
approved these changes
Apr 10, 2026
The coder.binaryDestination setting (and CODER_BINARY_DESTINATION env var) now accepts either a file path or a directory path: - File path (e.g. /usr/bin/coder): if the file exists, use it directly. Version is checked and reported. If the version mismatches and downloads are enabled, the binary is re-downloaded to the same path. If downloads are disabled, the existing binary is used as-is with a warning. - Directory path (existing behavior): look for the platform-specific name (e.g. coder-linux-amd64) first, then fall back to the simple name (coder / coder.exe). This supports package-manager-installed CLIs that use the simple name. Adds cliUtils.simpleName() returning "coder" (or "coder.exe" on Windows) and a unified resolveBinaryPath() method in CliManager used by both locateBinary() and fetchBinary(). Resolves #861
Always download to the platform-specific binary name (coder-linux-amd64) for temp files, old backups, signatures, and lock files. After a successful download, rename the result to the user's configured file name while still holding the lock to avoid races with other windows. Scoped rmOld to only clean files prefixed with the binary basename so it does not accidentally remove unrelated files when the target directory is shared (e.g. /usr/bin). Additional improvements: - Rename cliUtils.name() to fullName() to pair with simpleName() - Replace ResolvedBinary kind "file"/"dir" with source "file-path"/"directory" to clarify that stat always describes the binary, not the directory - Fix binaryDestination description: file paths are version-checked and updated on mismatch, not used without downloading - Update resolveBinaryPath JSDoc to remove misleading "as-is" language - Add fallback path to error handler so file-path destinations check the user's original binary when the download path has no usable binary - Simplify handleAnyBinaryFailure with tryCandidate closure and deferred findOldBinaries to avoid unnecessary I/O when earlier candidates match - On error recovery, rename fallback to resolved.binPath so the binary always ends up where the user expects - Add "starting download" back to the no-binary-found log message - Improve test coverage: file destination error fallback, simple name error fallback, platform-specific file destination, old backup restore - Unify test structure: shared disableSignatureVerification in top-level beforeEach, shared withFailedDownload helper, Binary Resolution group - Remove flaky lock/progress file assertions from concurrent tests
59f545c to
7cda5ed
Compare
c3d3903 to
8a691b6
Compare
The version check, lock-wait, and rename logic in fetchBinary used nested if/else-if blocks and a needsDownload flag that made the control flow hard to follow. This refactors it into sequential guard clauses (version match, downloads disabled, version mismatch) and replaces the flag with an early return. The duplicated rename-to- final-path logic is extracted into a small helper used in both the lock-wait and download paths. No behavior changes.
8a691b6 to
e866c3c
Compare
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.
Summary
The
coder.binaryDestinationsetting (andCODER_BINARY_DESTINATIONenv var) now accepts a file path in addition to a directory path.File path (e.g.
/usr/bin/coder): the extension checks its version and downloads a replacement if it does not match the server (and downloads are enabled). If downloads are disabled, the existing binary is used with a warning. Downloads always go to the platform-specific name first, then rename to the configured path under the lock.Directory path (existing behavior): looks for the platform-specific name (
coder-linux-amd64) first, then falls back to the simple name (coder/coder.exe). This supports package-manager-installed CLIs (e.g. viaapt,brew,winget) that use the simple name.Changes
cliUtils.simpleName()and renamename()tofullName()for clarityresolveBinaryPath()inCliManagerreturning aResolvedBinarydiscriminated union (source: "file-path" | "directory" | "not-found") used by bothlocateBinary()andfetchBinary()rmOldcleanup to only files prefixed with the binary basename, preventing accidental removal in shared directories like/usr/binhandleAnyBinaryFailuretries candidates in order (download path, user configured path, old backups) and renames the fallback toresolved.binPathso the binary ends up where the user expectsfetchBinarydecision tree: version check, lock-wait, and rename logic now use sequential guard clauses instead of nested branches, and arenameToFinalPathhelper replaces duplicated rename logicbinaryDestinationsetting description to accurately reflect version-check-then-download behaviorTest coverage
.old-*backup is restored to expected pathResolves #861