From 1dbc2132ef66138ec7395a7c57ec760c0bba1b72 Mon Sep 17 00:00:00 2001 From: Codex Date: Sun, 12 Jul 2026 18:00:59 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=A7=BB=E9=99=A4=20provider=20Secret?= =?UTF-8?q?=20=E6=97=A7=E9=98=BB=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/src/agentrun/provider-profile.ts | 92 ++------------------ scripts/src/agentrun/trigger.ts | 102 +---------------------- 2 files changed, 12 insertions(+), 182 deletions(-) diff --git a/scripts/src/agentrun/provider-profile.ts b/scripts/src/agentrun/provider-profile.ts index 839ab8b8..7a5ab152 100644 --- a/scripts/src/agentrun/provider-profile.ts +++ b/scripts/src/agentrun/provider-profile.ts @@ -17,19 +17,13 @@ import { } from "../agentrun-lanes"; import { refreshYamlLaneScript } from "./git-mirror"; import type { ConfirmOptions, DisclosureOptions } from "./options"; -import { - AGENTRUN_PROVIDER_ACTIVATION_FENCE_ISSUE, - providerSecretActivationPreflight, - providerSecretDesiredEncodedFingerprint, - providerSecretStagedActivation, - type ProviderSecretActivationTarget, -} from "./provider-activation"; import { compactAgentRunLaneStatusTarget } from "./trigger"; import { collectLaneSecretSources, createYamlLaneJobScript, inspectSecretSourceValue, restartYamlLaneScript, + secretSyncScript, type LaneSecretSource, type LaneSecretSourceInspection, yamlLaneGitopsPublishJobManifest, @@ -107,7 +101,7 @@ export function providerProfileHelp(): string { " bun scripts/cli.ts agentrun provider-profile validate --node NC01 --lane nc01-v02 --profile gpt.pika --wait", "", "Boundary:", - " confirmed apply returns an async job only after the provider Secret gate reports an exact data no-op; the worker skips the provider Secret write, publishes runtime GitOps using the current manager image, refreshes Argo and restarts the manager without rebuilding images or creating a PipelineRun.", + " confirmed apply syncs the selected YAML-declared provider Secret, publishes runtime GitOps using the current manager image, refreshes Argo and restarts the manager without rebuilding images or creating a PipelineRun.", ].join("\n"); } @@ -129,11 +123,6 @@ async function providerProfileApplyAsync(config: UniDeskConfig, options: Provide if (plan.ok !== true) return plan; const { spec, profile } = resolveProviderProfile(options); const secrets = spec.secrets.filter((secret) => secret.providerCredentialProfile === profile); - const activationTargets = providerProfileActivationTargets(inspectProviderProfileSources(spec, secrets)); - const activationPreflight = await providerSecretActivationPreflight(config, spec, activationTargets, { full: options.full || options.raw }); - if (activationPreflight.ok !== true) { - return providerProfileActivationBlockedResult(spec, profile, secrets, activationPreflight, "async-submit"); - } const args = [ "bun", "scripts/cli.ts", @@ -162,7 +151,6 @@ async function providerProfileApplyAsync(config: UniDeskConfig, options: Provide profile, job, jobCreated: true, - activationPreflight, statusCommand, next: { status: statusCommand, @@ -249,14 +237,7 @@ function providerProfilePlan(options: ProviderProfileOptions): Record ({ targetRef: secret.targetRef, value: inspection.sourceValue!.value })))]); + const secretPayload = captureJsonPayload(secretSync); + providerProfileApplyProgress(spec, profile, "secret-sync", secretSync.exitCode === 0 && secretPayload.ok !== false ? "succeeded" : "failed", { status: secretPayload.status ?? null }); + if (secretSync.exitCode !== 0 || secretPayload.ok === false) { + return applyFailure(configPath, spec, profile, "secret-sync", secretPayload, secretSync); } - const secretPayload = { - ok: true, - status: "skipped-exact-provider-secret-no-op", - secretSyncStarted: false, - providerSecretWriteSkipped: true, - skippedProviderSecretCount: inspected.length, - reason: "provider-secret-writes-require-agentrun-manager-activation-fence", - activationFenceIssue: AGENTRUN_PROVIDER_ACTIVATION_FENCE_ISSUE, - runtimeSecretValuesDecoded: false, - valuesPrinted: false, - }; - providerProfileApplyProgress(spec, profile, "secret-sync", "succeeded", { status: secretPayload.status }); providerProfileApplyProgress(spec, profile, "current-image-resolve", "running"); const liveBefore = await capture(config, spec.nodeKubeRoute, ["sh", "--", currentManagerImageScript(spec)]); const liveBeforePayload = captureJsonPayload(liveBefore); @@ -481,7 +451,6 @@ async function providerProfileApply(config: UniDeskConfig, options: ProviderProf target: compactAgentRunLaneStatusTarget(spec), profile: providerProfileSummary(spec, profile, secrets), steps: { - activationPreflight, secretSync: secretPayload, gitops: publish.payload, argo: argoPayload, @@ -510,38 +479,6 @@ async function providerProfileApply(config: UniDeskConfig, options: ProviderProf }; } -function providerProfileActivationBlockedResult( - spec: AgentRunLaneSpec, - profile: string, - secrets: readonly AgentRunLaneSecretSpec[], - activationPreflight: Record, - stage: "async-submit" | "worker-before-secret-sync", -): Record { - return { - ok: false, - command: "agentrun provider-profile apply", - mode: stage === "async-submit" ? "activation-preflight-blocked-before-job" : "activation-preflight-blocked-before-secret-sync", - status: "blocked", - degradedReason: activationPreflight.reason ?? "existing-runner-provider-secret-activation-risk", - phase: "activation-preflight", - stage, - mutation: false, - blockedBeforeMutation: true, - jobCreated: stage === "worker-before-secret-sync", - jobAlreadyRunning: stage === "worker-before-secret-sync", - secretSyncStarted: false, - target: { node: spec.nodeId, lane: spec.lane, namespace: spec.runtime.namespace, valuesPrinted: false }, - profile: providerProfileSummary(spec, profile, secrets), - activationPreflight, - stagedActivation: providerSecretStagedActivation(spec, [profile]), - next: { - observeRunners: `bun scripts/cli.ts agentrun control-plane cleanup-runners --node ${spec.nodeId} --lane ${spec.lane} --dry-run`, - retryAfterManagerFence: `bun scripts/cli.ts agentrun provider-profile apply --node ${spec.nodeId} --lane ${spec.lane} --profile ${profile} --confirm`, - }, - valuesPrinted: false, - }; -} - function providerProfileApplyProgress( spec: AgentRunLaneSpec, profile: string, @@ -618,17 +555,6 @@ function inspectProviderProfileSources(spec: AgentRunLaneSpec, secrets: readonly }); } -function providerProfileActivationTargets(items: readonly ProviderProfileInspectedSecret[]): ProviderSecretActivationTarget[] { - return items.map(({ secret, inspection }) => { - if (inspection.sourceValue === null) throw new Error(`provider profile source ${secret.id} is unavailable before activation preflight`); - return { - id: secret.id, - targetRef: secret.targetRef, - desiredEncodedFingerprint: providerSecretDesiredEncodedFingerprint(inspection.sourceValue.value), - }; - }); -} - function providerProfileSourceSummary(items: readonly ProviderProfileInspectedSecret[]): { ready: boolean; count: number; diff --git a/scripts/src/agentrun/trigger.ts b/scripts/src/agentrun/trigger.ts index 06d1ae31..5da28c28 100644 --- a/scripts/src/agentrun/trigger.ts +++ b/scripts/src/agentrun/trigger.ts @@ -39,7 +39,6 @@ import { triggerCurrentYamlLaneConfirmed } from "./cleanup-scripts"; import { readAgentRunClientConfig } from "./config"; import { displayValue } from "./options"; import { pathValue } from "./render"; -import { providerSecretActivationPreflight, providerSecretDesiredEncodedFingerprint, providerSecretStagedActivation } from "./provider-activation"; import { startAsyncAgentRunJob } from "./rest-bridge"; import { collectLaneSecretSources, inspectSecretSourceValue, restartYamlLaneScript, secretSyncScript } from "./secrets"; import { capture, captureJsonPayload, compactCapture, isGitSha, stringOrNull } from "./utils"; @@ -257,66 +256,7 @@ export async function secretSync(config: UniDeskConfig, options: SecretSyncOptio }; } const values = inspected.map(({ spec: item, inspection }) => ({ spec: item, value: inspection.sourceValue! })); - const providerSecretsByTargetRef = new Map(); - for (const secret of spec.secrets) { - if (secret.providerCredentialProfile === null) continue; - const targetRef = laneSecretTargetRefKey(secret.targetRef); - const existing = providerSecretsByTargetRef.get(targetRef); - if (existing !== undefined) { - throw new Error(`provider Secret targetRef ${targetRef} is declared by both ${existing.id} and ${secret.id}`); - } - providerSecretsByTargetRef.set(targetRef, secret); - } - const providerValues = values.filter(({ spec: item }) => providerSecretsByTargetRef.has(laneSecretTargetRefKey(item.targetRef))); - const providerSecrets = providerValues.map(({ spec: item }) => providerSecretsByTargetRef.get(laneSecretTargetRefKey(item.targetRef))!); - const providerActivationTargets = providerValues.map(({ spec: item, value }) => { - return { - id: item.id, - targetRef: item.targetRef, - desiredEncodedFingerprint: providerSecretDesiredEncodedFingerprint(value.value), - }; - }); - const activationPreflight = providerValues.length > 0 - ? await providerSecretActivationPreflight(config, spec, providerActivationTargets, { full: options.full || options.raw }) - : null; - const syncValues = values.filter(({ spec: item }) => !providerSecretsByTargetRef.has(laneSecretTargetRefKey(item.targetRef))); - if (activationPreflight !== null && activationPreflight.ok !== true) { - const profiles = providerSecrets - .map((secret) => secret.providerCredentialProfile) - .filter((profile): profile is string => profile !== null); - return { - ok: false, - command: "agentrun control-plane secret-sync", - mode: options.dryRun || !options.confirm ? "dry-run-blocked-before-mutation" : "confirm-blocked-before-mutation", - status: "blocked", - mutation: false, - blockedBeforeMutation: true, - secretSyncStarted: false, - configPath, - target: { node: spec.nodeId, lane: spec.lane, namespace: spec.runtime.namespace, valuesPrinted: false }, - degradedReason: activationPreflight.reason ?? "existing-runner-provider-secret-activation-risk", - filter: options.secretIds.length === 0 ? null : { secretIds: options.secretIds, selected: sources.map((source) => source.id) }, - plan: { - secretCount: plan.length, - items: plan, - omittedCount: 0, - valuesPrinted: false, - }, - activationPreflight, - execution: { - providerSecretClassification: "exact-target-ref", - providerSecretWriteBlockedCount: providerValues.length, - secretSyncStarted: false, - valuesPrinted: false, - }, - stagedActivation: providerSecretStagedActivation(spec, profiles), - next: { - observeRunners: `bun scripts/cli.ts agentrun control-plane cleanup-runners --node ${spec.nodeId} --lane ${spec.lane} --dry-run`, - retryAfterManagerFence: `bun scripts/cli.ts agentrun control-plane secret-sync --node ${spec.nodeId} --lane ${spec.lane}${options.secretIds.map((id) => ` --secret-id ${id}`).join("")} --confirm`, - }, - valuesPrinted: false, - }; - } + const syncValues = values; if (options.dryRun || !options.confirm) { return { ok: true, @@ -326,12 +266,9 @@ export async function secretSync(config: UniDeskConfig, options: SecretSyncOptio configPath, target: compactAgentRunLaneStatusTarget(spec), filter: options.secretIds.length === 0 ? null : { secretIds: options.secretIds, selected: sources.map((source) => source.id) }, - plan: { secretCount: plan.length, items: plan, activationPreflight, valuesPrinted: false }, + plan: { secretCount: plan.length, items: plan, valuesPrinted: false }, execution: { - providerSecretClassification: "exact-target-ref", - providerSecretWritePolicy: "skip-exact-no-op-until-manager-activation-fence", - providerSecretWriteSkippedCount: providerValues.length, - writableNonProviderSecretCount: syncValues.length, + writableSecretCount: syncValues.length, valuesPrinted: false, }, next: { @@ -341,34 +278,6 @@ export async function secretSync(config: UniDeskConfig, options: SecretSyncOptio valuesPrinted: false, }; } - if (syncValues.length === 0) { - return { - ok: true, - command: "agentrun control-plane secret-sync", - mode: "confirmed-provider-secret-no-op-skip", - mutation: false, - secretSyncStarted: false, - providerSecretWriteSkipped: providerValues.length > 0, - configPath, - target: compactAgentRunLaneStatusTarget(spec), - filter: options.secretIds.length === 0 ? null : { secretIds: options.secretIds, selected: sources.map((source) => source.id) }, - plan: { secretCount: plan.length, items: plan, valuesPrinted: false }, - activationPreflight, - result: { - ok: true, - status: "skipped-exact-provider-secret-no-op", - skippedProviderSecretCount: providerValues.length, - providerSecretClassification: "exact-target-ref", - reason: "provider-secret-writes-require-agentrun-manager-activation-fence", - runtimeSecretValuesDecoded: false, - valuesPrinted: false, - }, - next: { - status: `bun scripts/cli.ts agentrun control-plane status --node ${spec.nodeId} --lane ${spec.lane}`, - }, - valuesPrinted: false, - }; - } const result = await capture(config, spec.nodeKubeRoute, ["sh", "--", secretSyncScript(spec, syncValues.map(({ spec: item, value }) => ({ targetRef: item.targetRef, value: value.value })))]); const payload = captureJsonPayload(result); return { @@ -387,7 +296,6 @@ export async function secretSync(config: UniDeskConfig, options: SecretSyncOptio writableNonProviderSecretCount: syncValues.length, valuesPrinted: false, }, - activationPreflight, result: payload, capture: compactCapture(result, { full: result.exitCode !== 0, stdoutTailChars: 3000, stderrTailChars: 3000 }), next: { @@ -397,10 +305,6 @@ export async function secretSync(config: UniDeskConfig, options: SecretSyncOptio }; } -function laneSecretTargetRefKey(targetRef: { namespace: string; name: string; key: string }): string { - return `${targetRef.namespace}/${targetRef.name}/${targetRef.key}`; -} - export async function exposeAgentRun(_config: UniDeskConfig, options: ConfirmOptions): Promise> { const clientConfig = readAgentRunClientConfig(); const exposure = clientConfig.publicExposure;