blob: fa7f2ee40332c8a4bdf603806aaab29f655892df [file]
/*!
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { spawnSync } from "node:child_process";
import { mkdtempSync, readFileSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import process from "node:process";
import { fileURLToPath } from "node:url";
import { describe, expect, it } from "vitest";
import { validateReleaseInputs } from "./validate-release-inputs.mjs";
describe("validateReleaseInputs", () => {
it("accepts stable and prerelease channels", () => {
expect(validateReleaseInputs({ releaseTag: "ts-sdk/1.0.0", npmTag: "latest" })).toEqual({
version: "1.0.0",
packageName: "apache-airflow-ts-sdk",
packageFile: "apache-airflow-ts-sdk-1.0.0.tgz",
});
expect(
validateReleaseInputs({ releaseTag: "ts-sdk/1.0.0-beta1", npmTag: "beta" }).version,
).toBe("1.0.0-beta1");
expect(
validateReleaseInputs({ releaseTag: "ts-sdk/1.0.0-beta.2", npmTag: "next" }).version,
).toBe("1.0.0-beta.2");
expect(validateReleaseInputs({ releaseTag: "ts-sdk/1.0.0-rc-1", npmTag: "rc" }).version).toBe(
"1.0.0-rc-1",
);
});
it("rejects invalid versions", () => {
for (const releaseTag of ["1.0.0", "ts-sdk/01.0.0", "ts-sdk/1.0.0-01", "ts-sdk/1.0"]) {
expect(() => validateReleaseInputs({ releaseTag, npmTag: "latest" })).toThrow(
/Release tag|not valid SemVer/,
);
}
});
it("rejects mismatched npm tags", () => {
expect(() => validateReleaseInputs({ releaseTag: "ts-sdk/1.0.0", npmTag: "beta" })).toThrow(
/Stable releases must use the latest/,
);
expect(() =>
validateReleaseInputs({ releaseTag: "ts-sdk/1.0.0-beta1", npmTag: "latest" }),
).toThrow(/must use the beta or next/);
expect(() =>
validateReleaseInputs({ releaseTag: "ts-sdk/1.0.0-beta1", npmTag: "alpha" }),
).toThrow(/must use the beta or next/);
});
it("rejects a numeric-only prerelease identifier without duplicating the next dist-tag", () => {
expect(() => validateReleaseInputs({ releaseTag: "ts-sdk/1.0.0-0", npmTag: "beta" })).toThrow(
"Prerelease 1.0.0-0 must use the next npm dist-tag",
);
});
it("rejects a next-channel prerelease without duplicating the next dist-tag", () => {
expect(() =>
validateReleaseInputs({ releaseTag: "ts-sdk/1.0.0-next1", npmTag: "beta" }),
).toThrow("Prerelease 1.0.0-next1 must use the next npm dist-tag");
});
it("rejects malformed npm tags", () => {
for (const npmTag of ["", "1.0.0", "Beta", "bad tag", "-beta"]) {
expect(() => validateReleaseInputs({ releaseTag: "ts-sdk/1.0.0-beta1", npmTag })).toThrow(
/npm tag|must use/,
);
}
});
it("requires a release to advance the selected dist-tag", () => {
expect(
validateReleaseInputs({
releaseTag: "ts-sdk/1.0.0-beta.2",
npmTag: "beta",
currentDistTagVersion: "1.0.0-beta.1",
}).version,
).toBe("1.0.0-beta.2");
for (const releaseTag of ["ts-sdk/1.0.0-beta.1", "ts-sdk/1.0.0-beta.0"]) {
expect(() =>
validateReleaseInputs({
releaseTag,
npmTag: "beta",
currentDistTagVersion: "1.0.0-beta.1",
}),
).toThrow(/must be newer/);
}
});
it("writes GitHub Actions outputs when run as a command", () => {
const tempDirectory = mkdtempSync(join(tmpdir(), "ts-sdk-release-inputs-"));
const outputFile = join(tempDirectory, "github-output");
try {
const result = spawnSync(
process.execPath,
[fileURLToPath(import.meta.resolve("./validate-release-inputs.mjs"))],
{
encoding: "utf8",
env: {
...process.env,
GITHUB_OUTPUT: outputFile,
NPM_TAG: "beta",
RELEASE_TAG: "ts-sdk/1.0.0-beta1",
},
},
);
expect(result.status, result.stderr).toBe(0);
expect(readFileSync(outputFile, "utf8")).toBe(
"version=1.0.0-beta1\npackage_name=apache-airflow-ts-sdk\n" +
"package_file=apache-airflow-ts-sdk-1.0.0-beta1.tgz\n",
);
} finally {
rmSync(tempDirectory, { force: true, recursive: true });
}
});
});