This document provides a comprehensive overview of the CircleCI configuration set up for the thanos-parquet-gateway project, similar to the Thanos project's CI/CD pipeline.
The CircleCI configuration provides:
- Automated testing on every commit
- Docker image building and publishing to Quay.io
- Multi-architecture support (linux/amd64, linux/arm64)
- Release automation with GitHub releases and artifacts
.circleci/
├── config.yml # Main CircleCI configuration
.github/workflows/ # Alternative GitHub Actions (optional)
├── ci.yml # GitHub Actions workflow
scripts/
├── build-and-test.sh # Local development script
Dockerfile # Multi-stage Docker build
.dockerignore # Docker build optimization
- Runs on every commit
- Executes unit tests with
make test-norace - Runs linting with
make lint - Generates and stores test coverage
- Runs on tagged releases only
- Builds binaries for multiple OS/architecture combinations
- Uses promu for cross-compilation
- Stores build artifacts
- Runs on
mainbranch commits - Builds multi-architecture Docker images
- Pushes to
quay.io/thanos-io/thanos-parquet-gateway - Tags with
latestand git commit SHA
- Runs on version tags (v*..)
- Creates release tarballs
- Builds and publishes Docker images with version tags
- Stores release artifacts
The project uses build-time version injection, following the same approach as Thanos and other Prometheus ecosystem projects:
- Version Variables: Defined in
pkg/version/version.go - Build-time Injection: Go's
-ldflagsinjects values at build time - Prometheus Compatibility: Uses
github.com/prometheus/common/versionfor consistent output
- Git Tags: Primary source for releases (
git describe --tags) - Development Fallback: Uses
v0.0.0-devwhen no tags exist - VERSION File: Optional local override (not committed, for development)
- Git Info: Automatic fallback using
runtime/debugbuild info
make version # Show current version informationOutput includes:
- VERSION: Git tag or development version
- REVISION: Git commit SHA (short)
- BRANCH: Current git branch
- BUILD_USER: User@hostname who built the binary
- BUILD_DATE: ISO 8601 timestamp
For local development without git tags, you can optionally create a VERSION file:
echo "v0.1.0-dev" > VERSION # Optional: Set your development version
make build # Build with version injection
./parquet-gateway --version # Verify versionNote: The VERSION file is ignored by git and is only for local development convenience.
- Tag Release:
git tag v1.0.0 - Push Tag:
git push origin v1.0.0 - CI/CD: Automatically builds and publishes with proper version
The Dockerfile uses a multi-stage build pattern:
- Builder stage: Go 1.24 Alpine with build tools and version injection
- Runtime stage: Minimal Alpine Linux with CA certificates
Version information is injected at build time using Go's -ldflags:
- Version: Git tag or VERSION file content
- Revision: Git commit SHA (short)
- Branch: Git branch name
- Build User: User@hostname who built the binary
- Build Date: ISO 8601 timestamp of build
This follows Thanos's approach using the Prometheus version package for consistent output format.
- Non-root user (
thanos:thanos) - Minimal attack surface
- CA certificates for HTTPS
- Proper file permissions
make docker-build-local: Simple local build (single architecture)make docker-build: Multi-architecture build for CImake docker-test: Test Docker image functionalitymake docker-push: Push to registrymake docker-manifest: Create multi-arch manifest
The following environment variables must be configured in CircleCI:
| Variable | Description | Required |
|---|---|---|
QUAY_USERNAME |
Quay.io username or robot account | Yes |
QUAY_PASSWORD |
Quay.io password or token | Yes |
Images are published to:
- Registry:
quay.io - Repository:
thanos-io/thanos-parquet-gateway - Tags:
latest: Latest main branch<commit-sha>: Specific commitsv*.*.*: Release versions
- Docker with BuildKit support
- Go 1.24+
- Make
# Build and test everything
./scripts/build-and-test.sh
# Or manually:
make build # Build binary
make docker-build-local # Build Docker image
make docker-test # Test Docker imageInstall CircleCI CLI and run:
circleci config validate .circleci/config.yml
circleci local execute --job testmake build: Build the Go binary with version injectionmake test: Run tests with race detectionmake test-norace: Run tests without race detectionmake lint: Run linting and formattingmake version: Display version information that will be injected
make version: Show current version variablesmake deps: Ensure Go dependencies are up to datemake clean: Clean build artifacts
make docker-build-local: Local Docker buildmake docker-build: Multi-arch Docker buildmake docker-test: Test Docker imagemake docker-push: Push to registrymake docker-manifest: Create manifest
make crossbuild: Build for multiple platformsmake tarballs-release: Create release archives
An alternative GitHub Actions workflow is provided in .github/workflows/ci.yml that offers:
- Similar functionality to CircleCI
- Better GitHub integration
- Free for public repositories
- Automatic release creation
To use GitHub Actions instead of CircleCI:
- Set up the same environment variables as GitHub secrets
- Disable CircleCI
- The workflow will trigger automatically
- All branches: Run tests
- Main branch: Run tests + publish Docker images
- Version tags: Run tests + cross-build + publish release
- All PRs: Run tests
- Main branch: Run tests + publish Docker images
- Version tags: Run tests + publish release + create GitHub release
-
Docker rate limiting
- Use Docker Hub credentials in CI
- Consider using a Docker registry mirror
-
Build failures
- Check Go version compatibility
- Verify all dependencies are available
- Review test failures in CI logs
-
Registry push failures
- Verify Quay.io credentials
- Check repository permissions
- Ensure registry URLs are correct
# Test local build
make version # Show version info
make build && ./parquet-gateway --version
# Test Docker build
make docker-build-local
make docker-test
# Validate CircleCI config
circleci config validate .circleci/config.yml-
Container Security
- Non-root user execution
- Minimal base image (Alpine)
- No unnecessary packages
-
CI/CD Security
- Environment variables for secrets
- Limited scope tokens for registry access
- Signed Docker images (future enhancement)
-
Access Control
- Proper repository permissions
- Robot accounts for CI access
- Regular credential rotation
-
Security
- Docker image signing with Cosign
- SBOM generation
- Vulnerability scanning
-
Performance
- Build caching optimization
- Parallel test execution
- Registry mirror usage
-
Monitoring
- Build notifications
- Performance metrics
- Dependency update automation
For issues with the CI/CD setup:
- Check the CircleCI or GitHub Actions logs
- Verify environment variables are set correctly
- Test the build process locally
- Review this documentation for common solutions