A manual run with an empty tag input failed validation. It now uses the checked-out commit's short SHA, and the workflow input is optional. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
70 lines
2.3 KiB
JavaScript
70 lines
2.3 KiB
JavaScript
import { appendFileSync } from "node:fs";
|
|
import { execFileSync } from "node:child_process";
|
|
import { pathToFileURL } from "node:url";
|
|
|
|
/** Keep manual test builds out of the production channel. */
|
|
export function imagePublication({ event, ref, inputTag, revision }) {
|
|
if (!/^[0-9a-f]{40}$/.test(revision))
|
|
throw new Error("Expected the full SHA-1 of the checked-out commit.");
|
|
|
|
let tag, channel;
|
|
if (event === "workflow_dispatch") {
|
|
tag = inputTag || `dev-${revision.slice(0, 7)}`;
|
|
const commit = /^dev-([0-9a-f]{7,40})$/.exec(tag)?.[1];
|
|
if (!commit || tag !== tag.trim())
|
|
throw new Error(
|
|
"Manual image tags must be dev-<commit SHA> (7-40 lowercase hex characters).",
|
|
);
|
|
if (!revision.startsWith(commit))
|
|
throw new Error(
|
|
"The dev tag does not match the checked-out commit. Select the matching source branch or Git tag.",
|
|
);
|
|
channel = "dev";
|
|
} else if (event === "push" && ref?.startsWith("refs/tags/")) {
|
|
tag = ref.slice("refs/tags/".length);
|
|
if (
|
|
!/^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/.test(tag) ||
|
|
tag.length > 128 ||
|
|
tag !== tag.trim()
|
|
)
|
|
throw new Error(
|
|
"Production requires a stable Git version tag: vMAJOR.MINOR.PATCH or MAJOR.MINOR.PATCH.",
|
|
);
|
|
channel = "prod";
|
|
} else {
|
|
throw new Error(
|
|
"Image publication requires a version tag push or a manual dev build.",
|
|
);
|
|
}
|
|
return { tag, channel, revision };
|
|
}
|
|
|
|
if (
|
|
process.argv[1] &&
|
|
import.meta.url === pathToFileURL(process.argv[1]).href
|
|
) {
|
|
const env = process.env;
|
|
const revision = execFileSync("git", ["rev-parse", "HEAD"], {
|
|
encoding: "utf8",
|
|
}).trim();
|
|
const publication = imagePublication({
|
|
event: env.EVENT_NAME,
|
|
ref: env.GIT_REF,
|
|
inputTag: env.INPUT_TAG,
|
|
revision,
|
|
});
|
|
const registry = new URL(env.SERVER_URL).host;
|
|
const image = `${registry}/${env.REPOSITORY.toLowerCase()}`;
|
|
const source = `${env.SERVER_URL.replace(/\/$/, "")}/${env.REPOSITORY}`;
|
|
const outputs = { registry, image, source, ...publication };
|
|
appendFileSync(
|
|
env.GITHUB_OUTPUT,
|
|
Object.entries(outputs)
|
|
.map(([key, value]) => `${key}=${value}\n`)
|
|
.join(""),
|
|
);
|
|
console.log(
|
|
`Publishing ${image}:${publication.tag} and :${publication.channel} from ${revision}`,
|
|
);
|
|
}
|