A dependency-free node20 action that triggers application.deploy or compose.deploy, then follows the deployment to a terminal status so a failed build fails the CI run. Snapshots the deployment list before triggering, so a concurrent deployment is never mistaken for this one. Optionally points the application at a freshly built image first, which is what lets a workflow lint, test, push and deploy the same artifact.
81 lines
3.4 KiB
JavaScript
81 lines
3.4 KiB
JavaScript
"use strict";
|
|
|
|
const test = require("node:test");
|
|
const assert = require("node:assert/strict");
|
|
const fs = require("node:fs");
|
|
const os = require("node:os");
|
|
const path = require("node:path");
|
|
|
|
const core = require("../src/core");
|
|
|
|
function withEnv(vars, body) {
|
|
const saved = { ...process.env };
|
|
Object.assign(process.env, vars);
|
|
try {
|
|
return body();
|
|
} finally {
|
|
process.env = saved;
|
|
}
|
|
}
|
|
|
|
test("inputs come from INPUT_* with spaces folded to underscores", () => {
|
|
withEnv({ INPUT_DOCKER_IMAGE: " ghcr.io/acme/api:1 " }, () => {
|
|
assert.equal(core.getInput("docker-image"), "");
|
|
assert.equal(core.getInput("docker image"), "ghcr.io/acme/api:1");
|
|
});
|
|
});
|
|
|
|
test("an unset input falls back to its environment variable, then its default", () => {
|
|
withEnv({ INPUT_HOST: "", DOKPLOY_HOST: "https://dokploy.example.com" }, () => {
|
|
assert.equal(core.getInput("host", { fallbackEnv: "DOKPLOY_HOST" }), "https://dokploy.example.com");
|
|
});
|
|
withEnv({ INPUT_HOST: "https://explicit.example.com", DOKPLOY_HOST: "https://env.example.com" }, () => {
|
|
assert.equal(core.getInput("host", { fallbackEnv: "DOKPLOY_HOST" }), "https://explicit.example.com");
|
|
});
|
|
withEnv({}, () => {
|
|
assert.equal(core.getInput("title", { fallback: "CI deploy" }), "CI deploy");
|
|
assert.throws(() => core.getInput("api-key", { required: true }), /`api-key` is required/);
|
|
});
|
|
});
|
|
|
|
test("boolean inputs accept the usual spellings and reject the rest", () => {
|
|
withEnv({ INPUT_WAIT: "TRUE" }, () => assert.equal(core.getBooleanInput("wait", false), true));
|
|
withEnv({ INPUT_WAIT: "no" }, () => assert.equal(core.getBooleanInput("wait", true), false));
|
|
withEnv({ INPUT_WAIT: "" }, () => assert.equal(core.getBooleanInput("wait", true), true));
|
|
withEnv({ INPUT_WAIT: "maybe" }, () => assert.throws(() => core.getBooleanInput("wait"), /must be a boolean/));
|
|
});
|
|
|
|
test("number inputs reject anything that is not a non-negative number", () => {
|
|
withEnv({ INPUT_TIMEOUT: "900" }, () => assert.equal(core.getNumberInput("timeout", 600), 900));
|
|
withEnv({ INPUT_TIMEOUT: "" }, () => assert.equal(core.getNumberInput("timeout", 600), 600));
|
|
withEnv({ INPUT_TIMEOUT: "-1" }, () => assert.throws(() => core.getNumberInput("timeout", 600), /non-negative/));
|
|
withEnv({ INPUT_TIMEOUT: "soon" }, () => assert.throws(() => core.getNumberInput("timeout", 600), /non-negative/));
|
|
});
|
|
|
|
test("choice inputs name the alternatives when they are wrong", () => {
|
|
withEnv({ INPUT_ACTION: "REDEPLOY" }, () =>
|
|
assert.equal(core.getChoiceInput("action", ["deploy", "redeploy"], "deploy"), "redeploy"),
|
|
);
|
|
withEnv({ INPUT_ACTION: "restart" }, () =>
|
|
assert.throws(() => core.getChoiceInput("action", ["deploy", "redeploy"], "deploy"), /must be one of deploy, redeploy/),
|
|
);
|
|
});
|
|
|
|
test("multi-line outputs survive the heredoc encoding", () => {
|
|
const file = path.join(fs.mkdtempSync(path.join(os.tmpdir(), "dokploy-action-")), "output");
|
|
fs.writeFileSync(file, "");
|
|
|
|
withEnv({ GITHUB_OUTPUT: file }, () => {
|
|
core.setOutput("status", "done");
|
|
core.setOutput("logs", "line one\nline two");
|
|
});
|
|
|
|
const written = fs.readFileSync(file, "utf8");
|
|
assert.match(written, /^status<<ghadelimiter_[0-9a-f-]+\ndone\nghadelimiter_[0-9a-f-]+\n/);
|
|
assert.match(written, /logs<<ghadelimiter_[0-9a-f-]+\nline one\nline two\nghadelimiter_/);
|
|
});
|
|
|
|
test("workflow command payloads are escaped", () => {
|
|
assert.equal(core.escapeData("100% done\nnext"), "100%25 done%0Anext");
|
|
});
|