CI/CD GitHub Actions
Hub › Golang › Advanced › CI/CD GitHub Actions
Goal
Add a GitHub Actions workflow that lints, tests (unit + integration), builds, and pushes a Docker image to GitHub Container Registry.
Prerequisites
- Graceful shutdown
- A GitHub repository with the Go module pushed
The workflow
Create .github/workflows/ci.yml:
yaml
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
ci:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:17-alpine
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: pass
POSTGRES_DB: itemsdb
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 2s
--health-retries 5
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: "1.22"
- name: Lint
uses: golangci/golangci-lint-action@v6
with:
version: latest
- name: Unit tests
run: go test -v -short -count=1 ./...
env:
DATABASE_URL: postgres://postgres:pass@localhost:5432/itemsdb?sslmode=disable
- name: Build
run: go build -o /dev/null .
docker:
if: github.ref == 'refs/heads/main'
needs: ci
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v6
with:
push: true
tags: ghcr.io/${{ github.repository }}:${{ github.sha }}Key points:
- The
services.postgresblock starts a PostgreSQL container as a sidecar for integration tests. - Unit tests pass via
-shortflag (you can skip Testcontainers-based tests withtesting.Short()). - Docker push runs only on
mainbranch, after CI passes. - The image is tagged with the commit SHA for traceability.
Add build tags to tests
Update your integration tests to respect the -short flag:
go
func TestStoreCreateAndGet(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
// ... rest of test
}Now go test -short ./... skips Testcontainers tests (fast for CI lint), while go test ./... runs everything.
Checkpoint
Push the code to GitHub and open a PR. The CI workflow runs automatically:
bash
git push origin main
# Open https://github.com/<user>/<repo>/actions to see the workflowThe workflow should:
- Start a PostgreSQL service container.
- Run golangci-lint.
- Run unit tests against the service PostgreSQL.
- Build the binary.
- On main branch: build and push Docker image to GHCR.
You've completed the Golang Advanced tier. The intermediate CLI script has grown into a production-ready REST API with PostgreSQL, JWT auth, middleware, Docker, integration tests, benchmarks, graceful shutdown, and CI/CD.