# CI (triggered) name: CI on: push: branches: [master, main] pull_request: types: [opened, synchronize, reopened] jobs: # Check if CI should be skipped based on branch name or commit message skip-ci-check: runs-on: ubuntu-latest outputs: should-skip: ${{ steps.check.outputs.skip || 'false' }} steps: - name: Check out code (for commit message) uses: actions/checkout@v4 with: fetch-depth: 1 - name: Check if CI should be skipped id: check run: | SKIP=false # Simple skip pattern: @skipci (case-insensitive) SKIP_PATTERN="@skipci" # Get branch name (works for both push and PR) BRANCH_NAME="${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" # Get commit message (works for both push and PR) COMMIT_MSG="${GITHUB_EVENT_HEAD_COMMIT_MESSAGE:-}" if [ -z "$COMMIT_MSG" ]; then COMMIT_MSG="${GITHUB_EVENT_PULL_REQUEST_HEAD_COMMIT_MESSAGE:-}" fi if [ -z "$COMMIT_MSG" ]; then COMMIT_MSG=$(git log -1 --pretty=%B 2>/dev/null || echo "") fi # Check branch name (case-insensitive) if echo "$BRANCH_NAME" | grep -qiF "$SKIP_PATTERN"; then echo "Skipping CI: branch name contains '$SKIP_PATTERN'" SKIP=true fi # Check commit message (case-insensitive) if [ "$SKIP" = "false" ] && [ -n "$COMMIT_MSG" ]; then if echo "$COMMIT_MSG" | grep -qiF "$SKIP_PATTERN"; then echo "Skipping CI: commit message contains '$SKIP_PATTERN'" SKIP=true fi fi echo "skip=$SKIP" >> "$GITHUB_OUTPUT" echo "Branch: $BRANCH_NAME" echo "Commit: ${COMMIT_MSG:0:50}..." echo "Skip CI: $SKIP" lint-and-type-check: needs: skip-ci-check runs-on: ubuntu-latest if: &should_run ${{ needs.skip-ci-check.outputs.should-skip != 'true' }} container: image: node:20-bullseye steps: - name: Check out code uses: actions/checkout@v4 - name: Install dependencies run: npm ci - name: Generate Prisma Client run: npm run db:generate env: DATABASE_URL: postgresql://postgres:postgres@localhost:5432/mirrormatch?schema=public - name: Run ESLint run: npm run lint - name: Type check run: npm run type-check test: needs: skip-ci-check runs-on: ubuntu-latest if: *should_run container: image: node:20-bullseye services: postgres: image: postgres:15 env: POSTGRES_PASSWORD: postgres POSTGRES_DB: mirrormatch_test options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 ports: - 5432:5432 env: DATABASE_URL: postgresql://postgres:postgres@postgres:5432/mirrormatch_test?schema=public NEXTAUTH_SECRET: test-secret-key-for-ci NEXTAUTH_URL: http://localhost:3000 steps: - name: Check out code uses: actions/checkout@v4 - name: Install dependencies run: npm ci - name: Generate Prisma Client run: npm run db:generate - name: Run database migrations run: npm run db:push - name: Run tests run: npm run test:ci - name: Upload coverage reports uses: codecov/codecov-action@v4 with: files: ./coverage/coverage-final.json flags: unittests name: codecov-umbrella fail_ci_if_error: false continue-on-error: true build: needs: skip-ci-check runs-on: ubuntu-latest if: *should_run container: image: node:20-bullseye steps: - name: Check out code uses: actions/checkout@v4 - name: Install dependencies run: npm ci - name: Generate Prisma Client run: npm run db:generate env: # Use the same connection string we provide to the build step so Prisma can generate types DATABASE_URL: postgresql://postgres:postgres@localhost:5432/mirrormatch?schema=public - name: Build application run: npm run build env: DATABASE_URL: postgresql://postgres:postgres@localhost:5432/mirrormatch?schema=public NEXTAUTH_SECRET: test-secret-key-for-ci NEXTAUTH_URL: http://localhost:3000 secret-scanning: needs: skip-ci-check if: *should_run runs-on: ubuntu-latest container: image: zricethezav/gitleaks:latest steps: - name: Install Node.js for checkout action run: | apk add --no-cache nodejs npm curl - name: Check out code uses: actions/checkout@v4 with: fetch-depth: 0 - name: Scan for secrets run: gitleaks detect --source . --no-banner --redact --exit-code 0 continue-on-error: true dependency-scan: needs: skip-ci-check if: *should_run runs-on: ubuntu-latest container: image: aquasec/trivy:latest steps: - name: Install Node.js for checkout action run: | apk add --no-cache nodejs npm curl - name: Check out code uses: actions/checkout@v4 - name: Dependency vulnerability scan (Trivy) run: | trivy fs \ --scanners vuln \ --severity HIGH,CRITICAL \ --ignore-unfixed \ --timeout 10m \ --skip-dirs .git,node_modules \ --exit-code 0 \ . - name: Secret scan (Trivy) run: | trivy fs \ --scanners secret \ --timeout 10m \ --skip-dirs .git,node_modules \ --exit-code 0 \ . sast-scan: needs: skip-ci-check if: *should_run runs-on: ubuntu-latest container: image: ubuntu:22.04 steps: - name: Install Node.js for checkout action run: | apt-get update && apt-get install -y curl curl -fsSL https://deb.nodesource.com/setup_20.x | bash - apt-get install -y nodejs - name: Check out code uses: actions/checkout@v4 - name: Install Semgrep run: | apt-get update && apt-get install -y python3 python3-pip pip3 install semgrep - name: Run Semgrep scan run: semgrep --config=auto --error continue-on-error: true workflow-summary: runs-on: ubuntu-latest needs: [lint-and-type-check, test, build, secret-scanning, dependency-scan, sast-scan] if: always() steps: - name: Generate workflow summary run: | echo "## ๐Ÿ” CI Workflow Summary" >> $GITHUB_STEP_SUMMARY || true echo "" >> $GITHUB_STEP_SUMMARY || true echo "### Job Results" >> $GITHUB_STEP_SUMMARY || true echo "" >> $GITHUB_STEP_SUMMARY || true echo "| Job | Status |" >> $GITHUB_STEP_SUMMARY || true echo "|-----|--------|" >> $GITHUB_STEP_SUMMARY || true echo "| ๐Ÿ“ Lint & Type Check | ${{ needs.lint-and-type-check.result }} |" >> $GITHUB_STEP_SUMMARY || true echo "| ๐Ÿงช Tests | ${{ needs.test.result }} |" >> $GITHUB_STEP_SUMMARY || true echo "| ๐Ÿ—๏ธ Build | ${{ needs.build.result }} |" >> $GITHUB_STEP_SUMMARY || true echo "| ๐Ÿ” Secret Scanning | ${{ needs.secret-scanning.result }} |" >> $GITHUB_STEP_SUMMARY || true echo "| ๐Ÿ“ฆ Dependency Scan | ${{ needs.dependency-scan.result }} |" >> $GITHUB_STEP_SUMMARY || true echo "| ๐Ÿ” SAST Scan | ${{ needs.sast-scan.result }} |" >> $GITHUB_STEP_SUMMARY || true echo "" >> $GITHUB_STEP_SUMMARY || true echo "### ๐Ÿ“Š Summary" >> $GITHUB_STEP_SUMMARY || true echo "" >> $GITHUB_STEP_SUMMARY || true echo "All security and validation checks have completed." >> $GITHUB_STEP_SUMMARY || true