fuck it yolo merge to mommy #10
This file contains 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
name: HTML and CSS Validation | |
on: | |
pull_request: | |
paths: | |
- '**/*.html' | |
- '**/*.htm' | |
- '**/*.xhtml' | |
- '**/*.xht' | |
jobs: | |
validate-html: | |
runs-on: ubuntu-latest | |
permissions: | |
pull-requests: write | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 | |
- name: Get changed files | |
id: changed-files | |
run: | | |
FILES=$(git diff --name-only origin/${{ github.base_ref }} ${{ github.sha }} | grep -E '\.(html|htm|xhtml|xht|css)$' || true) | |
echo "$FILES" > changed_files.txt | |
if [ -s changed_files.txt ]; then | |
echo "has_changes=true" >> $GITHUB_OUTPUT | |
else | |
echo "has_changes=false" >> $GITHUB_OUTPUT | |
fi | |
- name: Set up Java | |
if: steps.changed-files.outputs.has_changes == 'true' | |
uses: actions/setup-java@v3 | |
with: | |
distribution: 'temurin' | |
java-version: '17' | |
- name: Download vnu.jar | |
if: steps.changed-files.outputs.has_changes == 'true' | |
run: | | |
wget -O vnu.jar https://github.com/validator/validator/releases/download/latest/vnu.jar | |
- name: Validate HTML and CSS | |
if: steps.changed-files.outputs.has_changes == 'true' | |
id: validation | |
continue-on-error: true | |
run: | | |
mkdir -p validation | |
echo '{"messages":[]}' > validation/errors.json | |
TEMP_LOG="validation/temp.json" | |
ALL_ERRORS="validation/errors.json" | |
while IFS= read -r file; do | |
if [ -f "$file" ]; then | |
echo "Validating file: $file" | |
# Validate single file | |
java -jar vnu.jar --format json --also-check-css "$file" > "$TEMP_LOG" 2>&1 || true | |
# Add the full file path to each message before merging | |
if [ -f "$TEMP_LOG" ] && [ -s "$TEMP_LOG" ]; then | |
jq --arg filepath "$file" '.messages = (.messages | map(. + {"filepath": $filepath}))' "$TEMP_LOG" > "validation/temp_with_path.json" | |
jq -s '.[0].messages + .[1].messages | {messages: .}' "$ALL_ERRORS" "validation/temp_with_path.json" > "validation/combined.json" | |
mv "validation/combined.json" "$ALL_ERRORS" | |
fi | |
fi | |
done < changed_files.txt | |
# Check if we have any actual errors or warnings (excluding pure info messages) | |
ISSUES=$(jq '[.messages[] | select(.type == "error" or (type == "info" and .subType == "warning"))] | length' "$ALL_ERRORS") | |
if [ "$ISSUES" -gt 0 ]; then | |
echo "has_errors=true" >> $GITHUB_OUTPUT | |
else | |
echo "has_errors=false" >> $GITHUB_OUTPUT | |
fi | |
- name: Post validation results | |
if: steps.changed-files.outputs.has_changes == 'true' | |
uses: actions/github-script@v7 | |
with: | |
script: | | |
const fs = require('fs'); | |
const hasErrors = '${{ steps.validation.outputs.has_errors }}' === 'true'; | |
let commentBody = '## HTML Validation Results\n\n'; | |
if (hasErrors) { | |
try { | |
const data = JSON.parse(fs.readFileSync('validation/errors.json', 'utf8')); | |
// Filter messages to only include errors and warnings | |
const significantMessages = data.messages.filter(msg => | |
msg.type === 'error' || (msg.type === 'info' && msg.subType === 'warning') | |
); | |
// Group messages by filepath | |
const groupedByFile = significantMessages.reduce((acc, msg) => { | |
const filepath = msg.filepath || msg.url.split('/').pop(); | |
if (!acc[filepath]) acc[filepath] = []; | |
acc[filepath].push(msg); | |
return acc; | |
}, {}); | |
if (Object.keys(groupedByFile).length > 0) { | |
commentBody += '❌ Validation found the following issues:\n\n'; | |
for (const [filepath, messages] of Object.entries(groupedByFile)) { | |
if (messages.length === 0) continue; // Skip files with no significant messages | |
commentBody += `### ${filepath}\n\n`; | |
// Group similar errors within each file | |
const errorGroups = messages.reduce((groups, msg) => { | |
// Create a key based on just the error message | |
const key = msg.message; | |
if (!groups[key]) { | |
groups[key] = { | |
message: msg, | |
count: 0, | |
lines: new Set() | |
}; | |
} | |
groups[key].count++; | |
groups[key].lines.add(msg.lastLine); | |
return groups; | |
}, {}); | |
// Output grouped errors | |
for (const group of Object.values(errorGroups)) { | |
const type = group.message.type === 'error' ? '🔴' : '⚠️'; | |
const lines = Array.from(group.lines).sort((a, b) => a - b); | |
const lineStr = lines.length === 1 | |
? `Line ${lines[0]}` | |
: `Lines ${lines.join(', ')}`; | |
commentBody += `${type} **${lineStr}:** ${group.message.message}\n\n`; | |
} | |
} | |
commentBody += '\nPlease fix these issues before merging.'; | |
} else { | |
commentBody += '✅ No significant issues found!'; | |
} | |
} catch (e) { | |
commentBody += '⚠️ Error parsing validation results. Please check the workflow logs.\n'; | |
console.error(e); | |
} | |
} else { | |
commentBody += '✅ All HTML and CSS validates successfully!'; | |
} | |
const comments = await github.rest.issues.listComments({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
issue_number: context.issue.number, | |
}); | |
const botComment = comments.data.find(comment => | |
comment.user.type === 'Bot' && | |
comment.body.includes('HTML Validation Results') | |
); | |
if (botComment) { | |
await github.rest.issues.updateComment({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
comment_id: botComment.id, | |
body: commentBody | |
}); | |
} else { | |
await github.rest.issues.createComment({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
issue_number: context.issue.number, | |
body: commentBody | |
}); | |
} | |
- name: Exit with error if validation failed | |
if: steps.validation.outputs.has_errors == 'true' | |
run: | | |
if [ -f validation/errors.json ]; then | |
ERRORS=$(jq '[.messages[] | select(.type == "error")] | length' validation/errors.json) | |
if [ "$ERRORS" -gt 0 ]; then | |
exit 1 | |
fi | |
fi |