go: Run ./... tasks against current module (#20190)

In #17108, we updated `go test ./...` to run against the package
directory, to fix cases in which the top-level project is not the go
module root. However, this leads to the confusing behavior of `go test
./...` only running tests in subdirectories of the current package.
Here, we change the behavior to instead walk up the dirtree to find the
closest `go.mod`, and run the `./...` tasks relative to that directory.
This might lead to more predictable behavior for these tasks.

Also see:
https://github.com/zed-industries/zed/pull/19987#issuecomment-2450159099

Release Notes:

- Improved go test and generate `./...` commands to run against the
current go module directory rather than the current package directory
This commit is contained in:
Roshan Padaki 2024-11-06 08:55:57 -05:00 committed by GitHub
parent 484e5df2ee
commit 1eb6fb0b5d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -408,6 +408,8 @@ fn adjust_runs(
pub(crate) struct GoContextProvider; pub(crate) struct GoContextProvider;
const GO_PACKAGE_TASK_VARIABLE: VariableName = VariableName::Custom(Cow::Borrowed("GO_PACKAGE")); const GO_PACKAGE_TASK_VARIABLE: VariableName = VariableName::Custom(Cow::Borrowed("GO_PACKAGE"));
const GO_MODULE_ROOT_TASK_VARIABLE: VariableName =
VariableName::Custom(Cow::Borrowed("GO_MODULE_ROOT"));
const GO_SUBTEST_NAME_TASK_VARIABLE: VariableName = const GO_SUBTEST_NAME_TASK_VARIABLE: VariableName =
VariableName::Custom(Cow::Borrowed("GO_SUBTEST_NAME")); VariableName::Custom(Cow::Borrowed("GO_SUBTEST_NAME"));
@ -447,15 +449,33 @@ impl ContextProvider for GoContextProvider {
(GO_PACKAGE_TASK_VARIABLE.clone(), package_name.to_string()) (GO_PACKAGE_TASK_VARIABLE.clone(), package_name.to_string())
}); });
let go_module_root_variable = local_abs_path
.as_deref()
.and_then(|local_abs_path| local_abs_path.parent())
.map(|buffer_dir| {
// Walk dirtree up until getting the first go.mod file
let module_dir = buffer_dir
.ancestors()
.find(|dir| dir.join("go.mod").is_file())
.map(|dir| dir.to_string_lossy().to_string())
.unwrap_or_else(|| ".".to_string());
(GO_MODULE_ROOT_TASK_VARIABLE.clone(), module_dir)
});
let _subtest_name = variables.get(&VariableName::Custom(Cow::Borrowed("_subtest_name"))); let _subtest_name = variables.get(&VariableName::Custom(Cow::Borrowed("_subtest_name")));
let go_subtest_variable = extract_subtest_name(_subtest_name.unwrap_or("")) let go_subtest_variable = extract_subtest_name(_subtest_name.unwrap_or(""))
.map(|subtest_name| (GO_SUBTEST_NAME_TASK_VARIABLE.clone(), subtest_name)); .map(|subtest_name| (GO_SUBTEST_NAME_TASK_VARIABLE.clone(), subtest_name));
Ok(TaskVariables::from_iter( Ok(TaskVariables::from_iter(
[go_package_variable, go_subtest_variable] [
.into_iter() go_package_variable,
.flatten(), go_subtest_variable,
go_module_root_variable,
]
.into_iter()
.flatten(),
)) ))
} }
@ -469,6 +489,7 @@ impl ContextProvider for GoContextProvider {
} else { } else {
Some("$ZED_DIRNAME".to_string()) Some("$ZED_DIRNAME".to_string())
}; };
let module_cwd = Some(GO_MODULE_ROOT_TASK_VARIABLE.template_value());
Some(TaskTemplates(vec![ Some(TaskTemplates(vec![
TaskTemplate { TaskTemplate {
@ -498,7 +519,7 @@ impl ContextProvider for GoContextProvider {
label: "go test ./...".into(), label: "go test ./...".into(),
command: "go".into(), command: "go".into(),
args: vec!["test".into(), "./...".into()], args: vec!["test".into(), "./...".into()],
cwd: package_cwd.clone(), cwd: module_cwd.clone(),
..TaskTemplate::default() ..TaskTemplate::default()
}, },
TaskTemplate { TaskTemplate {
@ -561,7 +582,7 @@ impl ContextProvider for GoContextProvider {
label: "go generate ./...".into(), label: "go generate ./...".into(),
command: "go".into(), command: "go".into(),
args: vec!["generate".into(), "./...".into()], args: vec!["generate".into(), "./...".into()],
cwd: package_cwd.clone(), cwd: module_cwd.clone(),
..TaskTemplate::default() ..TaskTemplate::default()
}, },
])) ]))