Modular CI/CD architecture for Epitrello with reusable actions.
.github/
├── workflows/
│ ├── deploy.yml # GCP deployment (staging, master branch) with Terraform
│ ├── backend-ci.yml # Backend tests (lint, build, unit, integration)
│ ├── frontend-ci.yml # Frontend lint, build, E2E Playwright
│ ├── code-quality.yml # Code quality (Prisma, CodeQL, dependencies)
│ ├── database-migrations.yml # Database migrations
│ └── cleanup-cost-management.yml # GCP cleanup and cost management
└── actions/
├── setup-backend/ # Reusable: Backend setup with DB
│ └── action.yml
└── setup-frontend/ # Reusable: Frontend setup
└── action.yml
Note: Old monolithic workflows (ci.yml and tests.yml) have been replaced.
Runs comprehensive backend testing suite.
Triggers:
- Push to
master,devbranches - Pull requests to these branches
- Changes in
backend/or workflow/action files
Jobs:
Single job that runs sequentially:
- Lint with ESLint
- Build with NestJS
- Unit tests with coverage (80% threshold for critical modules)
- Coverage report generation
- Codecov upload
- Integration test suite
- Requires
backend-testssuccess - PostgreSQL database service
Commands:
pnpm lint
pnpm build
pnpm test:unit:cov
pnpm test:integrationNote: Lint and build run in the same job as unit tests to share PostgreSQL service.
Validates frontend code quality, builds, and runs E2E tests.
Triggers:
- Push to
master,devbranches - Pull requests to these branches
- Changes in
frontend/or workflow/action files
Jobs:
- ESLint code linting
- TypeScript type checking
- Next.js build compilation
- Build artifact archival (optional)
- PostgreSQL + backend + frontend services
- Playwright E2E tests
- Upload Playwright report (artifact)
Commands:
pnpm lint
pnpm tsc --noEmit
pnpm build
pnpm test:e2e # in e2e-tests jobFrontend E2E tests (Playwright) run as part of the Frontend CI workflow (frontend-ci.yml), in the e2e-tests job.
Triggers: Same as Frontend CI (changes in frontend/, etc.)
Job e2e-tests:
- PostgreSQL service, migrations, backend and frontend build
- Start backend (port 4000) and frontend (port 3000)
- Run Playwright:
pnpm test:e2e - Upload Playwright report as artifact (on success or failure)
Prisma validation, CodeQL security analysis, and dependency review (lint runs in backend-ci / frontend-ci).
Triggers:
- Push to
master,devbranches - Pull requests to these branches
Jobs:
prisma-validate- Prisma schema validationcodeql-analysis- CodeQL security analysis (JavaScript/TypeScript)dependency-review- Dependency vulnerability review (PRs only)
Note: Lint runs in backend-ci.yml and frontend-ci.yml; not duplicated here.
Commands:
pnpm prisma validate # prisma-validate jobUnified deployment workflow for staging with automatic change detection.
Triggers:
- Push to
masterbranch - Pull requests targeting
master - Manual workflow dispatch
Features:
- Automatic change detection (backend/frontend/terraform)
- Tests run in dedicated CI workflows (backend-ci, frontend-ci); deploy relies on branch protection
- Security scanning with Trivy
- Terraform validation and deployment
- Docker image build and push to GCR
- Cloud Run (backend and frontend) deployment
- Smoke tests after deployment
Jobs:
detect-changes- Detect what changed (backend/frontend/terraform)security-scan- Trivy vulnerability scannerterraform-validate- Validate Terraform configurationbuild-backend- Build and push Docker image to GCRbuild-frontend- Build frontend Docker image (build inside image via Dockerfile)terraform-plan- Generate Terraform plan (state prefixterraform/state/<environment>)terraform-apply- Apply Terraform changes (state prefixterraform/state/staging)deploy-backend- Deploy to Cloud Rundeploy-frontend- Deploy to Cloud Runsmoke-tests- Run smoke testsnotify- Deployment status notification
Note: Backend and frontend tests run in backend-ci.yml and frontend-ci.yml (path-filtered). Deploy does not re-run them; rely on branch protection requiring those checks to pass before merge.
Environment:
staging- Deploy on push tomaster(and manual dispatch)
Required Secrets:
GCP_SERVICE_ACCOUNT- GCP Service Account email (for Workload Identity Federation)GCP_WORKLOAD_IDENTITY_PROVIDER- Workload Identity Provider resource nameGCP_PROJECT_ID- GCP Project IDSTAGING_API_URL- Backend API URL (fallback when service not found)
Automated Prisma database migration management.
Triggers:
- Push of migrations to
masterbranch - Manual workflow dispatch
Actions:
status- Check migration statusdeploy- Apply migrationsreset- Reset database (staging only)
Environment:
staging- Push tomasteror manual dispatch
Automated cost optimization and resource cleanup.
Triggers:
- Daily at 2 AM UTC
- Manual workflow dispatch
Jobs:
cleanup-storage- Delete old Cloud Storage objectscost-report- Generate cost reportidentify-unused-resources- Identify unused resourcesnotify- Send notification
Composite action for backend environment configuration.
Inputs:
node-version(default:20) - Node.js versionpnpm-version(default:9) - pnpm versionworking-directory(default:backend) - Backend directory path
Steps:
- Install pnpm
- Setup Node.js with dependency caching
- Install project dependencies
- Generate Prisma Client
- Execute database migrations
Usage:
- name: Setup Backend
uses: ./.github/actions/setup-backend
with:
node-version: '20'
pnpm-version: '9'Composite action for frontend environment configuration.
Inputs:
node-version(default:20) - Node.js versionpnpm-version(default:9) - pnpm versionworking-directory(default:frontend) - Frontend directory path
Steps:
- Install pnpm
- Setup Node.js with dependency caching
- Install project dependencies
Usage:
- name: Setup Frontend
uses: ./.github/actions/setup-frontend
with:
node-version: '20'The following modules must maintain minimum 80% test coverage:
| Module | File | Workflow |
|---|---|---|
| Workspaces | workspaces.service.ts |
backend-ci.yml |
| Invitations | invitations.service.ts |
backend-ci.yml |
email.service.ts |
backend-ci.yml |
- Codecov - Automatic integration with upload
- GitHub Summary - Coverage table in Actions tab
- Artifacts - Complete reports available for 30 days
Configure the following secrets in repository settings:
Backend:
CODECOV_TOKEN- Codecov upload tokenRESEND_API_KEY- Resend API key for email service (E2E tests)
Deployment (GCP):
GCP_SERVICE_ACCOUNT- GCP Service Account email (for Workload Identity Federation)GCP_WORKLOAD_IDENTITY_PROVIDER- Workload Identity Provider resource nameGCP_PROJECT_ID- GCP Project IDDB_NAME,DB_USER,DB_PASSWORD- Cloud SQL database name, user, and password (used by run-migrations; must match Terraform)STAGING_API_URL- Backend API URL (fallback when Cloud Run service not found)OAUTH_GITHUB_CLIENT_ID/OAUTH_GITHUB_CLIENT_SECRET- GitHub OAuth (optional; do not useGITHUB_prefix, reserved by GitHub)
GCP IAM for migrations: The service account in GCP_SERVICE_ACCOUNT must have roles/cloudsql.viewer (or roles/cloudsql.admin) on the project so the run-migrations action can read the Cloud SQL instance (public IP). It also needs roles/secretmanager.secretAccessor on the DB password secret (or use DB_PASSWORD from GitHub secrets).
Location: Settings > Secrets and variables > Actions
Complete test suite commands available in backend:
# Unit tests
pnpm test:unit # Run unit tests only
pnpm test:unit:cov # Run unit tests with coverage
# Integration tests
pnpm test:integration # Run integration tests
# E2E tests
pnpm test:e2e # Run end-to-end tests
# All tests
pnpm test:all # Run all test types sequentially
pnpm test:all:report # Run all tests with formatted report| Command | Description | Test Files |
|---|---|---|
test:unit |
Unit tests only | *.spec.ts in src/ |
test:unit:cov |
Unit tests with coverage | *.spec.ts in src/ |
test:integration |
Integration tests | Specific E2E tests |
test:e2e |
All end-to-end tests | *.e2e-spec.ts in test/ |
test:all |
Sequential test execution | All test files |
The deploy.yml workflow replaces the following legacy workflows:
deploy-staging.yml- Merged intodeploy.ymlterraform-staging.yml- Merged intodeploy.ymldocker-build.yml- Merged intodeploy.yml(GCR only)release.yml- Can be added todeploy.ymlif needed
All workflows are modular:
- Testing:
backend-ci.yml,frontend-ci.yml(E2E Playwright in frontend-ci) - Quality:
code-quality.yml - Infrastructure:
deploy.yml(Terraform plan/apply included) - Database:
database-migrations.yml - Maintenance:
cleanup-cost-management.yml
- Create reusable actions (completed)
- Create new workflow files (completed)
- Test new workflows in feature branches
- Remove legacy
ci.ymlandtests.ymlafter validation - Update README badges
- Shared reusable actions
- Workflows separated by responsibility
- Easy maintenance and extension
- Parallel job execution when possible
- Optimized caching (pnpm, Node.js)
- Targeted tests based on file changes
- Explicit naming conventions
- Single responsibility per workflow
- Integrated documentation
- Manual dispatch for deployments
- Staging-only deployment
- Centralized configuration in actions
Ensure version consistency:
node -v # Should be 20
pnpm -v # Should be 9
# Regenerate Prisma Client
pnpm prisma generateCustom actions must be in the same repository:
uses: ./.github/actions/setup-backend # Correct
uses: ./actions/setup-backend # IncorrectVerify PostgreSQL service health check:
services:
postgres:
options: >-
--health-cmd pg_isready
--health-interval 10sTo add or modify workflows:
- Create feature branch
- Modify workflow files
- Test using
workflow_dispatchif available - Create pull request with detailed description
- Ensure all checks pass before merging
- GitHub Actions Documentation
- Creating Composite Actions
- Workflow Syntax Reference
- Codecov GitHub Action