When `gcloud projects list` times out (10s limit) for users with many projects, the picker now includes a '⌨ Enter project ID manually' option so they can type a known project ID instead of waiting or failing. - Add '⌨ Enter project ID manually' item to project picker - Handle the new item by prompting for input and calling set_gcloud_project - Add EnterProjectId variant to SetupAction (tests) - Add test_project_select_enter_manually unit test Fixes #116 Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
---
|
||||
"@googleworkspace/cli": patch
|
||||
---
|
||||
|
||||
Add "Enter project ID manually" option to project picker in `gws auth setup`.
|
||||
|
||||
Users with large numbers of GCP projects often hit the 10-second listing timeout.
|
||||
The picker now includes a "⌨ Enter project ID manually" item so users can type a
|
||||
known project ID directly without waiting for `gcloud projects list` to complete.
|
||||
+58
-8
@@ -1003,14 +1003,24 @@ fn stage_project(ctx: &mut SetupContext) -> Result<SetupStage, GwsError> {
|
||||
}
|
||||
let current = get_gcloud_project()?.unwrap_or_default();
|
||||
|
||||
let mut items: Vec<SelectItem> = vec![SelectItem {
|
||||
label: "➕ Create new project".to_string(),
|
||||
description: "Create a new GCP project for gws".to_string(),
|
||||
selected: false,
|
||||
is_fixed: false,
|
||||
is_template: false,
|
||||
template_selects: vec![],
|
||||
}];
|
||||
let mut items: Vec<SelectItem> = vec![
|
||||
SelectItem {
|
||||
label: "➕ Create new project".to_string(),
|
||||
description: "Create a new GCP project for gws".to_string(),
|
||||
selected: false,
|
||||
is_fixed: false,
|
||||
is_template: false,
|
||||
template_selects: vec![],
|
||||
},
|
||||
SelectItem {
|
||||
label: "⌨ Enter project ID manually".to_string(),
|
||||
description: "Use an existing project ID you already know".to_string(),
|
||||
selected: false,
|
||||
is_fixed: false,
|
||||
is_template: false,
|
||||
template_selects: vec![],
|
||||
},
|
||||
];
|
||||
items.extend(projects.iter().map(|(id, name)| SelectItem {
|
||||
label: id.clone(),
|
||||
description: name.clone(),
|
||||
@@ -1075,6 +1085,30 @@ fn stage_project(ctx: &mut SetupContext) -> Result<SetupStage, GwsError> {
|
||||
ctx.project_id = project_name;
|
||||
Ok(SetupStage::EnableApis)
|
||||
}
|
||||
Some(item) if item.label.starts_with('⌨') => {
|
||||
let project_id = match ctx
|
||||
.wizard
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.show_input(
|
||||
"Enter GCP project ID",
|
||||
"Type your existing project ID",
|
||||
None,
|
||||
)
|
||||
.map_err(|e| GwsError::Validation(format!("TUI error: {e}")))?
|
||||
{
|
||||
crate::setup_tui::InputResult::Confirmed(v) if !v.is_empty() => v,
|
||||
_ => {
|
||||
return Err(GwsError::Validation(
|
||||
"Project entry cancelled by user".to_string(),
|
||||
))
|
||||
}
|
||||
};
|
||||
set_gcloud_project(&project_id)?;
|
||||
ctx.wiz(2, StepStatus::Done(project_id.clone()));
|
||||
ctx.project_id = project_id;
|
||||
Ok(SetupStage::EnableApis)
|
||||
}
|
||||
Some(item) => {
|
||||
set_gcloud_project(&item.label)?;
|
||||
ctx.wiz(2, StepStatus::Done(item.label.clone()));
|
||||
@@ -1481,6 +1515,7 @@ mod tests {
|
||||
LoginNewAccount,
|
||||
SetProject(String),
|
||||
CreateProject(String),
|
||||
EnterProjectId,
|
||||
EnableApis(Vec<String>),
|
||||
NoSelection,
|
||||
}
|
||||
@@ -1498,6 +1533,7 @@ mod tests {
|
||||
Some(item) if item.label.starts_with('➕') => {
|
||||
SetupAction::CreateProject(String::new())
|
||||
}
|
||||
Some(item) if item.label.starts_with('⌨') => SetupAction::EnterProjectId,
|
||||
Some(item) => SetupAction::SetProject(item.label.clone()),
|
||||
None => SetupAction::NoSelection,
|
||||
}
|
||||
@@ -1692,6 +1728,20 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_project_select_enter_manually() {
|
||||
let mut items = make_items(&[
|
||||
"➕ Create new project",
|
||||
"⌨ Enter project ID manually",
|
||||
"existing",
|
||||
]);
|
||||
items[1].selected = true;
|
||||
assert_eq!(
|
||||
resolve_project_selection(&items),
|
||||
SetupAction::EnterProjectId
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_project_select_none() {
|
||||
let items = make_items(&["➕ Create new project", "proj-a"]);
|
||||
|
||||
Reference in New Issue
Block a user