Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Added

- Support for `CODER_BINARY_DESTINATION` environment variable to set CLI download location (overridden by extension setting `coder.binaryDestination` if configured).

## [v1.11.0](https://github.com/coder/vscode-coder/releases/tag/v1.11.0) 2025-09-24

### Changed
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
"default": ""
},
"coder.binaryDestination": {
"markdownDescription": "The full path of the directory into which the Coder CLI will be downloaded. Defaults to the extension's global storage directory.",
"markdownDescription": "The full path of the directory into which the Coder CLI will be downloaded. Defaults to the value of `CODER_BINARY_DESTINATION` if not set, otherwise the extension's global storage directory.",
"type": "string",
"default": ""
},
Expand Down
27 changes: 25 additions & 2 deletions src/core/pathResolver.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as path from "path";
import { describe, it, expect, beforeEach } from "vitest";
import { describe, it, expect, beforeEach, vi } from "vitest";
import { MockConfigurationProvider } from "../__mocks__/testHelpers";
import { PathResolver } from "./pathResolver";

Expand All @@ -11,6 +11,7 @@ describe("PathResolver", () => {
let mockConfig: MockConfigurationProvider;

beforeEach(() => {
vi.unstubAllEnvs();
pathResolver = new PathResolver(basePath, codeLogPath);
mockConfig = new MockConfigurationProvider();
});
Expand All @@ -32,6 +33,7 @@ describe("PathResolver", () => {
});

it("should use default path when custom destination is empty or whitespace", () => {
vi.stubEnv("CODER_BINARY_DESTINATION", " ");
mockConfig.set("coder.binaryDestination", " ");
expect(pathResolver.getBinaryCachePath("deployment")).toBe(
path.join(basePath, "deployment", "bin"),
Expand All @@ -41,7 +43,28 @@ describe("PathResolver", () => {
it("should normalize custom paths", () => {
mockConfig.set("coder.binaryDestination", "/custom/../binary/./path");
expect(pathResolver.getBinaryCachePath("deployment")).toBe(
path.normalize("/custom/../binary/./path"),
"/binary/path",
);
});

it("should use CODER_BINARY_DESTINATION environment variable with proper precedence", () => {
// Use the global storage when the environment variable and setting are unset/blank
vi.stubEnv("CODER_BINARY_DESTINATION", "");
mockConfig.set("coder.binaryDestination", "");
expect(pathResolver.getBinaryCachePath("deployment")).toBe(
path.join(basePath, "deployment", "bin"),
);

// Test environment variable takes precedence over global storage
vi.stubEnv("CODER_BINARY_DESTINATION", " /env/binary/path ");
expect(pathResolver.getBinaryCachePath("deployment")).toBe(
"/env/binary/path",
);

// Test setting takes precedence over environment variable
mockConfig.set("coder.binaryDestination", " /setting/path ");
expect(pathResolver.getBinaryCachePath("deployment")).toBe(
"/setting/path",
);
});
});
Expand Down
11 changes: 7 additions & 4 deletions src/core/pathResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,14 @@ export class PathResolver {
* The caller must ensure this directory exists before use.
*/
public getBinaryCachePath(label: string): string {
const configPath = vscode.workspace
const settingPath = vscode.workspace
.getConfiguration()
.get<string>("coder.binaryDestination");
return configPath && configPath.trim().length > 0
? path.normalize(configPath)
.get<string>("coder.binaryDestination")
?.trim();
const binaryPath =
settingPath || process.env.CODER_BINARY_DESTINATION?.trim();
return binaryPath
? path.normalize(binaryPath)
: path.join(this.getGlobalConfigDir(label), "bin");
}

Expand Down