From 42573f939cac3e56b42834881f50850e0669a6ff Mon Sep 17 00:00:00 2001 From: Alex Way Date: Thu, 28 Mar 2024 08:56:27 +0000 Subject: [PATCH 1/6] feat: Add confirm step type --- crates/knope/src/step/confirm.rs | 37 ++++++++++++++++++++++++++++++++ crates/knope/src/step/mod.rs | 7 ++++++ 2 files changed, 44 insertions(+) create mode 100644 crates/knope/src/step/confirm.rs diff --git a/crates/knope/src/step/confirm.rs b/crates/knope/src/step/confirm.rs new file mode 100644 index 00000000..42a1de0a --- /dev/null +++ b/crates/knope/src/step/confirm.rs @@ -0,0 +1,37 @@ +use inquire::Confirm; +use miette::Diagnostic; + +use crate::{app_config, RunType}; + +pub(crate) fn confirm(mut run_type: RunType, message: &str) -> Result { + let (_, dry_run_stdout) = match &mut run_type { + RunType::DryRun { state, stdout } => (state, Some(stdout)), + RunType::Real(state) => (state, None), + }; + + if let Some(stdout) = dry_run_stdout { + writeln!(stdout, "Would prompt for the following message {message}")?; + return Ok(run_type); + } + + let confirmation = Confirm::new(message).with_default(true).prompt(); + + match confirmation { + Ok(true) => Ok(run_type), + Ok(false) => Err(Error::Confirm), + Err(err) => Err(Error::Prompt(err)), + } +} + +#[derive(Debug, Diagnostic, thiserror::Error)] +pub(crate) enum Error { + #[error("User did not confirm")] + Confirm, + #[error(transparent)] + Prompt(#[from] inquire::InquireError), + #[error("Unable to write to stdout: {0}")] + Stdout(#[from] std::io::Error), + #[error(transparent)] + #[diagnostic(transparent)] + AppConfig(#[from] app_config::Error), +} diff --git a/crates/knope/src/step/mod.rs b/crates/knope/src/step/mod.rs index 19cab3ff..abc1f587 100644 --- a/crates/knope/src/step/mod.rs +++ b/crates/knope/src/step/mod.rs @@ -13,6 +13,7 @@ use crate::{ }; pub mod command; +pub mod confirm; mod create_pull_request; pub mod issues; pub mod releases; @@ -95,6 +96,8 @@ pub(crate) enum Step { title: Template, body: Template, }, + /// Prompt the user to confirm the next step. + Confirm { message: String }, } impl Step { @@ -127,6 +130,7 @@ impl Step { Step::CreatePullRequest { base, title, body } => { create_pull_request::run(&base, title, body, run_type)? } + Step::Confirm { message } => confirm::confirm(run_type, message.as_str())?, }) } @@ -167,6 +171,9 @@ pub(super) enum Error { #[error(transparent)] #[diagnostic(transparent)] CreatePullRequest(#[from] create_pull_request::Error), + #[error(transparent)] + #[diagnostic(transparent)] + Confirm(#[from] confirm::Error), } /// The inner content of a [`Step::PrepareRelease`] step. From 011340f28fd547872f8bfdcefd32aa83e97f6aff Mon Sep 17 00:00:00 2001 From: Alex Way Date: Thu, 28 Mar 2024 18:29:11 +0000 Subject: [PATCH 2/6] feat: Add auto-confirmation commandline flag --- crates/knope/src/lib.rs | 12 +++++++++++- crates/knope/src/step/confirm.rs | 9 ++++++++- crates/knope/src/step/mod.rs | 4 ++-- crates/knope/src/workflow.rs | 5 +++-- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/crates/knope/src/lib.rs b/crates/knope/src/lib.rs index a0a377fa..f7699fab 100644 --- a/crates/knope/src/lib.rs +++ b/crates/knope/src/lib.rs @@ -96,7 +96,9 @@ pub fn run() -> Result<()> { RunType::Real(state) }; - workflow::run(workflow, state)?; + let assume_yes = matches.get_flag("assumeyes"); + + workflow::run(workflow, state, assume_yes)?; Ok(()) } @@ -104,6 +106,7 @@ const OVERRIDE_ONE_VERSION: &str = "override-one-version"; const OVERRIDE_MULTIPLE_VERSIONS: &str = "override-multiple-versions"; const PRERELEASE_LABEL: &str = "prerelease-label"; const VERBOSE: &str = "verbose"; +const ASSUMEYES: &str = "assumeyes"; fn build_cli(config: &ConfigSource) -> Command { let mut command = command!() @@ -113,6 +116,11 @@ fn build_cli(config: &ConfigSource) -> Command { .help("Pretend to run a workflow, outputting what _would_ happen without actually doing it.") .action(ArgAction::SetTrue) .global(true) + ).arg( + Arg::new(ASSUMEYES).long(ASSUMEYES).short('y') + .help("Automatic yes to prompts. Assume \"yes\" as answer to all prompts and run non-interactively.") + .action(ArgAction::SetTrue) + .global(true) ).arg( Arg::new(VERBOSE).long(VERBOSE).short('v') .help("Print extra information (for debugging)") @@ -157,10 +165,12 @@ fn build_cli(config: &ConfigSource) -> Command { .steps .iter() .any(|step| matches!(*step, Step::BumpVersion(_))); + let contains_prepare_release = workflow .steps .iter() .any(|step| matches!(*step, Step::PrepareRelease(_))); + if contains_bump_version || contains_prepare_release { if let Some(arg) = version_override_arg.clone() { subcommand = subcommand.arg(arg); diff --git a/crates/knope/src/step/confirm.rs b/crates/knope/src/step/confirm.rs index 42a1de0a..cba7110d 100644 --- a/crates/knope/src/step/confirm.rs +++ b/crates/knope/src/step/confirm.rs @@ -3,7 +3,14 @@ use miette::Diagnostic; use crate::{app_config, RunType}; -pub(crate) fn confirm(mut run_type: RunType, message: &str) -> Result { +pub(crate) fn confirm( + mut run_type: RunType, + message: &str, + assume_yes: bool, +) -> Result { + if assume_yes { + return Ok(run_type); + } let (_, dry_run_stdout) = match &mut run_type { RunType::DryRun { state, stdout } => (state, Some(stdout)), RunType::Real(state) => (state, None), diff --git a/crates/knope/src/step/mod.rs b/crates/knope/src/step/mod.rs index abc1f587..1e21bc12 100644 --- a/crates/knope/src/step/mod.rs +++ b/crates/knope/src/step/mod.rs @@ -101,7 +101,7 @@ pub(crate) enum Step { } impl Step { - pub(crate) fn run(self, run_type: RunType) -> Result { + pub(crate) fn run(self, run_type: RunType, assume_yes: bool) -> Result { Ok(match self { Step::SelectJiraIssue { status } => issues::jira::select_issue(&status, run_type)?, Step::TransitionJiraIssue { status } => { @@ -130,7 +130,7 @@ impl Step { Step::CreatePullRequest { base, title, body } => { create_pull_request::run(&base, title, body, run_type)? } - Step::Confirm { message } => confirm::confirm(run_type, message.as_str())?, + Step::Confirm { message } => confirm::confirm(run_type, message.as_str(), assume_yes)?, }) } diff --git a/crates/knope/src/workflow.rs b/crates/knope/src/workflow.rs index 5caa9708..ec4a492a 100644 --- a/crates/knope/src/workflow.rs +++ b/crates/knope/src/workflow.rs @@ -61,9 +61,9 @@ pub struct Error { } /// Run a series of [`Step`], each of which updates `state`. -pub(crate) fn run(workflow: Workflow, mut state: RunType) -> Result<(), Error> { +pub(crate) fn run(workflow: Workflow, mut state: RunType, assume_yes: bool) -> Result<(), Error> { for step in workflow.steps { - state = match step.run(state) { + state = match step.run(state, assume_yes) { Ok(state) => state, Err(err) => { return Err(Error { @@ -90,6 +90,7 @@ pub(crate) fn validate( state: state.clone(), stdout: Box::new(sink()), }, + false, ) .err() }) From 918969c7c1206309ac784d65e34c9a34a2e63111 Mon Sep 17 00:00:00 2001 From: Alex Way Date: Thu, 28 Mar 2024 18:35:50 +0000 Subject: [PATCH 3/6] docs: Add documentation for the Confirm step --- .../reference/Config File/Steps/confirm.md | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 docs/src/content/docs/reference/Config File/Steps/confirm.md diff --git a/docs/src/content/docs/reference/Config File/Steps/confirm.md b/docs/src/content/docs/reference/Config File/Steps/confirm.md new file mode 100644 index 00000000..96708f4d --- /dev/null +++ b/docs/src/content/docs/reference/Config File/Steps/confirm.md @@ -0,0 +1,26 @@ +--- +title: Confirm +--- + +Prompt the user to confirm a given message. Approving the prompt will continue to run the workflow. +Rejecting the prompt will stop the workflow and no further steps will be run. + +## Example + +```toml +[[workflows.steps]] +type = "Confirm" +message = "Are you sure you want to run the cleanup step?" +``` + +The example workflow above will promp the user with the following message: + +```shell + +? Are you sure you want to run the cleanup step? (Y/n) + +``` + +## Automatic confirmation + +If you want to automatically confirm all steps in a workflow, you can run the workflow with either the `--assumeyes` or `-y` flag. From 0b1dc10b8a4ecde0bc5e386c7aec2536239001be Mon Sep 17 00:00:00 2001 From: Alex Way Date: Thu, 28 Mar 2024 18:40:26 +0000 Subject: [PATCH 4/6] docs: Add documentation of -y argument to CLI docs --- docs/src/content/docs/reference/command-line-arguments.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/src/content/docs/reference/command-line-arguments.md b/docs/src/content/docs/reference/command-line-arguments.md index b23609b1..ea408ea0 100644 --- a/docs/src/content/docs/reference/command-line-arguments.md +++ b/docs/src/content/docs/reference/command-line-arguments.md @@ -71,3 +71,7 @@ producing an error if either of those packages isn't configured. [`BumpVersion`]: /reference/config-file/steps/bump-version [`PrepareRelease`]: /reference/config-file/steps/prepare-release + +### `--assumeyes` + +Automatically answer all confirmation steps with a "yes". See [`Confirm`](/reference/config-file/steps/confirm/) for more information about the `Confirm` step type. From e0c4dd4003f122bd18d70e97322d632cb081ff64 Mon Sep 17 00:00:00 2001 From: Alex Way Date: Tue, 7 May 2024 20:53:25 +0100 Subject: [PATCH 5/6] chore: Update test snapshots with assumeyes --- .../tests/default_workflows/document_change/stdout.log | 9 +++++---- .../release/help_multi_package/stdout.log | 2 ++ .../release/help_single_package/stdout.log | 2 ++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/crates/knope/tests/default_workflows/document_change/stdout.log b/crates/knope/tests/default_workflows/document_change/stdout.log index 49c85597..3d411505 100644 --- a/crates/knope/tests/default_workflows/document_change/stdout.log +++ b/crates/knope/tests/default_workflows/document_change/stdout.log @@ -1,7 +1,8 @@ Usage: knope[EXE] document-change [OPTIONS] Options: - --dry-run Pretend to run a workflow, outputting what _would_ happen without actually doing it. - -v, --verbose Print extra information (for debugging) - -h, --help Print help - -V, --version Print version + --dry-run Pretend to run a workflow, outputting what _would_ happen without actually doing it. + -y, --assumeyes Automatic yes to prompts. Assume "yes" as answer to all prompts and run non-interactively. + -v, --verbose Print extra information (for debugging) + -h, --help Print help + -V, --version Print version diff --git a/crates/knope/tests/default_workflows/release/help_multi_package/stdout.log b/crates/knope/tests/default_workflows/release/help_multi_package/stdout.log index 1539b1e1..be441da3 100644 --- a/crates/knope/tests/default_workflows/release/help_multi_package/stdout.log +++ b/crates/knope/tests/default_workflows/release/help_multi_package/stdout.log @@ -7,6 +7,8 @@ Options: Override the version set by `BumpVersion` or `PrepareRelease` for multiple packages. Format is like package_name=version, can be set multiple times. --prerelease-label Set the `prerelease_label` attribute of any `PrepareRelease` steps at runtime. [env: KNOPE_PRERELEASE_LABEL=] + -y, --assumeyes + Automatic yes to prompts. Assume "yes" as answer to all prompts and run non-interactively. -v, --verbose Print extra information (for debugging) -h, --help diff --git a/crates/knope/tests/default_workflows/release/help_single_package/stdout.log b/crates/knope/tests/default_workflows/release/help_single_package/stdout.log index fb5dee3e..844c3799 100644 --- a/crates/knope/tests/default_workflows/release/help_single_package/stdout.log +++ b/crates/knope/tests/default_workflows/release/help_single_package/stdout.log @@ -7,6 +7,8 @@ Options: Override the version set by `BumpVersion` or `PrepareRelease` for the package. --prerelease-label Set the `prerelease_label` attribute of any `PrepareRelease` steps at runtime. [env: KNOPE_PRERELEASE_LABEL=] + -y, --assumeyes + Automatic yes to prompts. Assume "yes" as answer to all prompts and run non-interactively. -v, --verbose Print extra information (for debugging) -h, --help From 245408fbe38b6b73626f6f73e8d4066bf723245d Mon Sep 17 00:00:00 2001 From: Alex Way Date: Tue, 7 May 2024 21:17:32 +0100 Subject: [PATCH 6/6] refactor: Move confirmation into prompt.rs --- crates/knope/src/prompt.rs | 9 ++++++++- crates/knope/src/step/confirm.rs | 17 +++++++---------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/crates/knope/src/prompt.rs b/crates/knope/src/prompt.rs index 1eab354f..6e7354c1 100644 --- a/crates/knope/src/prompt.rs +++ b/crates/knope/src/prompt.rs @@ -1,6 +1,6 @@ use std::fmt::Display; -use inquire::{InquireError, Password, Select}; +use inquire::{Confirm, InquireError, Password, Select}; use miette::{Diagnostic, Result}; pub(crate) fn select(items: Vec, prompt: &str) -> Result { @@ -15,6 +15,13 @@ pub(crate) fn get_input(prompt: &str) -> Result { .map_err(Error) } +pub(crate) fn confirm(prompt: &str) -> Result { + Confirm::new(prompt) + .with_default(true) + .prompt() + .map_err(Error) +} + #[derive(Debug, Diagnostic, thiserror::Error)] #[error("Failed to get user input")] #[diagnostic( diff --git a/crates/knope/src/step/confirm.rs b/crates/knope/src/step/confirm.rs index cba7110d..430f4081 100644 --- a/crates/knope/src/step/confirm.rs +++ b/crates/knope/src/step/confirm.rs @@ -1,7 +1,6 @@ -use inquire::Confirm; use miette::Diagnostic; -use crate::{app_config, RunType}; +use crate::{prompt, RunType}; pub(crate) fn confirm( mut run_type: RunType, @@ -21,12 +20,12 @@ pub(crate) fn confirm( return Ok(run_type); } - let confirmation = Confirm::new(message).with_default(true).prompt(); + let confirmation = prompt::confirm(message)?; - match confirmation { - Ok(true) => Ok(run_type), - Ok(false) => Err(Error::Confirm), - Err(err) => Err(Error::Prompt(err)), + if confirmation { + Ok(run_type) + } else { + Err(Error::Confirm) } } @@ -34,11 +33,9 @@ pub(crate) fn confirm( pub(crate) enum Error { #[error("User did not confirm")] Confirm, - #[error(transparent)] - Prompt(#[from] inquire::InquireError), #[error("Unable to write to stdout: {0}")] Stdout(#[from] std::io::Error), #[error(transparent)] #[diagnostic(transparent)] - AppConfig(#[from] app_config::Error), + Prompt(#[from] prompt::Error), }