fix(cms): detach and audit the publish-triggered deploy (systemd-safe)
CI Pipeline with Test Management / 🧪 Run Tests & Generate Reports (push) Waiting to run
CI Pipeline with Test Management / 🐳 Docker Integration Tests (push) Blocked by required conditions
CI Pipeline with Test Management / 🏗️ Build Docker Image (push) Blocked by required conditions
CI Pipeline with Test Management / 📊 Generate Test Summary (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / 🧪 Run Tests & Generate Reports (push) Waiting to run
Test Reporting & Gherkin Analysis / 📊 Analyze Test Coverage (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / 🔄 Sync with Linear (push) Blocked by required conditions
Test Reporting & Gherkin Analysis / ⚡ Performance Monitoring (push) Blocked by required conditions

A CMS publish's background deploy silently never ran under systemd
(naive 'cmd &' child died with the spawning shell; no log, no trace —
the site kept serving stale content). The spawn now uses
setsid+nohup+stdin-null so it survives any parent exit, and writes
deploy_spawned / deploy_exec_exit audit entries so a failed spawn can
never be silent again.

Closes MITHOME-72
This commit is contained in:
Do Siki
2026-08-19 15:16:19 +02:00
parent 219f5122bd
commit a29a1f461b
+14 -2
View File
@@ -305,9 +305,21 @@ const server = http.createServer(async (req, res) => {
// trigger a rebuild. Deploy only the explicitly configured environment; // trigger a rebuild. Deploy only the explicitly configured environment;
// never default to production. Overridable for tests. // never default to production. Overridable for tests.
if (outcome.hadChanges) { if (outcome.hadChanges) {
// WHY setsid+nohup+stdin-null: under systemd the naive `cmd &` child died
// together with the spawning shell (observed: the deploy never ran after a
// CMS publish, leaving the site on stale content). Full detachment makes it
// survive; the audit entries make the spawn observable instead of silent.
const deployCmd = process.env.CONTENT_EDITOR_DEPLOY_CMD const deployCmd = process.env.CONTENT_EDITOR_DEPLOY_CMD
|| `cd ../../../ && ./deploy.sh ${CMS_DEPLOY_ENV} > deploy.log 2>&1 &`; || `cd ../../../ && setsid nohup ./deploy.sh ${CMS_DEPLOY_ENV} > deploy.log 2>&1 < /dev/null &`;
exec(deployCmd); writeAudit('deploy_spawned', { clientAddress, user: CMS_USER, env: CMS_DEPLOY_ENV });
exec(deployCmd, deployError => {
writeAudit('deploy_exec_exit', {
clientAddress,
user: CMS_USER,
result: deployError ? 'error' : 'shell_exited',
error: deployError ? String(deployError.message).slice(0, 300) : undefined,
});
});
} }
res.end(JSON.stringify({ ok: true, output: outcome.output })); res.end(JSON.stringify({ ok: true, output: outcome.output }));
}); });