CI/CD Pipeline
CI/CD Pipeline
Project:
{{PROJECT_NAME}}Drop Version:{{VERSION}}0.1.0 Date:{{DATE}}2026-02-23 Author:{{AUTHOR}}Platform Architect (AI) Status:Draft |In Review| ApprovedReviewers:{{REVIEWERS}}Alem Bašić (CEO)
Document History
| Version | Date | Author | Changes |
|---|---|---|---|
| 0.1 | Initial draft from source code analysis |
1. Overview
Drop uses GitHub Actions for CI with a 5-job pipeline covering lint, typecheck, unit tests, E2E tests, and Docker build. The CD (automated deployment) pipeline to AWS App Runner is tracked as a pending item — currently CI builds but does not deploy automatically. Staging deployment is manual via fly deploy to Fly.io (Stockholm).
CI/CD Platform: {{PLATFORM}}GitHub Actions (.github/workflows/ci.yml)
Container Registry: {{REGISTRY}}AWS ECR (324480209768.dkr.ecr.eu-west-1.amazonaws.com/drop-web)
Deployment Target:Target (production): {{DEPLOY_TARGET}}AWS App Runner (eu-west-1)
Deployment Target (staging): Fly.io (Stockholm, region arn)
Strategy: {{STRATEGY}}Rolling (App Runner managed)
2. Pipeline Overview
flowchart LR
subgraph Source
PR[Pull Request]Request\nto main/master]
MERGE[MergePush to main]to\nmain/master]
end
subgraph CI[CI ["CI — runs on every push/PR"]
LINT[Lint1. &lint-and-typecheck\nnpm Format]run TEST_UNIT[Unitlint\ntsc Tests]--noEmit]
TEST_INT[IntegrationTEST[2. Tests]test\nvitest SAST[SAST Scan]
SCA[Dependency Scan]run]
BUILD[Build3. Artifact]build\nnext build]
E2E[4. e2e\nPlaywright\nuser-flows + full-flows]
DOCKER[5. docker-build\ndocker build -t drop-app:ci]
end
subgraph CD_DEV[CD_STG ["CD Staging — Dev Auto-Deploy"manual"]
DEPLOY_DEV[DeploySTG[fly todeploy\nFly.io Dev]
SMOKE_DEV[Smoke Tests]Stockholm]
end
subgraph CD_STAGING[CD_PROD ["CD — Staging (auto on main)"]
DEPLOY_STG[Deploy to Staging]
TEST_E2E[E2E Tests]
PERF[Performance Tests]
end
subgraph CD_PROD["CDProduction — Productionpending (manual gate)"implementation"]
APPROVAL[Manual Approval]Approval\nvia DEPLOY_PROD[DeployGitHub toEnvironments]
Production]PROD[aws SMOKE_PROD[Smoke Tests]
MONITOR[Verify Monitoring]apprunner\nstart-deployment]
end
PR --> LINT
MERGE --> LINT
LINT --> TEST_UNITTEST
TEST_UNIT --> TEST_INT
TEST_INT --> SAST
SAST --> SCA
SCALINT --> BUILD
MERGETEST --> CD_DEVE2E
BUILD --> DEPLOY_DEVE2E
DEPLOY_DEVE2E --> SMOKE_DEVDOCKER
SMOKE_DEVDOCKER --> DEPLOY_STGSTG
DEPLOY_STG --> TEST_E2E
TEST_E2E --> PERF
PERFDOCKER --> APPROVAL
APPROVAL --> DEPLOY_PROD
DEPLOY_PROD --> SMOKE_PROD
SMOKE_PROD --> MONITORPROD
3. Source Control Configuration
3.1 Branching Strategy
Strategy: {{BRANCH_STRATEGY}}GitHub Flow (feature branches off main, PR into main)
| Branch | Purpose | Naming Convention | Lifetime |
|---|---|---|---|
main |
Production-ready code | fixed | Permanent |
| |||
feature/* |
New features | feature/ |
Until merged |
fix/* |
Bug fixes | fix/ |
Until merged |
hotfix/* |
Production hotfixes | hotfix/ | |
| |
Until merged |
3.2 Branch Protection Rules
Protected Branches: main, develop
| Rule | main | |
|---|---|---|
| Require PR | Yes | |
| Required approvals | ||
| Dismiss stale reviews | Yes | |
| Require status checks | Yes | |
| Required checks | ||
| Require up-to-date | Yes | |
| Allow force push | No | |
| Allow deletions | No |
3.3 Code Review Requirements
- Minimum
{{APPROVALS}}1approval(s)approval required before merge - At least one approval from
aAlemcode ownerBašić (seeorCODEOWNERS)delegated lead) - All review comments must be resolved before merge
- Review turnaround SLA:
{{REVIEW_SLA}}24 business hours Auto-assign reviewers via: {{ASSIGN_MECHANISM}}
4. Build Stage
4.1 Build Tool & Configuration
| Parameter | Value |
|---|---|
| Build Tool | |
| Install Command | npm ci (requires python3, make, g++ for better-sqlite3 native deps) |
| Build Command | (Next.js standalone output) |
| Artifact Type | |
| Artifact Naming | |
| Tag Strategy | git-sha for builds, semantic version for releases |
| Base Image | node:22-alpine |
| Production Image User | nextjs (UID 1001, non-root) |
Multi-stage build:
Stage 1: deps — npm ci + native dependencies
Stage 2: builder — npm run build (Next.js standalone)
Stage 3: runner — minimal image, copies only public/ + .next/standalone/ + .next/static/
4.2 Dependency Caching
| Cache | Key | Restore Keys |
|---|---|---|
| Node modules | node-modules-linux-${{ |
node-modules- |
| Docker build layers | BuildKit layer cache via |
|
|
4.3 Artifact Generation
| Artifact | Storage | Retention | Signed |
|---|---|---|---|
| Docker image | drop-web repository |
90 days (non- |
|
playwright-report/ |
No | ||
qa-report.html) |
|||
| No |
5. Test Stages
5.1 Unit Tests
| Parameter | Value |
|---|---|
| Framework | |
| Command | (runs vitest run) |
| Test files | tests/**/*.test.ts |
| Setup | tests/setup.ts — sets NODE_ENV=test, in-memory databases |
| Coverage Tool | |
| Coverage Gate | |
| Failure Action | Block PR merge (CI job 2 test must pass) |
5.2 Integration Tests
| Parameter | Value |
|---|---|
| Framework | |
| Command | |
| Dependencies | |
| Failure Action | Block PR merge |
5.3 E2E Tests
| Parameter | Value |
|---|---|
| Framework | |
| Command | |
| Browser | Chromium only (installed in CI via npx playwright install chromium) |
| Environment | npm run build && npm run start) |
| Parallelization | |
| Retries | 2 (CI) |
| Timeout | 30,000ms |
| Base URL | http://localhost:3000 |
| Test suites | user-flows.spec.ts, full-flows.spec.ts, input-chaos.spec.ts (depends on user-flows) |
| Artifacts | Playwright HTML report + qa-report.html uploaded to GitHub Actions |
| Failure Action | Block |
5.4 Security Scanning
| Scan Type | Tool | Gate | |
|---|---|---|---|
| SAST | Pending |
Block on HIGH/CRITICAL | |
| SCA (dependencies) | npm audit — not yet in CI |
Pending |
Block on CRITICAL |
| Container scan | Pending |
Block on CRITICAL | |
| Secret scanning | Enabled via GitHub |
Block on any finding |
Note: Security scanning tracked in security/hardening-checklist.md. npm audit and Snyk integration are pending.
5.5 Linting & Formatting
| Tool | Purpose | Command | Auto-fix |
|---|---|---|---|
| Code linting | |
PR comment | |
| |||
| Type checking | |
No |
6. Deploy Stages
6.1 Deployment Strategy
Strategy: {{DEPLOY_STRATEGY}}Rolling (App Runner managed)
App Runner handles deployment atomically — new container version deployed, health checks verified, traffic shifted. No blue-green or canary at this stage.
RollingApp Runner Deployment:
BatchTrigger:size:aws{{BATCH_SIZE}}%apprunnerofstart-deploymentinstances(currently Pause between batches: {{PAUSE}}minmanual)- Health
checkcheck:wait:GETevery 30s{{HEALTH_WAIT}}s/api/health RollbackAuto-rollback:trigger:App Runner reverts if new deployment fails healthcheckchecks- Deployment time: ~3-5 minutes
Canary DeploymentStaging (ifFly.io) used):Deployment:
InitialCommand:canaryflyweight:deploy{{CANARY_INITIAL}}%(manual)Increment:Region:{{CANARY_INCREMENT}}%arnevery {{CANARY_INTERVAL}}min(Stockholm)PromotionAuto-scale:criteria:Scaleserrortorate0<when{{ERROR_THRESHOLD}}%,idle,p99 < {{LATENCY_THRESHOLD}}msRollback trigger: automaticauto-starts onthreshold breachrequest
6.2 Environment Promotion
PR Branch → DevCI (auto) → Staging (automanual onfly main merge)deploy) → Production (manual approval)apprunner start-deployment)
| Promotion | Trigger | Gate | Approver |
|---|---|---|---|
| → |
|
All CI checks pass | |
| |||
| → Production | Manual |
All |
6.3 Approval Gates
Production Approval Required: Yes (manual)
Approvers: {{PROD_APPROVERS}}Alem Bašić (atsole leastapprover {{APPROVAL_COUNT}}during required)MVP phase)
Approval Window: {{APPROVAL_WINDOW}}hNo automated timeout (pipelinemanual cancels after timeout)process)
Emergency Override: {{EMERGENCY_OVERRIDE}}Direct aws apprunner start-deployment via AWS Console (Alem only)
6.4 Feature Flags Integration
Feature Flag Tool: {{FF_TOOL}}Environment variables (build-time via Next.js NEXT_PUBLIC_FF_* pattern)
| Flag | Dev | Staging | Production |
|---|---|---|---|
NEXT_PUBLIC_FF_VIRTUAL_CARDS |
false | false | false |
NEXT_PUBLIC_FF_PHYSICAL_CARDS |
false | false | false |
NEXT_PUBLIC_FF_CARD_DETAILS |
false | false | false |
NEXT_PUBLIC_FF_CARD_FREEZE |
false | false | false |
NEXT_PUBLIC_FF_CARD_PIN |
false | false | false |
NEXT_PUBLIC_FF_SPENDING_LIMITS |
false | false | false |
NEXT_PUBLIC_FF_NOTIFICATIONS |
true | true | true |
NEXT_PUBLIC_FF_MERCHANT_DASHBOARD |
true | true | true |
Flag Validation:Note: FeatureFlags flagsare validatedbaked in stagingat beforebuild productiontime deployby KillNext.js. Switch:Changing Alla flag requires a new featuresbuild behindand flags for first {{FF_PERIOD}} daysdeployment.
7. Post-Deploy
7.1 Smoke Tests
| Check | Expected | Timeout |
|---|---|---|
Health endpoint GET /api/health |
HTTP "status":"ok" |
10s |
| DB connectivity (via health endpoint) | "db": {"status":"pass"} |
15s |
Auth endpoint GET /api/auth/me |
HTTP 401 (no cookie) | 10s |
| 10s | ||
Smoke test timeout: {{SMOKE_TIMEOUT}}2 min total
On failure: Auto-Manual rollback triggeredvia App Runner console (revert to previous deployment)
7.2 Monitoring Verification
After each deployment, verify via BetterStack and Slack:
| Metric | Threshold | Check Duration |
|---|---|---|
| 5 min post-deploy | ||
#drop-ops |
||
RUNNING |
||
/api/health) |
7.3 Rollback Triggers
Automatic rollback triggers:
SmokeApptestRunnerfailureError rate > {{AUTO_ROLLBACK_ERROR}}% for {{AUTO_ROLLBACK_DURATION}}min post-deployHealthhealth check failureonduring{{HEALTH_FAIL_THRESHOLD}}%deploymentof(AppinstancesRunner native)- BetterStack detects downtime → Slack alert → manual investigation
Manual rollback:
# rollback-plan.mdRollback via AWS CLI (revert to previous ECR image)
aws apprunner start-deployment \
--service-arn arn:aws:apprunner:eu-west-1:324480209768:service/drop-web/8e45b0d335304487a1880f4e32d6aeec \
--region eu-west-1
8. Pipeline Configuration Reference
Config File Location: {{CONFIG_PATH}} .github/workflows/ci.yml
Key environment variables injected by CI:
| Variable | Source | Purpose |
|---|---|---|
|
||
|
||
| push ||
SLACK_WEBHOOK |
9. Secret Injection Strategy
Strategy: {{SECRET_STRATEGY}}GitHub Actions Secrets for CI variables; AWS Secrets Manager for runtime application secrets.
| Secret Type | Storage | Injection Method | Rotation |
|---|---|---|---|
| Registry credentials (ECR) | |||
| OIDC |
Per-job (ephemeral) | ||
| App secrets (JWT_SECRET, DATABASE_URL) | |||
| Slack webhook | GitHub Actions Secret | Env var injection | On compromise |
OIDC Preferred: CloudGitHub credentialsActions injected viauses OIDC to assume AWS IAM role — no long-lived AWS keys stored in CIGitHub.
10. Pipeline Metrics
| Metric | Target | Current |
|---|---|---|
| Build duration (P50) | < |
TBD |
| < |
TBD | |
| Total pipeline duration | < |
TBD |
| Deploy frequency | TBD | |
| Lead time for changes | < |
TBD |
| Change failure rate | < |
TBD |
| MTTR | < |
TBD |
Related Documents
- Deployment Architecture
- Environment Configuration
DeploymentDisasterChecklistRollbackRecovery PlanTest Strategy
Approval
| Role | Name | Date | Signature |
|---|---|---|---|
| Author | Platform Architect (AI) | 2026-02-23 | |
| Reviewer | |||
| Approver | Alem Bašić |