fix(test): guard platform version cli values

This commit is contained in:
Vincent Koc
2026-06-20 03:24:44 +02:00
parent d76c1daa52
commit 4db7d6a90a
4 changed files with 189 additions and 53 deletions

View File

@@ -5,19 +5,21 @@ import { resolveAndroidVersion } from "./lib/android-version.ts";
type CliOptions = {
field: string | null;
format: "json" | "shell";
help: boolean;
rootDir: string;
};
function parseArgs(argv: string[]): CliOptions {
let field: string | null = null;
let format: "json" | "shell" = "json";
let help = false;
let rootDir = path.resolve(".");
for (let index = 0; index < argv.length; index += 1) {
const arg = argv[index];
switch (arg) {
case "--field": {
field = argv[index + 1] ?? null;
field = readOptionValue(argv, index, "--field");
index += 1;
break;
}
@@ -30,20 +32,15 @@ function parseArgs(argv: string[]): CliOptions {
break;
}
case "--root": {
const value = argv[index + 1];
if (!value) {
throw new Error("Missing value for --root.");
}
const value = readOptionValue(argv, index, "--root");
rootDir = path.resolve(value);
index += 1;
break;
}
case "-h":
case "--help": {
console.log(
`Usage: node --import tsx scripts/android-version.ts [--json|--shell] [--field name] [--root dir]\n`,
);
process.exit(0);
help = true;
break;
}
default: {
throw new Error(`Unknown argument: ${arg}`);
@@ -51,28 +48,57 @@ function parseArgs(argv: string[]): CliOptions {
}
}
return { field, format, rootDir };
return { field, format, help, rootDir };
}
const options = parseArgs(process.argv.slice(2));
const version = resolveAndroidVersion(options.rootDir);
if (options.field) {
const value = version[options.field as keyof typeof version];
if (value === undefined) {
throw new Error(`Unknown Android version field '${options.field}'.`);
function readOptionValue(argv: string[], index: number, flag: string): string {
const value = argv[index + 1];
if (!value || value.startsWith("--")) {
throw new Error(`Missing value for ${flag}.`);
}
process.stdout.write(`${value}\n`);
process.exit(0);
return value;
}
if (options.format === "shell") {
function printUsage(): void {
process.stdout.write(
[
`OPENCLAW_ANDROID_VERSION_NAME=${version.canonicalVersion}`,
`OPENCLAW_ANDROID_VERSION_CODE=${version.versionCode}`,
].join("\n") + "\n",
"Usage: node --import tsx scripts/android-version.ts [--json|--shell] [--field name] [--root dir]\n\n",
);
} else {
process.stdout.write(`${JSON.stringify(version, null, 2)}\n`);
}
function main(argv = process.argv.slice(2)): number {
const options = parseArgs(argv);
if (options.help) {
printUsage();
return 0;
}
const version = resolveAndroidVersion(options.rootDir);
if (options.field) {
const value = version[options.field as keyof typeof version];
if (value === undefined) {
throw new Error(`Unknown Android version field '${options.field}'.`);
}
process.stdout.write(`${value}\n`);
return 0;
}
if (options.format === "shell") {
process.stdout.write(
[
`OPENCLAW_ANDROID_VERSION_NAME=${version.canonicalVersion}`,
`OPENCLAW_ANDROID_VERSION_CODE=${version.versionCode}`,
].join("\n") + "\n",
);
} else {
process.stdout.write(`${JSON.stringify(version, null, 2)}\n`);
}
return 0;
}
try {
process.exitCode = main();
} catch (error) {
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
process.exitCode = 1;
}

View File

@@ -5,19 +5,21 @@ import { resolveIosVersion } from "./lib/ios-version.ts";
type CliOptions = {
field: string | null;
format: "json" | "shell";
help: boolean;
rootDir: string;
};
function parseArgs(argv: string[]): CliOptions {
let field: string | null = null;
let format: "json" | "shell" = "json";
let help = false;
let rootDir = path.resolve(".");
for (let index = 0; index < argv.length; index += 1) {
const arg = argv[index];
switch (arg) {
case "--field": {
field = argv[index + 1] ?? null;
field = readOptionValue(argv, index, "--field");
index += 1;
break;
}
@@ -30,20 +32,15 @@ function parseArgs(argv: string[]): CliOptions {
break;
}
case "--root": {
const value = argv[index + 1];
if (!value) {
throw new Error("Missing value for --root.");
}
const value = readOptionValue(argv, index, "--root");
rootDir = path.resolve(value);
index += 1;
break;
}
case "-h":
case "--help": {
console.log(
`Usage: node --import tsx scripts/ios-version.ts [--json|--shell] [--field name] [--root dir]\n`,
);
process.exit(0);
help = true;
break;
}
default: {
throw new Error(`Unknown argument: ${arg}`);
@@ -51,29 +48,58 @@ function parseArgs(argv: string[]): CliOptions {
}
}
return { field, format, rootDir };
return { field, format, help, rootDir };
}
const options = parseArgs(process.argv.slice(2));
const version = resolveIosVersion(options.rootDir);
if (options.field) {
const value = version[options.field as keyof typeof version];
if (value === undefined) {
throw new Error(`Unknown iOS version field '${options.field}'.`);
function readOptionValue(argv: string[], index: number, flag: string): string {
const value = argv[index + 1];
if (!value || value.startsWith("--")) {
throw new Error(`Missing value for ${flag}.`);
}
process.stdout.write(`${value}\n`);
process.exit(0);
return value;
}
if (options.format === "shell") {
function printUsage(): void {
process.stdout.write(
[
`OPENCLAW_IOS_VERSION=${version.canonicalVersion}`,
`OPENCLAW_MARKETING_VERSION=${version.marketingVersion}`,
`OPENCLAW_BUILD_VERSION=${version.buildVersion}`,
].join("\n") + "\n",
"Usage: node --import tsx scripts/ios-version.ts [--json|--shell] [--field name] [--root dir]\n\n",
);
} else {
process.stdout.write(`${JSON.stringify(version, null, 2)}\n`);
}
function main(argv = process.argv.slice(2)): number {
const options = parseArgs(argv);
if (options.help) {
printUsage();
return 0;
}
const version = resolveIosVersion(options.rootDir);
if (options.field) {
const value = version[options.field as keyof typeof version];
if (value === undefined) {
throw new Error(`Unknown iOS version field '${options.field}'.`);
}
process.stdout.write(`${value}\n`);
return 0;
}
if (options.format === "shell") {
process.stdout.write(
[
`OPENCLAW_IOS_VERSION=${version.canonicalVersion}`,
`OPENCLAW_MARKETING_VERSION=${version.marketingVersion}`,
`OPENCLAW_BUILD_VERSION=${version.buildVersion}`,
].join("\n") + "\n",
);
} else {
process.stdout.write(`${JSON.stringify(version, null, 2)}\n`);
}
return 0;
}
try {
process.exitCode = main();
} catch (error) {
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
process.exitCode = 1;
}

View File

@@ -1,4 +1,5 @@
// Android Version tests cover android version script behavior.
import { spawnSync } from "node:child_process";
import path from "node:path";
import { describe, expect, it } from "vitest";
import {
@@ -20,6 +21,47 @@ import {
installAndroidFixtureCleanup();
describe("resolveAndroidVersion", () => {
it("rejects missing CLI option values before reading version files", () => {
const result = spawnSync(
process.execPath,
["--import", "tsx", "scripts/android-version.ts", "--field"],
{
cwd: process.cwd(),
encoding: "utf8",
},
);
expect(result.status).toBe(1);
expect(result.stderr).toBe("Missing value for --field.\n");
});
it("prints selected fields from the CLI", () => {
const rootDir = writeAndroidFixture({
version: "2026.6.2",
versionCode: 2026060201,
});
const result = spawnSync(
process.execPath,
[
"--import",
"tsx",
"scripts/android-version.ts",
"--root",
rootDir,
"--field",
"canonicalVersion",
],
{
cwd: process.cwd(),
encoding: "utf8",
},
);
expect(result.status).toBe(0);
expect(result.stdout).toBe("2026.6.2\n");
expect(result.stderr).toBe("");
});
it("parses pinned release versions and Android version codes", () => {
const rootDir = writeAndroidFixture({
version: "2026.6.2",

View File

@@ -1,4 +1,5 @@
// Ios Version tests cover ios version script behavior.
import { spawnSync } from "node:child_process";
import fs from "node:fs";
import path from "node:path";
import { describe, expect, it } from "vitest";
@@ -16,6 +17,47 @@ import { installIosFixtureCleanup, writeIosFixture } from "./ios-version.test-su
installIosFixtureCleanup();
describe("resolveIosVersion", () => {
it("rejects missing CLI option values before reading version files", () => {
const result = spawnSync(
process.execPath,
["--import", "tsx", "scripts/ios-version.ts", "--field"],
{
cwd: process.cwd(),
encoding: "utf8",
},
);
expect(result.status).toBe(1);
expect(result.stderr).toBe("Missing value for --field.\n");
});
it("prints selected fields from the CLI", () => {
const rootDir = writeIosFixture({
version: "2026.4.6",
changelog: "# OpenClaw iOS Changelog\n\n## 2026.4.6\n\nStable notes.\n",
});
const result = spawnSync(
process.execPath,
[
"--import",
"tsx",
"scripts/ios-version.ts",
"--root",
rootDir,
"--field",
"canonicalVersion",
],
{
cwd: process.cwd(),
encoding: "utf8",
},
);
expect(result.status).toBe(0);
expect(result.stdout).toBe("2026.4.6\n");
expect(result.stderr).toBe("");
});
it("parses pinned release versions and derives Apple marketing fields", () => {
const rootDir = writeIosFixture({
version: "2026.4.6",