name: Optimized CI on: pull_request: push: branches: - main - 'feature/**' concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true jobs: backend-lint: name: "Backend Checkstyle & Tests" container: image: "cimg/openjdk:23.0-node" steps: - name: "Checkout" uses: actions/checkout@v4 with: fetch-depth: 0 - name: "Cache Gradle dependencies" uses: https://github.com/actions/cache@v4 with: path: | ~/.gradle/caches ~/.gradle/wrapper backend/.gradle key: gradle-${{ runner.os }}-${{ hashFiles('backend/build.gradle.kts', 'backend/gradle/wrapper/gradle-wrapper.properties') }} restore-keys: | gradle-${{ runner.os }}- - name: "Setup Gradle" working-directory: ./backend run: chmod +x ./gradlew - name: "Run Checkstyle" working-directory: ./backend run: ./gradlew checkstyleMain checkstyleTest --parallel --build-cache - name: "Run Tests" working-directory: ./backend run: ./gradlew test --parallel --build-cache - name: "Upload Test Results" if: always() uses: actions/upload-artifact@v4 with: name: backend-test-results path: backend/build/reports/tests/ retention-days: 7 - name: "Stop Gradle" if: always() working-directory: ./backend run: ./gradlew --stop backend-build: name: "Backend Build & Package" needs: backend-lint container: image: "cimg/openjdk:23.0-node" steps: - name: "Checkout" uses: actions/checkout@v4 - name: "Cache Gradle dependencies" uses: https://github.com/actions/cache@v4 with: path: | ~/.gradle/caches ~/.gradle/wrapper backend/.gradle key: gradle-${{ runner.os }}-${{ hashFiles('backend/build.gradle.kts', 'backend/gradle/wrapper/gradle-wrapper.properties') }} restore-keys: | gradle-${{ runner.os }}- - name: "Setup Gradle" working-directory: ./backend run: chmod +x ./gradlew - name: "Build JAR" working-directory: ./backend run: ./gradlew bootJar --parallel --build-cache - name: "Upload Artifacts" uses: actions/upload-artifact@v4 with: name: backend-jar path: backend/build/libs/*.jar retention-days: 5 - name: "Stop Gradle" if: always() working-directory: ./backend run: ./gradlew --stop frontend-lint: name: "Frontend Lint & Format" container: image: catthehacker/ubuntu:act-latest steps: - name: "Checkout Code" uses: actions/checkout@v4 - name: "Install Bun" uses: oven-sh/setup-bun@v2 with: bun-version: latest - name: "Cache Dependencies" uses: actions/cache@v4 with: path: frontend/node_modules key: ${{ runner.os }}-bun-${{ hashFiles('frontend/bun.lock') }} restore-keys: | ${{ runner.os }}-bun- - name: "Install dependencies" working-directory: ./frontend run: bun install --frozen-lockfile - name: "Run ESLint" working-directory: ./frontend run: bun run lint - name: "Run Prettier Check" working-directory: ./frontend run: bun run format:check frontend-test: name: "Frontend Tests" needs: frontend-lint container: image: catthehacker/ubuntu:act-latest steps: - name: "Checkout Code" uses: actions/checkout@v4 - name: "Install Bun" uses: oven-sh/setup-bun@v2 with: bun-version: latest - name: "Cache Dependencies" uses: actions/cache@v4 with: path: frontend/node_modules key: ${{ runner.os }}-bun-${{ hashFiles('frontend/bun.lock') }} restore-keys: | ${{ runner.os }}-bun- - name: "Install dependencies" working-directory: ./frontend run: bun install --frozen-lockfile - name: "Run Tests" working-directory: ./frontend run: bun run test --no-watch --browsers=ChromeHeadless - name: "Upload Test Results" if: always() uses: actions/upload-artifact@v4 with: name: frontend-test-results path: frontend/coverage/ retention-days: 7 frontend-build: name: "Frontend Build" needs: frontend-test container: image: catthehacker/ubuntu:act-latest steps: - name: "Checkout Code" uses: actions/checkout@v4 - name: "Install Bun" uses: oven-sh/setup-bun@v2 with: bun-version: latest - name: "Cache Dependencies" uses: actions/cache@v4 with: path: frontend/node_modules key: ${{ runner.os }}-bun-${{ hashFiles('frontend/bun.lock') }} restore-keys: | ${{ runner.os }}-bun- - name: "Cache Build" uses: actions/cache@v4 with: path: frontend/dist key: ${{ runner.os }}-dist-${{ github.sha }} restore-keys: | ${{ runner.os }}-dist- - name: "Install dependencies" working-directory: ./frontend run: bun install --frozen-lockfile - name: "Production Build" working-directory: ./frontend run: bun run build --configuration production - name: "Upload Build Artifacts" uses: actions/upload-artifact@v4 with: name: frontend-build path: frontend/dist/ retention-days: 5 pr-analysis: name: "PR Quality Analysis" if: github.event_name == 'pull_request' runs-on: ubuntu-latest needs: [backend-build, frontend-build] steps: - name: "Checkout Code" uses: actions/checkout@v4 with: fetch-depth: 0 - name: "Setup Node.js" uses: actions/setup-node@v4 with: node-version: 20 - name: "Code Size Analysis" run: | echo "### PR Size Analysis :mag:" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "| Metric | Value |" >> $GITHUB_STEP_SUMMARY echo "| --- | --- |" >> $GITHUB_STEP_SUMMARY echo "| Files changed | $(git diff --name-only origin/${{ github.base_ref }} | wc -l) |" >> $GITHUB_STEP_SUMMARY echo "| Lines added | $(git diff --stat origin/${{ github.base_ref }} | tail -n 1 | awk '{print $4}') |" >> $GITHUB_STEP_SUMMARY echo "| Lines removed | $(git diff --stat origin/${{ github.base_ref }} | tail -n 1 | awk '{print $6}') |" >> $GITHUB_STEP_SUMMARY - name: "PR Summary" run: | echo "### PR Summary :clipboard:" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "#### Modified Files by Type" >> $GITHUB_STEP_SUMMARY echo "| File Type | Count |" >> $GITHUB_STEP_SUMMARY echo "| --- | --- |" >> $GITHUB_STEP_SUMMARY echo "| Java (.java) | $(git diff --name-only origin/${{ github.base_ref }} | grep "\.java$" | wc -l) |" >> $GITHUB_STEP_SUMMARY echo "| TypeScript (.ts) | $(git diff --name-only origin/${{ github.base_ref }} | grep "\.ts$" | wc -l) |" >> $GITHUB_STEP_SUMMARY echo "| HTML (.html) | $(git diff --name-only origin/${{ github.base_ref }} | grep "\.html$" | wc -l) |" >> $GITHUB_STEP_SUMMARY echo "| CSS/SCSS (.css/.scss) | $(git diff --name-only origin/${{ github.base_ref }} | grep -E "\.(css|scss)$" | wc -l) |" >> $GITHUB_STEP_SUMMARY echo "| Configuration files | $(git diff --name-only origin/${{ github.base_ref }} | grep -E "\.(json|yml|yaml|properties|xml|gradle|kts)$" | wc -l) |" >> $GITHUB_STEP_SUMMARY - name: "Add Test Analysis" run: | echo "### Test Coverage Impact :test_tube:" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "| Component | Status |" >> $GITHUB_STEP_SUMMARY echo "| --- | --- |" >> $GITHUB_STEP_SUMMARY JAVA_FILES=$(git diff --name-only origin/${{ github.base_ref }} | grep "\.java$" | wc -l) JAVA_TEST_FILES=$(git diff --name-only origin/${{ github.base_ref }} | grep "Test\.java$" | wc -l) TS_FILES=$(git diff --name-only origin/${{ github.base_ref }} | grep "\.ts$" | grep -v "\.spec\.ts$" | wc -l) TS_TEST_FILES=$(git diff --name-only origin/${{ github.base_ref }} | grep "\.spec\.ts$" | wc -l) if [ $JAVA_FILES -gt 0 ] && [ $JAVA_TEST_FILES -eq 0 ]; then echo "| Backend | ⚠️ Java code changes without test updates |" >> $GITHUB_STEP_SUMMARY elif [ $JAVA_FILES -gt 0 ] && [ $JAVA_TEST_FILES -gt 0 ]; then echo "| Backend | ✅ Java code changes with test updates |" >> $GITHUB_STEP_SUMMARY elif [ $JAVA_FILES -eq 0 ]; then echo "| Backend | ➖ No Java code changes |" >> $GITHUB_STEP_SUMMARY fi if [ $TS_FILES -gt 0 ] && [ $TS_TEST_FILES -eq 0 ]; then echo "| Frontend | ⚠️ TypeScript code changes without test updates |" >> $GITHUB_STEP_SUMMARY elif [ $TS_FILES -gt 0 ] && [ $TS_TEST_FILES -gt 0 ]; then echo "| Frontend | ✅ TypeScript code changes with test updates |" >> $GITHUB_STEP_SUMMARY elif [ $TS_FILES -eq 0 ]; then echo "| Frontend | ➖ No TypeScript code changes |" >> $GITHUB_STEP_SUMMARY fi merge-readiness: name: "Merge Readiness Check" needs: [backend-lint, backend-build, frontend-lint, frontend-test, frontend-build] if: github.event_name == 'pull_request' runs-on: ubuntu-latest steps: - name: "Merge Status" run: | echo "### PR Readiness Status :rocket:" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "| Check | Status |" >> $GITHUB_STEP_SUMMARY echo "| --- | --- |" >> $GITHUB_STEP_SUMMARY echo "| Backend Checkstyle | ✅ Passed |" >> $GITHUB_STEP_SUMMARY echo "| Backend Tests | ✅ Passed |" >> $GITHUB_STEP_SUMMARY echo "| Backend Build | ✅ Passed |" >> $GITHUB_STEP_SUMMARY echo "| Frontend Lint | ✅ Passed |" >> $GITHUB_STEP_SUMMARY echo "| Frontend Tests | ✅ Passed |" >> $GITHUB_STEP_SUMMARY echo "| Frontend Build | ✅ Passed |" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "✅ **This PR is ready to merge!**" >> $GITHUB_STEP_SUMMARY