name: ๐Ÿงช Test Suite on: pull_request: branches: [main, develop] push: branches: [main, develop] permissions: contents: read pull-requests: write issues: write env: MIX_ENV: test ELIXIR_VERSION: '1.16' OTP_VERSION: '26' NODE_VERSION: '18' jobs: test: name: Test Suite runs-on: ubuntu-latest services: postgres: image: postgres:15 env: POSTGRES_PASSWORD: postgres POSTGRES_DB: wanderer_test options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 ports: - 5432:5432 steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Elixir/OTP uses: erlef/setup-beam@v1 with: elixir-version: ${{ env.ELIXIR_VERSION }} otp-version: ${{ env.OTP_VERSION }} - name: Cache Elixir dependencies uses: actions/cache@v3 with: path: | deps _build key: ${{ runner.os }}-mix-${{ hashFiles('**/mix.lock') }} restore-keys: ${{ runner.os }}-mix- - name: Install Elixir dependencies run: | mix deps.get mix deps.compile - name: Check code formatting id: format run: | if mix format --check-formatted; then echo "status=โœ… Passed" >> $GITHUB_OUTPUT echo "count=0" >> $GITHUB_OUTPUT else echo "status=โŒ Failed" >> $GITHUB_OUTPUT echo "count=1" >> $GITHUB_OUTPUT fi continue-on-error: true - name: Compile code and capture warnings id: compile run: | # Capture compilation output output=$(mix compile 2>&1 || true) echo "$output" > compile_output.txt # Count warnings warning_count=$(echo "$output" | grep -c "warning:" || echo "0") # Check if compilation succeeded if mix compile > /dev/null 2>&1; then echo "status=โœ… Success" >> $GITHUB_OUTPUT else echo "status=โŒ Failed" >> $GITHUB_OUTPUT fi echo "warnings=$warning_count" >> $GITHUB_OUTPUT echo "output<> $GITHUB_OUTPUT echo "$output" >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT continue-on-error: true - name: Setup database run: | mix ecto.create mix ecto.migrate - name: Run tests with coverage id: tests run: | # Run tests with coverage output=$(mix test --cover 2>&1 || true) echo "$output" > test_output.txt # Parse test results if echo "$output" | grep -q "0 failures"; then echo "status=โœ… All Passed" >> $GITHUB_OUTPUT test_status="success" else echo "status=โŒ Some Failed" >> $GITHUB_OUTPUT test_status="failed" fi # Extract test counts test_line=$(echo "$output" | grep -E "[0-9]+ tests?, [0-9]+ failures?" | head -1 || echo "0 tests, 0 failures") total_tests=$(echo "$test_line" | grep -o '[0-9]\+ tests\?' | grep -o '[0-9]\+' | head -1 || echo "0") failures=$(echo "$test_line" | grep -o '[0-9]\+ failures\?' | grep -o '[0-9]\+' | head -1 || echo "0") echo "total=$total_tests" >> $GITHUB_OUTPUT echo "failures=$failures" >> $GITHUB_OUTPUT echo "passed=$((total_tests - failures))" >> $GITHUB_OUTPUT # Calculate success rate if [ "$total_tests" -gt 0 ]; then success_rate=$(echo "scale=1; ($total_tests - $failures) * 100 / $total_tests" | bc) else success_rate="0" fi echo "success_rate=$success_rate" >> $GITHUB_OUTPUT exit_code=$? echo "exit_code=$exit_code" >> $GITHUB_OUTPUT continue-on-error: true - name: Generate coverage report id: coverage run: | # Generate coverage report with GitHub format output=$(mix coveralls.github 2>&1 || true) echo "$output" > coverage_output.txt # Extract coverage percentage coverage=$(echo "$output" | grep -o '[0-9]\+\.[0-9]\+%' | head -1 | sed 's/%//' || echo "0") if [ -z "$coverage" ]; then coverage="0" fi echo "percentage=$coverage" >> $GITHUB_OUTPUT # Determine status if (( $(echo "$coverage >= 80" | bc -l) )); then echo "status=โœ… Excellent" >> $GITHUB_OUTPUT elif (( $(echo "$coverage >= 60" | bc -l) )); then echo "status=โš ๏ธ Good" >> $GITHUB_OUTPUT else echo "status=โŒ Needs Improvement" >> $GITHUB_OUTPUT fi continue-on-error: true - name: Run Credo analysis id: credo run: | # Run Credo and capture output output=$(mix credo --strict --format=json 2>&1 || true) echo "$output" > credo_output.txt # Try to parse JSON output if echo "$output" | jq . > /dev/null 2>&1; then issues=$(echo "$output" | jq '.issues | length' 2>/dev/null || echo "0") high_issues=$(echo "$output" | jq '.issues | map(select(.priority == "high")) | length' 2>/dev/null || echo "0") normal_issues=$(echo "$output" | jq '.issues | map(select(.priority == "normal")) | length' 2>/dev/null || echo "0") low_issues=$(echo "$output" | jq '.issues | map(select(.priority == "low")) | length' 2>/dev/null || echo "0") else # Fallback: try to count issues from regular output regular_output=$(mix credo --strict 2>&1 || true) issues=$(echo "$regular_output" | grep -c "โ”ƒ" || echo "0") high_issues="0" normal_issues="0" low_issues="0" fi echo "total_issues=$issues" >> $GITHUB_OUTPUT echo "high_issues=$high_issues" >> $GITHUB_OUTPUT echo "normal_issues=$normal_issues" >> $GITHUB_OUTPUT echo "low_issues=$low_issues" >> $GITHUB_OUTPUT # Determine status if [ "$issues" -eq 0 ]; then echo "status=โœ… Clean" >> $GITHUB_OUTPUT elif [ "$issues" -lt 10 ]; then echo "status=โš ๏ธ Minor Issues" >> $GITHUB_OUTPUT else echo "status=โŒ Needs Attention" >> $GITHUB_OUTPUT fi continue-on-error: true - name: Run Dialyzer analysis id: dialyzer run: | # Ensure PLT is built mix dialyzer --plt # Run Dialyzer and capture output output=$(mix dialyzer --format=github 2>&1 || true) echo "$output" > dialyzer_output.txt # Count warnings and errors warnings=$(echo "$output" | grep -c "warning:" || echo "0") errors=$(echo "$output" | grep -c "error:" || echo "0") echo "warnings=$warnings" >> $GITHUB_OUTPUT echo "errors=$errors" >> $GITHUB_OUTPUT # Determine status if [ "$errors" -eq 0 ] && [ "$warnings" -eq 0 ]; then echo "status=โœ… Clean" >> $GITHUB_OUTPUT elif [ "$errors" -eq 0 ]; then echo "status=โš ๏ธ Warnings Only" >> $GITHUB_OUTPUT else echo "status=โŒ Has Errors" >> $GITHUB_OUTPUT fi continue-on-error: true - name: Create test results summary id: summary run: | # Calculate overall score format_score=${{ steps.format.outputs.count == '0' && '100' || '0' }} compile_score=${{ steps.compile.outputs.warnings == '0' && '100' || '80' }} test_score=${{ steps.tests.outputs.success_rate }} coverage_score=${{ steps.coverage.outputs.percentage }} credo_score=$(echo "scale=0; (100 - ${{ steps.credo.outputs.total_issues }} * 2)" | bc | sed 's/^-.*$/0/') dialyzer_score=$(echo "scale=0; (100 - ${{ steps.dialyzer.outputs.warnings }} * 2 - ${{ steps.dialyzer.outputs.errors }} * 10)" | bc | sed 's/^-.*$/0/') overall_score=$(echo "scale=1; ($format_score + $compile_score + $test_score + $coverage_score + $credo_score + $dialyzer_score) / 6" | bc) echo "overall_score=$overall_score" >> $GITHUB_OUTPUT # Determine overall status if (( $(echo "$overall_score >= 90" | bc -l) )); then echo "overall_status=๐ŸŒŸ Excellent" >> $GITHUB_OUTPUT elif (( $(echo "$overall_score >= 80" | bc -l) )); then echo "overall_status=โœ… Good" >> $GITHUB_OUTPUT elif (( $(echo "$overall_score >= 70" | bc -l) )); then echo "overall_status=โš ๏ธ Needs Improvement" >> $GITHUB_OUTPUT else echo "overall_status=โŒ Poor" >> $GITHUB_OUTPUT fi continue-on-error: true - name: Find existing PR comment if: github.event_name == 'pull_request' id: find_comment uses: peter-evans/find-comment@v3 with: issue-number: ${{ github.event.pull_request.number }} comment-author: 'github-actions[bot]' body-includes: '## ๐Ÿงช Test Results Summary' - name: Create or update PR comment if: github.event_name == 'pull_request' uses: peter-evans/create-or-update-comment@v4 with: comment-id: ${{ steps.find_comment.outputs.comment-id }} issue-number: ${{ github.event.pull_request.number }} edit-mode: replace body: | ## ๐Ÿงช Test Results Summary **Overall Quality Score: ${{ steps.summary.outputs.overall_score }}%** ${{ steps.summary.outputs.overall_status }} ### ๐Ÿ“Š Metrics Dashboard | Category | Status | Count | Details | |----------|---------|-------|---------| | ๐Ÿ“ **Code Formatting** | ${{ steps.format.outputs.status }} | ${{ steps.format.outputs.count }} issues | `mix format --check-formatted` | | ๐Ÿ”จ **Compilation** | ${{ steps.compile.outputs.status }} | ${{ steps.compile.outputs.warnings }} warnings | `mix compile` | | ๐Ÿงช **Tests** | ${{ steps.tests.outputs.status }} | ${{ steps.tests.outputs.failures }}/${{ steps.tests.outputs.total }} failed | Success rate: ${{ steps.tests.outputs.success_rate }}% | | ๐Ÿ“Š **Coverage** | ${{ steps.coverage.outputs.status }} | ${{ steps.coverage.outputs.percentage }}% | `mix coveralls` | | ๐ŸŽฏ **Credo** | ${{ steps.credo.outputs.status }} | ${{ steps.credo.outputs.total_issues }} issues | High: ${{ steps.credo.outputs.high_issues }}, Normal: ${{ steps.credo.outputs.normal_issues }}, Low: ${{ steps.credo.outputs.low_issues }} | | ๐Ÿ” **Dialyzer** | ${{ steps.dialyzer.outputs.status }} | ${{ steps.dialyzer.outputs.errors }} errors, ${{ steps.dialyzer.outputs.warnings }} warnings | `mix dialyzer` | ### ๐ŸŽฏ Quality Gates Based on the project's quality thresholds: - **Compilation Warnings**: ${{ steps.compile.outputs.warnings }}/148 (limit: 148) - **Credo Issues**: ${{ steps.credo.outputs.total_issues }}/87 (limit: 87) - **Dialyzer Warnings**: ${{ steps.dialyzer.outputs.warnings }}/161 (limit: 161) - **Test Coverage**: ${{ steps.coverage.outputs.percentage }}%/50% (minimum: 50%) - **Test Failures**: ${{ steps.tests.outputs.failures }}/0 (limit: 0)
๐Ÿ“ˆ Progress Toward Goals Target goals for the project: - โœจ **Zero compilation warnings** (currently: ${{ steps.compile.outputs.warnings }}) - โœจ **โ‰ค10 Credo issues** (currently: ${{ steps.credo.outputs.total_issues }}) - โœจ **Zero Dialyzer warnings** (currently: ${{ steps.dialyzer.outputs.warnings }}) - โœจ **โ‰ฅ85% test coverage** (currently: ${{ steps.coverage.outputs.percentage }}%) - โœ… **Zero test failures** (currently: ${{ steps.tests.outputs.failures }})
๐Ÿ”ง Quick Actions To improve code quality: ```bash # Fix formatting issues mix format # View detailed Credo analysis mix credo --strict # Check Dialyzer warnings mix dialyzer # Generate detailed coverage report mix coveralls.html ```
--- ๐Ÿค– *Auto-generated by GitHub Actions* โ€ข Updated: ${{ github.event.head_commit.timestamp }} > **Note**: This comment will be updated automatically when new commits are pushed to this PR.