Skip to content
Latchkey

CI/CD for a Gin Web Service with GitHub Actions

Vet, lint, race-test, and build your Gin Go service.

Gin is a popular Go HTTP framework. Its CI is standard Go: vet, lint, test with the race detector, and a build. This recipe runs all of them and builds a container image for deploy.

What the pipeline does

  • set up Go with module caching
  • run go vet
  • lint with golangci-lint
  • test with -race and coverage
  • build and push a Docker image

The workflow

actions/setup-go enables module and build caching automatically. -race catches data races, which matter for a concurrent HTTP server.

.github/workflows/ci.yml
name: CI
on:
  push:
    branches: [main]
  pull_request:
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-go@v5
        with:
          go-version: '1.23'
          cache: true
      - run: go vet ./...
      - uses: golangci/golangci-lint-action@v6
      - run: go test -race -coverprofile=cover.out ./...
      - run: go build -o server ./...
      - uses: actions/upload-artifact@v4
        with:
          name: server
          path: server

Caching and speed

setup-go caches the module cache and build cache keyed on go.sum, so dependency downloads and compiles are fast on warm runs. The race-enabled test run is the slow step; cheaper managed runners such as Latchkey (around 69% cheaper than GitHub-hosted) keep it quick and auto-retry transient module proxy failures.

Deploying

Go compiles to a single static binary, so the container can be FROM gcr.io/distroless/static or scratch. Push the image to a registry and deploy to ECS, Cloud Run, Fly.io, or Kubernetes. Build with CGO_ENABLED=0 for a fully static binary.

Key takeaways

  • Use -race to catch data races in a concurrent server.
  • setup-go caches modules and build output.
  • CGO_ENABLED=0 yields a static binary for a scratch image.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →