name: WordPress Theme Check on: pull_request: types: [opened, labeled, synchronize] permissions: pull-requests: write jobs: theme-check: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v3 - name: Setup Node.js uses: actions/setup-node@v3 with: node-version: '20' - name: Install @wordpress/env run: npm install -g @wordpress/env - name: Write .wp-env.json to provide configuration for the WordPress environment run: | echo '{ "mappings": { "wp-content/themes": "${{ github.workspace }}" } }' > .wp-env.json - name: Start WordPress environment run: | wp-env start wp-env run cli wp core install --url=http://localhost:8888 --title="Test Site" --admin_user=admin --admin_password=admin_password --admin_email=admin@example.com --skip-email - name: Install and activate Theme Check plugin run: | wp-env run cli wp plugin install https://github.com/WordPress/theme-check/archive/refs/heads/master.zip --activate - name: Get changed root folders uses: actions/github-script@v6 with: script: | const { owner, repo, number } = context.issue; let allFiles = []; let page = 1; while (true) { const { data: files } = await github.rest.pulls.listFiles({ owner, repo, pull_number: number, per_page: 100, page: page }); allFiles = allFiles.concat(files); if (files.length < 100) break; page++; } console.log('files', allFiles.map(file => file.filename)); const rootFolders = new Set(); for (const file of allFiles) { const parts = file.filename.split('/'); if (parts.length > 1 && !parts[0].startsWith('.')) { rootFolders.add(parts[0]); } } const rootFoldersArray = Array.from(rootFolders); core.exportVariable('THEME_FOLDERS', rootFoldersArray.join(',')); console.log(`Changed root folders: ${rootFoldersArray.join(', ')}`); - name: Debug THEME_FOLDERS run: echo "THEME_FOLDERS is ${{ env.THEME_FOLDERS }}" - name: Run Theme Check for each folder if: env.THEME_FOLDERS != '' run: | IFS=',' read -ra FOLDERS <<< "${{ env.THEME_FOLDERS }}" for THEME_FOLDER in "${FOLDERS[@]}"; do echo "Processing theme folder: $THEME_FOLDER" # Activate theme wp-env run cli wp theme activate $THEME_FOLDER # Run Theme Check set +e THEME_CHECK_RESULT=$(wp-env run cli wp theme-check run $THEME_FOLDER --format=json) THEME_CHECK_EXIT_CODE=$? set -e # Store results in environment variables echo "THEME_CHECK_RESULT_${THEME_FOLDER//-/_}<> $GITHUB_ENV echo "$THEME_CHECK_RESULT" >> $GITHUB_ENV echo "EOF" >> $GITHUB_ENV echo "THEME_CHECK_EXIT_CODE_${THEME_FOLDER//-/_}=$THEME_CHECK_EXIT_CODE" >> $GITHUB_ENV done - name: Find and delete previous comment uses: actions/github-script@v6 with: github-token: ${{secrets.GITHUB_TOKEN}} script: | const { owner, repo, number } = context.issue; const { data: comments } = await github.rest.issues.listComments({ owner, repo, issue_number: number, }); const botComment = comments.find(comment => comment.user.type === 'Bot' && comment.body.includes('Theme-Check results') ); if (botComment) { await github.rest.issues.deleteComment({ owner, repo, comment_id: botComment.id, }); } - name: Comment PR if: env.THEME_FOLDERS != '' uses: actions/github-script@v6 with: github-token: ${{secrets.GITHUB_TOKEN}} script: | const fs = require('fs'); let fullComment = ''; const folders = process.env.THEME_FOLDERS.split(','); let hasErrors = false; const emojis = { 'REQUIRED': '❎', 'WARNING': 'âš ī¸', 'RECOMMENDED': '💡', 'INFO': 'â„šī¸', }; fullComment += 'Theme-Check results\n'; fullComment += '--- \n'; for (const folder of folders) { const envVarName = `THEME_CHECK_RESULT_${folder.replace(/-/g, '_')}`; const exitCodeVarName = `THEME_CHECK_EXIT_CODE_${folder.replace(/-/g, '_')}`; const themeCheckResult = process.env[envVarName]; const themeCheckExitCode = parseInt(process.env[exitCodeVarName]); console.log(`Theme Check Result for ${folder}: ${themeCheckResult}`); console.log(`Theme Check Exit Code for ${folder}: ${themeCheckExitCode}`); if (themeCheckExitCode !== 0) { hasErrors = true; } const comments = JSON.parse(themeCheckResult); if (themeCheckExitCode !== 0) { fullComment += `### ${folder}: There are required changes on the theme ❌.\n`; } else { fullComment += `### ${folder}: No changes required ✅.\n`; } const groupedComments = {}; for (const check of comments) { if (!groupedComments[check.type]) { groupedComments[check.type] = []; } groupedComments[check.type].push(check.value); } // Add REQUIRED comments to the main body for (const type of ['REQUIRED']) { if (groupedComments[type]) { fullComment += `**${emojis[type]} ${type}**\n`; groupedComments[type].forEach(value => { fullComment += `- ${value}\n`; }); fullComment += '\n'; } } for (const [type, groupComments] of Object.entries(groupedComments)) { if (type !== 'REQUIRED' && type !== 'INFO') { fullComment += `
\n${emojis[type]} ${type} (${groupComments.length})\n\n`; groupComments.forEach(value => { fullComment += `- ${value}\n`; }); fullComment += '\n
\n\n'; } } fullComment += '--- \n'; } // Post message. This could be optional in the future when theme-check 'fails' on all the REQUIRED change. // Example issue that needs to be fixed: https://github.com/WordPress/theme-check/issues/465 github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: fullComment }); if (hasErrors) { core.setFailed('One or more themes have required changes. Please review the comments and make necessary updates.'); }