Merge pull request #584 from AAVSO/ut-flake-mitigation #1087
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # This workflow will build a Java project with Ant and run VStar's plugin UTs | |
| # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-ant | |
| name: Plug-in Unit Tests | |
| on: | |
| push: | |
| branches: | |
| - "**" | |
| pull_request: | |
| branches: [ master ] | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| jobs: | |
| build: | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| java: [ '17', '21', '23' ] | |
| name: Java ${{ matrix.java }} Plugin UTs | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Java | |
| uses: actions/setup-java@v4 | |
| with: | |
| java-version: ${{ matrix.java }} | |
| distribution: 'temurin' | |
| - name: Create plugin dir | |
| run: | |
| mkdir -p ~/vstar_plugins | |
| - name: Create plugin libs dir | |
| run: | |
| mkdir -p ~/vstar_plugin_libs | |
| - name: Build and test with coverage | |
| id: tests | |
| uses: nick-fields/retry@v3 | |
| with: | |
| timeout_minutes: 25 | |
| max_attempts: 2 | |
| command: | | |
| ant -noinput -buildfile build.xml dist | |
| cd plugin | |
| ant -noinput -buildfile build.xml coverage-report | |
| - name: Extract test and coverage metrics | |
| if: always() | |
| id: metrics | |
| run: | | |
| SUMMARY="plugin/test_report/summary.txt" | |
| COV_XML="plugin/test_report/coverage/coverage.xml" | |
| TESTS=0; FAILURES=0; ERRORS=0 | |
| if [ -f "$SUMMARY" ]; then | |
| while IFS= read -r line; do | |
| t=$(echo "$line" | grep -oP 'Tests run: \K[0-9]+' || true) | |
| f=$(echo "$line" | grep -oP 'Failures: \K[0-9]+' || true) | |
| e=$(echo "$line" | grep -oP 'Errors: \K[0-9]+' || true) | |
| [ -n "$t" ] && TESTS=$((TESTS + t)) | |
| [ -n "$f" ] && FAILURES=$((FAILURES + f)) | |
| [ -n "$e" ] && ERRORS=$((ERRORS + e)) | |
| done < "$SUMMARY" | |
| fi | |
| PASSED=$((TESTS - FAILURES - ERRORS)) | |
| LINE_COV="N/A"; BRANCH_COV="N/A" | |
| if [ -f "$COV_XML" ]; then | |
| LINE_M=$(grep -oP '<counter type="LINE" missed="\K[0-9]+' "$COV_XML" | tail -1 || true) | |
| LINE_C=$(grep -oP '<counter type="LINE" missed="[0-9]+" covered="\K[0-9]+' "$COV_XML" | tail -1 || true) | |
| BRANCH_M=$(grep -oP '<counter type="BRANCH" missed="\K[0-9]+' "$COV_XML" | tail -1 || true) | |
| BRANCH_C=$(grep -oP '<counter type="BRANCH" missed="[0-9]+" covered="\K[0-9]+' "$COV_XML" | tail -1 || true) | |
| if [ -n "$LINE_M" ] && [ -n "$LINE_C" ]; then | |
| TOTAL_L=$((LINE_M + LINE_C)) | |
| if [ "$TOTAL_L" -gt 0 ]; then | |
| LINE_COV="$((LINE_C * 100 / TOTAL_L))%" | |
| fi | |
| fi | |
| if [ -n "$BRANCH_M" ] && [ -n "$BRANCH_C" ]; then | |
| TOTAL_B=$((BRANCH_M + BRANCH_C)) | |
| if [ "$TOTAL_B" -gt 0 ]; then | |
| BRANCH_COV="$((BRANCH_C * 100 / TOTAL_B))%" | |
| fi | |
| fi | |
| fi | |
| echo "tests=$TESTS" >> "$GITHUB_OUTPUT" | |
| echo "passed=$PASSED" >> "$GITHUB_OUTPUT" | |
| echo "failures=$FAILURES" >> "$GITHUB_OUTPUT" | |
| echo "errors=$ERRORS" >> "$GITHUB_OUTPUT" | |
| echo "line_cov=$LINE_COV" >> "$GITHUB_OUTPUT" | |
| echo "branch_cov=$BRANCH_COV" >> "$GITHUB_OUTPUT" | |
| - name: Post step summary | |
| if: always() && steps.metrics.outputs.tests != '0' | |
| run: | | |
| STATUS="${{ steps.tests.outcome == 'success' && 'All tests passed' || 'Tests failed' }}" | |
| cat >> "$GITHUB_STEP_SUMMARY" <<EOF | |
| ## Plugin Unit Tests (Java ${{ matrix.java }}) | |
| **${STATUS}** | |
| | Metric | Value | | |
| |--------|-------| | |
| | Tests | ${{ steps.metrics.outputs.tests }} | | |
| | Passed | ${{ steps.metrics.outputs.passed }} | | |
| | Failures | ${{ steps.metrics.outputs.failures }} | | |
| | Errors | ${{ steps.metrics.outputs.errors }} | | |
| | Line Coverage | ${{ steps.metrics.outputs.line_cov }} | | |
| | Branch Coverage | ${{ steps.metrics.outputs.branch_cov }} | | |
| EOF | |
| - name: Comment on PR | |
| if: >- | |
| always() && | |
| github.event_name == 'pull_request' && | |
| matrix.java == '17' && | |
| steps.metrics.outputs.tests != '0' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const outcome = '${{ steps.tests.outcome }}'; | |
| const status = outcome === 'success' ? 'All tests passed' : 'Tests failed'; | |
| const tests = '${{ steps.metrics.outputs.tests }}'; | |
| const passed = '${{ steps.metrics.outputs.passed }}'; | |
| const failures = '${{ steps.metrics.outputs.failures }}'; | |
| const errors = '${{ steps.metrics.outputs.errors }}'; | |
| const body = [ | |
| '## Plugin Unit Tests', | |
| '', | |
| `**${status}** (Java 17)`, | |
| '', | |
| '| Metric | Value |', | |
| '|--------|-------|', | |
| `| Tests | ${tests} |`, | |
| `| Passed | ${passed} |`, | |
| `| Failures | ${failures} |`, | |
| `| Errors | ${errors} |`, | |
| ].join('\n'); | |
| const { data: comments } = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| }); | |
| const existing = comments.find(c => | |
| c.user.type === 'Bot' && c.body.startsWith('## Plugin Unit Tests') | |
| ); | |
| if (existing) { | |
| await github.rest.issues.updateComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| comment_id: existing.id, | |
| body: body, | |
| }); | |
| } else { | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| body: body, | |
| }); | |
| } | |
| - name: Upload coverage report | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: plugin-coverage-report-java${{ matrix.java }} | |
| path: plugin/test_report/ | |
| - name: Checkout gh-pages | |
| if: >- | |
| github.event_name == 'push' && | |
| github.ref == 'refs/heads/master' && | |
| matrix.java == '17' && | |
| steps.metrics.outputs.tests != '0' | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: gh-pages | |
| path: _site | |
| - name: Publish to dashboard | |
| if: >- | |
| github.event_name == 'push' && | |
| github.ref == 'refs/heads/master' && | |
| matrix.java == '17' && | |
| steps.metrics.outputs.tests != '0' | |
| run: | | |
| DATE=$(date -u +%Y-%m-%d) | |
| mkdir -p _site/health/data _site/health/coverage/plugins | |
| cat > _site/health/data/plugin-coverage.json <<DATAJSON | |
| { | |
| "updated": "${DATE}", | |
| "java_version": "17", | |
| "tests": ${{ steps.metrics.outputs.tests }}, | |
| "passed": ${{ steps.metrics.outputs.passed }}, | |
| "failures": ${{ steps.metrics.outputs.failures }}, | |
| "errors": ${{ steps.metrics.outputs.errors }}, | |
| "line_coverage": "${{ steps.metrics.outputs.line_cov }}", | |
| "branch_coverage": "${{ steps.metrics.outputs.branch_cov }}" | |
| } | |
| DATAJSON | |
| rm -rf _site/health/coverage/plugins/* | |
| if [ -d "plugin/test_report/coverage" ]; then | |
| cp -r plugin/test_report/coverage/* _site/health/coverage/plugins/ | |
| fi | |
| cd _site | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git config user.name "github-actions[bot]" | |
| git add -A | |
| git diff --cached --quiet && exit 0 | |
| git commit -m "Update plugin coverage data [${DATE}]" | |
| for i in 1 2 3; do | |
| git pull --rebase origin gh-pages && git push origin gh-pages && break | |
| echo "Push attempt $i failed, retrying in $((i * 5))s..." | |
| sleep $((i * 5)) | |
| done |