diff --git a/docs/runware_serverless_apps_env_set.md b/docs/runware_serverless_apps_env_set.md index 40c2861..5ebf5d6 100644 --- a/docs/runware_serverless_apps_env_set.md +++ b/docs/runware_serverless_apps_env_set.md @@ -9,6 +9,12 @@ Create or update one plain-text environment variable. Prefer --value-file so the value is not visible in process lists; use --value-file - to read from stdin. +A change records a new version with the same image and rolls the workload when +the app is active, initializing, or failed and its image is deployable. A +stopped or stopping app applies it on resume. An unchanged value records no +version. A write during an in-flight rollout returns 409 and does not store +the value. + The server rejects (HTTP 422) reserved platform names, names that collide with an attached secret's injected env var, and adding a binding past the 100-variable-plus-secret ceiling. Overwriting an existing key is always diff --git a/docs/runware_serverless_apps_env_unset.md b/docs/runware_serverless_apps_env_unset.md index 0646aa9..203a328 100644 --- a/docs/runware_serverless_apps_env_unset.md +++ b/docs/runware_serverless_apps_env_unset.md @@ -6,6 +6,11 @@ Remove an environment variable Remove one plain-text environment variable from an application. +A delete records a new version with the same image and rolls the workload when +the app is active, initializing, or failed and its image is deployable. A +stopped or stopping app applies it on resume. A delete during an in-flight +rollout returns 409 and does not remove the value. + ``` runware serverless apps env unset [flags] ``` diff --git a/docs/runware_serverless_deploy.md b/docs/runware_serverless_deploy.md index 3cc25f6..8c29d26 100644 --- a/docs/runware_serverless_deploy.md +++ b/docs/runware_serverless_deploy.md @@ -40,12 +40,14 @@ what a project keeps out of version control is a different question from what it ships. Either way .env files are never uploaded, and neither are .git, __pycache__, .venv, node_modules or the usual build and tool caches. -Environment variables must be supplied at create with --env or --env-file. An -app's environment is frozen into the version this command creates, which is -what the worker is rendered from, so setting one afterwards with 'apps env set' -stores it without it ever reaching a pod. Prefer --env-file for anything secret: -a value passed as --env is visible in the process list and recorded in shell -history. +Pass --env or --env-file on create to set the application's initial environment. +Change a variable afterwards with 'apps env set' or 'apps env unset': a change +records a new version with the same image and rolls the workload when the app +is active, initializing, or failed and its image is deployable. A stopped or +stopping app applies it on resume. A write during an in-flight rollout +returns 409 and does not store the value. Prefer --env-file for anything +secret: a value passed as --env is visible in the process list and recorded +in shell history. Anything the app downloads at runtime belongs on a --volume. The app runs in a sandbox whose filesystem is part of the checkpointed state, so an unmounted diff --git a/docs/runware_serverless_secrets_attach.md b/docs/runware_serverless_secrets_attach.md index 33ea154..b04225b 100644 --- a/docs/runware_serverless_secrets_attach.md +++ b/docs/runware_serverless_secrets_attach.md @@ -7,8 +7,11 @@ Attach an organisation secret to an application Record that an organisation secret is attached to an application, optionally under a different environment variable name. -The organisation secret must already exist (see 'secrets set'). This is a -control-plane association only in this API release — it does not roll workers. +The organisation secret must already exist (see 'secrets set'). Attaching rolls +the live deployment so a running worker picks up the value. If a rollout is +already in progress, this attach reaches the worker on the next deploy. An +application that is not live records the attachment only; the next deploy or +resume reads it. ``` runware serverless secrets attach [flags] diff --git a/docs/runware_serverless_secrets_detach.md b/docs/runware_serverless_secrets_detach.md index 0278c7d..d6cc9fb 100644 --- a/docs/runware_serverless_secrets_detach.md +++ b/docs/runware_serverless_secrets_detach.md @@ -4,8 +4,12 @@ Detach a secret from an application ### Synopsis -Remove the control-plane attachment from an application. Does not remove the -organisation secret. +Remove an organisation secret's attachment from an application. The organisation +secret itself remains. + +Detaching rolls the live deployment so a running worker stops receiving the +value. If a rollout is already in progress, the worker stops receiving it on +the next deploy. An application that is not live records the removal only. ``` runware serverless secrets detach [flags] diff --git a/docs/runware_serverless_secrets_set.md b/docs/runware_serverless_secrets_set.md index e2df83a..3c32ba7 100644 --- a/docs/runware_serverless_secrets_set.md +++ b/docs/runware_serverless_secrets_set.md @@ -6,7 +6,12 @@ Create or update an organisation secret Create an organisation-scoped secret, or update its value if the name already exists. -This does not attach the secret to an application. Use 'secrets attach' for that. +Creating a secret does not attach it to an application. Use 'secrets attach' for that. +Updating an existing secret re-encrypts the value and rolls every live application +that attaches it, so a running worker picks up the new value. If a rollout is already +in progress, the new value reaches that worker on the next deploy. An application +that is not live picks it up on its next deploy. + The secret value is never printed. Prefer --value-file so the value is not visible in process lists; use --value-file - to read from stdin. diff --git a/internal/api/serverless/secrets.go b/internal/api/serverless/secrets.go index 6dbfd73..e7e781a 100644 --- a/internal/api/serverless/secrets.go +++ b/internal/api/serverless/secrets.go @@ -103,7 +103,8 @@ func (c *Client) CreateSecret(ctx context.Context, body SecretCreate) (*Secret, } } -// UpdateSecret replaces the value of an existing organisation secret. +// UpdateSecret replaces the value of an existing organisation secret and rolls +// every live deployment that attaches it. func (c *Client) UpdateSecret(ctx context.Context, name string, body SecretUpdate) (*Secret, error) { if c.apiKey == "" { return nil, transport.ErrNoAPIKey @@ -203,8 +204,8 @@ func (c *Client) ListAppSecrets(ctx context.Context, appID string, params *ListA } } -// AttachAppSecret records that an organisation secret is attached to an app. -// This is a control-plane association only in this API release. +// AttachAppSecret records that an organisation secret is attached to an app +// and rolls the live deployment so a running worker picks up the value. func (c *Client) AttachAppSecret(ctx context.Context, appID string, body SecretAttach) error { if c.apiKey == "" { return transport.ErrNoAPIKey @@ -237,7 +238,8 @@ func (c *Client) AttachAppSecret(ctx context.Context, appID string, body SecretA } } -// DetachAppSecret removes a secret attachment from an app. It does not delete +// DetachAppSecret removes a secret attachment from an app and rolls the live +// deployment so a running worker stops receiving the value. It does not delete // the organisation secret. func (c *Client) DetachAppSecret(ctx context.Context, appID, secretName string) error { if c.apiKey == "" { diff --git a/internal/cmd/serverless/deploy.go b/internal/cmd/serverless/deploy.go index b87ce33..1bad132 100644 --- a/internal/cmd/serverless/deploy.go +++ b/internal/cmd/serverless/deploy.go @@ -170,12 +170,14 @@ what a project keeps out of version control is a different question from what it ships. Either way .env files are never uploaded, and neither are .git, __pycache__, .venv, node_modules or the usual build and tool caches. -Environment variables must be supplied at create with --env or --env-file. An -app's environment is frozen into the version this command creates, which is -what the worker is rendered from, so setting one afterwards with 'apps env set' -stores it without it ever reaching a pod. Prefer --env-file for anything secret: -a value passed as --env is visible in the process list and recorded in shell -history. +Pass --env or --env-file on create to set the application's initial environment. +Change a variable afterwards with 'apps env set' or 'apps env unset': a change +records a new version with the same image and rolls the workload when the app +is active, initializing, or failed and its image is deployable. A stopped or +stopping app applies it on resume. A write during an in-flight rollout +returns 409 and does not store the value. Prefer --env-file for anything +secret: a value passed as --env is visible in the process list and recorded +in shell history. Anything the app downloads at runtime belongs on a --volume. The app runs in a sandbox whose filesystem is part of the checkpointed state, so an unmounted diff --git a/internal/cmd/serverless/env.go b/internal/cmd/serverless/env.go index d0566a0..127ddb5 100644 --- a/internal/cmd/serverless/env.go +++ b/internal/cmd/serverless/env.go @@ -93,6 +93,12 @@ func newAppsEnvSetCmd(logger *log.Logger) *cobra.Command { Prefer --value-file so the value is not visible in process lists; use --value-file - to read from stdin. +A change records a new version with the same image and rolls the workload when +the app is active, initializing, or failed and its image is deployable. A +stopped or stopping app applies it on resume. An unchanged value records no +version. A write during an in-flight rollout returns 409 and does not store +the value. + The server rejects (HTTP 422) reserved platform names, names that collide with an attached secret's injected env var, and adding a binding past the 100-variable-plus-secret ceiling. Overwriting an existing key is always @@ -142,7 +148,12 @@ func newAppsEnvUnsetCmd(logger *log.Logger) *cobra.Command { return &cobra.Command{ Use: "unset ", Short: "Remove an environment variable", - Long: "Remove one plain-text environment variable from an application.", + Long: `Remove one plain-text environment variable from an application. + +A delete records a new version with the same image and rolls the workload when +the app is active, initializing, or failed and its image is deployable. A +stopped or stopping app applies it on resume. A delete during an in-flight +rollout returns 409 and does not remove the value.`, Example: ` # remove an environment variable runware serverless apps env unset my-app MY_KEY`, Args: cobra.ExactArgs(2), @@ -187,14 +198,9 @@ const ( var envNamePattern = regexp.MustCompile(`^[A-Za-z_][A-Za-z0-9_]{0,127}$`) // buildEnvironmentVariables turns --env KEY=VALUE pairs and --env-file paths into -// the create request's map. -// -// These belong on the CREATE request and nowhere else: an app's environment is -// frozen into its version snapshot, which is what the deployer renders from, and -// no endpoint creates a further version -- `deploy` re-applies an existing one by -// number and says so. So a variable set through the /environment-variables -// endpoints after the app exists is stored, listed back, and never reaches a -// worker. Passing it here is the only route that ends up in a pod. +// the create request's map. After the app exists, 'apps env set' and 'apps env +// unset' record a new version with the same image and roll the workload; this +// helper only builds the create-time map. // // Files are read before the inline pairs are applied, so an explicit --env wins // over a file entry with the same name. diff --git a/internal/cmd/serverless/secrets.go b/internal/cmd/serverless/secrets.go index f1c823a..9d3fd4f 100644 --- a/internal/cmd/serverless/secrets.go +++ b/internal/cmd/serverless/secrets.go @@ -96,7 +96,12 @@ func newSecretsSetCmd(logger *log.Logger) *cobra.Command { Short: "Create or update an organisation secret", Long: `Create an organisation-scoped secret, or update its value if the name already exists. -This does not attach the secret to an application. Use 'secrets attach' for that. +Creating a secret does not attach it to an application. Use 'secrets attach' for that. +Updating an existing secret re-encrypts the value and rolls every live application +that attaches it, so a running worker picks up the new value. If a rollout is already +in progress, the new value reaches that worker on the next deploy. An application +that is not live picks it up on its next deploy. + The secret value is never printed. Prefer --value-file so the value is not visible in process lists; use --value-file - to read from stdin.`, Example: ` # create or update a secret from a file @@ -223,8 +228,11 @@ func newSecretsAttachCmd(logger *log.Logger) *cobra.Command { Long: `Record that an organisation secret is attached to an application, optionally under a different environment variable name. -The organisation secret must already exist (see 'secrets set'). This is a -control-plane association only in this API release — it does not roll workers.`, +The organisation secret must already exist (see 'secrets set'). Attaching rolls +the live deployment so a running worker picks up the value. If a rollout is +already in progress, this attach reaches the worker on the next deploy. An +application that is not live records the attachment only; the next deploy or +resume reads it.`, Example: ` # attach a secret using its name as the env var runware serverless secrets attach my-app FOO @@ -265,8 +273,12 @@ func newSecretsDetachCmd(logger *log.Logger) *cobra.Command { cmd := &cobra.Command{ Use: "detach ", Short: "Detach a secret from an application", - Long: `Remove the control-plane attachment from an application. Does not remove the -organisation secret.`, + Long: `Remove an organisation secret's attachment from an application. The organisation +secret itself remains. + +Detaching rolls the live deployment so a running worker stops receiving the +value. If a rollout is already in progress, the worker stops receiving it on +the next deploy. An application that is not live records the removal only.`, Example: ` # detach a secret from an application runware serverless secrets detach my-app FOO`, Args: cobra.ExactArgs(2),