Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 37 additions & 12 deletions src/commands/command_approval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ use color_print::cformat;
use worktrunk::config::{Approvals, require_approvals_path};
use worktrunk::git::{GitError, HookType};
use worktrunk::styling::{
INFO_SYMBOL, WARNING_SYMBOL, eprint, eprintln, hint_message, prompt_message, stderr,
warning_message,
INFO_SYMBOL, WARNING_SYMBOL, eprint, eprintln, format_heading, hint_message, prompt_message,
stderr, warning_message,
};

use super::hook_filter::{HookSource, ParsedFilter};
Expand Down Expand Up @@ -113,7 +113,7 @@ fn display_project_name(project_id: &str) -> &str {

/// The batch as the user sees it: a header, then each command's label and its
/// template. Shared by the prompt and by `--yes` on `wt config approvals add`.
fn print_command_batch(header: &str, commands: &[&ApprovableCommand]) {
fn print_command_batch(header: impl std::fmt::Display, commands: &[&ApprovableCommand]) {
eprintln!("{header}");
for cmd in commands {
// Uses INFO_SYMBOL (○) since this is a preview, not active execution
Expand All @@ -124,34 +124,59 @@ fn print_command_batch(header: &str, commands: &[&ApprovableCommand]) {

/// The batch `wt config approvals add --yes` is about to trust. Nothing is
/// being asked, but the batch still prints: it is the record of what an
/// unattended run just approved. Lives beside [`prompt_for_batch_approval`]
/// unattended run just approved. Lives beside [`prompt_for_batch_review`]
/// so the two headers stay parallel.
pub fn announce_batch_approval(commands: &[&ApprovableCommand], project_id: &str) {
let project_name = display_project_name(project_id);
let count = commands.len();
let plural = if count == 1 { "" } else { "s" };
print_command_batch(
&cformat!(
"{WARNING_SYMBOL} <yellow>Approving <bold>{count}</> command{plural} for <bold>{project_name}</> (--yes):</>"
format_heading(
&cformat!(
"Approving <bold>{count}</> command{plural} for <bold>{project_name}</> (--yes):"
),
None,
),
commands,
);
}

pub fn prompt_for_batch_approval(
fn prompt_for_batch_approval(
commands: &[&ApprovableCommand],
project_id: &str,
) -> anyhow::Result<bool> {
let project_name = display_project_name(project_id);
let count = commands.len();
let plural = if count == 1 { "" } else { "s" };

print_command_batch(
&cformat!(
"{WARNING_SYMBOL} <yellow><bold>{project_name}</> needs approval to execute <bold>{count}</> command{plural}:</>"
),
commands,
let header = cformat!(
"{WARNING_SYMBOL} <yellow><bold>{project_name}</> needs approval to execute <bold>{count}</> command{plural}:</>"
);
prompt_for_batch_approval_with_header(commands, header)
}

/// Prompt used by `wt config approvals add`, where reviewing approvals is the
/// command's expected workflow rather than an interruption to another action.
pub fn prompt_for_batch_review(
commands: &[&ApprovableCommand],
project_id: &str,
) -> anyhow::Result<bool> {
let project_name = display_project_name(project_id);
let count = commands.len();
let plural = if count == 1 { "" } else { "s" };

let header = format_heading(
&cformat!("Review <bold>{count}</> command{plural} for <bold>{project_name}</>:"),
None,
);
prompt_for_batch_approval_with_header(commands, header)
}

fn prompt_for_batch_approval_with_header(
commands: &[&ApprovableCommand],
header: impl std::fmt::Display,
) -> anyhow::Result<bool> {
print_command_batch(header, commands);

// Check if stdin is a TTY before attempting to prompt
// This happens AFTER showing the commands so they appear in CI/CD logs
Expand Down
4 changes: 2 additions & 2 deletions src/commands/config/approvals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use worktrunk::styling::{
};

use crate::cli::SwitchFormat;
use crate::commands::command_approval::{announce_batch_approval, prompt_for_batch_approval};
use crate::commands::command_approval::{announce_batch_approval, prompt_for_batch_review};
use crate::commands::project_config::{
ApprovableCommand, collect_commands_for_aliases, collect_commands_for_hooks,
};
Expand Down Expand Up @@ -236,7 +236,7 @@ pub fn add_approvals(show_all: bool, yes: bool) -> anyhow::Result<()> {
announce_batch_approval(&batch, &project_id);
true
} else {
prompt_for_batch_approval(&batch, &project_id)?
prompt_for_batch_review(&batch, &project_id)?
};

if !approved {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ exit_code: 1
----- stdout -----

----- stderr -----
▲ origin needs approval to execute 1 command:
Review 1 command for origin:
○ pre-start:
  echo 'test'
✗ Cannot prompt for approval in non-interactive environment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ exit_code: 1
----- stdout -----

----- stderr -----
▲ repo needs approval to execute 1 command:
Review 1 command for repo:
○ pre-start:
echo 'hello'
✗ Cannot prompt for approval in non-interactive environment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ exit_code: 1
----- stdout -----

----- stderr -----
▲ origin needs approval to execute 1 command:
Review 1 command for origin:
○ alias deploy:
  echo deploying {{ branch }}
✗ Cannot prompt for approval in non-interactive environment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ exit_code: 0
----- stdout -----

----- stderr -----
▲ Approving 2 commands for repo (--yes):
Approving 2 commands for repo (--yes):
○ pre-merge:
  cargo test
○ alias deploy:
Expand Down
Loading