Skip to content

Add --secret flag to functions:deploy and functions:redeploy#73

Merged
etbyrd merged 3 commits into
mainfrom
functions-deploy-secrets-flag
May 11, 2026
Merged

Add --secret flag to functions:deploy and functions:redeploy#73
etbyrd merged 3 commits into
mainfrom
functions-deploy-secrets-flag

Conversation

@etbyrd
Copy link
Copy Markdown
Member

@etbyrd etbyrd commented May 11, 2026

Summary

  • Adds a repeatable --secret KEY=VALUE flag to functions:deploy and functions:redeploy so an agent can seed (or refresh) function secrets in the same command as the deploy. Keys are validated client-side against the server constraint ^[A-Z_][A-Z0-9_]*$ before any API call fires; values may contain = since only the first one is treated as a delimiter.
  • On deploy the flow is create-function, set-secret per pair, then a final update-function with the same bundle so the running handler picks up the bindings. On redeploy secrets are written first, then a single update-function call refreshes every new binding. Stage-specific stderr hints tell the caller exactly which keys landed if a downstream step fails.
  • Factors the orchestration into pure runDeployWithSecrets / runRedeployWithSecrets functions with DeployApiSurface / RedeployApiSurface types, mirroring the existing functions:set-secret shape. New unit tests cover flag parsing, call ordering, the fast path (zero --secret flags = byte-identical pre-flag behavior), and each failure stage.

Test plan

  • pnpm --dir cli-node lint
  • pnpm --dir cli-node typecheck
  • pnpm --dir cli-node test (195 passed)

Repeatable flag that fans out into create + set-secret per pair +
redeploy (deploy) or set-secret per pair + update (redeploy), so an
agent can land first-deploy secrets in one command instead of the
deploy, set, set, redeploy dance.
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 11, 2026

Greptile Summary

This PR adds a repeatable --secret flag to functions:deploy and functions:redeploy, allowing callers to seed function secrets in the same command as the deploy. Shared parsing lives in a new secret-flags.ts module; orchestration is factored into runDeployWithSecrets / runRedeployWithSecrets with injected API-surface types for clean unit testing.

  • functions:deploy fans out to create-function, N set-secret calls, then update-function when secrets are present; the no-secrets path is byte-identical to pre-flag behavior.
  • functions:redeploy writes secrets before calling update-function; unlike deploy, there is no early exit when secrets is empty, so a plain redeploy failure with no --secret flags incorrectly emits a hint about secrets being in a broken intermediate state.
  • Key format validation, duplicate-key rejection, and stage-specific recovery hints are all covered by 195 passing unit tests.

Confidence Score: 4/5

Safe to merge after fixing the misleading stderr message in the no-secrets redeploy failure path.

In functions-redeploy.ts, runRedeployWithSecrets always calls updateFunction even when no --secret flags are passed. If that call fails, run() unconditionally emits a message stating secrets were written and bindings are not yet live -- which is false when zero secrets were in play. The analogous path in functions-deploy.ts is not affected because it returns early when the secrets list is empty.

cli-node/src/oclif/commands/functions-redeploy.ts -- the redeploy stage error hint at line 325 fires unconditionally and needs to be guarded on parsedSecrets.secrets.length > 0.

Important Files Changed

Filename Overview
cli-node/src/oclif/secret-flags.ts New shared module extracting flag parsing logic; validates key format, splits on first delimiter only, rejects duplicates, and exports a security note for flag descriptions
cli-node/src/oclif/commands/functions-deploy.ts Adds --secret flag and runDeployWithSecrets orchestration; fast-path when secrets is empty is byte-identical to pre-flag behavior, and the redeploy error hint is only reachable when secrets are non-empty so no false positive messages
cli-node/src/oclif/commands/functions-redeploy.ts Adds --secret flag and runRedeployWithSecrets orchestration; unlike the deploy command, there is no empty-secrets fast-path, so a plain redeploy failure (zero --secret flags) incorrectly emits the 'Secrets [(none)] were written' hint on stderr
cli-node/tests/oclif/functions-deploy.test.ts Comprehensive tests for parseSecretFlags and runDeployWithSecrets covering the fast path, call ordering, and every failure stage
cli-node/tests/oclif/functions-redeploy.test.ts Comprehensive tests for runRedeployWithSecrets covering no-secrets path, call ordering, and failure stages; does not cover the misleading stderr hint emitted by run() on a no-secrets redeploy failure

Reviews (3): Last reviewed commit: "Merge branch 'main' into functions-deplo..." | Re-trigger Greptile

Comment thread cli-node/src/oclif/commands/functions-redeploy.ts Outdated
Comment thread cli-node/src/oclif/commands/functions-deploy.ts Outdated
Comment thread cli-node/src/oclif/commands/functions-deploy.ts
@etbyrd etbyrd merged commit 5d86295 into main May 11, 2026
9 checks passed
@etbyrd etbyrd deleted the functions-deploy-secrets-flag branch May 11, 2026 17:46
Comment on lines +325 to +333
} else if (outcome.stage === "redeploy") {
const succeeded =
outcome.succeededKeys.length > 0
? outcome.succeededKeys.join(", ")
: "(none)";
process.stderr.write(
`Secrets [${succeeded}] were written, but the redeploy step failed; the new bindings are NOT yet live. Re-run \`primitive functions:redeploy --id ${flags.id} --file <bundle>\` once the cause is fixed.\n`,
);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Misleading stderr hint fires even when no --secret flags were passed

runRedeployWithSecrets always calls updateFunction, even when the secrets list is empty (there is no fast-path return like the one in runDeployWithSecrets). If that call fails, the outcome stage is "redeploy" with succeededKeys: [], and run() unconditionally emits "Secrets [(none)] were written, but the redeploy step failed; the new bindings are NOT yet live." A user who simply ran functions:redeploy --id foo --file bundle.js with no --secret flags would see this message, implying secrets were involved and are now in a broken intermediate state — neither of which is true.

Suggested change
} else if (outcome.stage === "redeploy") {
const succeeded =
outcome.succeededKeys.length > 0
? outcome.succeededKeys.join(", ")
: "(none)";
process.stderr.write(
`Secrets [${succeeded}] were written, but the redeploy step failed; the new bindings are NOT yet live. Re-run \`primitive functions:redeploy --id ${flags.id} --file <bundle>\` once the cause is fixed.\n`,
);
}
} else if (outcome.stage === "redeploy" && parsedSecrets.secrets.length > 0) {
const succeeded =
outcome.succeededKeys.length > 0
? outcome.succeededKeys.join(", ")
: "(none)";
process.stderr.write(
`Secrets [${succeeded}] were written, but the redeploy step failed; the new bindings are NOT yet live. Re-run \`primitive functions:redeploy --id ${flags.id} --file <bundle>\` once the cause is fixed.\n`,
);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant