From 9366cfa94f88c13198fc8081346c54e83eb8f0ce Mon Sep 17 00:00:00 2001 From: DustyWalker Date: Tue, 5 Aug 2025 16:52:14 +0200 Subject: [PATCH] feat: add .forgejo/workflows/ci.yml - comprehensive CI pipeline configuration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI/CD pipeline with comprehensive automation: - Multi-stage workflow with dependency caching - Linting, formatting, and TypeScript type checking - Unit tests with coverage reporting across all packages - Integration tests with PostgreSQL, Redis, and MinIO services - Docker build and container testing - Security scanning with npm audit and Snyk - Dependency update monitoring - Deployment readiness validation - Matrix testing strategy for monorepo packages - Artifact management and retention policies 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .forgejo/workflows/ci.yml | 397 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 397 insertions(+) create mode 100644 .forgejo/workflows/ci.yml diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml new file mode 100644 index 0000000..2fc5fa2 --- /dev/null +++ b/.forgejo/workflows/ci.yml @@ -0,0 +1,397 @@ +name: CI Pipeline + +on: + push: + branches: [ main, develop, 'feature/*', 'hotfix/*' ] + pull_request: + branches: [ main, develop ] + workflow_dispatch: + +env: + NODE_VERSION: '18' + PNPM_VERSION: '8.15.0' + +jobs: + # Install dependencies and cache + setup: + name: Setup Dependencies + runs-on: ubuntu-latest + outputs: + cache-key: ${{ steps.cache-keys.outputs.node-modules }} + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + registry-url: 'https://registry.npmjs.org' + + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: ${{ env.PNPM_VERSION }} + run_install: false + + - name: Get pnpm store directory + shell: bash + run: | + echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV + + - name: Generate cache keys + id: cache-keys + run: | + echo "node-modules=${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}" >> $GITHUB_OUTPUT + + - name: Setup pnpm cache + uses: actions/cache@v3 + with: + path: ${{ env.STORE_PATH }} + key: ${{ steps.cache-keys.outputs.node-modules }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Cache node_modules + uses: actions/cache@v3 + id: cache-node-modules + with: + path: | + node_modules + packages/*/node_modules + key: ${{ steps.cache-keys.outputs.node-modules }}-modules + restore-keys: | + ${{ runner.os }}-pnpm-modules- + + # Linting and formatting + lint: + name: Lint & Format Check + runs-on: ubuntu-latest + needs: setup + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Restore dependencies + uses: actions/cache@v3 + with: + path: | + node_modules + packages/*/node_modules + key: ${{ needs.setup.outputs.cache-key }}-modules + + - name: Run ESLint + run: pnpm lint + + - name: Check Prettier formatting + run: pnpm format:check + + - name: TypeScript type check + run: pnpm typecheck + + # Unit tests + test: + name: Unit Tests + runs-on: ubuntu-latest + needs: setup + strategy: + matrix: + package: [api, worker, frontend, shared] + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Restore dependencies + uses: actions/cache@v3 + with: + path: | + node_modules + packages/*/node_modules + key: ${{ needs.setup.outputs.cache-key }}-modules + + - name: Run tests for ${{ matrix.package }} + run: pnpm --filter @ai-renamer/${{ matrix.package }} test + + - name: Generate coverage report + run: pnpm --filter @ai-renamer/${{ matrix.package }} test:coverage + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v3 + with: + file: ./packages/${{ matrix.package }}/coverage/lcov.info + flags: ${{ matrix.package }} + name: ${{ matrix.package }}-coverage + fail_ci_if_error: false + + # Integration tests + integration-test: + name: Integration Tests + runs-on: ubuntu-latest + needs: setup + services: + postgres: + image: postgres:16-alpine + env: + POSTGRES_PASSWORD: test_password + POSTGRES_DB: ai_image_renamer_test + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + ports: + - 5432:5432 + + redis: + image: redis:7-alpine + options: >- + --health-cmd "redis-cli ping" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + ports: + - 6379:6379 + + minio: + image: minio/minio:latest + env: + MINIO_ROOT_USER: test_user + MINIO_ROOT_PASSWORD: test_password + options: >- + --health-cmd "curl -f http://localhost:9000/minio/health/live" + --health-interval 30s + --health-timeout 20s + --health-retries 3 + ports: + - 9000:9000 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Restore dependencies + uses: actions/cache@v3 + with: + path: | + node_modules + packages/*/node_modules + key: ${{ needs.setup.outputs.cache-key }}-modules + + - name: Setup test environment + run: | + cp .env.example .env.test + echo "DATABASE_URL=postgresql://postgres:test_password@localhost:5432/ai_image_renamer_test" >> .env.test + echo "REDIS_URL=redis://localhost:6379" >> .env.test + echo "MINIO_ENDPOINT=localhost:9000" >> .env.test + echo "MINIO_ACCESS_KEY=test_user" >> .env.test + echo "MINIO_SECRET_KEY=test_password" >> .env.test + + - name: Run database migrations + run: pnpm --filter @ai-renamer/api db:migrate + + - name: Run integration tests + run: pnpm test:integration + env: + NODE_ENV: test + + # Build application + build: + name: Build Application + runs-on: ubuntu-latest + needs: [setup, lint, test] + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Restore dependencies + uses: actions/cache@v3 + with: + path: | + node_modules + packages/*/node_modules + key: ${{ needs.setup.outputs.cache-key }}-modules + + - name: Build all packages + run: pnpm build + + - name: Upload build artifacts + uses: actions/upload-artifact@v3 + with: + name: build-artifacts + path: | + packages/*/dist + packages/*/build + retention-days: 7 + + # Docker build and test + docker: + name: Docker Build & Test + runs-on: ubuntu-latest + needs: [setup, lint, test] + if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop') + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build Docker image + uses: docker/build-push-action@v5 + with: + context: . + target: production + tags: ai-bulk-image-renamer:${{ github.sha }} + cache-from: type=gha + cache-to: type=gha,mode=max + outputs: type=docker,dest=/tmp/image.tar + + - name: Upload Docker image artifact + uses: actions/upload-artifact@v3 + with: + name: docker-image + path: /tmp/image.tar + retention-days: 1 + + - name: Test Docker image + run: | + docker load < /tmp/image.tar + docker run --rm --name test-container -d \ + -e NODE_ENV=test \ + ai-bulk-image-renamer:${{ github.sha }} + sleep 10 + docker logs test-container + docker stop test-container + + # Security scanning + security: + name: Security Scan + runs-on: ubuntu-latest + needs: setup + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Restore dependencies + uses: actions/cache@v3 + with: + path: | + node_modules + packages/*/node_modules + key: ${{ needs.setup.outputs.cache-key }}-modules + + - name: Run npm audit + run: pnpm audit --audit-level moderate + continue-on-error: true + + - name: Run Snyk security scan + uses: snyk/actions/node@master + continue-on-error: true + env: + SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} + with: + args: --severity-threshold=medium + + # Dependency updates check + dependency-updates: + name: Check Dependency Updates + runs-on: ubuntu-latest + if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: ${{ env.PNPM_VERSION }} + + - name: Check for outdated dependencies + run: pnpm outdated + + - name: Create dependency update issue + if: failure() + uses: actions/github-script@v6 + with: + script: | + github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: 'Dependency Updates Available', + body: 'Automated check found outdated dependencies. Please review and update.', + labels: ['dependencies', 'maintenance'] + }) + + # Deployment readiness check + deploy-check: + name: Deployment Readiness + runs-on: ubuntu-latest + needs: [build, docker, security, integration-test] + if: github.ref == 'refs/heads/main' + steps: + - name: Deployment ready + run: | + echo "✅ All checks passed - ready for deployment" + echo "Build artifacts and Docker image are available" + echo "Security scans completed" + echo "Integration tests passed" \ No newline at end of file