CI/CD Pipelines

Aveloxis uses GitHub Actions for continuous integration and deployment. All workflows are in .github/workflows/.

Workflows

Tests (test.yml)

Trigger: Every push to any branch, every PR to main.

Runs go test -race ./... with race detection enabled. Uploads coverage artifact on main branch pushes.

Tests split into two tiers:

  • Unit tier (default, always runs). Pure Go, no database, covers source-contract tests and logic that can be exercised in-process.

  • Integration tier (gated by AVELOXIS_TEST_DB). Runs SQL against a live Postgres. Tests skip with a clear message when the env var is unset, so local go test ./... stays fast. To run locally:

    # Create a scratch DB on your existing Postgres instance.
    psql -h localhost -U aveloxis -d postgres -c "CREATE DATABASE aveloxis_test;"
    
    # Apply the schema.
    AVELOXIS_DBNAME=aveloxis_test aveloxis migrate --config /path/to/test.json
    
    # Run only the integration suite.
    AVELOXIS_TEST_DB="host=localhost port=5432 user=aveloxis password=... dbname=aveloxis_test sslmode=prefer" \
      go test ./... -run 'Integration|RealignDueDates_|CompleteJob_' -v
    
    # Drop when done.
    psql -h localhost -U aveloxis -d postgres -c "DROP DATABASE aveloxis_test;"
    

    Never run the integration suite against the production aveloxis database. RealignDueDates is unscoped — it updates every status='queued' row in the queue, and an integration test that passes 7*24h would silently realign the entire fleet.

    Conventions for adding integration tests:

    • Name the test TestX_YIntegration or put it in a file ending in _integration_test.go.

    • Seed rows with nanosecond-suffixed synthetic slugs (see seedRealignRepo in internal/db/queue_realign_integration_test.go) so parallel or repeated runs do not collide on ON CONFLICT constraints.

    • Prefer strict-equality assertions (approxEqual(..., time.Millisecond)) where the SQL does not involve NOW(), since source-text tests cannot catch interval-arithmetic drift and this is where runtime regressions hide.

Lint (lint.yml)

Trigger: Every PR to main.

Runs golangci-lint with --only-new-issues so existing code doesn’t block PRs. 5-minute timeout for large codebases.

CodeQL (codeql.yml)

Trigger: Every PR to main, plus weekly Monday scan.

Runs GitHub’s CodeQL security analysis with security-extended query suite for Go. Results appear in the Security tab on GitHub.

Container Build (container-build.yml)

Trigger: Every PR to main.

Tests building the Docker image on:

  • Ubuntu with Docker

  • Ubuntu with Podman

  • macOS with Docker (via colima)

Verifies the binary runs inside the container (aveloxis version). Does NOT push images.

Docker Publish (docker-publish.yml)

Trigger: Every push to main.

Builds and publishes Docker images to GitHub Container Registry (ghcr.io/aveloxis/aveloxis). Tags:

  • latest — always the most recent main build

  • Git SHA — for pinning to a specific commit

  • Date stamp (YYYY.MM.DD) — for pinning to a specific day

Status Badges

All workflows have status badges at the top of the README:

  • Tests

  • Lint

  • CodeQL

  • Container Build

  • Docker Publish

Dockerfile

The multi-stage Dockerfile in the repo root:

  1. Builder stagegolang:1.25-alpine, downloads dependencies, builds a static binary

  2. Runtime stagealpine:3.20, copies the binary, includes git/curl/ca-certificates for facade and libyear phases

Exposed ports: 5555 (monitor), 8082 (web), 8383 (API).

Default command: aveloxis serve --workers 4 --monitor :5555

Running in Docker

# Pull from GHCR
docker pull ghcr.io/aveloxis/aveloxis:latest

# Start all three processes
docker run -d --name aveloxis-serve \
  -v ./aveloxis.json:/app/aveloxis.json \
  -v /data/repos:/data \
  -p 5555:5555 \
  ghcr.io/aveloxis/aveloxis:latest serve --workers 40

docker run -d --name aveloxis-web \
  -v ./aveloxis.json:/app/aveloxis.json \
  -p 8082:8082 \
  ghcr.io/aveloxis/aveloxis:latest web

docker run -d --name aveloxis-api \
  -v ./aveloxis.json:/app/aveloxis.json \
  -p 8383:8383 \
  ghcr.io/aveloxis/aveloxis:latest api

All containers share the same aveloxis.json and connect to the same PostgreSQL database.