Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
12 changes: 12 additions & 0 deletions test/install/context.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,18 @@ test("resolveInstallContext supports native Windows paths and Git Bash cwd input
);
});

test("integration harness keeps the host runtime platform for node-backed dependencies", async () => {
const harness = await createInstallIntegrationHarness();

try {
const dependencies = harness.createDependencies();

assert.equal(dependencies.runtime.platform, process.platform);
} finally {
await harness.cleanup();
}
});

test(
"resolveInstallContext assembles project, platform, version, and managed path context without using real machine paths",
{ skip: process.platform === "win32" },
Expand Down
83 changes: 45 additions & 38 deletions test/install/rerun.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { createInstallIntegrationHarness } from "./harness.js";
const MODEL_KEY = "qwen3-235b-a22b-instruct-2507-fp8" as const;
const MODEL_REF = formatOpencodeModelRef(MODEL_KEY);
const SECOND_RUN_BACKUP_TIMESTAMP = "20260409T110000Z";
const SKIP_POSIX_HOST_INTEGRATION = process.platform === "win32";

type InstallScope = "project" | "user";
type InstallerFixture = Awaited<ReturnType<typeof createInstallerFixture>>;
Expand Down Expand Up @@ -281,44 +282,50 @@ test("no-op rerun in user scope keeps managed config stable and skips new backup
}
});

test("no-op rerun in user scope repairs drifted POSIX secret permissions without creating a new backup", async () => {
const fixture = await createInstallerFixture();

try {
const firstResult = await runScopedInstall(fixture, "user", {
clockIso: "2026-04-09T10:00:00.000Z",
});

assert.equal(firstResult.status, "success");

await chmod(fixture.managedPaths.secretPath, 0o644);
await chmod(dirname(fixture.managedPaths.secretPath), 0o755);

const beforeManagedState = await snapshotManagedState(fixture);

const secondResult = await runScopedInstall(fixture, "user", {
clockIso: "2026-04-09T11:00:00.000Z",
});

assert.equal(secondResult.status, "success");
await assertManagedStateUnchanged(fixture, beforeManagedState, ["secret"]);
await assertBackupMissing(
fixture,
fixture.managedPaths.secretPath,
SECOND_RUN_BACKUP_TIMESTAMP,
);
assert.equal(
(await stat(fixture.managedPaths.secretPath)).mode & 0o777,
0o600,
);
assert.equal(
(await stat(dirname(fixture.managedPaths.secretPath))).mode & 0o777,
0o700,
);
} finally {
await fixture.harness.cleanup();
}
});
test(
"no-op rerun in user scope repairs drifted POSIX secret permissions without creating a new backup",
{ skip: SKIP_POSIX_HOST_INTEGRATION },
async () => {
const fixture = await createInstallerFixture();

try {
const firstResult = await runScopedInstall(fixture, "user", {
clockIso: "2026-04-09T10:00:00.000Z",
});

assert.equal(firstResult.status, "success");

await chmod(fixture.managedPaths.secretPath, 0o644);
await chmod(dirname(fixture.managedPaths.secretPath), 0o755);

const beforeManagedState = await snapshotManagedState(fixture);

const secondResult = await runScopedInstall(fixture, "user", {
clockIso: "2026-04-09T11:00:00.000Z",
});

assert.equal(secondResult.status, "success");
await assertManagedStateUnchanged(fixture, beforeManagedState, [
"secret",
]);
await assertBackupMissing(
fixture,
fixture.managedPaths.secretPath,
SECOND_RUN_BACKUP_TIMESTAMP,
);
assert.equal(
(await stat(fixture.managedPaths.secretPath)).mode & 0o777,
0o600,
);
assert.equal(
(await stat(dirname(fixture.managedPaths.secretPath))).mode & 0o777,
0o700,
);
} finally {
await fixture.harness.cleanup();
}
},
);

test("repeated project-scope reruns stay stable while refreshing install-state only", async () => {
const fixture = await createInstallerFixture();
Expand Down
8 changes: 7 additions & 1 deletion test/install/test-deps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -520,13 +520,19 @@ export function createStubbedTestInstallDependencies(
export function createNodeBackedTestInstallDependencies(
overrides: CreateNodeInstallDependenciesOverrides = {},
): InstallDependencies {
const runtimeOverrides = Object.fromEntries(
Object.entries(overrides.runtime ?? {}).filter(
([, value]) => value !== undefined,
),
) as InstallRuntimeOverrides;

return createNodeInstallDependencies({
clock: overrides.clock,
commands: overrides.commands,
fs: overrides.fs,
input: overrides.input,
prompts: overrides.prompts,
runtime: createTestInstallRuntime(overrides.runtime),
runtime: runtimeOverrides,
});
}

Expand Down
Loading