Skip to main content
The microservices-app project uses GitHub Actions for continuous integration and deployment. All workflows are defined in .github/workflows/ci.yml.

Workflow Triggers

The CI workflow runs on:
  • Pull Requests - All PR events (open, synchronize, reopened)
  • Push to main - When changes are merged to the main branch
  • Manual Dispatch - Via GitHub UI (workflow_dispatch)

Concurrency Control

The workflow uses concurrency groups to prevent redundant builds:
concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
  cancel-in-progress: ${{ github.event_name == 'pull_request' }}
Pull request builds are cancelled when new commits are pushed. Main branch builds always complete.

Path-Based Job Filtering

The changes job uses dorny/paths-filter to detect which parts of the codebase changed:
FilterPathsTriggers Jobs
protoproto/**contract
goservices/**, proto/**go-lint, go-test, nix-build
frontendfrontend/**frontend-lint, frontend-build
nodenode-services/**node-lint, node-test
nix**/*.nix, flake.nix, flake.locknix-build
Jobs only run if relevant files changed, reducing CI time and resource usage.

Jobs Reference

contract

Runs on: Pull requests when proto/** files change Purpose: Validates Protocol Buffers schema contracts Steps:
  1. Checkout with full git history (fetch-depth: 0)
  2. Install buf CLI via bufbuild/buf-action@v1
  3. Run buf lint to check proto style and conventions
  4. Run buf breaking --against '.git#branch=main' to detect breaking API changes
Note: Breaking change detection is skipped if proto/ doesn’t exist on main yet (new projects).

go-lint

Runs on: Pull requests when Go files change (services/**, proto/**) Purpose: Enforces Go code quality standards Steps:
  1. Checkout repository
  2. Install Go from services/go.mod version
  3. Run golangci-lint v2.10 in services/ directory
Configuration: Uses .golangci.yml in the services directory.

go-test

Runs on: Pull requests when Go files change Purpose: Runs Go unit tests Steps:
  1. Checkout repository
  2. Install Go from services/go.mod version
  3. Run go test ./... in services/ directory

frontend-lint

Runs on: Pull requests when frontend/** files change Purpose: Validates TypeScript/React code quality Steps:
  1. Checkout repository
  2. Install Node.js 22 with npm cache
  3. Run npm ci in frontend/
  4. Run npx biome check src/ for linting and formatting checks
Tools: Uses Biome for fast TypeScript linting.

frontend-build

Runs on: Pull requests when frontend/** files change Purpose: Verifies frontend builds successfully with type checking Steps:
  1. Checkout repository
  2. Install Node.js 22 with npm cache
  3. Run npm ci and npm run build in frontend/
Build includes:
  • TypeScript type checking
  • Vite production build
  • Asset optimization

node-lint

Runs on: Pull requests when node-services/** files change Purpose: Lints Node.js microservices Strategy: Matrix job for each service:
  • auth-service
  • custom-lang-service
Steps (per service):
  1. Checkout repository
  2. Install Node.js 22 with service-specific npm cache
  3. Run npm ci in node-services/<service>/
  4. Run npx biome check .

node-test

Runs on: Pull requests when node-services/** files change Purpose: Runs unit tests for Node.js microservices Strategy: Matrix job for each service:
  • auth-service
  • custom-lang-service
Steps (per service):
  1. Checkout repository
  2. Install Node.js 22 with service-specific npm cache
  3. Run npm ci in node-services/<service>/
  4. Run npm test (Vitest)

nix-build

Runs on: Any push/PR when Go or Nix files change Purpose: Builds reproducible service binaries and container images with Nix Runner: blacksmith-2vcpu-ubuntu-2404 (custom runner for Nix builds) Steps:
  1. Checkout repository
  2. Install Nix with flakes enabled
  3. Configure Cachix cache (hackz-megalo-cup) for build acceleration
  4. Build service binaries: nix build .#caller .#greeter .#gateway
  5. Build container images: nix build .#caller-image .#greeter-image .#gateway-image
  6. (Main branch only) Push images to ghcr.io with SHA and latest tags
Image Registry: ghcr.io/hackz-megalo-cup/<service>:<sha> and ghcr.io/hackz-megalo-cup/<service>:latest Authentication: Uses GitHub token with packages: write permission.

render-manifests

Runs on: Push to main branch only (after nix-build succeeds) Purpose: Regenerates Kubernetes manifests from nixidy modules and creates auto-merge PR Runner: blacksmith-2vcpu-ubuntu-2404 Steps:
  1. Checkout repository
  2. Install Nix with flakes enabled
  3. Configure Cachix cache (skip push)
  4. Run bash scripts/gen-manifests.sh to render nixidy manifests
  5. Create PR via peter-evans/create-pull-request@v7:
    • Branch: chore/render-manifests
    • Title: “chore: render nixidy manifests”
    • Auto-delete branch after merge
  6. Enable auto-merge with squash strategy
Why: Ensures deploy/manifests/ stays in sync with nixidy source definitions in deploy/k8s/*.nix.

Workflow Status Badge

Add CI status badge to your README:
![CI](https://github.com/hackz-megalo-cup/microservices-app/workflows/CI/badge.svg)
Or for main branch only:
![CI](https://github.com/hackz-megalo-cup/microservices-app/workflows/CI/badge.svg?branch=main)

Skipping CI on Push to Main

Most validation jobs skip on push events to main:
if: >
  needs.changes.outputs.go == 'true'
  && github.event_name != 'push'
Rationale: Pull requests already validated the code. Main branch only needs:
  • nix-build - To build and push container images
  • render-manifests - To update Kubernetes manifests
This reduces redundant CI time after merging.

Caching Strategy

JobCache TypeLocation
Node jobsnpm dependencies<service>/package-lock.json
Go jobsGo modulesAutomatic via setup-go
Nix jobsCachix binary cachecachix.org/hackz-megalo-cup

Debugging Failed CI

Contract Failures

# Run locally with devenv
buf-check
Common issues:
  • Breaking changes in proto files (field removals, type changes)
  • Lint violations (naming conventions, required fields)

Go Lint/Test Failures

# Format and lint
cd services
golangci-lint run ./...
go test ./...

Frontend Failures

# Lint and build
cd frontend
npm ci
npx biome check src/
npm run build

Nix Build Failures

# Test nix builds locally
nix build .#caller .#greeter .#gateway
nix build .#caller-image
Check flake.nix syntax and ensure all Go dependencies are vendored.

Environment Variables

VariableSourceUsage
GITHUB_TOKENAutomaticAuthentication for gh CLI, packages
CACHIX_AUTH_TOKENRepository secretPush to Cachix binary cache

Permissions

Jobs use minimal required permissions:
permissions:
  contents: read          # Most jobs
  packages: write         # nix-build (ghcr.io push)
  pull-requests: write    # render-manifests (create PR)

Build docs developers (and LLMs) love