Skip to content

Merge pull request #749 from Sitecore/bcn/bf/filter-use-shared-select… #801

Merge pull request #749 from Sitecore/bcn/bf/filter-use-shared-select…

Merge pull request #749 from Sitecore/bcn/bf/filter-use-shared-select… #801

Workflow file for this run

name: Playwright Tests
on:
# Run on push (commits) to these branches
push:
branches:
- main
- dev
- staging
- QA-Automation
- QA-Automation_NextFW
# Run when PR is opened, updated, or reopened targeting these branches
pull_request:
branches:
- main
- dev
- staging
- QA-Automation
- QA-Automation_NextFW
types: [ opened, synchronize, reopened ]
# Allow manual trigger from GitHub Actions UI
workflow_dispatch:
permissions:
contents: read
pull-requests: write
actions: read
jobs:
# Job to check PR branch build when PR is opened to dev, staging, or main
check-pr-build:
if: github.event_name == 'pull_request' && (github.base_ref == 'dev' || github.base_ref == 'main' || github.base_ref == 'staging')
uses: ./.github/workflows/pr-build-check.yml
with:
pr-branch: ${{ github.head_ref }}
base-branch: ${{ github.base_ref }}
pr-number: ${{ github.event.pull_request.number }}
pr-title: ${{ github.event.pull_request.title }}
author-name: ${{ github.event.pull_request.user.name || github.event.pull_request.user.login }}
author-username: ${{ github.event.pull_request.user.login }}
secrets: inherit
test:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
# Step 0: Checkout repository (needed for composite actions)
- name: Checkout repository
uses: actions/checkout@v4
# Step 0.5: Determine registry URL based on PR branch
- name: Determine registry URL
id: registry-url
run: |
# Default to production URL
REGISTRY_URL="https://blok.sitecore.com"
REGISTRY_TYPE="production"
if [ "${{ github.event_name }}" == "pull_request" ]; then
BASE_REF="${{ github.base_ref }}"
HEAD_REF="${{ github.head_ref }}"
# If PR is targeting main, use production URL
if [ "$BASE_REF" == "main" ]; then
REGISTRY_URL="https://blok.sitecore.com"
REGISTRY_TYPE="production"
# If PR is targeting staging or dev, use staging URL
elif [ "$BASE_REF" == "staging" ] || [ "$BASE_REF" == "dev" ]; then
REGISTRY_URL="https://blok-staging.vercel.app"
REGISTRY_TYPE="staging"
fi
else
# For direct pushes, check the branch
BRANCH="${{ github.ref_name }}"
if [ "$BRANCH" == "main" ]; then
REGISTRY_URL="https://blok.sitecore.com"
REGISTRY_TYPE="production"
else
REGISTRY_URL="https://blok-staging.vercel.app"
REGISTRY_TYPE="staging"
fi
fi
echo "url=${REGISTRY_URL}" >> $GITHUB_OUTPUT
echo "type=${REGISTRY_TYPE}" >> $GITHUB_OUTPUT
echo "Using ${REGISTRY_TYPE} registry URL: ${REGISTRY_URL}"
# Step 1: Checkout QA-Automation_NextFW branch (Next.js app)
- name: Checkout Next.js app (QA-Automation_NextFW)
uses: actions/checkout@v4
with:
ref: QA-Automation_NextFW
path: app
# Step 1.5: Update components-config.json in app directory
- name: Update components-config.json URLs
run: |
REGISTRY_URL="${{ steps.registry-url.outputs.url }}"
CONFIG_FILE="app/components-config.json"
if [ ! -f "$CONFIG_FILE" ]; then
echo "components-config.json not found, skipping update"
exit 0
fi
echo "Updating components-config.json URLs to use: ${REGISTRY_URL}"
# Use Node.js to update the JSON file properly
node -e "
const fs = require('fs');
const configPath = '$CONFIG_FILE';
const newUrl = '${REGISTRY_URL}';
const oldUrl = 'https://blok.sitecore.com';
try {
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
let updated = false;
// Update bulkInstall.url if it exists
if (config.bulkInstall && config.bulkInstall.url) {
if (config.bulkInstall.url.includes(oldUrl)) {
config.bulkInstall.url = config.bulkInstall.url.replace(oldUrl, newUrl);
updated = true;
console.log('✓ Updated bulkInstall.url');
}
}
// Update additionalComponents array URLs
if (config.additionalComponents && Array.isArray(config.additionalComponents)) {
config.additionalComponents = config.additionalComponents.map(url => {
if (typeof url === 'string' && url.includes(oldUrl)) {
updated = true;
return url.replace(oldUrl, newUrl);
}
return url;
});
if (updated) {
console.log('✓ Updated additionalComponents URLs');
}
}
if (updated) {
fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n', 'utf8');
console.log('components-config.json updated successfully');
} else {
console.log('ℹNo URLs to update in components-config.json');
}
} catch (error) {
console.error('Error updating components-config.json:', error.message);
process.exit(1);
}
"
# Step 2: Verify Docker files exist in app directory (from QA-Automation_NextFW branch)
- name: Verify Docker files in app directory
run: |
echo "=== Verifying Docker files in app directory ==="
echo "The QA-Automation_NextFW branch should contain all required files"
echo ""
# Check required files
REQUIRED_FILES=("Dockerfile" "install-components.sh" "components-config.json" "components.json" "package.json" "tsconfig.json")
MISSING_FILES=()
for file in "${REQUIRED_FILES[@]}"; do
if [ -f "app/$file" ]; then
echo "✅ $file found in app directory"
else
MISSING_FILES+=("$file")
echo "❌ $file NOT found in app directory"
fi
done
# Check .dockerignore (optional but recommended)
if [ -f "app/.dockerignore" ]; then
echo "✅ .dockerignore found in app directory"
else
echo "⚠️ .dockerignore not found - creating basic one..."
echo "node_modules" > app/.dockerignore
echo ".next" >> app/.dockerignore
echo ".git" >> app/.dockerignore
echo "components/ui/" >> app/.dockerignore
echo "✅ Created basic .dockerignore"
fi
# Exit if required files are missing
if [ ${#MISSING_FILES[@]} -gt 0 ]; then
echo ""
echo "❌ Missing required files in QA-Automation_NextFW branch:"
printf ' - %s\n' "${MISSING_FILES[@]}"
echo ""
echo "Please commit these files to the QA-Automation_NextFW branch:"
echo " - Dockerfile"
echo " - install-components.sh"
echo " - components-config.json (if not already present)"
exit 1
fi
echo ""
echo "✅ All required files found in app directory"
# Step 3: Verify Docker is available
- name: Verify Docker is available
run: |
echo "=== Verifying Docker is available ==="
# Verify Docker is available
if ! command -v docker &> /dev/null; then
echo "❌ Docker is not available!"
exit 1
else
echo "✅ Docker is available"
docker --version
fi
echo "✅ Docker setup verified"
# Step 4: Build Docker image
- name: Build Docker image
working-directory: ./app
run: |
echo "=== Building Docker image ==="
echo "This will install components and prepare the app in an isolated environment"
echo ""
echo "Build context: $(pwd)"
echo "Files in build context:"
ls -la | head -20
echo ""
# Build with progress output
docker build -t nextjs-app:dev --target dev . 2>&1 | tee docker-build.log
# Check build success
if [ ${PIPESTATUS[0]} -eq 0 ]; then
echo "✅ Docker image built successfully"
echo ""
echo "Image details:"
docker images nextjs-app:dev --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
else
echo "❌ Docker build failed!"
echo "Build log (last 50 lines):"
tail -50 docker-build.log || true
exit 1
fi
# Step 5: Run Docker container
- name: Run Docker container
run: |
echo "=== Starting Docker container ==="
# Remove any existing container with the same name
docker rm -f nextjs-dev 2>/dev/null || true
# Start container
CONTAINER_ID=$(docker run -d \
--name nextjs-dev \
-p 3000:3000 \
nextjs-app:dev)
if [ -n "$CONTAINER_ID" ]; then
echo "✅ Docker container started"
echo "Container ID: $CONTAINER_ID"
echo ""
echo "Container status:"
docker ps -f name=nextjs-dev --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
else
echo "❌ Failed to start Docker container!"
exit 1
fi
# Step 6: Wait for dev server to be ready
- name: Wait for dev server
run: |
echo "Waiting for Next.js dev server to start in Docker container..."
timeout=120
elapsed=0
while [ $elapsed -lt $timeout ]; do
if curl -f -s http://localhost:3000 > /dev/null 2>&1; then
echo "✅ Dev server is ready and responding!"
curl -s http://localhost:3000 | head -n 5
exit 0
fi
echo "⏳ Waiting for dev server... ($elapsed/$timeout seconds)"
sleep 3
elapsed=$((elapsed + 3))
done
echo "❌ Dev server failed to start within $timeout seconds"
echo "Docker container logs:"
docker logs nextjs-dev || true
exit 1
# Step 7: Setup cloudflared tunnel for dev server
- name: Expose dev server via tunnel
id: tunnel-dev
run: |
echo "🌐 Setting up public URL tunnel for dev server..."
# Verify local server is still running
if ! curl -f -s http://localhost:3000 > /dev/null 2>&1; then
echo "❌ Local dev server is not responding on localhost:3000"
exit 1
fi
echo "✅ Local dev server is running on localhost:3000"
# Download and install cloudflared
curl -L --output cloudflared https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64
chmod +x cloudflared
sudo mv cloudflared /usr/local/bin/ || mv cloudflared /usr/local/bin/
# Start cloudflared tunnel in background
echo "Starting cloudflared tunnel..."
/usr/local/bin/cloudflared tunnel --url http://localhost:3000 > cloudflared.log 2>&1 &
CLOUDFLARED_PID=$!
echo $CLOUDFLARED_PID > cloudflared.pid
echo "Cloudflared started with PID: $CLOUDFLARED_PID"
# Wait for cloudflared to start and extract the URL
echo "Waiting for tunnel to be ready..."
sleep 10
# Extract the public URL from cloudflared output
PUBLIC_URL=""
for i in {1..50}; do
# Check if cloudflared is still running
if ! kill -0 $CLOUDFLARED_PID 2>/dev/null; then
echo "⚠️ Cloudflared process died!"
echo "Cloudflared log:"
cat cloudflared.log || true
break
fi
if [ -f cloudflared.log ]; then
# Try multiple URL patterns
PUBLIC_URL=$(grep -oE 'https://[a-zA-Z0-9-]+\.trycloudflare\.com' cloudflared.log 2>/dev/null | head -1)
# Alternative pattern matching
if [ -z "$PUBLIC_URL" ]; then
PUBLIC_URL=$(grep -oE 'https://[^[:space:]]+\.trycloudflare\.com' cloudflared.log 2>/dev/null | head -1)
fi
# Check for "https://" anywhere in the log
if [ -z "$PUBLIC_URL" ] && grep -q "https://" cloudflared.log; then
PUBLIC_URL=$(grep "https://" cloudflared.log | grep -oE 'https://[^[:space:]]+' | head -1)
fi
if [ -n "$PUBLIC_URL" ]; then
echo "Found URL: $PUBLIC_URL"
# Verify the tunnel is actually working by testing the public URL
echo "Verifying tunnel is working (attempt $i/50)..."
sleep 3
# Test the URL multiple times to ensure it's stable
SUCCESS_COUNT=0
for test_attempt in {1..3}; do
if curl -f -s --max-time 15 "$PUBLIC_URL" > /dev/null 2>&1; then
SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
fi
sleep 1
done
if [ $SUCCESS_COUNT -ge 2 ]; then
echo "✅ Tunnel is working and responding! ($SUCCESS_COUNT/3 tests passed)"
break
else
echo "⏳ Tunnel URL found but not responding yet (only $SUCCESS_COUNT/3 tests passed), waiting..."
sleep 2
fi
fi
fi
sleep 1
done
if [ -n "$PUBLIC_URL" ]; then
# Final verification
echo "Performing final verification..."
VERIFY_COUNT=0
for verify_attempt in {1..5}; do
if curl -f -s --max-time 15 "$PUBLIC_URL" > /dev/null 2>&1; then
VERIFY_COUNT=$((VERIFY_COUNT + 1))
fi
sleep 1
done
if [ $VERIFY_COUNT -ge 3 ]; then
echo "✅ Public URL is working: $PUBLIC_URL"
echo "✅ Verified $VERIFY_COUNT/5 times successfully"
echo "url=$PUBLIC_URL" >> $GITHUB_OUTPUT
echo "::notice title=🌐 Dev Server URL::Your dev server is accessible at: $PUBLIC_URL"
else
echo "⚠️ URL extracted but tunnel verification failed ($VERIFY_COUNT/5 tests passed)"
echo "URL: $PUBLIC_URL"
echo "url=$PUBLIC_URL" >> $GITHUB_OUTPUT
echo "::warning title=🌐 Tunnel URL (Verification Failed)::URL: $PUBLIC_URL - Only $VERIFY_COUNT/5 verification tests passed."
fi
else
echo "⚠️ Could not extract public URL"
echo "Cloudflared log:"
cat cloudflared.log || true
fi
# Step 8: Checkout QA-Automation branch (tests)
- name: Checkout tests (QA-Automation)
uses: actions/checkout@v4
with:
ref: QA-Automation
path: tests
# Step 9: Run tests using composite action
- name: Run Playwright Tests
id: run-tests
uses: ./.github/actions/run-tests
with:
tests-path: tests
base-url: http://localhost:3000
# Step 11.6: Get commit/PR author information
- name: Get author information
id: author-info
if: always()
run: |
if [ "${{ github.event_name }}" == "pull_request" ]; then
# For Pull Requests
AUTHOR_USERNAME="${{ github.event.pull_request.user.login }}"
AUTHOR_NAME="${{ github.event.pull_request.user.name || github.event.pull_request.user.login }}"
else
# For direct commits/pushes
AUTHOR_USERNAME="${{ github.actor }}"
AUTHOR_NAME="${{ github.event.head_commit.author.name || github.actor }}"
fi
echo "username=$AUTHOR_USERNAME" >> $GITHUB_OUTPUT
echo "name=$AUTHOR_NAME" >> $GITHUB_OUTPUT
# Step 11.7: Generate workflow summary
- name: Generate workflow summary
if: always()
run: |
STATUS="${{ steps.run-tests.outputs.status }}"
TOTAL="${{ steps.run-tests.outputs.total }}"
PASSED="${{ steps.run-tests.outputs.passed }}"
FAILED="${{ steps.run-tests.outputs.failed }}"
SKIPPED="${{ steps.run-tests.outputs.skipped }}"
# Set defaults if empty
STATUS="${STATUS:-unknown}"
TOTAL="${TOTAL:-0}"
PASSED="${PASSED:-0}"
FAILED="${FAILED:-0}"
SKIPPED="${SKIPPED:-0}"
# Determine emoji and text based on status
if [ "$STATUS" == "failed" ]; then
STATUS_EMOJI="❌"
STATUS_TEXT="Failed"
elif [ "$STATUS" == "passed" ]; then
STATUS_EMOJI="✅"
STATUS_TEXT="Passed"
else
STATUS_EMOJI="⚠️"
STATUS_TEXT="Unknown"
fi
WORKFLOW_RUN_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
REPORT_URL="${WORKFLOW_RUN_URL}#artifacts"
echo "## Playwright Test Results Summary" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### ${STATUS_EMOJI} Test Status: ${STATUS_TEXT}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Test Metrics" >> $GITHUB_STEP_SUMMARY
echo "| Metric | Count |" >> $GITHUB_STEP_SUMMARY
echo "| --- | --- |" >> $GITHUB_STEP_SUMMARY
echo "| **Total Tests** | ${TOTAL} |" >> $GITHUB_STEP_SUMMARY
echo "| ✅ **Passed** | ${PASSED} |" >> $GITHUB_STEP_SUMMARY
echo "| ❌ **Failed** | ${FAILED} |" >> $GITHUB_STEP_SUMMARY
echo "| **Skipped** | ${SKIPPED} |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Component Installation" >> $GITHUB_STEP_SUMMARY
echo "- **Registry URL**: \`${{ steps.registry-url.outputs.url }}\`" >> $GITHUB_STEP_SUMMARY
echo "- **Registry Type**: ${{ steps.registry-url.outputs.type }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Test Details" >> $GITHUB_STEP_SUMMARY
echo "- **Repository**: \`${{ github.repository }}\`" >> $GITHUB_STEP_SUMMARY
echo "- **Branch**: \`${{ github.ref_name }}\`" >> $GITHUB_STEP_SUMMARY
echo "- **Commit**: \`${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY
echo "- **Author**: ${{ steps.author-info.outputs.name }} (@${{ steps.author-info.outputs.username }})" >> $GITHUB_STEP_SUMMARY
echo "- **Workflow**: [${{ github.workflow }}](${WORKFLOW_RUN_URL})" >> $GITHUB_STEP_SUMMARY
echo "- **Run Number**: #${{ github.run_number }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Test Report" >> $GITHUB_STEP_SUMMARY
echo "- **Playwright Report**: [View Report](${REPORT_URL})" >> $GITHUB_STEP_SUMMARY
echo " - Download the \`playwright-report\` artifact to view the full HTML report" >> $GITHUB_STEP_SUMMARY
echo " - Open \`index.html\` in a browser after downloading" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ "$STATUS" == "failed" ]; then
echo "### ⚠️ Action Required" >> $GITHUB_STEP_SUMMARY
echo "Some tests have failed. Please review the test results and fix the issues." >> $GITHUB_STEP_SUMMARY
elif [ "$STATUS" == "passed" ]; then
echo "### All Tests Passed" >> $GITHUB_STEP_SUMMARY
echo "All Playwright tests completed successfully!" >> $GITHUB_STEP_SUMMARY
else
echo "### Status Unknown" >> $GITHUB_STEP_SUMMARY
echo "Unable to parse test results. Please check the workflow logs for details." >> $GITHUB_STEP_SUMMARY
fi
# Step 11.8: Output test status notices
- name: Output test status notices
if: always()
run: |
STATUS="${{ steps.run-tests.outputs.status }}"
TOTAL="${{ steps.run-tests.outputs.total }}"
PASSED="${{ steps.run-tests.outputs.passed }}"
FAILED="${{ steps.run-tests.outputs.failed }}"
SKIPPED="${{ steps.run-tests.outputs.skipped }}"
# Set defaults if empty
STATUS="${STATUS:-unknown}"
TOTAL="${TOTAL:-0}"
PASSED="${PASSED:-0}"
FAILED="${FAILED:-0}"
SKIPPED="${SKIPPED:-0}"
if [ "$STATUS" == "failed" ]; then
echo "::error title=Tests Failed::Playwright tests failed. Total: ${TOTAL}, Passed: ${PASSED}, Failed: ${FAILED}, Skipped: ${SKIPPED}"
echo "::notice title=Test Results::Total: ${TOTAL} | Passed: ${PASSED} | Failed: ${FAILED} | Skipped: ${SKIPPED}"
elif [ "$STATUS" == "passed" ]; then
echo "::notice title=Tests Passed::All Playwright tests passed successfully. Total: ${TOTAL}, Passed: ${PASSED}, Skipped: ${SKIPPED}"
else
echo "::warning title=Test Status Unknown::Unable to parse test results. Total: ${TOTAL}, Passed: ${PASSED}, Failed: ${FAILED}, Skipped: ${SKIPPED}"
fi
echo "::notice title=Test Report::Download the 'playwright-report' artifact to view the full HTML test report"
# Step 11.8.5: Prepare event details for Teams notification
- name: Prepare event details
id: event-details
if: always()
run: |
if [ "${{ github.event_name }}" == "pull_request" ]; then
EVENT_TYPE="Pull Request"
EVENT_DETAILS="PR #${{ github.event.pull_request.number }}: ${{ github.event.pull_request.title }}"
else
EVENT_TYPE="Direct Commit"
COMMIT_MSG="${{ github.event.head_commit.message }}"
# Remove newlines and carriage returns, replace with spaces, then clean up multiple spaces
COMMIT_MSG=$(printf '%s' "$COMMIT_MSG" | tr '\n\r' ' ' | sed 's/[[:space:]]\+/ /g' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
# Truncate if too long
if [ ${#COMMIT_MSG} -gt 100 ]; then
COMMIT_MSG="${COMMIT_MSG:0:97}..."
fi
EVENT_DETAILS="Commit: ${COMMIT_MSG}"
fi
echo "type=${EVENT_TYPE}" >> $GITHUB_OUTPUT
echo "details=${EVENT_DETAILS}" >> $GITHUB_OUTPUT
# Step 11.9: Send test results to Teams channel
- name: Send test results to Teams
if: always()
uses: ./.github/actions/send-teams-notification
with:
notification-type: test-results
build-status: success
build-exit-code: 0
test-status: ${{ steps.run-tests.outputs.status }}
total: ${{ steps.run-tests.outputs.total }}
passed: ${{ steps.run-tests.outputs.passed }}
failed: ${{ steps.run-tests.outputs.failed }}
skipped: ${{ steps.run-tests.outputs.skipped }}
author-name: ${{ steps.author-info.outputs.name }}
author-username: ${{ steps.author-info.outputs.username }}
pr-number: ${{ github.event.pull_request.number || '' }}
pr-title: ${{ github.event.pull_request.title || '' }}
event-type: ${{ steps.event-details.outputs.type }}
event-details: ${{ steps.event-details.outputs.details }}
registry-url: ${{ steps.registry-url.outputs.url }}
registry-type: ${{ steps.registry-url.outputs.type }}
webhook-url: ${{ secrets.TEAMS_WEBHOOK_URL }}
github-server-url: ${{ github.server_url }}
github-repository: ${{ github.repository }}
github-ref-name: ${{ github.ref_name }}
github-sha: ${{ github.sha }}
github-workflow: ${{ github.workflow }}
github-run-number: ${{ github.run_number }}
github-run-id: ${{ github.run_id }}
continue-on-error: true
# Step 11.10: Fail workflow if tests failed
- name: Fail workflow if tests failed
if: always()
run: |
STATUS="${{ steps.run-tests.outputs.status }}"
EXIT_CODE="${{ steps.run-tests.outputs.exit-code }}"
# Set default if empty
STATUS="${STATUS:-unknown}"
EXIT_CODE="${EXIT_CODE:-0}"
echo "Test Status: ${STATUS}"
echo "Test Exit Code: ${EXIT_CODE}"
# Fail the workflow if tests failed
if [ "$STATUS" == "failed" ] || [ "$EXIT_CODE" != "0" ]; then
echo "❌ Tests failed! Failing workflow..."
exit 1
else
echo "✅ All tests passed!"
exit 0
fi
# Step 12: Cleanup - Stop Docker container and tunnel
- name: Stop Docker container and tunnel
if: always()
run: |
echo "Stopping cloudflared tunnel..."
if [ -f cloudflared.pid ]; then
PID=$(cat cloudflared.pid)
echo "Killing cloudflared process $PID"
kill $PID 2>/dev/null || true
rm cloudflared.pid
fi
pkill -f "cloudflared tunnel" || true
echo "Tunnel stopped"
echo "Stopping Docker container..."
docker stop nextjs-dev 2>/dev/null || true
docker rm nextjs-dev 2>/dev/null || true
echo "✅ Docker container stopped and removed"
# Clean up Docker image (optional - comment out if you want to keep it)
# docker rmi nextjs-app:dev 2>/dev/null || true
# Step 13-14: Upload artifacts using composite action
- name: Upload Test Artifacts
uses: ./.github/actions/upload-artifacts
with:
tests-path: tests
app-path: app
# Step 15: Comment on PR with test results
- name: Comment on PR with test results
if: github.event_name == 'pull_request' && always()
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const status = '${{ steps.run-tests.outputs.status }}' || 'unknown';
const total = '${{ steps.run-tests.outputs.total }}' || '0';
const passed = '${{ steps.run-tests.outputs.passed }}' || '0';
const failed = '${{ steps.run-tests.outputs.failed }}' || '0';
const skipped = '${{ steps.run-tests.outputs.skipped }}' || '0';
const author = '@${{ steps.author-info.outputs.username }}' || '@${{ github.actor }}';
const workflowRunUrl = `${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}`;
const prUrl = `${{ github.server_url }}/${{ github.repository }}/pull/${{ github.event.pull_request.number }}`;
const reportUrl = `${workflowRunUrl}#artifacts`;
// Get specific person's GitHub username from secret, or use email-based lookup
let specificPerson = '';
const notificationUsername = '${{ secrets.NOTIFICATION_USERNAME }}';
if (notificationUsername) {
specificPerson = `@${notificationUsername}`;
} else {
// Try to find user by email vishath.amarasinghe@sitecore.com
try {
const searchResult = await github.rest.search.users({
q: 'vishath.amarasinghe@sitecore.com in:email'
});
if (searchResult.data.items.length > 0) {
specificPerson = `@${searchResult.data.items[0].login}`;
}
} catch (e) {
// If search fails, mention email in comment
specificPerson = 'vishath.amarasinghe@sitecore.com';
}
}
// Determine status emoji and text
let statusEmoji, statusText;
if (status === 'failed') {
statusEmoji = '❌';
statusText = 'Failed';
} else if (status === 'passed') {
statusEmoji = '✅';
statusText = 'Passed';
} else {
statusEmoji = '⚠️';
statusText = 'Unknown';
}
// Build mentions
const mentions = specificPerson ? `${author} ${specificPerson}` : author;
// Build comment with markdown
const registryUrl = '${{ steps.registry-url.outputs.url }}' || 'https://blok.sitecore.com';
const registryType = '${{ steps.registry-url.outputs.type }}' || 'production';
const comment = `## ${statusEmoji} Playwright Test Results
${mentions}
**Status:** ${statusText} | **Workflow:** [${{ github.workflow }}](${workflowRunUrl})
| Metric | Count |
|--------|-------|
| **Total Tests** | ${total} |
| ✅ **Passed** | ${passed} |
| ❌ **Failed** | ${failed} |
| ⏭️ **Skipped** | ${skipped} |
### Component Installation
- **Registry URL:** \`${registryUrl}\` (${registryType})
- Components were installed and tested using the ${registryType} registry
### Details
- **Repository:** \`${{ github.repository }}\`
- **Branch:** \`${{ github.ref_name }}\`
- **Commit:** \`${{ github.sha }}\`
- **Author:** ${author}
- **Workflow Run:** [View Details](${workflowRunUrl})
- **Pull Request:** [View PR](${prUrl})
### Test Report
- **Playwright Report:** [Download Report](${reportUrl})
- Download the \`playwright-report\` artifact from the workflow run
- Extract and open \`index.html\` in a browser to view the full HTML report
- The report includes detailed test results, screenshots, and traces
${status === 'failed' || parseInt(failed) > 0 ? '**Some tests failed. Please review the test results and download the report for details.**' : status === 'passed' ? '**All tests passed successfully!**' : '**Unable to parse test results. Please check the workflow logs for details.**'}
---
*This is an automated notification from GitHub Actions. Email notifications are sent to mentioned users.*`;
// Create comment on PR
try {
await github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});
} catch (error) {
console.error('Error creating PR comment:', error.message);
}
# Step 16: Log test results for direct commits
- name: Log test results for direct commits
if: github.event_name != 'pull_request' && always()
run: |
STATUS="${{ steps.run-tests.outputs.status }}"
TOTAL="${{ steps.run-tests.outputs.total }}"
PASSED="${{ steps.run-tests.outputs.passed }}"
FAILED="${{ steps.run-tests.outputs.failed }}"
SKIPPED="${{ steps.run-tests.outputs.skipped }}"
# Set defaults if empty
STATUS="${STATUS:-unknown}"
TOTAL="${TOTAL:-0}"
PASSED="${PASSED:-0}"
FAILED="${FAILED:-0}"
SKIPPED="${SKIPPED:-0}"
echo "## Test Results Summary"
echo "Status: ${STATUS}"
echo "Total: ${TOTAL}"
echo "Passed: ${PASSED}"
echo "Failed: ${FAILED}"
echo "Skipped: ${SKIPPED}"
echo "Registry URL: ${{ steps.registry-url.outputs.url }} (${{ steps.registry-url.outputs.type }})"
echo "Author: ${{ steps.author-info.outputs.name }} (@${{ steps.author-info.outputs.username }})"
echo "Workflow Run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
echo ""
echo "Note: GitHub will automatically send email notifications to the commit author."
echo "To notify vishath.amarasinghe@sitecore.com, add their GitHub username to NOTIFICATION_USERNAME secret."