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.
This commit is contained in:
78
test/helpers.js
Normal file
78
test/helpers.js
Normal file
@@ -0,0 +1,78 @@
|
||||
"use strict";
|
||||
|
||||
/** A DokployClient stand-in that records calls and replays canned answers. */
|
||||
class FakeApi {
|
||||
/**
|
||||
* @param {object} handlers Procedure name -> value, or (input, call) => value.
|
||||
* A value may be a function returning a promise, or an array consumed one
|
||||
* entry per call so a poller can see a status change.
|
||||
*/
|
||||
constructor(handlers = {}) {
|
||||
this.handlers = handlers;
|
||||
this.calls = [];
|
||||
this.counts = {};
|
||||
}
|
||||
|
||||
#dispatch(kind, procedure, input) {
|
||||
this.calls.push({ kind, procedure, input });
|
||||
const index = (this.counts[procedure] = (this.counts[procedure] ?? 0) + 1) - 1;
|
||||
|
||||
if (!(procedure in this.handlers)) {
|
||||
throw new Error(`FakeApi: unexpected ${kind} ${procedure}`);
|
||||
}
|
||||
const handler = this.handlers[procedure];
|
||||
if (typeof handler === "function") return Promise.resolve(handler(input, index));
|
||||
if (Array.isArray(handler) && handler.__sequence) {
|
||||
return Promise.resolve(handler[Math.min(index, handler.length - 1)]);
|
||||
}
|
||||
return Promise.resolve(handler);
|
||||
}
|
||||
|
||||
query(procedure, input) {
|
||||
return this.#dispatch("query", procedure, input);
|
||||
}
|
||||
|
||||
mutate(procedure, input) {
|
||||
return this.#dispatch("mutate", procedure, input);
|
||||
}
|
||||
|
||||
procedures() {
|
||||
return this.calls.map((call) => call.procedure);
|
||||
}
|
||||
|
||||
find(procedure) {
|
||||
return this.calls.find((call) => call.procedure === procedure);
|
||||
}
|
||||
}
|
||||
|
||||
/** Marks an array as "one entry per call" rather than a literal return value. */
|
||||
function sequence(values) {
|
||||
const copy = [...values];
|
||||
copy.__sequence = true;
|
||||
return copy;
|
||||
}
|
||||
|
||||
/** A clock that only moves when something sleeps, so tests never really wait. */
|
||||
function fakeClock(start = 0) {
|
||||
let current = start;
|
||||
return {
|
||||
now: () => current,
|
||||
sleep: async (ms) => {
|
||||
current += Math.max(ms, 1);
|
||||
},
|
||||
advance: (ms) => {
|
||||
current += ms;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function collectingLog() {
|
||||
const lines = [];
|
||||
return {
|
||||
lines,
|
||||
info: (message) => lines.push(`info: ${message}`),
|
||||
warning: (message) => lines.push(`warning: ${message}`),
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = { FakeApi, sequence, fakeClock, collectingLog };
|
||||
Reference in New Issue
Block a user