Skip to content

Workflow file for this run

name: Check for linter warnings / exceptions
on:
pull_request_target:
branches:
- master
jobs:
check-linter:
runs-on: ubuntu-latest
steps:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.base.sha }}
- name: Fetch base and target branches
run: |
git fetch origin +refs/heads/${{ github.event.pull_request.base.ref }}:refs/remotes/origin/${{ github.event.pull_request.base.ref }}
git fetch origin +refs/pull/${{ github.event.pull_request.number }}/merge:refs/remotes/pull/${{ github.event.pull_request.number }}/merge
- name: Install dependencies
run: npm ci
- name: Get the diff
run: git diff --name-only origin/${{ github.event.pull_request.base.ref }}...refs/remotes/pull/${{ github.event.pull_request.number }}/merge | grep '^\(modules\|src\|libraries\|creative\)/.*\.js$' > __changed_files.txt || true
- name: Run linter on base branch
run: npx eslint --no-inline-config --format json $(cat __changed_files.txt | xargs stat --printf '%n\n' 2> /dev/null) > __base.json || true
- name: Check out PR
run: git checkout ${{ github.event.pull_request.head.sha }}
- name: Install dependencies
run: npm ci
- name: Run linter on PR
run: npx eslint --no-inline-config --format json $(cat __changed_files.txt | xargs stat --printf '%n\n' 2> /dev/null) > __pr.json || true
- name: Compare them and post comment if necessary
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const path = require('path');
const process = require('process');
function parse(fn) {
return JSON.parse(fs.readFileSync(fn)).reduce((memo, data) => {
const file = path.relative(process.cwd(), data.filePath);
if (!memo.hasOwnProperty(file)) { memo[file] = { errors: 0, warnings: 0} }
data.messages.forEach(({severity}) => {
memo[file][severity > 1 ? 'errors' : 'warnings']++;
});
return memo;
}, {})
}
function mkDiff(old, new_) {
const files = Object.fromEntries(
Object.entries(new_)
.map(([file, {errors, warnings}]) => {
const {errors: oldErrors, warnings: oldWarnings} = old[file] || {};
return [file, {errors: Math.max(0, errors - (oldErrors ?? 0)), warnings: Math.max(0, warnings - (oldWarnings ?? 0))}]
})
.filter(([_, {errors, warnings}]) => errors > 0 || warnings > 0)
)
return Object.values(files).reduce((memo, {warnings, errors}) => {
memo.errors += errors;
memo.warnings += warnings;
return memo;
}, {errors: 0, warnings: 0, files})
}
function mkComment({errors, warnings, files}) {
function pl(noun, number) {
return noun + (number === 1 ? '' : 's')
}
if (errors === 0 && warnings === 0) return;
const summary = [];
if (errors) summary.push(`**${errors}** linter ${pl('error', errors)}`)
if (warnings) summary.push(`**${warnings}** linter ${pl('warning', warnings)}`)
let cm = `Tread carefully! This PR adds ${summary.join(' and ')} (possibly disabled through directives):\n\n`;
Object.entries(files).forEach(([file, {errors, warnings}]) => {
const summary = [];
if (errors) summary.push(`+${errors} ${pl('error', errors)}`);
if (warnings) summary.push(`+${warnings} ${pl('warning', warnings)}`)
cm += ` * \`${file}\` (${summary.join(', ')})\n`
})
return cm;
}
const [base, pr] = ['__base.json', '__pr.json'].map(parse);
const comment = mkComment(mkDiff(base, pr));
if (comment) {
github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: comment
});
}