Etapa G: detect_go_main prefiere cmd/<nombre-receta> entre varios mains
eksctl tiene cmd/eksctl (CLI) + cmd/schema (helper de codegen que panica); detect elegía arbitrariamente y selló el binario equivocado (schema) — un fallo SILENCIOSO (sella OK pero envía la herramienta incorrecta). Ahora, a igual clase, el dir cuyo file_name == recipe.name gana. Test detect_go_main_prefers_cmd_matching_recipe_name. Lección: smoke-testear que el binario instalado es el ESPERADO, no solo que selló.
This commit is contained in:
@@ -485,7 +485,7 @@ fn detect_build_system(src: &Path) -> BuildSys {
|
||||
/// scripts/tools/internal y ocultos/`_`). Elige el principal por heurística: raíz > `cmd/<x>` >
|
||||
/// menor profundidad. Devuelve un path estilo go (`.`, `./cmd/mlr`). Una receta puede forzar el
|
||||
/// paquete vía `build.flags` (gana sobre la auto-detección).
|
||||
fn detect_go_main(src: &Path) -> String {
|
||||
fn detect_go_main(src: &Path, pkg_name: &str) -> String {
|
||||
fn is_main_go(path: &Path) -> bool {
|
||||
let Ok(text) = std::fs::read_to_string(path) else { return false };
|
||||
// El primer token significativo de un .go es la cláusula `package` (tras build-constraints
|
||||
@@ -562,17 +562,22 @@ fn detect_go_main(src: &Path) -> String {
|
||||
}
|
||||
}
|
||||
}
|
||||
// raíz (prioridad 0) > cmd/<x> (1) > resto (2); a igual clase, menor profundidad.
|
||||
let key = |p: &PathBuf| -> (u8, usize) {
|
||||
// raíz (prioridad 0) > cmd/<x> (1) > resto (2); a igual clase, el dir cuyo nombre coincide con el
|
||||
// de la receta (p.ej. cmd/eksctl para la receta `eksctl`) gana sobre otros mains hermanos (cmd/
|
||||
// schema, un helper de codegen que panica) — sin esto detect elegía arbitrariamente entre varios
|
||||
// mains y sellaba el binario EQUIVOCADO; luego, a igual nombre, menor profundidad.
|
||||
let key = |p: &PathBuf| -> (u8, u8, usize) {
|
||||
let s = p.to_string_lossy();
|
||||
let depth = p.components().count();
|
||||
if s.is_empty() {
|
||||
(0, depth)
|
||||
let name_match = if p.file_name().map(|f| f == pkg_name).unwrap_or(false) { 0 } else { 1 };
|
||||
let class = if s.is_empty() {
|
||||
0
|
||||
} else if s.starts_with("cmd/") || s == "cmd" {
|
||||
(1, depth)
|
||||
1
|
||||
} else {
|
||||
(2, depth)
|
||||
}
|
||||
2
|
||||
};
|
||||
(class, name_match, depth)
|
||||
};
|
||||
found.sort_by_key(key);
|
||||
match found.first() {
|
||||
@@ -740,7 +745,7 @@ fn resolve_phases(recipe: &Recipe, src: &Path) -> hammer_core::Result<Phases> {
|
||||
// el nombre. Offline+reproducible: vendor (vendor_go_deps) + GOPROXY=off + -trimpath
|
||||
// -buildid=. El toolchain `go` llega por deps.build=["go"] (overlay).
|
||||
let pkg = if recipe.build.flags.is_empty() {
|
||||
detect_go_main(src)
|
||||
detect_go_main(src, &recipe.name)
|
||||
} else {
|
||||
flags.clone()
|
||||
};
|
||||
@@ -839,7 +844,19 @@ commit = "deadbeef"
|
||||
std::fs::create_dir_all(d.path().join(sub)).unwrap();
|
||||
std::fs::write(d.path().join(sub).join("main.go"), b"package main\nfunc main(){}\n").unwrap();
|
||||
}
|
||||
assert_eq!(detect_go_main(d.path()), "./cmd/mlr");
|
||||
assert_eq!(detect_go_main(d.path(), "mlr"), "./cmd/mlr");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn detect_go_main_prefers_cmd_matching_recipe_name() {
|
||||
// eksctl-like: cmd/eksctl (CLI real) + cmd/schema (helper que panica). El dir que coincide
|
||||
// con el name de la receta gana sobre el hermano ⇒ no sella el binario equivocado.
|
||||
let d = tempfile::tempdir().unwrap();
|
||||
for sub in ["cmd/schema", "cmd/eksctl"] {
|
||||
std::fs::create_dir_all(d.path().join(sub)).unwrap();
|
||||
std::fs::write(d.path().join(sub).join("main.go"), b"package main\nfunc main(){}\n").unwrap();
|
||||
}
|
||||
assert_eq!(detect_go_main(d.path(), "eksctl"), "./cmd/eksctl");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -853,7 +870,7 @@ commit = "deadbeef"
|
||||
b"/*\nCopyright The Helm Authors.\nLicensed under the Apache License 2.0\n*/\n\npackage main\n\nfunc main() {}\n",
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(detect_go_main(d.path()), "./cmd/helm");
|
||||
assert_eq!(detect_go_main(d.path(), "helm"), "./cmd/helm");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user