mirror of
https://github.com/dtzp555-max/ocp.git
synced 2026-07-19 09:44:07 +00:00
fix(setup): preserve user-customised plist/systemd env vars on re-setup (#90)
* fix(setup): merge plist/systemd env vars instead of overwriting
setup.mjs previously wrote the launchd plist and the Linux systemd unit
with writeFileSync(path, NEW_TEMPLATE_STRING), which silently dropped any
user-customised env vars (CLAUDE_HEARTBEAT_INTERVAL, CLAUDE_CACHE_TTL,
etc.) on every re-setup or upgrade. This change introduces
scripts/lib/plist-merge.mjs which preserves keys present only in the
existing file and lets the template's known keys win. Linux variant uses
the same logic against Environment=KEY=VALUE lines.
Tests added in test-features.mjs cover preserve / override / first-install
for both formats.
No cli.js citation needed: this is OCP-internal installer behaviour with
no corresponding cli.js operation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(setup): plist-merge code-quality follow-up
Three issues raised by the code-quality reviewer on 0fd1838:
1. mergeSystemdEnv now early-returns when the template has no
Environment= anchor, instead of silently dropping preserved lines
(defensive guard for a future template change).
2. Both parsers (parsePlistEnv, parseSystemdEnv) now Buffer-normalise
their input, removing the TypeError-vs-coerce asymmetry.
3. Two idempotency tests added (calling merge twice on the same
input/output pair must be stable).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: dtzp555 <dtzp555@gmail.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
* 5. Optionally starts the proxy
|
||||
*/
|
||||
import { readFileSync, writeFileSync, existsSync, mkdirSync, unlinkSync, readdirSync, chmodSync } from "node:fs";
|
||||
import { mergePlistEnv, mergeSystemdEnv } from "./scripts/lib/plist-merge.mjs";
|
||||
import { execSync } from "node:child_process";
|
||||
import { join, dirname } from "node:path";
|
||||
import { homedir } from "node:os";
|
||||
@@ -424,9 +425,15 @@ if (!DRY_RUN) {
|
||||
</plist>
|
||||
`;
|
||||
|
||||
writeFileSync(plistPath, plistXml);
|
||||
const existingPlist = existsSync(plistPath) ? readFileSync(plistPath, "utf8") : null;
|
||||
const finalPlistXml = mergePlistEnv(existingPlist, plistXml);
|
||||
writeFileSync(plistPath, finalPlistXml);
|
||||
chmodSync(plistPath, 0o600);
|
||||
log(`Plist written: ${plistPath} (mode 600)`);
|
||||
if (existingPlist && finalPlistXml !== plistXml) {
|
||||
log(`Plist written: ${plistPath} (mode 600, preserved user env vars)`);
|
||||
} else {
|
||||
log(`Plist written: ${plistPath} (mode 600)`);
|
||||
}
|
||||
|
||||
// Bootout first (in case it was already loaded) then bootstrap
|
||||
try { execSync(`launchctl bootout gui/$(id -u) "${plistPath}" 2>/dev/null`); } catch { /* ignore */ }
|
||||
@@ -459,9 +466,15 @@ StandardError=append:${logPath}
|
||||
WantedBy=default.target
|
||||
`;
|
||||
|
||||
writeFileSync(servicePath, serviceUnit);
|
||||
const existingService = existsSync(servicePath) ? readFileSync(servicePath, "utf8") : null;
|
||||
const finalServiceUnit = mergeSystemdEnv(existingService, serviceUnit);
|
||||
writeFileSync(servicePath, finalServiceUnit);
|
||||
chmodSync(servicePath, 0o600);
|
||||
log(`Service file written: ${servicePath} (mode 600)`);
|
||||
if (existingService && finalServiceUnit !== serviceUnit) {
|
||||
log(`Service file written: ${servicePath} (mode 600, preserved user env vars)`);
|
||||
} else {
|
||||
log(`Service file written: ${servicePath} (mode 600)`);
|
||||
}
|
||||
|
||||
execSync(`systemctl --user daemon-reload`);
|
||||
execSync(`systemctl --user enable ocp-proxy`);
|
||||
|
||||
Reference in New Issue
Block a user