198 lines
6.7 KiB
Markdown
198 lines
6.7 KiB
Markdown
# ADR-017: CI/CD and Branching Strategy
|
|
|
|
**Date**: 2025-12-12
|
|
|
|
**Status**: Accepted
|
|
|
|
**Implemented**: 2026-01-09
|
|
|
|
## Context
|
|
|
|
The project has Gitea workflows but lacks a documented standard for how code moves from a developer's machine to production. This can lead to inconsistent deployment processes and uncertainty about code quality.
|
|
|
|
## Decision
|
|
|
|
We will formalize the end-to-end CI/CD process using:
|
|
|
|
1. **Trunk-Based Development**: All work is merged to `main` branch.
|
|
2. **Automated Test Deployment**: Every push to `main` triggers deployment to test environment.
|
|
3. **Manual Production Deployment**: Production deployments require explicit confirmation.
|
|
4. **Semantic Versioning**: Automated version bumping on deployments.
|
|
|
|
## Consequences
|
|
|
|
- **Positive**: Automates quality control and creates a safe, repeatable path to production. Increases development velocity and reduces deployment-related errors.
|
|
- **Negative**: Initial setup effort for the CI/CD pipeline. May slightly increase the time to merge code due to mandatory checks.
|
|
|
|
## Implementation Details
|
|
|
|
### Branching Strategy
|
|
|
|
**Trunk-Based Development**:
|
|
|
|
```text
|
|
main ─────●─────●─────●─────●─────●─────▶
|
|
│ │ │ │ │
|
|
│ │ │ │ └── Deploy to Prod (manual)
|
|
│ │ │ └── v0.9.70 (patch bump)
|
|
│ │ └── Deploy to Test (auto)
|
|
│ └── v0.9.69 (patch bump)
|
|
└── Feature complete
|
|
```
|
|
|
|
- All development happens on `main` branch
|
|
- Feature branches are short-lived (< 1 day)
|
|
- Every merge to `main` triggers test deployment
|
|
- Production deploys are manual with confirmation
|
|
|
|
### Pipeline Stages
|
|
|
|
**Deploy to Test** (Automatic on push to `main`):
|
|
|
|
```yaml
|
|
jobs:
|
|
deploy-to-test:
|
|
steps:
|
|
- Checkout code
|
|
- Setup Node.js 20
|
|
- Install dependencies (npm ci)
|
|
- Bump patch version (npm version patch)
|
|
- TypeScript type-check
|
|
- Prettier check
|
|
- ESLint check
|
|
- Run unit tests with coverage
|
|
- Run integration tests with coverage
|
|
- Run E2E tests with coverage
|
|
- Merge coverage reports
|
|
- Check database schema hash
|
|
- Build React application
|
|
- Deploy to test server (rsync)
|
|
- Install production dependencies
|
|
- Reload PM2 processes
|
|
- Update schema hash in database
|
|
```
|
|
|
|
**Deploy to Production** (Manual trigger):
|
|
|
|
```yaml
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
confirmation:
|
|
description: 'Type "deploy-to-prod" to confirm'
|
|
required: true
|
|
|
|
jobs:
|
|
deploy-production:
|
|
steps:
|
|
- Verify confirmation phrase
|
|
- Checkout main branch
|
|
- Install dependencies
|
|
- Bump minor version (npm version minor)
|
|
- Check production schema hash
|
|
- Build React application
|
|
- Deploy to production server
|
|
- Reload PM2 processes
|
|
- Update schema hash
|
|
```
|
|
|
|
### Version Bumping Strategy
|
|
|
|
| Trigger | Version Change | Example |
|
|
| -------------------------- | -------------- | --------------- |
|
|
| Push to main (test deploy) | Patch bump | 0.9.69 → 0.9.70 |
|
|
| Production deploy | Minor bump | 0.9.70 → 0.10.0 |
|
|
| Major release | Manual | 0.10.0 → 1.0.0 |
|
|
|
|
**Commit Message Format**:
|
|
|
|
```text
|
|
ci: Bump version to 0.9.70 [skip ci]
|
|
```
|
|
|
|
The `[skip ci]` tag prevents version bump commits from triggering another workflow.
|
|
|
|
### Database Schema Management
|
|
|
|
Schema changes are tracked via SHA-256 hash:
|
|
|
|
```sql
|
|
CREATE TABLE public.schema_info (
|
|
environment VARCHAR(50) PRIMARY KEY,
|
|
schema_hash VARCHAR(64) NOT NULL,
|
|
deployed_at TIMESTAMP DEFAULT NOW()
|
|
);
|
|
```
|
|
|
|
**Deployment Checks**:
|
|
|
|
1. Calculate hash of `sql/master_schema_rollup.sql`
|
|
2. Compare with hash in target database
|
|
3. If mismatch: **FAIL** deployment (manual migration required)
|
|
4. If match: Continue deployment
|
|
5. After deploy: Update hash in database
|
|
|
|
### Quality Gates
|
|
|
|
| Check | Required | Blocking |
|
|
| --------------------- | -------- | ---------------------- |
|
|
| TypeScript type-check | ✅ | No (continue-on-error) |
|
|
| Prettier formatting | ✅ | No |
|
|
| ESLint | ✅ | No |
|
|
| Unit tests | ✅ | No |
|
|
| Integration tests | ✅ | No |
|
|
| E2E tests | ✅ | No |
|
|
| Schema hash check | ✅ | **Yes** |
|
|
| Build | ✅ | **Yes** |
|
|
|
|
### Environment Variables
|
|
|
|
Secrets are injected from Gitea repository settings:
|
|
|
|
| Secret | Test | Production |
|
|
| -------------------------------------------------------------- | ------------------ | ------------- |
|
|
| `DB_DATABASE_TEST` / `DB_DATABASE_PROD` | flyer-crawler-test | flyer-crawler |
|
|
| `REDIS_PASSWORD_TEST` / `REDIS_PASSWORD_PROD` | \*\*\* | \*\*\* |
|
|
| `VITE_GOOGLE_GENAI_API_KEY_TEST` / `VITE_GOOGLE_GENAI_API_KEY` | \*\*\* | \*\*\* |
|
|
|
|
### Coverage Reporting
|
|
|
|
Coverage reports are generated and published:
|
|
|
|
```text
|
|
https://flyer-crawler-test.projectium.com/coverage/
|
|
```
|
|
|
|
Coverage merging combines:
|
|
|
|
- Unit test coverage (Vitest)
|
|
- Integration test coverage (Vitest)
|
|
- E2E test coverage (Vitest)
|
|
- Server V8 coverage (c8)
|
|
|
|
### Gitea Workflows
|
|
|
|
| Workflow | Trigger | Purpose |
|
|
| ----------------------------- | ------------ | ------------------------- |
|
|
| `deploy-to-test.yml` | Push to main | Automated test deployment |
|
|
| `deploy-to-prod.yml` | Manual | Production deployment |
|
|
| `manual-db-backup.yml` | Manual | Create database backup |
|
|
| `manual-db-restore.yml` | Manual | Restore from backup |
|
|
| `manual-db-reset-test.yml` | Manual | Reset test database |
|
|
| `manual-db-reset-prod.yml` | Manual | Reset production database |
|
|
| `manual-deploy-major.yml` | Manual | Major version release |
|
|
| `manual-redis-flush-prod.yml` | Manual | Flush Redis cache |
|
|
|
|
## Key Files
|
|
|
|
- `.gitea/workflows/deploy-to-test.yml` - Test deployment pipeline
|
|
- `.gitea/workflows/deploy-to-prod.yml` - Production deployment pipeline
|
|
- `.gitea/workflows/manual-db-backup.yml` - Database backup workflow
|
|
- `ecosystem.config.cjs` - PM2 configuration
|
|
|
|
## Related ADRs
|
|
|
|
- [ADR-014](./0014-containerization-and-deployment-strategy.md) - Containerization Strategy
|
|
- [ADR-010](./0010-testing-strategy-and-standards.md) - Testing Strategy
|
|
- [ADR-019](./0019-data-backup-and-recovery-strategy.md) - Backup Strategy
|