Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions .github/workflows/lint-css.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
name: Lint CSS

on:
# Run on direct pushes to integration branches and on all pull requests.
push:
branches:
- develop
- main
- master
- trunk
pull_request:
# Allow manually triggering the workflow.
workflow_dispatch:
Comment on lines +3 to +13

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Skip linting when a PR has no stylesheet changes.

When the changed-file list is empty, Line 74 still runs wp-scripts lint-style with no paths, which scans the entire repository. This makes unrelated PRs—and every push/manual run—hit the known baseline of approximately 27,000 violations. Skip the step for CSS-free PRs and make full-repository linting an explicit, separately controlled behavior.

Also applies to: 49-52, 72-74

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/lint-css.yml around lines 3 - 13, Update the lint-style
workflow step to run only when the pull request changed-file list contains
stylesheet files, so CSS-free PRs skip repository-wide scanning. Make
full-repository linting available only through an explicit, separately
controlled push or workflow_dispatch path rather than running by default on
every trigger. Preserve the existing stylesheet lint command for runs that are
intentionally enabled.


# Cancels all previous workflow runs for the same branch that have not yet completed.
concurrency:
# The concurrency group contains the workflow name and the branch name.
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
lint:
runs-on: ubuntu-latest

name: "Lint: CSS"

steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Cache Node.js modules
id: cache-node-modules
uses: actions/cache@v4
with:
path: node_modules
key: ${{ runner.os }}-node_modules-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node_modules-
# The lint stage doesn't run the unit tests or use code style, so no need for PHPUnit, WPCS or phpcompatibility.
- name: 'Install NPM packages'
if: steps.cache-node-modules.outputs.cache-hit != 'true'
run: npm ci --prefer-offline --no-audit --ignore-scripts

- name: Get only files changed in this PR
id: changed-files
uses: actions/github-script@v6
with:
script: |
if (!context.payload.pull_request) {
core.warning("No pull request context available. Skipping changed files retrieval.");
core.setOutput('files', '');
return '';
}

const changedFiles = await github.paginate(
github.rest.pulls.listFiles,
{
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number,
}
);
const cssFiles = changedFiles
.filter(file => file.status !== 'removed')
.map(file => file.filename)
.filter(filename => filename.endsWith('.scss') || filename.endsWith('.css'))
.join(' ');
Comment on lines +63 to +67

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🔴 Critical | ⚡ Quick win

Pass changed filenames as arguments, not shell text.

Line 74 interpolates PR-controlled filenames into an unquoted shell command. This both breaks filenames containing spaces and permits shell metacharacters such as ;, $(), or backticks to execute on the runner. Serialize the file list (for example, as JSON), pass it through env, and invoke npx through an argv-based Node/Python wrapper with -- before the filenames.

Also applies to: 72-74

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/lint-css.yml around lines 63 - 67, Update the changed-file
handling around cssFiles and the line-74 lint invocation so PR-controlled
filenames are not interpolated into shell text. Serialize the filtered CSS/SCSS
filenames (for example, as JSON), pass the serialized value through the workflow
environment, and use an argv-based Node or Python wrapper to parse it and invoke
npx with -- before the filenames, preserving spaces and preventing shell
interpretation.


core.setOutput('files', cssFiles);
return cssFiles;

# If this is a PR then lint only css/scss changed in the PR, if not a PR then lint them all.
- name: Run stylelint
run: npx wp-scripts lint-style ${{ steps.changed-files.outputs.files || '' }}
6 changes: 6 additions & 0 deletions .stylelintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"extends": "@wordpress/stylelint-config/scss-stylistic",
"rules": {
"selector-class-pattern": null
}
}
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@
"dist": "npx webpack --mode production && composer install --no-dev && composer dump-autoload --no-dev -o && ./scripts/dist.sh && composer install",
"dist:dotorg": "npm run dist:keep-build-folder",
"dist:keep-build-folder": "npx webpack --mode production && composer install --no-dev && composer dump-autoload --no-dev -o && ./scripts/dist.sh --keep-build-folder",
"lint": "./vendor/bin/phpcs && npm run lint:js",
"lint": "./vendor/bin/phpcs && npm run lint:js && npm run lint:css",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Do not add full CSS linting to the aggregate command before the baseline is clean.

Line 15 makes npm run lint fail on every clean checkout that reaches the CSS stage because the repository currently contains approximately 27,000 existing Stylelint violations. Either clean the baseline first or keep full CSS linting separate until it is actionable.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@package.json` at line 15, Update the aggregate lint script in package.json so
npm run lint does not invoke full CSS linting while the existing Stylelint
baseline remains failing; keep CSS linting available through its separate
command, or clean the violations before re-adding it to the aggregate.

"lint-staged-precommit": "lint-staged",
"lint:php": "./vendor/bin/phpcs",
"lint:php:fix": "./vendor/bin/phpcbf",
"lint:js": "wp-scripts lint-js",
"lint:js:fix": "wp-scripts lint-js --fix",
"lint:css": "wp-scripts lint-style",
"lint:css:fix": "wp-scripts lint-style --fix",
"test:php": "./scripts/setup-phpunit.sh",
"test:php:run": "docker compose exec phpunit vendor/bin/phpunit",
"test:php:coverage": "docker compose exec phpunit vendor/bin/phpunit --coverage-clover=./coverage/clover.xml --coverage-html=./coverage/html",
Expand All @@ -28,7 +30,8 @@
},
"lint-staged": {
"*.php": "./vendor/bin/phpcs",
"*.js": "wp-scripts lint-js"
"*.js": "wp-scripts lint-js",
"*.scss": "wp-scripts lint-style"
},
"files": [
"LICENSE.txt",
Expand Down
Loading