Makefiles work but the syntax is painful: tabs vs spaces, shell escaping, .PHONY everywhere, platform-specific commands. Task uses YAML, runs cross-platform, and handles dependencies cleanly.
Installation
# macOS
brew install go-task
# Linux
sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d
# Or via npm
npm install -g @go-task/cliBasic Taskfile
# Taskfile.yml
version: "3"
tasks:
build:
desc: Build the application
cmds:
- go build -o bin/app ./cmd/app
test:
desc: Run tests
cmds:
- go test ./...
lint:
desc: Run linters
cmds:
- golangci-lint run
dev:
desc: Run with hot reload
cmds:
- air -c .air.tomltask build
task test
task --list # Show all available tasksDependencies
tasks:
build:
deps: [lint, test]
cmds:
- go build -o bin/app ./cmd/app
docker:
deps: [build]
cmds:
- docker build -t myorg/app:latest .
deploy:
deps: [docker]
cmds:
- kubectl set image deployment/app app=myorg/app:{{.TAG}}
vars:
TAG:
sh: git rev-parse --short HEADtask deploy runs lint → test → build → docker → deploy in order. Dependencies run in parallel when possible.
Master this topic with hands-on labs
Go beyond reading — build real projects in sandboxed environments with expert video guidance.
Browse Courses →Variables
version: "3"
vars:
APP_NAME: order-api
VERSION:
sh: git describe --tags --always
GO_FILES:
sh: find . -name '*.go' -type f
tasks:
build:
cmds:
- go build -ldflags "-X main.version={{.VERSION}}" -o bin/{{.APP_NAME}}
info:
cmds:
- echo "Building {{.APP_NAME}} version {{.VERSION}}"Environment Variables
tasks:
test:
env:
DATABASE_URL: postgres://localhost:5432/test
REDIS_URL: redis://localhost:6379
cmds:
- go test ./...
test-ci:
dotenv: [".env.test"]
cmds:
- go test -race -coverprofile=coverage.out ./...Conditional Execution
tasks:
generate:
desc: Generate code (only if sources changed)
sources:
- api/openapi.yaml
generates:
- internal/api/server.go
cmds:
- oapi-codegen -generate server api/openapi.yaml > internal/api/server.go
install-tools:
desc: Install development tools
status:
- which golangci-lint
- which air
cmds:
- go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
- go install github.com/air-verse/air@latestsources/generates skips the task if outputs are newer than inputs. status skips if all checks pass.
Get weekly IT automation tips
Docker, Ansible, Terraform, MLOps — curated insights delivered to your inbox. No spam.
Subscribe Free →Multi-Platform
tasks:
clean:
cmds:
- rm -rf bin/
platforms: [linux, darwin]
clean:windows:
cmds:
- Remove-Item -Recurse -Force bin
platforms: [windows]
open:
cmds:
- cmd: open http://localhost:3000
platforms: [darwin]
- cmd: xdg-open http://localhost:3000
platforms: [linux]Namespaces (Included Taskfiles)
# Taskfile.yml
version: "3"
includes:
docker: ./taskfiles/Docker.yml
k8s: ./taskfiles/Kubernetes.yml
db: ./taskfiles/Database.ymltask docker:build
task k8s:deploy
task db:migrateReal-World Example
version: "3"
vars:
APP: order-api
TAG:
sh: git rev-parse --short HEAD
REGISTRY: ghcr.io/myorg
tasks:
default:
cmds:
- task --list
setup:
desc: Install development dependencies
status:
- which air
- which golangci-lint
cmds:
- go install github.com/air-verse/air@latest
- go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
dev:
desc: Start development server with hot reload
deps: [setup]
cmds:
- air
test:
desc: Run tests
cmds:
- go test -race -count=1 ./...
test-coverage:
desc: Run tests with coverage report
cmds:
- go test -race -coverprofile=coverage.out ./...
- go tool cover -html=coverage.out -o coverage.html
- echo "Coverage report: coverage.html"
lint:
desc: Run linters
cmds:
- golangci-lint run
build:
desc: Build binary
deps: [lint, test]
cmds:
- CGO_ENABLED=0 go build -ldflags "-s -w -X main.version={{.TAG}}" -o bin/{{.APP}}
docker-build:
desc: Build Docker image
cmds:
- docker build -t {{.REGISTRY}}/{{.APP}}:{{.TAG}} .
docker-push:
desc: Push Docker image
deps: [docker-build]
cmds:
- docker push {{.REGISTRY}}/{{.APP}}:{{.TAG}}
deploy:
desc: Deploy to Kubernetes
deps: [docker-push]
cmds:
- kubectl set image deployment/{{.APP}} {{.APP}}={{.REGISTRY}}/{{.APP}}:{{.TAG}}
- kubectl rollout status deployment/{{.APP}}
clean:
desc: Clean build artifacts
cmds:
- rm -rf bin/ coverage.out coverage.htmlTask vs Make
| Feature | Task | Make |
|---|---|---|
| Syntax | YAML | Makefile (tabs!) |
| Cross-platform | Yes | Needs GNU Make |
| Variables | Clean YAML | Complex escaping |
| Dependencies | Parallel by default | Sequential by default |
| Conditional skip | sources/generates/status | File timestamps only |
| Namespaces | includes | Recursive make |
| Learning curve | Low | Medium |
---
Ready to go deeper? Master DevOps automation with hands-on courses at CopyPasteLearn.
Ready to learn by doing?
Stop reading tutorials — start building. Expert video courses with hands-on labs in real sandboxed environments.
Related Articles
Quality vs Cost in DevOps
The quality-cost tradeoff in DevOps is real but misunderstood. Learn why cutting quality to reduce cost usually increases total cost, and how to find.
Platform Engineering vs DevOps
Platform engineering and DevOps solve different problems. Learn how platform teams build internal developer platforms, where DevOps still applies.
Ansible vs Terraform When to Use
Ansible and Terraform solve different infrastructure problems. Learn when to use each, when to use both together, and how they complement each other.
Tekton Cloud Native CI/CD
Tekton runs CI/CD pipelines as Kubernetes custom resources. Learn how Tekton works, how to build pipelines with Tasks and Pipelines, and when to choose it.
Telepresence Local Kubernetes Dev
Telepresence connects your local machine to a remote Kubernetes cluster for fast development. Learn how to intercept traffic, debug services locally, and skip.
Terraform Ansible Kubernetes Stack
Combine Terraform, Ansible, and Kubernetes for complete DevOps infrastructure. Provision, configure, and deploy end to end.
Explore topics
Browse more articles on the topics covered here.