diff --git a/CI_CD_WORKFLOW_ARCHITECTURE.md b/CI_CD_WORKFLOW_ARCHITECTURE.md new file mode 100644 index 0000000..c5a4f1a --- /dev/null +++ b/CI_CD_WORKFLOW_ARCHITECTURE.md @@ -0,0 +1,739 @@ +# ๐Ÿ—๏ธ TimeTracker CI/CD Workflow Architecture + +> Complete visual guide to the GitHub Actions pipeline system + +--- + +## ๐Ÿ“Š **High-Level Overview** + +```mermaid +graph TB + subgraph "Code Changes" + A[Developer Pushes Code] + B[Create Pull Request] + C[Create Release/Tag] + end + + subgraph "Workflows" + D[๐Ÿ”ต Development CD] + E[๐ŸŸข Release CD] + F[๐ŸŸก Comprehensive CI] + G[๐ŸŸ  Migration Check] + H[๐ŸŸฃ GitHub Pages] + end + + subgraph "Outputs" + I[Dev Docker Image] + J[Release Docker Image] + K[Test Reports] + L[Migration Validation] + M[Documentation Site] + end + + A -->|push to develop| D + B -->|PR to main/develop| F + B -->|PR with model changes| G + C -->|push to main/tags| E + C -->|release published| H + + D --> I + E --> J + F --> K + G --> L + H --> M + + style D fill:#0066ff,stroke:#003d99,color:#fff + style E fill:#00cc66,stroke:#009944,color:#fff + style F fill:#ffcc00,stroke:#cc9900,color:#000 + style G fill:#ff9933,stroke:#cc6600,color:#fff + style H fill:#9933ff,stroke:#6600cc,color:#fff +``` + +--- + +## ๐Ÿ”ต **1. Development CD Workflow** + +**File:** `.github/workflows/cd-development.yml` + +### **Triggers:** +- โœ… Push to `develop` branch (automatic) +- ๐Ÿ”˜ Manual trigger via workflow_dispatch (with force build option) + +### **Flow Diagram:** + +```mermaid +graph LR + A[Push to develop] --> B[Quick Tests] + B -->|Pass| C[Build & Push] + B -->|Fail| D{Force Build?} + D -->|Yes| C + D -->|No| E[Stop] + + C --> F[Login to GHCR] + F --> G[Build Docker Image] + G --> H[Tag: develop] + H --> I[Push to Registry] + I --> J[Create Dev Release] + + style B fill:#ffd700 + style C fill:#4CAF50 + style J fill:#FF9800 +``` + +### **Jobs:** + +#### **Job 1: quick-tests** โšก +```yaml +Duration: ~2-5 minutes +Runs: Smoke tests only +Services: PostgreSQL 16 +Purpose: Fast feedback for developers +``` + +**Steps:** +1. ๐Ÿ“ฅ Checkout code +2. ๐Ÿ Set up Python 3.11 +3. ๐Ÿ“ฆ Install dependencies (cached) +4. ๐Ÿงช Run smoke tests (`pytest -m smoke`) + +#### **Job 2: build-and-push** ๐Ÿณ +```yaml +Duration: ~10-15 minutes +Depends on: quick-tests (or force_build) +Purpose: Create development Docker image +``` + +**Steps:** +1. ๐Ÿ“ฅ Checkout code (full history) +2. ๐Ÿณ Set up Docker Buildx +3. ๐Ÿ” Login to GHCR (ghcr.io) +4. ๐Ÿท๏ธ Extract metadata (tags & labels) +5. ๐Ÿ”จ Build & push Docker image + - Tag: `develop` + - Tag: `dev-YYYYMMDD-HHMMSS` + - Tag: `dev-{commit_sha}` +6. ๐Ÿ“‹ Generate changelog +7. ๐ŸŽ‰ Create GitHub Release + - Name: `Development Build - {timestamp}` + - Tag: `dev-{timestamp}` + - Pre-release: true + +### **Outputs:** +- ๐Ÿณ Docker Images: + - `ghcr.io/drytrix/timetracker:develop` + - `ghcr.io/drytrix/timetracker:dev-20251010-120000` + - `ghcr.io/drytrix/timetracker:dev-abc1234` +- ๐Ÿ“ฆ GitHub Release (pre-release, auto-generated) + +### **Permissions:** +```yaml +permissions: write-all +``` +โœ… Full access to contents, packages, releases + +--- + +## ๐ŸŸข **2. Release CD Workflow** + +**File:** `.github/workflows/cd-release.yml` + +### **Triggers:** +- โœ… Push to `main` or `master` branch +- ๐Ÿท๏ธ Push version tags (`v*.*.*`) +- ๐ŸŽ‰ Release published +- ๐Ÿ”˜ Manual trigger (with version input) + +### **Flow Diagram:** + +```mermaid +graph TD + A[Trigger Release] --> B{Skip Tests?} + B -->|No| C[Full Test Suite] + B -->|Yes| D[Build & Push] + C -->|Pass| D + C -->|Fail| E[Stop] + + D --> F[Determine Version] + F --> G[Build Multi-Platform] + G --> H[Security Scan] + H --> I[Push to Registry] + I --> J{Has Tag?} + J -->|Yes| K[Create Release] + J -->|No| L[Skip Release] + + K --> M[Generate Manifests] + M --> N[Upload Artifacts] + + style C fill:#ffd700 + style D fill:#4CAF50 + style H fill:#ff5722 + style K fill:#FF9800 +``` + +### **Jobs:** + +#### **Job 1: full-test-suite** ๐Ÿงช +```yaml +Duration: ~15-25 minutes +Runs: ALL tests with coverage +Services: PostgreSQL 16 +Skippable: via skip_tests input +``` + +**Tests Include:** +- โœ… Smoke tests +- โœ… Unit tests +- โœ… Integration tests +- โœ… Security tests +- โœ… API tests +- โœ… Database tests +- ๐Ÿ“Š Coverage reports (Codecov) +- ๐Ÿ“‹ Test result publishing + +#### **Job 2: build-and-push** ๐Ÿณ +```yaml +Duration: ~20-30 minutes +Depends on: full-test-suite (if not skipped) +Builds: Multi-platform (amd64, arm64) +``` + +**Steps:** +1. ๐Ÿ“ฅ Checkout code +2. ๐Ÿ” Determine version (from tag or input) +3. ๐Ÿณ Set up Docker Buildx (multi-platform) +4. ๐Ÿ” Login to GHCR +5. ๐Ÿท๏ธ Extract metadata +6. ๐Ÿ”จ Build & push multi-platform images + - Platforms: `linux/amd64`, `linux/arm64` + - Tag: `latest` + - Tag: `v{version}` (e.g., `v1.2.3`) + - Tag: `{major}.{minor}` (e.g., `1.2`) +7. ๐Ÿ”’ Run security scan (Trivy) +8. ๐Ÿ“Š Upload scan results + +#### **Job 3: create-release** ๐ŸŽ‰ +```yaml +Duration: ~2-5 minutes +Depends on: build-and-push +Runs: Only if triggered by tag +``` + +**Steps:** +1. ๐Ÿ“ฅ Checkout code +2. ๐Ÿ“‹ Generate changelog +3. ๐ŸŽ‰ Create GitHub Release + - Name: `Release {version}` + - Tag: `v{version}` + - Changelog included + - NOT a pre-release + +#### **Job 4: generate-deployment-manifests** ๐Ÿ“ฆ +```yaml +Duration: ~1-2 minutes +Depends on: create-release +Purpose: Generate K8s/Docker deployment files +``` + +**Generates:** +- `docker-compose.prod.yml` - Docker Compose config +- `kubernetes-deployment.yml` - K8s deployment +- `kubernetes-service.yml` - K8s service +- `values.yaml` - Helm values + +### **Outputs:** +- ๐Ÿณ Docker Images (multi-platform): + - `ghcr.io/drytrix/timetracker:latest` + - `ghcr.io/drytrix/timetracker:v1.2.3` + - `ghcr.io/drytrix/timetracker:1.2` +- ๐Ÿ“ฆ GitHub Release (production) +- ๐Ÿ“„ Deployment manifests (artifacts) +- ๐Ÿ”’ Security scan reports + +### **Permissions:** +```yaml +Job 1: None (tests only) +Job 2: packages: write, contents: read +Job 3: contents: write +Job 4: None (manifest generation) +``` + +--- + +## ๐ŸŸก **3. Comprehensive CI Workflow** + +**File:** `.github/workflows/ci-comprehensive.yml` + +### **Triggers:** +- ๐Ÿ”€ Pull requests to `main` or `develop` + +### **Flow Diagram:** + +```mermaid +graph TD + A[PR Opened/Updated] --> B[Smoke Tests] + + B -->|Pass| C1[Unit: models] + B -->|Pass| C2[Unit: routes] + B -->|Pass| C3[Unit: api] + B -->|Pass| C4[Unit: utils] + + C1 --> D1[Integration: auth] + C2 --> D1 + C3 --> D1 + C4 --> D1 + + D1 --> D2[Integration: timer] + D1 --> D3[Integration: projects] + D1 --> D4[Integration: invoices] + + D2 --> E[Database Tests] + D3 --> E + D4 --> E + + E --> F[Security Tests] + F --> G[Code Quality] + + G --> H1[Black Format] + G --> H2[Flake8 Lint] + G --> H3[Bandit Security] + G --> H4[Safety Check] + + H1 --> I[Coverage Report] + H2 --> I + H3 --> I + H4 --> I + + I --> J[Comment on PR] + + style B fill:#ffd700 + style E fill:#2196F3 + style F fill:#ff5722 + style I fill:#4CAF50 +``` + +### **Jobs:** + +#### **Job 1: smoke-tests** โšก (~5 min) +Fast critical tests for immediate feedback + +#### **Job 2: unit-tests** ๐Ÿงฉ (~10 min) +Parallel matrix testing: +- `models` - User, Client, Project, TimeEntry, Invoice, Task +- `routes` - Page routes, navigation +- `api` - API endpoints +- `utils` - Helper functions + +#### **Job 3: integration-tests** ๐Ÿ”— (~15 min) +Parallel matrix testing: +- `auth` - Login, logout, permissions +- `timer` - Start/stop timer, time tracking +- `projects` - Project CRUD, relationships +- `invoices` - Invoice generation, PDF export + +#### **Job 4: database-tests** ๐Ÿ—„๏ธ (~10 min) +- Schema validation +- Migrations +- Relationships +- Constraints + +#### **Job 5: security-tests** ๐Ÿ”’ (~8 min) +- Authentication checks +- Authorization rules +- CSRF protection +- XSS prevention +- SQL injection prevention + +#### **Job 6: code-quality** ๐ŸŽจ (~5 min) +Parallel checks: +- **Black** - Code formatting +- **Flake8** - Style & error checking +- **Bandit** - Security vulnerabilities +- **Safety** - Dependency vulnerabilities + +#### **Job 7: coverage-report** ๐Ÿ“Š (~2 min) +- Aggregate all coverage data +- Generate unified report +- Comment coverage % on PR +- Upload to Codecov + +### **Outputs:** +- ๐Ÿ“Š Test results (artifacts) +- ๐Ÿ“ˆ Coverage reports (Codecov) +- ๐Ÿ’ฌ PR comments with results +- ๐Ÿท๏ธ Status checks on PR + +### **Permissions:** +```yaml +coverage-report job: + contents: read + pull-requests: write + issues: write +``` + +--- + +## ๐ŸŸ  **4. Migration Check Workflow** + +**File:** `.github/workflows/migration-check.yml` + +### **Triggers:** +- ๐Ÿ”€ Pull requests that modify: + - `app/models/**` + - `migrations/**` + - `requirements.txt` +- โœ… Push to `main` with same paths + +### **Flow Diagram:** + +```mermaid +graph LR + A[Model/Migration Change] --> B[Check for Migrations] + B --> C{Migration Exists?} + C -->|Yes| D[Validate Migration] + C -->|No| E[Warning Comment] + + D --> F[Apply Migration] + F --> G{Success?} + G -->|Yes| H[Test Rollback] + G -->|No| I[Error Comment] + + H --> J{Rollback OK?} + J -->|Yes| K[Success Comment] + J -->|No| L[Warning Comment] + + style D fill:#4CAF50 + style F fill:#2196F3 + style H fill:#FF9800 +``` + +### **Jobs:** + +#### **Job 1: validate-migrations** ๐Ÿ” +```yaml +Duration: ~5-8 minutes +Services: PostgreSQL 16 +Purpose: Ensure migrations are safe +``` + +**Steps:** +1. ๐Ÿ“ฅ Checkout code (full history) +2. ๐Ÿ Set up Python 3.11 +3. ๐Ÿ“ฆ Install dependencies +4. ๐Ÿ” Check for migration changes +5. โœ… Validate migration syntax +6. ๐Ÿ”จ Apply migrations (test DB) +7. โ†ฉ๏ธ Test rollback +8. ๐Ÿ“‹ Generate migration report +9. ๐Ÿงช Run migration tests + +#### **Job 2: comment-on-pr** ๐Ÿ’ฌ +```yaml +Duration: ~1 minute +Depends on: validate-migrations +Runs: Only on PRs +``` + +**Comments Include:** +- โœ… Migration validation status +- ๐Ÿ“Š Schema changes detected +- โš ๏ธ Warnings (if any) +- ๐Ÿ” Review checklist + +### **Outputs:** +- ๐Ÿ’ฌ PR comments with migration status +- ๐Ÿ“‹ Migration validation report +- ๐Ÿท๏ธ Status checks + +### **Permissions:** +```yaml +Job 1: None (validation only) +Job 2: + contents: read + pull-requests: write + issues: write +``` + +--- + +## ๐ŸŸฃ **5. GitHub Pages Workflow** + +**File:** `.github/workflows/static.yml` + +### **Triggers:** +- ๐ŸŽ‰ Release published + +### **Flow Diagram:** + +```mermaid +graph LR + A[Release Published] --> B[Build Site] + B --> C[Upload Artifact] + C --> D[Deploy to Pages] + D --> E[Live Documentation] + + style B fill:#4CAF50 + style E fill:#9933ff +``` + +### **Jobs:** + +#### **Job 1: build** ๐Ÿ”จ +```yaml +Duration: ~2 minutes +Purpose: Prepare site content +``` + +**Steps:** +1. ๐Ÿ“ฅ Checkout code +2. โš™๏ธ Setup Pages configuration +3. ๐Ÿ“ฆ Upload repository as artifact + +#### **Job 2: deploy** ๐Ÿš€ +```yaml +Duration: ~1 minute +Depends on: build +Environment: github-pages +``` + +**Steps:** +1. ๐ŸŒ Deploy to GitHub Pages + +### **Outputs:** +- ๐ŸŒ Live documentation site +- ๐Ÿ“„ URL: `https://drytrix.github.io/TimeTracker/` + +### **Permissions:** +```yaml +permissions: + contents: read + pages: write + id-token: write +``` + +--- + +## ๐Ÿ”„ **Complete Development Cycle** + +```mermaid +sequenceDiagram + participant Dev as Developer + participant Repo as GitHub Repo + participant CI as CI Workflows + participant CD as CD Workflows + participant GHCR as Container Registry + participant Pages as GitHub Pages + + Dev->>Repo: 1. Create feature branch + Dev->>Repo: 2. Make changes + Dev->>Repo: 3. Push commits + Dev->>Repo: 4. Open PR to develop + + Repo->>CI: Trigger CI Pipeline + CI->>CI: Run comprehensive tests + CI->>CI: Check migrations (if models changed) + CI->>Repo: Comment results on PR + + Dev->>Repo: 5. Merge PR to develop + + Repo->>CD: Trigger Development CD + CD->>CD: Quick smoke tests + CD->>CD: Build Docker image + CD->>GHCR: Push dev image + CD->>Repo: Create dev release + + Dev->>Repo: 6. Create PR: develop โ†’ main + + Repo->>CI: Trigger CI Pipeline (again) + CI->>CI: Full test validation + + Dev->>Repo: 7. Merge PR to main + + Repo->>CD: Trigger Release CD + CD->>CD: Full test suite + CD->>CD: Build multi-platform image + CD->>CD: Security scan + CD->>GHCR: Push release image + CD->>Repo: Create production release + CD->>Repo: Upload deployment manifests + + Repo->>Pages: Trigger Pages Deploy + Pages->>Pages: Build & deploy docs +``` + +--- + +## ๐Ÿ“‹ **Workflow Comparison** + +| Feature | Development CD | Release CD | Comprehensive CI | Migration Check | GitHub Pages | +|---------|---------------|------------|------------------|----------------|--------------| +| **Trigger** | Push to `develop` | Push to `main`/tags | Pull requests | Model changes | Release published | +| **Test Level** | Smoke only | Full suite | All tests | Migration tests | None | +| **Duration** | ~5-10 min | ~40-60 min | ~30-45 min | ~5-10 min | ~3 min | +| **Docker Build** | โœ… Single platform | โœ… Multi-platform | โŒ No | โŒ No | โŒ No | +| **Security Scan** | โŒ No | โœ… Trivy | โœ… Bandit | โŒ No | โŒ No | +| **Coverage** | โŒ Disabled | โœ… Full | โœ… Full | โŒ N/A | โŒ N/A | +| **Release Created** | โœ… Pre-release | โœ… Production | โŒ No | โŒ No | โŒ No | +| **PR Comments** | โŒ No | โŒ No | โœ… Yes | โœ… Yes | โŒ No | +| **Artifacts** | Docker image | Docker + Manifests | Test reports | Migration report | Documentation | + +--- + +## ๐ŸŽฏ **Key Features** + +### **1. Fast Feedback Loop** โšก +- Smoke tests run in ~5 minutes +- Parallel test execution +- Early failure detection + +### **2. Comprehensive Coverage** ๐Ÿ“Š +- 137 tests across all layers +- Unit, integration, security tests +- Database and migration validation + +### **3. Security First** ๐Ÿ”’ +- Code scanning (Bandit) +- Dependency scanning (Safety) +- Container scanning (Trivy) +- Authentication/authorization tests + +### **4. Multi-Platform Support** ๐ŸŒ +- Linux amd64 (Intel/AMD) +- Linux arm64 (Apple Silicon, ARM servers) + +### **5. Developer Experience** ๐Ÿ‘จโ€๐Ÿ’ป +- PR comments with test results +- Coverage reports on every PR +- Migration validation warnings +- Force build option for emergencies + +### **6. Production Ready** ๐Ÿš€ +- Full test suite before release +- Security scanning +- Deployment manifests auto-generated +- GitHub Pages documentation + +--- + +## ๐Ÿ“Š **Test Coverage Breakdown** + +```yaml +Total Tests: 137 + +By Type: + - Smoke Tests: 13 (critical paths) + - Unit Tests: 40+ (models, utils) + - Integration Tests: 30+ (routes, API) + - Security Tests: 25+ (auth, XSS, CSRF) + - Database Tests: 15+ (schema, migrations) + - API Tests: 14+ (endpoints) + +By Marker: + - @pytest.mark.smoke: 13 + - @pytest.mark.unit: 40 + - @pytest.mark.integration: 30 + - @pytest.mark.security: 25 + - @pytest.mark.database: 15 + - @pytest.mark.api: 14 + - @pytest.mark.models: 20 + - @pytest.mark.routes: 18 +``` + +--- + +## ๐Ÿ” **Permissions Summary** + +| Workflow | Workflow Level | Job Level | Purpose | +|----------|----------------|-----------|---------| +| **cd-development.yml** | `write-all` | Inherited | Full access for releases | +| **cd-release.yml** | None | Per-job | Least privilege per job | +| **ci-comprehensive.yml** | None | Coverage job only | PR comments | +| **migration-check.yml** | None | Comment job only | PR comments | +| **static.yml** | Pages + ID token | Inherited | GitHub Pages deploy | + +--- + +## ๐Ÿš€ **Next Steps After Workflow Runs** + +### **After Development CD:** +1. โœ… Check dev release created +2. ๐Ÿณ Pull dev image: `docker pull ghcr.io/drytrix/timetracker:develop` +3. ๐Ÿงช Test in dev environment +4. โœ… Verify functionality + +### **After Release CD:** +1. โœ… Check production release created +2. ๐Ÿ“ฆ Download deployment manifests +3. ๐Ÿณ Pull release image: `docker pull ghcr.io/drytrix/timetracker:latest` +4. ๐Ÿš€ Deploy to production using manifests +5. ๐Ÿ“š Check GitHub Pages updated + +### **After PR CI:** +1. ๐Ÿ“Š Review test results in PR comments +2. ๐Ÿ“ˆ Check coverage report +3. โš ๏ธ Address any warnings +4. ๐Ÿ” Review migration validation (if applicable) +5. โœ… Merge when all checks pass + +--- + +## ๐ŸŽ‰ **Success Criteria** + +All workflows should show: +- โœ… All jobs completed successfully +- โœ… No security vulnerabilities found +- โœ… Test coverage โ‰ฅ 50% (for full runs) +- โœ… All code quality checks passed +- โœ… Docker images pushed to GHCR +- โœ… Releases created with proper tags +- โœ… PR comments posted (for CI) + +--- + +## ๐Ÿ“ž **Monitoring & Debugging** + +### **Check Workflow Status:** +``` +GitHub โ†’ Actions tab +``` + +### **View Logs:** +``` +Actions โ†’ Select workflow run โ†’ Select job โ†’ View logs +``` + +### **Common Issues:** + +1. **Tests Failing:** + - Check test logs + - Run locally: `pytest -v` + - Check database connections + +2. **Docker Build Failing:** + - Check Dockerfile syntax + - Verify dependencies in requirements.txt + - Check for file permissions + +3. **Release Creation Failing:** + - Verify permissions are `write-all` + - Check repository settings + - Ensure tags are unique + +4. **Coverage Below Threshold:** + - Add more tests + - Or disable coverage check for dev: `--no-cov` + +--- + +## ๐Ÿ“š **Related Documentation** + +- [GitHub Actions Documentation](https://docs.github.com/en/actions) +- [Pytest Documentation](https://docs.pytest.org/) +- [Docker Documentation](https://docs.docker.com/) +- [GitHub Container Registry](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry) + +--- + +**Last Updated:** October 10, 2025 +**Version:** 1.0.0 +**Status:** โœ… All workflows operational + diff --git a/tests/test_invoices.py b/tests/test_invoices.py index f208706..874ebec 100644 --- a/tests/test_invoices.py +++ b/tests/test_invoices.py @@ -1,31 +1,9 @@ import pytest from datetime import datetime, date, timedelta from decimal import Decimal -from app import create_app, db +from app import db from app.models import User, Project, Invoice, InvoiceItem, Settings -@pytest.fixture -def app(): - """Create and configure a new app instance for each test.""" - app = create_app() - app.config['TESTING'] = True - app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:' - - with app.app_context(): - db.create_all() - yield app - db.drop_all() - -@pytest.fixture -def client(app): - """A test client for the app.""" - return app.test_client() - -@pytest.fixture -def runner(app): - """A test runner for the app's Click commands.""" - return app.test_cli_runner() - @pytest.fixture def sample_user(app): """Create a sample user for testing.""" diff --git a/tests/test_new_features.py b/tests/test_new_features.py index 2c10d1b..9829e65 100644 --- a/tests/test_new_features.py +++ b/tests/test_new_features.py @@ -1,30 +1,29 @@ import pytest -from app import create_app, db +from app import db from app.models import Project, User, SavedFilter @pytest.mark.smoke @pytest.mark.api -def test_burndown_endpoint_available(client, app_context): - app = create_app({'TESTING': True, 'SQLALCHEMY_DATABASE_URI': 'sqlite:///:memory:'}) - with app.app_context(): - db.create_all() - # Minimal entities - u = User(username='admin') - u.role = 'admin' - u.is_active = True - db.session.add(u) - p = Project(name='X', client_id=1, billable=False) - db.session.add(p) - db.session.commit() - # Just ensure route exists; not full auth flow here - # This is a placeholder smoke test to be expanded in integration tests - assert True +def test_burndown_endpoint_available(client, app): + """Test that burndown endpoint is available.""" + # Minimal entities + u = User(username='admin') + u.role = 'admin' + u.is_active = True + db.session.add(u) + p = Project(name='X', client_id=1, billable=False) + db.session.add(p) + db.session.commit() + # Just ensure route exists; not full auth flow here + # This is a placeholder smoke test to be expanded in integration tests + assert True @pytest.mark.smoke @pytest.mark.models -def test_saved_filter_model_roundtrip(app_context): +def test_saved_filter_model_roundtrip(app): + """Test that SavedFilter can be created and serialized.""" # Ensure SavedFilter can be created and serialized sf = SavedFilter(user_id=1, name='My Filter', scope='time', payload={'project_id': 1, 'tag': 'deep'}) db.session.add(sf)