import { mkdtemp, writeFile } from "node:fs/promises"; import { tmpdir } from "node:os"; import path from "node:path"; import { describe, expect, it } from "vitest"; import { parseArgs, readArtifactPackageCandidateMetadata, validateOpenClawPackageSpec, } from "../../scripts/resolve-openclaw-package-candidate.mjs"; describe("resolve-openclaw-package-candidate", () => { it("accepts only OpenClaw release package specs for npm candidates", () => { expect(() => validateOpenClawPackageSpec("openclaw@beta")).not.toThrow(); expect(() => validateOpenClawPackageSpec("openclaw@alpha")).not.toThrow(); expect(() => validateOpenClawPackageSpec("openclaw@latest")).not.toThrow(); expect(() => validateOpenClawPackageSpec("openclaw@2026.4.27")).not.toThrow(); expect(() => validateOpenClawPackageSpec("openclaw@2026.4.27-1")).not.toThrow(); expect(() => validateOpenClawPackageSpec("openclaw@2026.4.27-beta.2")).not.toThrow(); expect(() => validateOpenClawPackageSpec("openclaw@2026.4.27-alpha.2")).not.toThrow(); expect(() => validateOpenClawPackageSpec("@evil/openclaw@1.0.0")).toThrow( "package_spec must be openclaw@alpha", ); expect(() => validateOpenClawPackageSpec("openclaw@canary")).toThrow( "package_spec must be openclaw@alpha", ); expect(() => validateOpenClawPackageSpec("openclaw@2026.04.27")).toThrow( "package_spec must be openclaw@alpha", ); expect(() => validateOpenClawPackageSpec("openclaw@npm:other-package")).toThrow( "package_spec must be openclaw@alpha", ); expect(() => validateOpenClawPackageSpec("openclaw@file:../other-package.tgz")).toThrow( "package_spec must be openclaw@alpha", ); }); it("parses optional empty workflow inputs without rejecting the command line", () => { expect( parseArgs([ "--source", "npm", "--package-ref", "release/2026.4.27", "--package-spec", "openclaw@beta", "--package-url", "", "--package-sha256", "", "--artifact-dir", ".", "--output-dir", ".artifacts/docker-e2e-package", ]), ).toMatchObject({ artifactDir: ".", outputDir: ".artifacts/docker-e2e-package", packageSha256: "", packageRef: "release/2026.4.27", packageSpec: "openclaw@beta", packageUrl: "", source: "npm", }); }); it("reads package source metadata from package artifacts", async () => { const dir = await mkdtemp(path.join(tmpdir(), "openclaw-package-candidate-")); await writeFile( path.join(dir, "package-candidate.json"), JSON.stringify( { packageRef: "release/2026.4.30", packageSourceSha: "66ce632b9b7c5c7fdd3e66c739687d51638ad6e2", packageTrustedReason: "repository-branch-history", sha256: "a".repeat(64), }, null, 2, ), ); await expect(readArtifactPackageCandidateMetadata(dir)).resolves.toMatchObject({ packageRef: "release/2026.4.30", packageSourceSha: "66ce632b9b7c5c7fdd3e66c739687d51638ad6e2", packageTrustedReason: "repository-branch-history", sha256: "a".repeat(64), }); }); });