Skip to content

FORGE-985-Maven Publishing Redux #100

FORGE-985-Maven Publishing Redux

FORGE-985-Maven Publishing Redux #100

Workflow file for this run

name: Test Coverage
on:
pull_request:
branches: [main]
permissions:
contents: read
pull-requests: write
issues: write
jobs:
test-coverage:
runs-on: ubuntu-latest
strategy:
matrix:
# Workspace package names
workspace:
- "@dittolive/ditto-chat-core"
- "@dittolive/ditto-chat-ui"
include:
- workspace: "@dittolive/ditto-chat-core"
path: "sdks/js/ditto-chat-core"
- workspace: "@dittolive/ditto-chat-ui"
path: "sdks/js/ditto-chat-ui"
fail-fast: false
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "24"
cache: "npm"
cache-dependency-path: "package-lock.json"
- name: Install dependencies
run: npm ci
- name: Run tests with coverage
run: npm run test:coverage -w ${{ matrix.workspace }}
continue-on-error: false
- name: Generate coverage report
working-directory: ${{ matrix.path }}
run: |
# Generate coverage summary
if [ -f "coverage/coverage-summary.json" ]; then
echo "COVERAGE_SUMMARY<<EOF" >> $GITHUB_ENV
cat coverage/coverage-summary.json
echo "EOF" >> $GITHUB_ENV
fi
- name: Upload coverage reports
if: always()
uses: actions/upload-artifact@v4
with:
name: coverage-report-${{ hashFiles(format('{0}/package.json', matrix.path)) }}
path: ${{ matrix.path }}/coverage/
retention-days: 15
- name: Parse coverage data
id: coverage
working-directory: ${{ matrix.path }}
run: |
if [ -f "coverage/coverage-summary.json" ]; then
# Extract overall coverage percentages
LINES=$(jq -r '.total.lines.pct' coverage/coverage-summary.json)
STATEMENTS=$(jq -r '.total.statements.pct' coverage/coverage-summary.json)
FUNCTIONS=$(jq -r '.total.functions.pct' coverage/coverage-summary.json)
BRANCHES=$(jq -r '.total.branches.pct' coverage/coverage-summary.json)
echo "lines=$LINES" >> $GITHUB_OUTPUT
echo "statements=$STATEMENTS" >> $GITHUB_OUTPUT
echo "functions=$FUNCTIONS" >> $GITHUB_OUTPUT
echo "branches=$BRANCHES" >> $GITHUB_OUTPUT
else
echo "lines=0" >> $GITHUB_OUTPUT
echo "statements=0" >> $GITHUB_OUTPUT
echo "functions=0" >> $GITHUB_OUTPUT
echo "branches=0" >> $GITHUB_OUTPUT
fi
- name: Comment PR with coverage results
if: always()
uses: actions/github-script@v7
with:
script: |
const workspace = '${{ matrix.workspace }}';
const lines = parseFloat('${{ steps.coverage.outputs.lines }}');
const statements = parseFloat('${{ steps.coverage.outputs.statements }}');
const functions = parseFloat('${{ steps.coverage.outputs.functions }}');
const branches = parseFloat('${{ steps.coverage.outputs.branches }}');
// Determine coverage status
const getCoverageEmoji = (pct) => {
if (pct >= 80) return '🟒';
if (pct >= 60) return '🟑';
if (pct >= 40) return '🟠';
return 'πŸ”΄';
};
const getCoverageColor = (pct) => {
if (pct >= 80) return 'green';
if (pct >= 60) return 'yellow';
if (pct >= 40) return 'orange';
return 'red';
};
const overallCoverage = (lines + statements + functions + branches) / 4;
const statusEmoji = getCoverageEmoji(overallCoverage);
const body = `## ${statusEmoji} Test Coverage Report - \`${workspace}\`
### Overall Coverage: ${overallCoverage.toFixed(2)}%
| Metric | Coverage | Status |
|--------|----------|--------|
| ${getCoverageEmoji(lines)} Lines | **${lines}%** | ${getCoverageColor(lines)} |
| ${getCoverageEmoji(statements)} Statements | **${statements}%** | ${getCoverageColor(statements)} |
| ${getCoverageEmoji(functions)} Functions | **${functions}%** | ${getCoverageColor(functions)} |
| ${getCoverageEmoji(branches)} Branches | **${branches}%** | ${getCoverageColor(branches)} |
---
πŸ“Š **[View Detailed Coverage Report](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})**
<details>
<summary>ℹ️ Coverage Thresholds</summary>
- 🟒 **Excellent** (β‰₯ 80%)
- 🟑 **Good** (60-79%)
- 🟠 **Fair** (40-59%)
- πŸ”΄ **Poor** (< 40%)
</details>
`;
// Find existing comment
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
const botComment = comments.find(comment =>
comment.user.type === 'Bot' &&
comment.body.includes(`Test Coverage Report - \`${workspace}\``)
);
// Update or create comment
if (botComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: body
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: body
});
}
// Set status based on coverage threshold
if (overallCoverage < 70) {
core.setFailed(`Coverage is below 70% for ${workspace}: ${overallCoverage.toFixed(2)}%`);
}
- name: Check coverage threshold
working-directory: ${{ matrix.path }}
run: |
LINES=${{ steps.coverage.outputs.lines }}
STATEMENTS=${{ steps.coverage.outputs.statements }}
FUNCTIONS=${{ steps.coverage.outputs.functions }}
BRANCHES=${{ steps.coverage.outputs.branches }}
# Calculate overall coverage
OVERALL=$(awk "BEGIN {printf \"%.2f\", ($LINES + $STATEMENTS + $FUNCTIONS + $BRANCHES) / 4}")
THRESHOLD=70
echo "πŸ“Š Coverage Summary:"
echo " Lines: $LINES%"
echo " Statements: $STATEMENTS%"
echo " Functions: $FUNCTIONS%"
echo " Branches: $BRANCHES%"
echo " Overall: $OVERALL%"
# Compare using awk
BELOW_THRESHOLD=$(awk "BEGIN {print ($OVERALL < $THRESHOLD)}")
if [ "$BELOW_THRESHOLD" = "1" ]; then
echo "::error::Overall coverage is below ${THRESHOLD}% threshold: $OVERALL%"
echo "❌ Coverage threshold check failed for ${{ matrix.workspace }}"
exit 1
else
echo "βœ… Coverage threshold check passed for ${{ matrix.workspace }} (${OVERALL}%)"
fi