Migrating from Mage
Mage (magefile.org) uses Go functions as build tasks. Jake provides similar functionality with a simpler DSL that doesn’t require compiling.
Syntax Comparison
Section titled “Syntax Comparison”| Mage | Jake |
|---|---|
magefile.go | Jakefile |
func Build() | task build: |
mg.Deps(Install) | [install] |
sh.Run(...) | Direct command |
//go:build mage | Not needed |
Basic Task Conversion
Section titled “Basic Task Conversion”//go:build mage
package main
import "github.com/magefile/mage/sh"
// Build compiles the applicationfunc Build() error { return sh.Run("go", "build", "-o", "app", ".")}# Build compiles the applicationtask build: go build -o app .Dependencies
Section titled “Dependencies”import "github.com/magefile/mage/mg"
func Build() error { mg.Deps(Install, Generate) return sh.Run("go", "build", "-o", "app")}
func Install() error { return sh.Run("go", "mod", "download")}
func Generate() error { return sh.Run("go", "generate", "./...")}task build: [install, generate] go build -o app
task install: go mod download
task generate: go generate ./...Error Handling
Section titled “Error Handling”func Deploy() error { if err := Build(); err != nil { return fmt.Errorf("build failed: %w", err) } if err := sh.Run("rsync", "-avz", "dist/", "server:/app/"); err != nil { return err } return nil}task deploy: [build] rsync -avz dist/ server:/app/Jake automatically stops on command failure.
Environment Variables
Section titled “Environment Variables”func Build() error { env := map[string]string{ "CGO_ENABLED": "0", "GOOS": "linux", } return sh.RunWith(env, "go", "build", "-o", "app")}task build: CGO_ENABLED=0 GOOS=linux go build -o appOr use @export:
@export CGO_ENABLED=0
task build: GOOS=linux go build -o appConditional Logic
Section titled “Conditional Logic”import "runtime"
func Install() error { if runtime.GOOS == "darwin" { return sh.Run("brew", "install", "deps") } return sh.Run("apt-get", "install", "deps")}@platform macostask install: brew install deps
@platform linuxtask install: apt-get install depsFile Operations
Section titled “File Operations”import "github.com/magefile/mage/sh"
func Clean() error { return sh.Rm("dist")}
func Prepare() error { return os.MkdirAll("dist", 0755)}task clean: rm -rf dist
task prepare: mkdir -p distVerbose/Debug Output
Section titled “Verbose/Debug Output”import "github.com/magefile/mage/mg"
func Build() error { if mg.Verbose() { fmt.Println("Building with verbose output...") } return sh.Run("go", "build", "-v", "-o", "app")}task build: @if is_verbose() echo "Building with verbose output..." go build -v -o app @else go build -o app @endNamespaced Targets
Section titled “Namespaced Targets”type Docker mg.Namespace
func (Docker) Build() error { return sh.Run("docker", "build", "-t", "myapp", ".")}
func (Docker) Push() error { return sh.Run("docker", "push", "myapp")}Usage: mage docker:build
Using imports:
task build: docker build -t myapp .
task push: docker push myapp# Jakefile@import "docker.jake" as docker
task release: [docker.build, docker.push] echo "Released!"Usage: jake docker.build
Complete Migration Example
Section titled “Complete Migration Example”Before (magefile.go)
Section titled “Before (magefile.go)”//go:build mage
package main
import ( "fmt" "os" "github.com/magefile/mage/mg" "github.com/magefile/mage/sh")
var Default = Build
// Install downloads dependenciesfunc Install() error { fmt.Println("Installing dependencies...") return sh.Run("go", "mod", "download")}
// Build compiles the applicationfunc Build() error { mg.Deps(Install) fmt.Println("Building...") env := map[string]string{"CGO_ENABLED": "0"} return sh.RunWith(env, "go", "build", "-o", "bin/app", "./cmd/app")}
// Test runs the test suitefunc Test() error { mg.Deps(Build) return sh.Run("go", "test", "-v", "./...")}
// Clean removes build artifactsfunc Clean() error { fmt.Println("Cleaning...") return sh.Rm("bin")}
type Docker mg.Namespace
// Build builds the Docker imagefunc (Docker) Build() error { mg.Deps(Build) return sh.Run("docker", "build", "-t", "myapp:latest", ".")}
// Push pushes to registryfunc (Docker) Push() error { return sh.Run("docker", "push", "myapp:latest")}After (Jakefile)
Section titled “After (Jakefile)”@export CGO_ENABLED=0
@defaulttask build: [install] @desc "Build the application" @pre echo "Building..." go build -o bin/app ./cmd/app
task install: @desc "Install dependencies" @pre echo "Installing dependencies..." go mod download
task test: [build] @desc "Run the test suite" go test -v ./...
task clean: @desc "Remove build artifacts" @pre echo "Cleaning..." rm -rf bin/
# Docker namespace via import or inline@group dockertask docker-build: [build] @desc "Build Docker image" docker build -t myapp:latest .
@group dockertask docker-push: @desc "Push to registry" docker push myapp:latestCLI Comparison
Section titled “CLI Comparison”| Mage | Jake |
|---|---|
mage | jake |
mage build | jake build |
mage -l | jake --list |
mage -v build | jake -v build |
mage docker:build | jake docker-build |
mage -compile ./bin | Not needed (interpreted) |
Key Differences
Section titled “Key Differences”| Feature | Mage | Jake |
|---|---|---|
| Language | Go | DSL |
| Compilation | Required first run | None (interpreted) |
| File deps | Manual | Native file recipes |
| Parallel | Manual goroutines | -j flag |
| Namespaces | mg.Namespace | @import as |
What You Gain
Section titled “What You Gain”- No compilation - Runs immediately
- File dependency tracking - Built-in
filerecipes - Simpler syntax - No Go boilerplate
- Parallel execution - Built-in with
-j - Watch mode -
jake -w build
What You Lose
Section titled “What You Lose”- Go type safety - No compile-time checks
- Go ecosystem - Can’t import Go packages
- Complex logic - Move to external scripts
See Also
Section titled “See Also”- File Targets - Dependency tracking
- Imports - Namespacing with imports
- Parallel Execution