refactor: share platform secret source helpers

This commit is contained in:
Codex
2026-06-14 02:21:35 +00:00
parent 5a5002f42c
commit 4ebadadfeb
3 changed files with 87 additions and 155 deletions
+39 -2
View File
@@ -98,6 +98,14 @@ interface DesiredSecret {
fingerprint: string | null;
}
export interface EnvSourceFileMaterial {
sourceRef: string;
sourcePath: string;
sourcePathRedacted: string;
values: Record<string, string>;
valuesPrinted: false;
}
export function secretsHelp(): Record<string, unknown> {
return {
command: "secrets plan|sync|status",
@@ -673,7 +681,26 @@ function secretRoot(config: SecretDistributionConfig): string {
return isAbsolute(root) ? root : rootPath(root);
}
function parseEnvFile(text: string): Record<string, string> {
export function readTextFile(path: string): string {
if (!existsSync(path)) throw new Error(`required secret source ${redactRepoPath(path)} is missing`);
return readFileSync(path, "utf8");
}
export function readEnvSourceFile(params: { root: string; sourceRef: string; missingMessage?: (sourcePath: string) => string }): EnvSourceFileMaterial {
const sourcePath = join(params.root, params.sourceRef);
if (!existsSync(sourcePath)) {
throw new Error(params.missingMessage?.(sourcePath) ?? `required secret source ${redactRepoPath(sourcePath)} is missing`);
}
return {
sourceRef: params.sourceRef,
sourcePath,
sourcePathRedacted: redactRepoPath(sourcePath),
values: parseEnvFile(readFileSync(sourcePath, "utf8")),
valuesPrinted: false,
};
}
export function parseEnvFile(text: string): Record<string, string> {
const result: Record<string, string> = {};
for (const rawLine of text.split(/\r?\n/u)) {
const line = rawLine.trim();
@@ -692,6 +719,16 @@ function unquoteEnvValue(value: string): string {
return value;
}
export function requiredEnvValue(values: Record<string, string>, key: string, sourceRef: string): string {
const value = values[key];
if (value === undefined || value.length === 0) throw new Error(`${sourceRef} is missing required key ${key}`);
return value;
}
export function fingerprintSecretValues(values: Record<string, string>, keys: string[]): string {
return fingerprintValues(values, keys);
}
function writeEnvFile(path: string, values: Record<string, string>): void {
mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
const lines = Object.keys(values).sort().map((key) => `${key}=${quoteEnv(values[key])}`);
@@ -704,7 +741,7 @@ function quoteEnv(value: string): string {
return `'${value.replaceAll("'", "'\"'\"'")}'`;
}
function redactRepoPath(path: string): string {
export function redactRepoPath(path: string): string {
const root = rootPath();
return path.startsWith(`${root}/`) ? path.slice(root.length + 1) : path;
}