mirror of
https://github.com/kikootwo/ReadMeABook.git
synced 2026-06-02 20:30:10 +00:00
428d9a12e0
Strips ANSI color codes from test output for reliable parsing and updates grep logic to use the last relevant lines for test files, tests, and duration. This enhances robustness when extracting test statistics from vitest output in the GitHub Actions workflow.
260 lines
10 KiB
YAML
260 lines
10 KiB
YAML
name: Backend Tests
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
workflow_call:
|
|
inputs:
|
|
send_notification:
|
|
description: "Whether to send Discord notification"
|
|
type: boolean
|
|
default: true
|
|
secrets:
|
|
WEBHOOK_URL:
|
|
description: "Discord webhook URL"
|
|
required: false
|
|
outputs:
|
|
success:
|
|
description: "Whether tests passed"
|
|
value: ${{ jobs.test.outputs.success }}
|
|
total:
|
|
description: "Total number of tests"
|
|
value: ${{ jobs.test.outputs.total }}
|
|
passed:
|
|
description: "Number of passed tests"
|
|
value: ${{ jobs.test.outputs.passed }}
|
|
failed:
|
|
description: "Number of failed tests"
|
|
value: ${{ jobs.test.outputs.failed }}
|
|
duration:
|
|
description: "Test duration in seconds"
|
|
value: ${{ jobs.test.outputs.duration }}
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
test:
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
success: ${{ steps.test-results.outputs.success }}
|
|
total: ${{ steps.test-results.outputs.total }}
|
|
passed: ${{ steps.test-results.outputs.passed }}
|
|
failed: ${{ steps.test-results.outputs.failed }}
|
|
duration: ${{ steps.test-results.outputs.duration }}
|
|
test_files: ${{ steps.test-results.outputs.test_files }}
|
|
test_files_passed: ${{ steps.test-results.outputs.test_files_passed }}
|
|
test_files_failed: ${{ steps.test-results.outputs.test_files_failed }}
|
|
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Set up Node.js
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '20'
|
|
cache: 'npm'
|
|
|
|
- name: Install dependencies
|
|
run: npm ci
|
|
|
|
- name: Run tests
|
|
id: run-tests
|
|
continue-on-error: true
|
|
run: |
|
|
START_TIME=$(date +%s)
|
|
npm test 2>&1 | tee test-output.txt
|
|
TEST_EXIT_CODE=${PIPESTATUS[0]}
|
|
END_TIME=$(date +%s)
|
|
echo "exit_code=$TEST_EXIT_CODE" >> $GITHUB_OUTPUT
|
|
echo "start_time=$(date -u +"%H:%M:%S")" >> $GITHUB_OUTPUT
|
|
echo "elapsed=$((END_TIME - START_TIME))" >> $GITHUB_OUTPUT
|
|
|
|
- name: Parse test results
|
|
id: test-results
|
|
if: always()
|
|
run: |
|
|
# Parse the test output from vitest's default reporter
|
|
if [ -f test-output.txt ]; then
|
|
# Strip ANSI color codes for reliable parsing
|
|
sed -i 's/\x1b\[[0-9;]*m//g' test-output.txt
|
|
|
|
# Debug: show relevant lines
|
|
echo "=== Relevant test output lines ==="
|
|
grep -E "(Test Files|Tests|Duration)" test-output.txt | tail -5 || true
|
|
echo "==================================="
|
|
|
|
# Extract test file count (e.g., "Test Files 81 passed (81)")
|
|
TEST_FILES_LINE=$(grep "Test Files" test-output.txt | tail -1 || echo "")
|
|
if [ -n "$TEST_FILES_LINE" ]; then
|
|
TEST_FILES_PASSED=$(echo "$TEST_FILES_LINE" | grep -oE "[0-9]+ passed" | grep -oE "[0-9]+" | head -1 || echo "0")
|
|
TEST_FILES_FAILED=$(echo "$TEST_FILES_LINE" | grep -oE "[0-9]+ failed" | grep -oE "[0-9]+" | head -1 || echo "0")
|
|
TEST_FILES=$(echo "$TEST_FILES_LINE" | grep -oE "\([0-9]+\)" | grep -oE "[0-9]+" | head -1 || echo "0")
|
|
else
|
|
TEST_FILES_PASSED=0
|
|
TEST_FILES_FAILED=0
|
|
TEST_FILES=0
|
|
fi
|
|
|
|
# Extract test count - look for line containing "Tests" followed by number, exclude "Test Files"
|
|
TESTS_LINE=$(grep -E "Tests\s+[0-9]+" test-output.txt | grep -v "Test Files" | tail -1 || echo "")
|
|
if [ -n "$TESTS_LINE" ]; then
|
|
PASSED=$(echo "$TESTS_LINE" | grep -oE "[0-9]+ passed" | grep -oE "[0-9]+" | head -1 || echo "0")
|
|
FAILED=$(echo "$TESTS_LINE" | grep -oE "[0-9]+ failed" | grep -oE "[0-9]+" | head -1 || echo "0")
|
|
TOTAL=$(echo "$TESTS_LINE" | grep -oE "\([0-9]+\)" | grep -oE "[0-9]+" | head -1 || echo "0")
|
|
else
|
|
PASSED=0
|
|
FAILED=0
|
|
TOTAL=0
|
|
fi
|
|
|
|
# Extract duration (e.g., "Duration 26.97s")
|
|
DURATION_LINE=$(grep -E "Duration\s+[0-9]+" test-output.txt | tail -1 || echo "")
|
|
if [ -n "$DURATION_LINE" ]; then
|
|
DURATION=$(echo "$DURATION_LINE" | grep -oE "[0-9]+\.[0-9]+s" | head -1 | sed 's/s//' || echo "0")
|
|
else
|
|
DURATION="${{ steps.run-tests.outputs.elapsed }}"
|
|
fi
|
|
|
|
# Determine success based on exit code and failed count
|
|
if [ "${{ steps.run-tests.outputs.exit_code }}" = "0" ] && [ "${FAILED:-0}" = "0" ]; then
|
|
SUCCESS="true"
|
|
else
|
|
SUCCESS="false"
|
|
fi
|
|
else
|
|
TOTAL=0
|
|
PASSED=0
|
|
FAILED=1
|
|
TEST_FILES=0
|
|
TEST_FILES_PASSED=0
|
|
TEST_FILES_FAILED=1
|
|
DURATION=0
|
|
SUCCESS="false"
|
|
fi
|
|
|
|
# Set defaults for empty values
|
|
TOTAL=${TOTAL:-0}
|
|
PASSED=${PASSED:-0}
|
|
FAILED=${FAILED:-0}
|
|
TEST_FILES=${TEST_FILES:-0}
|
|
TEST_FILES_PASSED=${TEST_FILES_PASSED:-0}
|
|
TEST_FILES_FAILED=${TEST_FILES_FAILED:-0}
|
|
DURATION=${DURATION:-0}
|
|
|
|
echo "=== Parsed values ==="
|
|
echo "TEST_FILES_PASSED=$TEST_FILES_PASSED"
|
|
echo "TEST_FILES=$TEST_FILES"
|
|
echo "PASSED=$PASSED"
|
|
echo "TOTAL=$TOTAL"
|
|
echo "DURATION=$DURATION"
|
|
echo "SUCCESS=$SUCCESS"
|
|
echo "===================="
|
|
|
|
echo "total=$TOTAL" >> $GITHUB_OUTPUT
|
|
echo "passed=$PASSED" >> $GITHUB_OUTPUT
|
|
echo "failed=$FAILED" >> $GITHUB_OUTPUT
|
|
echo "duration=$DURATION" >> $GITHUB_OUTPUT
|
|
echo "success=$SUCCESS" >> $GITHUB_OUTPUT
|
|
echo "test_files=$TEST_FILES" >> $GITHUB_OUTPUT
|
|
echo "test_files_passed=$TEST_FILES_PASSED" >> $GITHUB_OUTPUT
|
|
echo "test_files_failed=$TEST_FILES_FAILED" >> $GITHUB_OUTPUT
|
|
|
|
echo "## 🧪 Test Results" >> $GITHUB_STEP_SUMMARY
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
if [ "$SUCCESS" = "true" ]; then
|
|
echo "### ✅ All tests passed!" >> $GITHUB_STEP_SUMMARY
|
|
else
|
|
echo "### ❌ Some tests failed" >> $GITHUB_STEP_SUMMARY
|
|
fi
|
|
echo "" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Metric | Value |" >> $GITHUB_STEP_SUMMARY
|
|
echo "|--------|-------|" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Test Files | $TEST_FILES_PASSED passed ($TEST_FILES) |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Tests | $PASSED passed ($TOTAL) |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Duration | ${DURATION}s |" >> $GITHUB_STEP_SUMMARY
|
|
|
|
- name: Send Discord notification
|
|
if: always() && (inputs.send_notification != false)
|
|
env:
|
|
WEBHOOK_URL: ${{ secrets.WEBHOOK_URL }}
|
|
run: |
|
|
if [ -z "$WEBHOOK_URL" ]; then
|
|
echo "No webhook URL provided, skipping notification"
|
|
exit 0
|
|
fi
|
|
|
|
SUCCESS="${{ steps.test-results.outputs.success }}"
|
|
TOTAL="${{ steps.test-results.outputs.total }}"
|
|
PASSED="${{ steps.test-results.outputs.passed }}"
|
|
FAILED="${{ steps.test-results.outputs.failed }}"
|
|
DURATION="${{ steps.test-results.outputs.duration }}"
|
|
TEST_FILES="${{ steps.test-results.outputs.test_files }}"
|
|
TEST_FILES_PASSED="${{ steps.test-results.outputs.test_files_passed }}"
|
|
TEST_FILES_FAILED="${{ steps.test-results.outputs.test_files_failed }}"
|
|
|
|
if [ "$SUCCESS" = "true" ]; then
|
|
COLOR=5763719
|
|
TITLE="✅ Tests Passed"
|
|
DESCRIPTION="All tests completed successfully for **ReadMeABook**"
|
|
TEST_FILES_VALUE="$TEST_FILES_PASSED passed ($TEST_FILES)"
|
|
TESTS_VALUE="$PASSED passed ($TOTAL)"
|
|
else
|
|
COLOR=15548997
|
|
TITLE="❌ Tests Failed"
|
|
DESCRIPTION="Some tests failed for **ReadMeABook**"
|
|
TEST_FILES_VALUE="$TEST_FILES_PASSED passed, $TEST_FILES_FAILED failed ($TEST_FILES)"
|
|
TESTS_VALUE="$PASSED passed, $FAILED failed ($TOTAL)"
|
|
fi
|
|
|
|
curl -H "Content-Type: application/json" \
|
|
-X POST \
|
|
-d "{
|
|
\"embeds\": [{
|
|
\"title\": \"$TITLE\",
|
|
\"description\": \"$DESCRIPTION\",
|
|
\"color\": $COLOR,
|
|
\"fields\": [
|
|
{
|
|
\"name\": \"📁 Test Files\",
|
|
\"value\": \"\`$TEST_FILES_VALUE\`\",
|
|
\"inline\": true
|
|
},
|
|
{
|
|
\"name\": \"🧪 Tests\",
|
|
\"value\": \"\`$TESTS_VALUE\`\",
|
|
\"inline\": true
|
|
},
|
|
{
|
|
\"name\": \"⏱️ Duration\",
|
|
\"value\": \"\`${DURATION}s\`\",
|
|
\"inline\": true
|
|
},
|
|
{
|
|
\"name\": \"🌿 Branch\",
|
|
\"value\": \"\`${{ github.ref_name }}\`\",
|
|
\"inline\": true
|
|
},
|
|
{
|
|
\"name\": \"📋 Commit\",
|
|
\"value\": \"[\`$(echo ${{ github.sha }} | cut -c1-7)\`](${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }})\",
|
|
\"inline\": true
|
|
},
|
|
{
|
|
\"name\": \"🔗 Workflow\",
|
|
\"value\": \"[View Run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})\",
|
|
\"inline\": true
|
|
}
|
|
],
|
|
\"footer\": {
|
|
\"text\": \"ReadMeABook CI/CD • Test Suite\"
|
|
},
|
|
\"timestamp\": \"$(date -u +"%Y-%m-%dT%H:%M:%SZ")\"
|
|
}]
|
|
}" \
|
|
"$WEBHOOK_URL"
|
|
|
|
- name: Fail if tests failed
|
|
if: steps.test-results.outputs.success != 'true'
|
|
run: exit 1
|