diff --git a/lib/backend-api/schema.graphql b/lib/backend-api/schema.graphql index e07abac007b..7c630ead9b1 100644 --- a/lib/backend-api/schema.graphql +++ b/lib/backend-api/schema.graphql @@ -2995,6 +2995,9 @@ type Mutation { """Delete secret with given ID""" deleteAppSecret(input: DeleteAppSecretInput!): DeleteAppSecretPayload + + """Redeploy the active version of an app.""" + redeployActiveVersion(input: RedeployActiveVersionInput!): RedeployActiveVersionPayload tokenAuth(input: ObtainJSONWebTokenInput!): ObtainJSONWebTokenPayload generateDeployToken(input: GenerateDeployTokenInput!): GenerateDeployTokenPayload verifyAccessToken(token: String): Verify @@ -3441,6 +3444,18 @@ input DeleteAppSecretInput { clientMutationId: String } +"""Redeploy the active version of an app.""" +type RedeployActiveVersionPayload { + app: DeployApp! + clientMutationId: String +} + +input RedeployActiveVersionInput { + """ID of the app to redeploy.""" + id: ID! + clientMutationId: String +} + type ObtainJSONWebTokenPayload { payload: GenericScalar! refreshExpiresIn: Int! diff --git a/lib/backend-api/src/query.rs b/lib/backend-api/src/query.rs index 236e5dd26c5..f85d86d4de6 100644 --- a/lib/backend-api/src/query.rs +++ b/lib/backend-api/src/query.rs @@ -15,6 +15,20 @@ use crate::{ GraphQLApiFailure, WasmerClient, }; +pub async fn redeploy_app_by_id( + client: &WasmerClient, + app_id: impl Into, +) -> Result, anyhow::Error> { + client + .run_graphql_strict(types::RedeployActiveApp::build( + RedeployActiveAppVariables { + id: types::Id::from(app_id), + }, + )) + .await + .map(|v| v.redeploy_active_version.map(|v| v.app)) +} + /// Revoke an existing token pub async fn revoke_token( client: &WasmerClient, diff --git a/lib/backend-api/src/types.rs b/lib/backend-api/src/types.rs index 87b8939e9bb..c5d4857d41d 100644 --- a/lib/backend-api/src/types.rs +++ b/lib/backend-api/src/types.rs @@ -1069,6 +1069,23 @@ mod queries { pub apps: DeployAppConnection, } + #[derive(cynic::QueryVariables, Debug)] + pub struct RedeployActiveAppVariables { + pub id: cynic::Id, + } + + #[derive(cynic::QueryFragment, Debug)] + #[cynic(graphql_type = "Mutation", variables = "RedeployActiveAppVariables")] + pub struct RedeployActiveApp { + #[arguments(input: { id: $id })] + pub redeploy_active_version: Option, + } + + #[derive(cynic::QueryFragment, Debug)] + pub struct RedeployActiveVersionPayload { + pub app: DeployApp, + } + #[derive(cynic::QueryVariables, Debug)] pub struct PublishDeployAppVars { pub config: String, diff --git a/lib/cli/src/commands/app/secrets/create.rs b/lib/cli/src/commands/app/secrets/create.rs index 839de2216c7..77301e752c9 100644 --- a/lib/cli/src/commands/app/secrets/create.rs +++ b/lib/cli/src/commands/app/secrets/create.rs @@ -40,6 +40,10 @@ pub struct CmdAppSecretsCreate { #[clap(long, name = "from-file", conflicts_with = "name")] pub from_file: Option, + /// Whether or not to redeploy the app after creating the secrets. + #[clap(long)] + pub redeploy: bool, + /* --- Parameters --- */ /// The name of the secret to create. #[clap(name = "name")] @@ -153,13 +157,30 @@ impl CmdAppSecretsCreate { } else { if !self.quiet { eprintln!("Succesfully created secret(s):"); - for secret in secrets { + for secret in &secrets { eprintln!("{}", secret.name.bold()); } - eprintln!( - "{}: In order for secrets to appear in your app, re-deploy it.", - "Info".bold() - ); + + let should_redeploy = self.redeploy || { + if !self.non_interactive && self.from_file.is_some() { + let theme = ColorfulTheme::default(); + dialoguer::Confirm::with_theme(&theme) + .with_prompt("Do you want to redeploy your app?") + .interact()? + } else { + false + } + }; + + if should_redeploy { + wasmer_api::query::redeploy_app_by_id(client, app_id).await?; + eprintln!("{} Deployment complete", "ð–¥”".yellow().bold()); + } else { + eprintln!( + "{}: In order for secrets to appear in your app, re-deploy it.", + "Info".bold() + ); + } } Ok(()) diff --git a/lib/cli/src/commands/app/secrets/update.rs b/lib/cli/src/commands/app/secrets/update.rs index f45d239db2b..32c20bd586d 100644 --- a/lib/cli/src/commands/app/secrets/update.rs +++ b/lib/cli/src/commands/app/secrets/update.rs @@ -45,6 +45,10 @@ pub struct CmdAppSecretsUpdate { )] pub from_file: Option, + /// Whether or not to redeploy the app after creating the secrets. + #[clap(long)] + pub redeploy: bool, + /* --- Parameters --- */ /// The name of the secret to update. #[clap(name = "name")] @@ -147,14 +151,30 @@ impl CmdAppSecretsUpdate { } else { if !self.quiet { eprintln!("Succesfully updated secret(s):"); - for secret in secrets { + for secret in &secrets { eprintln!("{}", secret.name.bold()); } - eprintln!( - "{}: In order for secrets to appear in your app, re-deploy it.", - "Info".bold() - ); + let should_redeploy = self.redeploy || { + if !self.non_interactive && self.from_file.is_some() { + let theme = ColorfulTheme::default(); + dialoguer::Confirm::with_theme(&theme) + .with_prompt("Do you want to redeploy your app?") + .interact()? + } else { + false + } + }; + + if should_redeploy { + wasmer_api::query::redeploy_app_by_id(client, app_id).await?; + eprintln!("{} Deployment complete", "ð–¥”".yellow().bold()); + } else { + eprintln!( + "{}: In order for secrets to appear in your app, re-deploy it.", + "Info".bold() + ); + } } Ok(())