diff --git a/docs/pages/docs/providers/go.md b/docs/pages/docs/providers/go.md index b4bc51be9..972621764 100644 --- a/docs/pages/docs/providers/go.md +++ b/docs/pages/docs/providers/go.md @@ -34,12 +34,12 @@ go get ## Build If your project has multiple binaries, you can specify which one to run with the `NIXPACKS_GO_BIN` environment variable. -Otherwise, the first binary found in the project's `cmd` directory the in the project's root directory will be used. +Otherwise, the first binary found in the project's root directory or the project's `cmd` directory will be used. ``` -go build -o out ./cmd/{name} -# Or go build -o out +# Or if there are no .go files in the root directory +go build -o out ./cmd/{name} ``` diff --git a/examples/go-gin/cmd/server/main.go b/examples/go-gin/cmd/server/main.go new file mode 100644 index 000000000..c4c5db985 --- /dev/null +++ b/examples/go-gin/cmd/server/main.go @@ -0,0 +1,17 @@ +package main + +import ( + "github.com/gin-gonic/gin" +) + +var Router *gin.Engine + +func main() { + r := gin.Default() + r.GET("/", func(c *gin.Context) { + c.JSON(200, gin.H{ + "message": "Hello world!", + }) + }) + r.Run() +} diff --git a/src/providers/go.rs b/src/providers/go.rs index 874ea6aa5..cb0a27cd3 100644 --- a/src/providers/go.rs +++ b/src/providers/go.rs @@ -65,26 +65,38 @@ impl Provider for GolangProvider { setup.set_nix_archive(archive); plan.add_phase(setup); + let is_go_module = app.includes_file("go.mod"); - if app.includes_file("go.mod") { + if is_go_module { let mut install = Phase::install(Some("go mod download".to_string())); install.add_cache_directory(GO_BUILD_CACHE_DIR.to_string()); plan.add_phase(install); } + let has_root_go_files = app.find_files("*.go").ok().map_or(false, |files| { + files + .iter() + .any(|file| file.parent() == Some(app.source.as_path())) + }); + let build_command = if let Some(name) = env.get_config_variable("GO_BIN") { Some(format!("go build -o {BINARY_NAME} ./cmd/{name}")) + } else if is_go_module && has_root_go_files { + Some(format!("go build -o {BINARY_NAME}")) } else if app.includes_directory("cmd") { // Try to find a command in the cmd directory app.find_directories("cmd/*") .ok() - .and_then(|dirs| dirs.into_iter().next()) + .and_then(|dirs| { + dirs.into_iter() + .find(|path| path.parent().map_or(false, |p| p.ends_with("cmd"))) + }) .and_then(|path| { path.file_name() .and_then(|os_str| os_str.to_str()) .map(|name| format!("go build -o {BINARY_NAME} ./cmd/{name}")) }) - } else if app.includes_file("go.mod") { + } else if is_go_module { Some(format!("go build -o {BINARY_NAME}")) } else if app.includes_file("main.go") { Some(format!("go build -o {BINARY_NAME} main.go"))