|
| 1 | +# gobake: The Build Orchestrator Go Was Missing |
| 2 | + |
| 3 | +If you've spent any significant time in the JavaScript ecosystem, you know the comfort of `package.json`. It's the source of truth for your project—metadata, dependencies, and a unified task runner. If you're coming from C++, you might have a love-hate relationship with CMake. But what about Go? |
| 4 | + |
| 5 | +Go has an incredible toolchain (`go build`, `go test`, `go install`), but it lacks a standardized **orchestrator**. When your project grows beyond a single binary, you inevitably reach for `Makefile` or a collection of brittle `.sh` scripts. |
| 6 | + |
| 7 | +That's why I built **gobake**. |
| 8 | + |
| 9 | +## The Gap in the Go Toolchain |
| 10 | + |
| 11 | +Go is famous for its "batteries included" philosophy. However, once you need to manage: |
| 12 | +1. **Project Metadata:** Versioning, authors, and descriptions. |
| 13 | +2. **Task Orchestration:** Running tests, then building, then tagging a release. |
| 14 | +3. **Cross-Platform Binaries:** Building for multiple architectures with specific flags. |
| 15 | +4. **Dev-Tool Management:** Ensuring everyone on the team has the same linting tools. |
| 16 | + |
| 17 | +...you're suddenly out of the Go world and back into the wild west of shell scripts. `gobake` fixes this by allowing you to write your build logic in the language you already love: **Go**. |
| 18 | + |
| 19 | +## What is gobake? |
| 20 | + |
| 21 | +`gobake` is a Go-native build orchestrator. It replaces static configuration with a type-safe `Recipe.go` file. It's inspired by projects like `nob.h`, but tailored specifically for the Gopher workflow. |
| 22 | + |
| 23 | +```mermaid |
| 24 | +graph TD |
| 25 | + A["recipe.piml (Metadata)"] --> B["gobake Engine"] |
| 26 | + C["Recipe.go (Logic)"] --> B |
| 27 | + B --> D{Task Runner} |
| 28 | + D --> E["Build Binary"] |
| 29 | + D --> F["Run Tests"] |
| 30 | + D --> G["Git Tag/Release"] |
| 31 | + D --> H["Auto-Versioning"] |
| 32 | +``` |
| 33 | + |
| 34 | +### The Anatomy of a Baked Project |
| 35 | + |
| 36 | +A `gobake` project centers around two files: |
| 37 | + |
| 38 | +1. **`recipe.piml`**: A [PIML](https://fezcode.github.io/posts/piml) file for project metadata. |
| 39 | +2. **`Recipe.go`**: A Go file where you define your tasks and logic. |
| 40 | + |
| 41 | +### Type-Safe Tasks |
| 42 | + |
| 43 | +Instead of worrying about tab vs. space in a Makefile, you define tasks with a clean Go API. Since version 0.3.0, we use the `//go:build gobake` tag to ensure your recipe stays separated from your main application logic while remaining perfectly valid Go: |
| 44 | + |
| 45 | +```go |
| 46 | +//go:build gobake |
| 47 | +package bake_recipe |
| 48 | + |
| 49 | +import ( |
| 50 | + "fmt" |
| 51 | + "github.com/fezcode/gobake" |
| 52 | +) |
| 53 | + |
| 54 | +func Run(bake *gobake.Engine) error { |
| 55 | + bake.LoadRecipeInfo("recipe.piml") |
| 56 | + |
| 57 | + bake.Task("build", "Builds the binary", func(ctx *gobake.Context) error { |
| 58 | + ctx.Log("Building v%s...", bake.Info.Version) |
| 59 | + return ctx.Run("go", "build", "-o", "bin/app", "./cmd/main.go") |
| 60 | + }) |
| 61 | + |
| 62 | + bake.TaskWithDeps("release", "Build and Tag", []string{"build"}, func(ctx *bake.Context) error { |
| 63 | + return ctx.Run("git", "tag", "v"+bake.Info.Version) |
| 64 | + }) |
| 65 | + |
| 66 | + return nil |
| 67 | +} |
| 68 | +``` |
| 69 | + |
| 70 | +## Why Choose gobake? |
| 71 | + |
| 72 | +### 1. Zero New Syntax |
| 73 | +If you know Go, you know `gobake`. You don't need to learn the esoteric syntax of `make` or the sprawling configuration of a CI/CD YAML just to run a local build. |
| 74 | + |
| 75 | +### 2. Built-in Versioning |
| 76 | +Managing semantic versions is a chore. `gobake` handles it natively: |
| 77 | +```bash |
| 78 | +gobake bump patch # Increments 1.0.0 to 1.0.1 in recipe.piml |
| 79 | +``` |
| 80 | + |
| 81 | +### 3. Dependency & Tool Management |
| 82 | +`gobake` can manage your `go get` dependencies and development tools (like `golangci-lint`) directly through the CLI, keeping your `recipe.piml` updated as the source of truth. The `init` command now automatically handles `go mod` setup and library acquisition. |
| 83 | + |
| 84 | +### 4. Cross-Compilation Made Easy |
| 85 | +Baking binaries for different platforms is a first-class citizen: |
| 86 | +```go |
| 87 | +ctx.BakeBinary("linux", "amd64", "dist/app-linux") |
| 88 | +``` |
| 89 | + |
| 90 | +## Getting Started |
| 91 | + |
| 92 | +To use `gobake`, you need two things: the **CLI tool** for running tasks and the **library** as a dependency in your project (since your `Recipe.go` will import it). |
| 93 | + |
| 94 | +### 1. Install the CLI |
| 95 | +```bash |
| 96 | +go install github.com/fezcode/gobake/cmd/gobake@latest |
| 97 | +``` |
| 98 | + |
| 99 | +### 2. Initialize Your Project |
| 100 | +The easiest way to get started is with the `init` command (refined in v0.3.0): |
| 101 | +```bash |
| 102 | +gobake init |
| 103 | +``` |
| 104 | + |
| 105 | +The `init` command is smart: it handles `go mod init` (if needed), scaffolds your `recipe.piml` and `Recipe.go`, and runs `go mod tidy` to automatically pull in the `github.com/fezcode/gobake` library as a dependency. |
| 106 | + |
| 107 | +If you are adding it to an existing project and want to do it manually: |
| 108 | +```bash |
| 109 | +go get github.com/fezcode/gobake |
| 110 | +``` |
| 111 | + |
| 112 | +And run your first task: |
| 113 | +```bash |
| 114 | +gobake build |
| 115 | +``` |
| 116 | + |
| 117 | +## Conclusion |
| 118 | + |
| 119 | +Go deserves a build system that feels like Go. `gobake` aims to provide that missing orchestration layer—giving you the "package.json feel" without sacrificing the performance and type-safety of the Go ecosystem. |
| 120 | + |
| 121 | +Check it out on GitHub: [github.com/fezcode/gobake](https://github.com/fezcode/gobake) |
| 122 | +Or visit the project page: [/projects/gobake](/projects/gobake) |
| 123 | + |
| 124 | +Happy baking! 🥐 |
0 commit comments