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
1 change: 1 addition & 0 deletions docs/docs/commands/doctor.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Options:
-o, --only <ONLY> When set, only the checks listed will run
-f, --fix <FIX> When set, if a fix is specified it will also run [default: true] [possible values: true, false]
-n, --no-cache When set cache will be disabled, forcing all file based checks to run
--yolo Automatically approve all fix prompts without asking
(excluded default args)
```

Expand Down
4 changes: 4 additions & 0 deletions scope/src/doctor/commands/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ pub struct DoctorRunArgs {
/// Do not ask, create report on failure
#[arg(long, default_value = "false", env = "SCOPE_DOCTOR_AUTO_PUBLISH")]
pub auto_publish_report: bool,
/// Automatically approve all fix prompts without asking
#[arg(long, short = 'y', default_value = "false")]
pub yolo: bool,
}

fn get_cache(args: &DoctorRunArgs) -> Arc<dyn FileCache> {
Expand Down Expand Up @@ -101,6 +104,7 @@ pub async fn doctor_run(found_config: &FoundConfig, args: &DoctorRunArgs) -> Res
let run_groups = RunGroups {
group_actions: transform.groups,
all_paths,
yolo: args.yolo,
};

let result = run_groups.execute().await?;
Expand Down
19 changes: 18 additions & 1 deletion scope/src/doctor/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ where
{
pub(crate) group_actions: BTreeMap<String, GroupActionContainer<T>>,
pub(crate) all_paths: Vec<String>,
pub(crate) yolo: bool,
}

impl<T> RunGroups<T>
Expand Down Expand Up @@ -293,8 +294,9 @@ where
));
action_span.pb_set_style(&progress_bar_without_pos());

let prompt_fn = if self.yolo { auto_approve } else { prompt_user };
Copy link
Collaborator

Choose a reason for hiding this comment

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

❤️ Easy peezy. Like it.

let action_result = action
.run_action(prompt_user)
.run_action(prompt_fn)
.instrument(action_span.clone())
.await?;

Expand Down Expand Up @@ -362,6 +364,14 @@ fn prompt_user(prompt_text: &str, maybe_help_text: &Option<String>) -> bool {
})
}

fn auto_approve(prompt_text: &str, maybe_help_text: &Option<String>) -> bool {
println!("{} Yes (auto-approved)", prompt_text);
if let Some(help_text) = maybe_help_text {
println!("[{}]", help_text);
}
true
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm wondering if it is worth while to write the context of the prompt and help text with an additional log that it's being automatically applied.

I can't quite picture in my head what the user experience or backend traces look like.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think that makes sense - will do that

}

async fn report_action_output<T>(
group_name: &str,
action: &T,
Expand Down Expand Up @@ -753,6 +763,7 @@ mod tests {
"group_2".to_string(),
"group_3".to_string(),
],
yolo: false,
};

let exit_code = run_groups.execute().await?;
Expand Down Expand Up @@ -784,6 +795,7 @@ mod tests {
"skipped_1".to_string(),
"skipped_2".to_string(),
],
yolo: false,
};

let exit_code = run_groups.execute().await?;
Expand Down Expand Up @@ -821,6 +833,7 @@ mod tests {
"user_denies".to_string(),
"skipped".to_string(),
],
yolo: false,
};

let exit_code = run_groups.execute().await?;
Expand Down Expand Up @@ -868,6 +881,7 @@ mod tests {
"user_denies".to_string(),
"succeeds_2".to_string(),
],
yolo: false,
};

let exit_code = run_groups.execute().await?;
Expand Down Expand Up @@ -911,6 +925,7 @@ mod tests {
"fails".to_string(),
"succeeds_2".to_string(),
],
yolo: false,
};

let exit_code = run_groups.execute().await?;
Expand Down Expand Up @@ -1019,6 +1034,7 @@ mod tests {
let run_groups = RunGroups {
group_actions: BTreeMap::new(),
all_paths: Vec::new(),
yolo: false,
};

let group_span = info_span!("test_group", "indicatif.pb_show" = true);
Expand Down Expand Up @@ -1072,6 +1088,7 @@ mod tests {
let run_groups = RunGroups {
group_actions: BTreeMap::new(),
all_paths: Vec::new(),
yolo: false,
};

let group_span = info_span!("test_group", "indicatif.pb_show" = true);
Expand Down
20 changes: 20 additions & 0 deletions scope/tests/scope_doctor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,3 +270,23 @@ fn test_group_skip_subsequent_groups_run() {

test_helper.clean_work_dir();
}

#[test]
fn test_yolo_flag_auto_approves_fix_prompts() {
let test_helper = ScopeTestHelper::new(
"test_yolo_flag_auto_approves_fix_prompts",
"fix-with-prompt",
);

// Without --yolo, the fix would be skipped because user can't confirm in non-interactive mode.
// With --yolo, the fix should run automatically and succeed.
let result = test_helper.doctor_run(Some(&["--yolo"]));

result
.success()
.stdout(predicate::str::contains(
"Check initially failed, fix was successful, group: \"prompt-test\", name: \"needs-approval\"",
));

test_helper.clean_work_dir();
}
18 changes: 18 additions & 0 deletions scope/tests/test-cases/fix-with-prompt/.scope/group.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
apiVersion: scope.github.com/v1alpha
kind: ScopeDoctorGroup
metadata:
name: prompt-test
description: Test fix that requires user confirmation
spec:
actions:
- name: needs-approval
description: A fix that needs user approval before running
check:
commands:
- test -f {{ working_dir }}/approved-file.txt
fix:
prompt:
text: "Do you want to create the file?"
extraContext: "This will create approved-file.txt"
commands:
- touch {{ working_dir }}/approved-file.txt