feat: 支持 runner transient env

This commit is contained in:
Codex
2026-06-01 17:50:13 +08:00
parent 7c59181642
commit 44ff391918
5 changed files with 125 additions and 4 deletions
+40 -1
View File
@@ -15,9 +15,16 @@ export interface RunnerJobRenderOptions {
imagePullPolicy?: string;
backoffLimit?: number;
ttlSecondsAfterFinished?: number;
transientEnv?: RunnerTransientEnv[];
dryRun?: boolean;
}
export interface RunnerTransientEnv {
name: string;
value: string;
sensitive?: boolean;
}
interface CredentialProjection {
profile: BackendProfile | string;
secretRef: SecretRef;
@@ -28,6 +35,7 @@ interface CredentialProjection {
export function renderRunnerJobDryRun(options: RunnerJobRenderOptions): JsonRecord {
const render = renderRunnerJobManifest({ ...options, dryRun: true });
const manifest = redactTransientEnvInManifest(render.manifest, options.transientEnv ?? []);
return {
dryRun: true,
mutation: false,
@@ -48,6 +56,7 @@ export function renderRunnerJobDryRun(options: RunnerJobRenderOptions): JsonReco
sourceCommit: render.sourceCommit,
},
secretRefs: render.secretRefs.map((item) => ({ profile: item.profile, name: item.secretRef.name, namespace: item.secretRef.namespace ?? render.namespace, keys: item.secretRef.keys ?? [], mountPath: item.runtimeMountPath, projectionPath: item.projectionMountPath, writableCopy: true, valuesPrinted: false })),
transientEnv: summarizeTransientEnv(options.transientEnv ?? []),
retention: {
ttlSecondsAfterFinished: render.ttlSecondsAfterFinished,
},
@@ -56,7 +65,7 @@ export function renderRunnerJobDryRun(options: RunnerJobRenderOptions): JsonReco
events: `./scripts/agentrun runs events ${options.run.id} --manager-url ${options.managerUrl} --after-seq 0 --limit 100`,
},
warnings: render.warnings,
manifest: render.manifest,
manifest,
};
}
@@ -151,9 +160,39 @@ function runnerEnv(options: RunnerJobRenderOptions, context: { namespace: string
{ name: "HOME", value: "/home/agentrun" },
{ name: "CODEX_HOME", value: codexHome },
...(selectedSecret ? [{ name: "AGENTRUN_CODEX_SECRET_HOME", value: selectedSecret.projectionMountPath }] : []),
...transientEnvVars(options.transientEnv ?? []),
];
}
function transientEnvVars(items: RunnerTransientEnv[]): JsonRecord[] {
return items.map((item) => ({ name: item.name, value: item.value }));
}
function summarizeTransientEnv(items: RunnerTransientEnv[]): JsonRecord {
return {
count: items.length,
names: items.map((item) => item.name),
valuesPrinted: false,
};
}
function redactTransientEnvInManifest(manifest: JsonRecord, items: RunnerTransientEnv[]): JsonRecord {
if (items.length === 0) return manifest;
const names = new Set(items.map((item) => item.name));
const copy = JSON.parse(JSON.stringify(manifest)) as JsonRecord;
const spec = copy.spec as JsonRecord | undefined;
const template = spec?.template as JsonRecord | undefined;
const podSpec = template?.spec as JsonRecord | undefined;
const containers = Array.isArray(podSpec?.containers) ? podSpec.containers as JsonRecord[] : [];
for (const container of containers) {
const env = Array.isArray(container.env) ? container.env as JsonRecord[] : [];
for (const entry of env) {
if (typeof entry.name === "string" && names.has(entry.name)) entry.value = "REDACTED";
}
}
return copy;
}
function credentialProjections(run: RunRecord, namespace: string): CredentialProjection[] {
const policy: ExecutionPolicy = run.executionPolicy;
const credentials = (policy.secretScope.providerCredentials ?? []).filter((item) => item.profile === run.backendProfile);