fix: sync scoped ssh runtime deploy env

This commit is contained in:
Codex
2026-06-02 08:40:58 +00:00
parent 5dba1a06be
commit 7de9782dc2
4 changed files with 55 additions and 1 deletions
+8
View File
@@ -17,6 +17,7 @@ import {
type DeployJsonServiceContract,
} from "./deploy-json-contract";
import { d601K3sGuardShellLines } from "./d601-k3s-guard";
import { composeRuntimeEnvValue } from "./runtime-env";
export type ArtifactRegistryAction = "plan" | "render" | "status" | "health" | "install" | "deploy-backend-core" | "deploy-service";
type ArtifactDeployEnvironment = "prod" | "dev";
@@ -1676,6 +1677,8 @@ function downloadRemoteFile(options: ArtifactRegistryOptions, remotePath: string
"ssh",
options.providerId,
"download",
"--chunk-bytes",
"96000",
remotePath,
localPath,
], repoRoot, { timeoutMs });
@@ -2455,13 +2458,18 @@ function verifyLocalArtifactLabels(
}
function d601DevFrontendAuthPatchScript(config: UniDeskConfig): string {
const sshClientToken = composeRuntimeEnvValue("UNIDESK_SSH_CLIENT_TOKEN");
if (sshClientToken === null) throw new Error("UNIDESK_SSH_CLIENT_TOKEN must be present in .state/docker-compose.env before deploying dev frontend");
const sshClientRouteAllowlist = composeRuntimeEnvValue("UNIDESK_SSH_CLIENT_ROUTE_ALLOWLIST") ?? "G14,G14:*,D601,D601:*";
const secretData = {
AUTH_USERNAME: base64(config.auth.username),
AUTH_PASSWORD: base64(config.auth.password),
SESSION_SECRET: base64(config.auth.sessionSecret),
UNIDESK_SSH_CLIENT_TOKEN: base64(sshClientToken),
};
const configData = {
SESSION_TTL_SECONDS: String(config.auth.sessionTtlSeconds),
UNIDESK_SSH_CLIENT_ROUTE_ALLOWLIST: sshClientRouteAllowlist,
};
return [
d601K3sGuardScript(),
+6
View File
@@ -10,6 +10,7 @@ import { startJob } from "./jobs";
import { coreInternalFetch } from "./microservices";
import { codeQueueSourceImportPreflight, codeQueueSourceSubdir } from "./code-queue-source-guard";
import { d601K3sGuardShellLines, d601NativeKubeconfig } from "./d601-k3s-guard";
import { composeRuntimeEnvValue } from "./runtime-env";
import {
compareDeployJsonExecutorMirrors,
deployJsonCommitImage,
@@ -1513,13 +1514,18 @@ function devK3sPrepullImages(service: UniDeskMicroserviceConfig): string[] {
}
function syncDevFrontendAuthScript(config: UniDeskConfig): string {
const sshClientToken = composeRuntimeEnvValue("UNIDESK_SSH_CLIENT_TOKEN");
if (sshClientToken === null) throw new Error("UNIDESK_SSH_CLIENT_TOKEN must be present in .state/docker-compose.env before deploying dev frontend");
const sshClientRouteAllowlist = composeRuntimeEnvValue("UNIDESK_SSH_CLIENT_ROUTE_ALLOWLIST") ?? "G14,G14:*,D601,D601:*";
const data = {
AUTH_USERNAME: Buffer.from(config.auth.username, "utf8").toString("base64"),
AUTH_PASSWORD: Buffer.from(config.auth.password, "utf8").toString("base64"),
SESSION_SECRET: Buffer.from(config.auth.sessionSecret, "utf8").toString("base64"),
UNIDESK_SSH_CLIENT_TOKEN: Buffer.from(sshClientToken, "utf8").toString("base64"),
};
const runtimeConfig = {
SESSION_TTL_SECONDS: String(config.auth.sessionTtlSeconds),
UNIDESK_SSH_CLIENT_ROUTE_ALLOWLIST: sshClientRouteAllowlist,
};
return [
"set -euo pipefail",
+36
View File
@@ -0,0 +1,36 @@
import { existsSync, readFileSync } from "node:fs";
import { rootPath } from "./config";
export function canonicalComposeEnvFile(): string {
return rootPath(".state", "docker-compose.env");
}
function unquoteEnvValue(value: string): string {
const trimmed = value.trim();
if (trimmed.length < 2) return trimmed;
const first = trimmed[0];
const last = trimmed[trimmed.length - 1];
if ((first !== "\"" && first !== "'") || last !== first) return trimmed;
return trimmed.slice(1, -1);
}
export function readEnvFileValues(path: string): Map<string, string> {
const values = new Map<string, string>();
if (!existsSync(path)) return values;
for (const line of readFileSync(path, "utf8").split(/\r?\n/u)) {
if (line.trim().length === 0 || line.trimStart().startsWith("#")) continue;
const index = line.indexOf("=");
if (index <= 0) continue;
const key = line.slice(0, index).trim();
if (!/^[A-Za-z_][A-Za-z0-9_]*$/u.test(key)) continue;
values.set(key, unquoteEnvValue(line.slice(index + 1)));
}
return values;
}
export function composeRuntimeEnvValue(key: string, env: NodeJS.ProcessEnv = process.env): string | null {
const fromProcess = env[key]?.trim();
if (fromProcess !== undefined && fromProcess.length > 0) return fromProcess;
const fromFile = readEnvFileValues(canonicalComposeEnvFile()).get(key)?.trim();
return fromFile === undefined || fromFile.length === 0 ? null : fromFile;
}