fix(install): preserve user fleet data on re-seed + refresh active units (CRITICAL) (#632)
Co-authored-by: Jason Woltje <jason@diversecanvas.com> Co-committed-by: Jason Woltje <jason@diversecanvas.com>
This commit was merged in pull request #632.
This commit is contained in:
@@ -14,7 +14,14 @@
|
||||
*/
|
||||
|
||||
import { execSync } from 'node:child_process';
|
||||
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
||||
import {
|
||||
existsSync,
|
||||
mkdirSync,
|
||||
readFileSync,
|
||||
writeFileSync,
|
||||
readdirSync,
|
||||
copyFileSync,
|
||||
} from 'node:fs';
|
||||
import { homedir } from 'node:os';
|
||||
import { dirname, join, resolve } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
@@ -536,6 +543,47 @@ export function readRosterAgentNames(mosaicHome = join(homedir(), '.config', 'mo
|
||||
return names;
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the ACTIVE systemd user units from the freshly re-seeded copies.
|
||||
*
|
||||
* The re-seed updates `~/.config/mosaic/systemd/user/*.service`, but the units
|
||||
* systemd actually runs live at `~/.config/systemd/user/`. Without this copy,
|
||||
* shipped unit fixes (e.g. the socket-env change) never take effect after
|
||||
* `mosaic update` until `mosaic fleet install` is re-run. Best-effort + scoped:
|
||||
* only refreshes when a fleet is already installed (the active dir already
|
||||
* carries `mosaic-*` units), so non-fleet hosts are untouched.
|
||||
*/
|
||||
export function refreshActiveFleetUnits(
|
||||
mosaicHome = join(homedir(), '.config', 'mosaic'),
|
||||
env: NodeJS.ProcessEnv = process.env,
|
||||
): { refreshed: string[]; ok: boolean; reason?: string } {
|
||||
const src = join(mosaicHome, 'systemd', 'user');
|
||||
const configHome = env['XDG_CONFIG_HOME'] ?? join(homedir(), '.config');
|
||||
const dest = join(configHome, 'systemd', 'user');
|
||||
if (!existsSync(src)) return { refreshed: [], ok: true };
|
||||
// Only refresh when a fleet is already installed (active dir has mosaic units).
|
||||
const fleetInstalled =
|
||||
existsSync(dest) &&
|
||||
readdirSync(dest).some((f) => f.startsWith('mosaic-') && f.endsWith('.service'));
|
||||
if (!fleetInstalled) return { refreshed: [], ok: true };
|
||||
const units = readdirSync(src).filter((f) => f.startsWith('mosaic-') && f.endsWith('.service'));
|
||||
const refreshed: string[] = [];
|
||||
for (const unit of units) {
|
||||
try {
|
||||
copyFileSync(join(src, unit), join(dest, unit));
|
||||
refreshed.push(unit);
|
||||
} catch {
|
||||
// best-effort per unit
|
||||
}
|
||||
}
|
||||
try {
|
||||
execSync('systemctl --user daemon-reload', { stdio: 'ignore', timeout: 15_000 });
|
||||
} catch {
|
||||
// non-systemd host or no session bus — non-fatal
|
||||
}
|
||||
return { refreshed, ok: true };
|
||||
}
|
||||
|
||||
/** Build the per-agent systemd relaunch commands (drain+relaunch via restart). */
|
||||
export function buildRelaunchCommands(agentNames: string[]): string[][] {
|
||||
return agentNames.map((name) => [
|
||||
|
||||
Reference in New Issue
Block a user