openvibers/openvibe.host Commits

deploy --install-units on a service already at its target installs unit files that differ, and restarts nothing (#146)

OP OpenVibers committed 21 days ago · dccb16083c · 3 files, +25 −0

Changes

ddiff --git a/README.md b/README.md
iindex 084ead8..43726de 100644
---- a/README.md
++++ b/README.md
@@@ -233,6 +233,7 @@ Counts only, never a row about a person. A database that does not answer prints
1. Take the per-service lock. A `release-layout` service goes to its own engine ([docs/deploy-strategies.md](docs/deploy-strategies.md#release-layout-release-layout)); an in-place strategy refuses a checkout that has a `releases/current` layout.
2. `git fetch` as the owner, then work out the from/to shas, changed files, per-package install need and whether a restart is needed (`noRestartPaths`).
++ Already at the target: nothing happens, except that `--install-units` still installs unit files that differ from the checkout (result `units-installed`, nothing restarted; in-place strategies).
3. Refuse a tracked local change or a wrong branch.
4. **Protected sessions** (only if a restart is needed): refuse, wait (`--wait-idle` or drain policy `wait`), report (drain policy `report`, Events SSE), or `--force`.
5. `git merge --ff-only` as the owner (rollback uses `git reset --hard <sha>`).
ddiff --git a/lib/release-ops.js b/lib/release-ops.js
iindex 6b26923..ea33447 100644
---- a/lib/release-ops.js
++++ b/lib/release-ops.js
@@@ -470,6 +470,14 @@ async function apply(ctx, svc, mode, opts = {}) {
if (plan.branch !== svc.branch) throw new OpError(`${svc.repo} is on "${plan.branch}", expected "${svc.branch}"`, EXIT.USAGE);
if (plan.dirty.length) throw new OpError(`${svc.repo} has tracked local changes (${plan.dirty.slice(0, 5).join(', ')}${plan.dirty.length > 5 ? ', …' : ''}); commit or discard them first`, EXIT.VALIDATION);
if (plan.upToDate && !opts.restart) {
++ // --install-units still installs unit files that differ (say a drop-in the inventory gained after the
++ // commit that carries it was deployed); nothing restarts for it.
++ if (opts.installUnits && plan.unitDrift.length && mode === 'deploy') {
++ await installUnits(ctx, svc, record);
++ log(`already at ${plan.to.slice(0, 12)}; installed unit files only, nothing restarted`);
++ record.result = 'units-installed';
++ return { exitCode: EXIT.OK, record, plan };
++ }
log(`already at ${plan.to.slice(0, 12)}; nothing to do`);
record.result = 'unchanged';
writeRecord = false;
ddiff --git a/test/strategy-in-place.test.js b/test/strategy-in-place.test.js
iindex 5eaa48c..0316cd7 100644
---- a/test/strategy-in-place.test.js
++++ b/test/strategy-in-place.test.js
@@@ -508,6 +508,22 @@ runTests([
assert.strictEqual((await lastRecord(host, 'network')).strategy, 'git-checkout');
}),
++ test('--install-units on a service already at its target installs drifted unit files and restarts nothing', async () => {
++ const host = networkHost();
++ host.put('/etc/systemd/system/openvibe-network.service', '[Service]\nExecStart=node old.js\n');
++ const r = await host.cli('deploy', 'network', '--install-units');
++ assert.strictEqual(r.code, 0, r.out);
++ assert.match(r.out, /installed unit files only, nothing restarted/);
++ assert.strictEqual(host.read('/etc/systemd/system/openvibe-network.service'), '[Service]\nExecStart=node server/index.js\n');
++ assert.deepStrictEqual(host.restarts(), []);
++ const rec = await lastRecord(host, 'network');
++ assert.strictEqual(rec.result, 'units-installed');
++ assert.deepStrictEqual(rec.unitsInstalled, ['openvibe-network.service']);
++ // Without the flag, or with nothing to install, an up-to-date deploy still does nothing.
++ const again = await host.cli('deploy', 'network', '--install-units');
++ assert.match(again.out, /nothing to do/);
++ }),
++
test('unit bootstrap enables an installed service before its first restart', async () => {
const host = networkHost();
const raw = JSON.parse(host.read('/etc/openvibe/host.json'));