A complete example of trunk-based development with modular GitHub Actions CI/CD pipeline deploying to Google Cloud Run using OIDC authentication.
This project demonstrates trunk-based development practices with:
- Single main branch - All development happens on
main - Short-lived feature branches - Merged within 1-2 days
- Modular CI/CD pipeline - Reusable workflows for different stages
- Google Cloud Run deployment - Serverless container deployment
- OIDC authentication - Secure keyless authentication to Google Cloud
- Multi-environment strategy - Local β Staging β Production
- Feature flags - Decouple deployment from feature releases
- Automated testing - Unit, integration, and smoke tests
- Security scanning - Vulnerability detection in CI
- Blue-green deployments - Zero-downtime production releases
- Node.js 18+
- Docker
- Git
- Google Cloud CLI (
gcloud) - GitHub CLI (optional)
- Google Cloud Project with billing enabled
-
Clone and setup:
git clone <repository-url> cd ci-test npm install npm run prepare # Setup git hooks
-
Start development:
npm run dev
-
Run tests:
npm test # All tests npm run test:unit # Unit tests only npm run test:coverage # With coverage
-
Create feature branch (optional, keep short-lived):
git checkout -b feature/new-feature
-
Make changes and commit (follows conventional commits):
git add . git commit -m "feat: add new user authentication"
-
Push and create PR:
git push origin feature/new-feature # Create PR via GitHub UI or CLI -
Merge to main after CI passes and review approval
The pipeline automatically triggers on:
- Push to main β Full CI/CD (deploy to staging β production)
- Pull request β CI only (tests and validation)
The CI/CD pipeline is split into reusable workflows:
-
CI Workflow (
ci.yml)- Code linting and formatting
- Security audit
- Unit tests with coverage
- Build validation
-
Build & Push Workflow (
build-and-push.yml)- Docker image build
- Push to Google Artifact Registry
- Container vulnerability scanning
- Multi-tag support
-
Deploy Workflow (
deploy-cloud-run.yml)- Deploy to Google Cloud Run
- Environment-specific configuration
- Post-deployment testing
- Traffic management for production
-
Main Orchestrator (
main.yml)- Coordinates all workflows
- Environment-specific deployments
- Deployment notifications
env.example- Template for environment variablesconfig/environments/local.json- Local development configconfig/environments/staging.json- Staging environment configconfig/environments/production.json- Production environment config
-
Run the OIDC setup script:
./scripts/setup-gcp-oidc.sh your-github-username ci-test
-
The script will:
- Create the
github-saservice account - Set up Workload Identity Federation
- Create Artifact Registry repository
- Configure necessary IAM permissions
- Create the
-
Configure branch protection (see
.github/branch-protection.md):- Require PR reviews
- Require status checks
- Restrict direct pushes to main
-
Set up environments:
staging- Auto-deploy from mainproduction- Requires manual approvalproduction-traffic- Controls production traffic rollout
-
Add repository secrets:
# Staging environment STAGING_DATABASE_URL STAGING_REDIS_URL STAGING_SENTRY_DSN # Production environment PRODUCTION_DATABASE_URL PRODUCTION_REDIS_URL PRODUCTION_SENTRY_DSN
- Unit Tests (
tests/unit/) - Individual component testing - Integration Tests (
tests/integration/) - Service interaction testing - Smoke Tests (
tests/smoke/) - Basic functionality validation - Performance Tests (
tests/performance/) - Load and performance testing
# Local testing
npm run test:unit
npm run test:integration
npm run test:smoke -- --env=local
# CI/CD testing (automatic)
# - Unit tests run on every commit
# - Integration tests run in staging
# - Smoke tests run in all environments- Staging: Deploys automatically to Cloud Run on main branch push
- Production: Requires manual approval, then blue-green deployment with gradual traffic rollout
- CI Pipeline: Runs on every push/PR
- Build & Push: Creates Docker image and pushes to Artifact Registry
- Deploy Staging: Automatic deployment with integration tests
- Deploy Production: Manual approval β Deploy β Gradual traffic rollout (10% β 50% β 100%)
-
Staging:
cloud-run/staging.yaml- 0-5 instances
- 512Mi memory
- Auto-scaling based on traffic
-
Production:
cloud-run/production.yaml- 1-10 instances minimum
- 1Gi memory
- Always-on with faster scaling
Feature flags allow deploying code without releasing features:
// In your code
if (config.features.newUI) {
// New feature code
} else {
// Existing code
}Configure in environment files:
local.json: Enable all features for developmentstaging.json: Enable features for testingproduction.json: Control feature rollout
- Linting: Code style enforcement
- Testing: Unit tests must pass
- Commit format: Conventional commit validation
- Dependency scanning: npm audit
- Container scanning: Trivy vulnerability scanner
- SARIF upload: Results to GitHub Security tab
- No direct pushes to main
- Require PR reviews
- Require passing status checks
- Automatic branch deletion
All environments include:
/healthendpoint- Kubernetes liveness/readiness probes
- Automated health validation in deployments
- Local: Debug logging to console
- Staging: Structured logging with metrics
- Production: Minimal logging with full monitoring stack
- Health check failures trigger automatic rollback
- Failed deployments revert to previous version
# Rollback staging
./scripts/deploy.sh rollback staging
# Rollback production
./scripts/deploy.sh rollback productionThis project uses Conventional Commits:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
Types: feat, fix, docs, style, refactor, perf, test, chore, ci, build, revert
Examples:
feat: add user authentication
fix(api): resolve login endpoint error
docs: update deployment guide
ci: add security scanning to pipeline
- Follow trunk-based development practices
- Keep feature branches short-lived (< 2 days)
- Write tests for new features
- Use conventional commit messages
- Ensure CI passes before merging
-
CI failing on main branch
- Check GitHub Actions logs
- Verify all required secrets are set
- Ensure branch protection rules are configured
-
Deployment failures
- Check deployment logs:
kubectl logs -n <namespace> - Verify environment configuration
- Check health endpoint manually
- Check deployment logs:
-
Pre-commit hooks failing
- Run
npm run lint:fixto auto-fix linting issues - Ensure all tests pass:
npm test - Check commit message format
- Run
- Check GitHub Issues for known problems
- Review GitHub Actions workflow logs
- Verify environment configuration files
- Check deployment script logs