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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ codevhub skill office --dir /media/usb/codev-office # download somewhere else

Both files land side by side, and the command prints the exact line to run from that folder (`bash codev-office-<os>-setup.sh`, or `powershell -ExecutionPolicy Bypass -File .\codev-office-windows-setup.ps1`). A bundle downloaded for another OS is never executed on this machine.

Two flags are passed straight through to the setup script: `--minimal` (skip the optional extras) and `--skip-verify` (skip the bundle's own SHA-256 check).
Two flags are passed straight through to the setup script: `--skip-verify` (skip the bundle's own SHA-256 check) and `--force-skills` (replace already-installed skills with the bundled versions).

## Switching between self-hosted and proprietary models

Expand Down
6 changes: 3 additions & 3 deletions src/lib/help.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ Skill hub:
(--platform ubuntu|macos|windows to fetch for another OS
[implies --download-only], --dir <path> for the download
folder, --download-only to skip running the installer,
--minimal / --skip-verify passed through to the
installer, --force-skills to replace already-installed
skills with the bundled versions)
--skip-verify passed through to the installer,
--force-skills to replace already-installed skills
with the bundled versions)
`);
}
15 changes: 4 additions & 11 deletions src/lib/office.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { officeDownloadsDir } from "@/lib/paths.js";
// installer that prompts for sudo/UAC, which an Ink render would fight over.

export const OFFICE_USAGE =
"Usage: codevhub skill office [--platform ubuntu|macos|windows] [--dir <path>] [--download-only] [--minimal] [--skip-verify] [--force-skills]";
"Usage: codevhub skill office [--platform ubuntu|macos|windows] [--dir <path>] [--download-only] [--skip-verify] [--force-skills]";

export type OfficePlatform = "ubuntu" | "macos" | "windows";

Expand All @@ -34,7 +34,6 @@ export interface OfficeArgs {
platform?: OfficePlatform;
dir?: string;
downloadOnly: boolean;
minimal: boolean;
skipVerify: boolean;
forceSkills: boolean;
// Deliberately unadvertised (absent from OFFICE_USAGE and `codevhub help`):
Expand All @@ -50,7 +49,6 @@ export interface OfficeArgs {
export function parseOfficeArgs(argv: string[]): OfficeArgs {
const parsed: OfficeArgs = {
downloadOnly: false,
minimal: false,
skipVerify: false,
forceSkills: false,
uninstall: false,
Expand Down Expand Up @@ -91,9 +89,6 @@ export function parseOfficeArgs(argv: string[]): OfficeArgs {
case "--download-only":
parsed.downloadOnly = true;
break;
case "--minimal":
parsed.minimal = true;
break;
case "--skip-verify":
parsed.skipVerify = true;
break;
Expand All @@ -120,9 +115,9 @@ export function parseOfficeArgs(argv: string[]): OfficeArgs {
// The two modes take disjoint flag sets — reject mixtures loudly rather
// than silently forwarding a flag the target script would choke on.
if (parsed.uninstall) {
if (parsed.minimal || parsed.skipVerify || parsed.forceSkills) {
if (parsed.skipVerify || parsed.forceSkills) {
parsed.error =
"--minimal/--skip-verify/--force-skills do not apply with --uninstall";
"--skip-verify/--force-skills do not apply with --uninstall";
}
} else if (parsed.yes || parsed.skillsOnly || parsed.purgeDownloads) {
parsed.error = "--yes/--skills-only/--purge-downloads require --uninstall";
Expand Down Expand Up @@ -206,16 +201,14 @@ export function installerArgs(
platform: OfficePlatform,
): string[] {
// The bash scripts take GNU-style flags; the PowerShell script takes
// -Minimal / -SkipVerify / -ForceSkills switches.
// -SkipVerify / -ForceSkills switches.
if (platform === "windows") {
return [
...(parsed.minimal ? ["-Minimal"] : []),
...(parsed.skipVerify ? ["-SkipVerify"] : []),
...(parsed.forceSkills ? ["-ForceSkills"] : []),
];
}
return [
...(parsed.minimal ? ["--minimal"] : []),
...(parsed.skipVerify ? ["--skip-verify"] : []),
...(parsed.forceSkills ? ["--force-skills"] : []),
];
Expand Down
11 changes: 3 additions & 8 deletions tests/lib/download.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@
return 0;
},
);
expect(code).toBe(0);

Check failure on line 310 in tests/lib/download.test.ts

View workflow job for this annotation

GitHub Actions / matrix (windows-latest)

tests/lib/download.test.ts > runSkillOffice > --download-only stages both files and never spawns

AssertionError: expected 1 to be +0 // Object.is equality - Expected + Received - 0 + 1 ❯ tests/lib/download.test.ts:310:16
expect(spawns).toEqual([]);
expect(readFileSync(join(dir, bundleName)).equals(BUNDLE)).toBe(true);
expect(readFileSync(join(dir, scriptName)).equals(SCRIPT)).toBe(true);
Expand All @@ -317,17 +317,17 @@
const dir = join(tempDir, "office");
let spawned: { command: string; args: string[]; cwd: string } | null = null;
const code = await runSkillOffice(
["--dir", dir, "--minimal", "--skip-verify"],
["--dir", dir, "--skip-verify"],
baseUrl,
async (command, args, cwd) => {
spawned = { command, args, cwd };
return 0;
},
);
expect(code).toBe(0);

Check failure on line 327 in tests/lib/download.test.ts

View workflow job for this annotation

GitHub Actions / matrix (windows-latest)

tests/lib/download.test.ts > runSkillOffice > runs the installer via bash with translated flags

AssertionError: expected 1 to be +0 // Object.is equality - Expected + Received - 0 + 1 ❯ tests/lib/download.test.ts:327:16
expect(spawned).toEqual({
command: "bash",
args: [join(dir, scriptName), "--minimal", "--skip-verify"],
args: [join(dir, scriptName), "--skip-verify"],
cwd: dir,
});
});
Expand All @@ -335,7 +335,7 @@
test("propagates the installer's exit code", async () => {
const dir = join(tempDir, "office");
const code = await runSkillOffice(["--dir", dir], baseUrl, async () => 7);
expect(code).toBe(7);

Check failure on line 338 in tests/lib/download.test.ts

View workflow job for this annotation

GitHub Actions / matrix (windows-latest)

tests/lib/download.test.ts > runSkillOffice > propagates the installer's exit code

AssertionError: expected 1 to be 7 // Object.is equality - Expected + Received - 7 + 1 ❯ tests/lib/download.test.ts:338:16
});

test("a cross-platform --platform forces download-only", async () => {
Expand All @@ -352,7 +352,7 @@
},
);
expect(code).toBe(0);
expect(spawns).toEqual([]);

Check failure on line 355 in tests/lib/download.test.ts

View workflow job for this annotation

GitHub Actions / matrix (windows-latest)

tests/lib/download.test.ts > runSkillOffice > a cross-platform --platform forces download-only

AssertionError: expected [ 'powershell.exe' ] to deeply equal [] - Expected + Received - [] + [ + "powershell.exe", + ] ❯ tests/lib/download.test.ts:355:18
expect(existsSync(join(dir, "codev-office-windows.zip"))).toBe(true);
});

Expand All @@ -365,7 +365,7 @@
["--download-only", "--dir", dir],
baseUrl,
);
expect(code).toBe(0);

Check failure on line 368 in tests/lib/download.test.ts

View workflow job for this annotation

GitHub Actions / matrix (windows-latest)

tests/lib/download.test.ts > runSkillOffice > always refetches the setup script, but reuses a finished bundle

AssertionError: expected 1 to be +0 // Object.is equality - Expected + Received - 0 + 1 ❯ tests/lib/download.test.ts:368:16
expect(readFileSync(join(dir, scriptName)).equals(SCRIPT)).toBe(true);
// No checksum to disagree with, so the existing bundle is trusted as-is.
expect(readFileSync(join(dir, bundleName), "utf8")).toBe("stale-bundle");
Expand All @@ -382,7 +382,7 @@
["--download-only", "--dir", dir],
baseUrl,
);
expect(code).toBe(0);

Check failure on line 385 in tests/lib/download.test.ts

View workflow job for this annotation

GitHub Actions / matrix (windows-latest)

tests/lib/download.test.ts > runSkillOffice > drops a stale .partial for the script instead of resuming onto it

AssertionError: expected 1 to be +0 // Object.is equality - Expected + Received - 0 + 1 ❯ tests/lib/download.test.ts:385:16
expect(readFileSync(join(dir, scriptName)).equals(SCRIPT)).toBe(true);
// Both requests went out without a Range header.
expect(rangeLog).toEqual([undefined, undefined]);
Expand All @@ -398,7 +398,7 @@
let spawned: { command: string; args: string[]; cwd: string } | null = null;
const code = await withPlatform("win32", () =>
runSkillOffice(
["--dir", dir, "--minimal", "--skip-verify"],
["--dir", dir, "--skip-verify"],
baseUrl,
async (command, args, cwd) => {
spawned = { command, args, cwd };
Expand All @@ -414,7 +414,6 @@
"Bypass",
"-File",
join(dir, "codev-office-windows-setup.ps1"),
"-Minimal",
"-SkipVerify",
],
cwd: dir,
Expand Down Expand Up @@ -456,7 +455,7 @@
return 0;
},
);
expect(code).toBe(0);

Check failure on line 458 in tests/lib/download.test.ts

View workflow job for this annotation

GitHub Actions / matrix (windows-latest)

tests/lib/download.test.ts > runSkillOffice > --uninstall fetches only the uninstall script and runs it with passthroughs

AssertionError: expected 1 to be +0 // Object.is equality - Expected + Received - 0 + 1 ❯ tests/lib/download.test.ts:458:16
expect(spawned).toEqual({
command: "bash",
args: [join(dir, uninstallName), "--yes", "--skills-only"],
Expand All @@ -468,7 +467,6 @@

const NO_FLAGS = {
downloadOnly: false,
minimal: false,
skipVerify: false,
forceSkills: false,
uninstall: false,
Expand All @@ -480,22 +478,19 @@
describe("installerArgs", () => {
const base = {
...NO_FLAGS,
minimal: true,
skipVerify: true,
forceSkills: true,
};

test("bash platforms get GNU-style flags", () => {
expect(installerArgs(base, "ubuntu")).toEqual([
"--minimal",
"--skip-verify",
"--force-skills",
]);
});

test("windows gets PowerShell switches", () => {
expect(installerArgs(base, "windows")).toEqual([
"-Minimal",
"-SkipVerify",
"-ForceSkills",
]);
Expand Down
5 changes: 1 addition & 4 deletions tests/lib/office.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ describe("parseOfficeArgs", () => {
test("defaults", () => {
expect(parseOfficeArgs([])).toEqual({
downloadOnly: false,
minimal: false,
skipVerify: false,
forceSkills: false,
uninstall: false,
Expand All @@ -42,15 +41,13 @@ describe("parseOfficeArgs", () => {
"--dir",
"/tmp/x",
"--download-only",
"--minimal",
"--skip-verify",
"--force-skills",
]);
expect(parsed).toEqual({
platform: "windows",
dir: "/tmp/x",
downloadOnly: true,
minimal: true,
skipVerify: true,
forceSkills: true,
uninstall: false,
Expand All @@ -75,7 +72,7 @@ describe("parseOfficeArgs", () => {
});

test("rejects install flags combined with --uninstall", () => {
expect(parseOfficeArgs(["--uninstall", "--minimal"]).error).toMatch(
expect(parseOfficeArgs(["--uninstall", "--skip-verify"]).error).toMatch(
/do not apply with --uninstall/,
);
});
Expand Down
Loading