Files
dokploy-deploy-action/test/core.test.js
Max Vojtkov c23b44983b Deploy Dokploy applications from GitHub and Gitea Actions
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.
2026-08-09 03:37:35 +03:00

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");
});