Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
7508a29
ci: lint the workflows and templates with actionlint
pauloiankoski Oct 30, 2026
85d651a
feat(plugin-check): add the shared Plugin Check workflow and report a…
pauloiankoski Oct 30, 2026
b196b3a
docs(plugin-check): use neutral example names
pauloiankoski Oct 30, 2026
498329d
docs(plugin-check): reference the workflow and the action at main
pauloiankoski Oct 30, 2026
ae432cf
fix(plugin-check): bootstrap pup without forwarding arguments
pauloiankoski Oct 31, 2026
d86f255
fix(plugin-check): count only this repository's runs and validate the…
pauloiankoski Oct 31, 2026
21a5833
fix(plugin-check): read the 100 newest runs on the branch, the most o…
pauloiankoski Oct 31, 2026
672612b
fix(plugin-check): call the report action with the self-repository re…
pauloiankoski Oct 31, 2026
887aad8
Post the Plugin Check comment with the pr-comment action, not peter-e…
pauloiankoski Nov 3, 2026
58b83a4
Say that the Plugin Check comment comes from pr-comment
pauloiankoski Nov 3, 2026
b717d34
Say that pup reads .gitattributes too, and why bin/pup.phar still mat…
pauloiankoski Nov 3, 2026
60b9150
Pin the exact output of the Plugin Check scripts as golden files
pauloiankoski Nov 3, 2026
207af34
Add the Plugin Check compare in JavaScript, next to the bash script
pauloiankoski Nov 3, 2026
c631598
Add the baseline lookup in JavaScript, next to the bash script
pauloiankoski Nov 3, 2026
6144039
Fail on a Plugin Check baseline count too large to compare exactly
pauloiankoski Nov 3, 2026
bf3b903
Run the Plugin Check report with github-script instead of bash
pauloiankoski Nov 3, 2026
42b2118
Remove the Plugin Check bash scripts and their tests
pauloiankoski Nov 3, 2026
0157eca
Rename the Plugin Check mode ratchet to baseline
pauloiankoski Nov 3, 2026
4d87f46
Say how the Plugin Check compare reads a count written as 1.0
pauloiankoski Nov 3, 2026
7f77356
Build the Plugin Check finish badge and the could-not-run comment in …
pauloiankoski Nov 3, 2026
7d9367d
Read the Plugin Check excluded checks from .plugin-check.json when th…
pauloiankoski Nov 3, 2026
ba4096d
Install pup with the shared pup action in the Plugin Check workflow
pauloiankoski Nov 4, 2026
1a27702
Read the Plugin Check baseline from a committed file
pauloiankoski Nov 4, 2026
5bfea78
Remove the Plugin Check run lookup
pauloiankoski Nov 4, 2026
5f52ba8
Remove the advisory baseline and the baseline label
pauloiankoski Nov 4, 2026
1d9431d
Tell the author how to make and lower the Plugin Check baseline
pauloiankoski Nov 4, 2026
189ffa6
Check the target branch too when the repository has no Plugin Check b…
pauloiankoski Nov 4, 2026
f7ea8f0
Say when a pull request changes the Plugin Check baseline file
pauloiankoski Nov 4, 2026
abd240d
End the reason of an invalid Plugin Check baseline message with a ful…
pauloiankoski Nov 4, 2026
a700fc2
Document the committed Plugin Check baseline
pauloiankoski Nov 4, 2026
f0af2c9
Build the Plugin Check zip with the zip-name and release-zip actions
pauloiankoski Nov 4, 2026
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
363 changes: 363 additions & 0 deletions .github/actions/plugin-check-report/README.md

Large diffs are not rendered by default.

150 changes: 150 additions & 0 deletions .github/actions/plugin-check-report/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
# Compares a WordPress.org Plugin Check results file with a baseline: the counts per rule in a file
# the repository commits, `.plugin-check-baseline.json`. Only a rule with more errors than the
# baseline fails (baseline mode), or any error at all (strict mode). It also saves this run's counts
# as a new baseline, to copy into the repository, and writes the short body for the pull request
# comment.
#
# It does not run Plugin Check and it does not post the comment. The reusable workflow
# .github/workflows/plugin-check.yml does both, so this action stays usable with a results file
# from anywhere. It does write the comment's body, with the "Check Finished" badge, and a body that
# says Plugin Check could not run when there was nothing to compare.
#
# The work is in one JavaScript file next to this file, plugin-check-report.js. Each step below is
# an actions/github-script step that requires it by path, so there is nothing to build: the file in
# the repository is the file that runs. The same file runs from a command line; see the README.
name: Plugin Check report
description: Compares Plugin Check results with the repository's baseline file, and saves a new baseline

inputs:
results:
description: >-
Path of the results file wordpress/plugin-check-action writes, `plugin-check-results.txt`. A
missing file fails the compare step: that is how a broken build or a broken check shows up.
required: true
comment-file:
description: >-
Where to write the short Markdown body for the pull request comment. Empty writes none. The
file is only written when the compare runs, so a caller can tell "no result" from a result.
required: false
default: ''
mode:
description: >-
`baseline`: fail only when a rule has more errors than the baseline. `strict`: fail on any
error, baseline or not.
required: false
default: 'baseline'
comment-marker:
description: >-
Hidden first line of the comment body, which the caller searches for to find its own
comment. Empty uses `<!-- plugin-check:<owner>/<repo> -->`.
required: false
default: ''
baseline-file:
description: >-
Path of the baseline file the repository commits: `{"errors": {code: n}, "warnings": {code: n}}`.
A relative path is read from the working directory.
required: false
default: '.plugin-check-baseline.json'
base-results:
description: >-
Path of the Plugin Check results of the pull request's target branch. Used as the baseline when
there is no baseline file, so a pull request is still compared with something. Empty when
nothing was checked on the target branch. Not used in `strict` mode.
required: false
default: ''
base-required:
description: >-
`true` when the caller checked the target branch because there is no baseline file. A missing
`base-results` file then fails the compare, so a target branch that could not be checked never
passes as "no baseline".
required: false
default: 'false'
baseline-changed:
description: >-
`true` when the pull request changes the baseline file. The comment then says so, because the
pull request is compared with its own change and a reviewer should look at the file's diff.
required: false
default: 'false'

outputs:
artifact-url:
description: 'Link to the plugin-check-report artifact this run uploaded. Empty when there was nothing to upload.'
value: ${{ steps.artifact.outputs.artifact-url }}

runs:
using: 'composite'
steps:
# One folder per run under RUNNER_TEMP, cleared first, so a second use of the action in the same
# job never reads the first one's files.
- name: Set file paths
id: paths
uses: actions/github-script@v9
env:
# github-script's require() resolves against the workspace of the repository being built,
# not this action's directory, so the path has to be passed in.
ACTION_PATH: ${{ github.action_path }}
INPUT_COMMENT_MARKER: ${{ inputs.comment-marker }}
with:
script: |
const { runPaths } = require(`${process.env.ACTION_PATH}/plugin-check-report.js`)
process.exitCode = runPaths({ core, env: process.env })

# A baseline made from this run, uploaded even when the compare below fails. It is the easy way
# to update the committed file: download the artifact and copy its baseline.json.
- name: Write a new baseline
uses: actions/github-script@v9
env:
ACTION_PATH: ${{ github.action_path }}
RESULTS: ${{ inputs.results }}
REPORT_DIR: ${{ steps.paths.outputs.report }}
with:
script: |
const { runUpdate } = require(`${process.env.ACTION_PATH}/plugin-check-report.js`)
process.exitCode = runUpdate({ core, env: process.env })

# The comment links to this artifact: the results, and the new baseline.json.
- name: Upload the report
id: artifact
uses: actions/upload-artifact@v7
with:
name: plugin-check-report
path: ${{ steps.paths.outputs.report }}
if-no-files-found: ignore

# Fails the step when the mode says so. Also writes the comment body and the same text to the
# job summary. The step ends with an exit status, not an extra error annotation: the messages
# above it already say what is wrong.
- name: Compare with the baseline
uses: actions/github-script@v9
env:
ACTION_PATH: ${{ github.action_path }}
RESULTS: ${{ inputs.results }}
COMMENT_FILE: ${{ inputs.comment-file }}
PLUGIN_CHECK_MODE: ${{ inputs.mode }}
PLUGIN_CHECK_BASELINE: ${{ inputs.baseline-file }}
PLUGIN_CHECK_BASE_RESULTS: ${{ inputs.base-results }}
PLUGIN_CHECK_BASE_REQUIRED: ${{ inputs.base-required }}
PLUGIN_CHECK_BASELINE_CHANGED: ${{ inputs.baseline-changed }}
COMMENT_MARKER: ${{ steps.paths.outputs.marker }}
ARTIFACT_URL: ${{ steps.artifact.outputs.artifact-url }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
with:
script: |
const { runCompare } = require(`${process.env.ACTION_PATH}/plugin-check-report.js`)
process.exitCode = runCompare({ core, env: process.env })

# When the build or the check broke, the compare wrote no body. Say so, instead of leaving "in
# progress" behind. Runs after a failed step too, but not when the run was cancelled. A body the
# compare wrote is left as it is.
- name: Write the comment if the compare could not run
if: ${{ !cancelled() && inputs.comment-file != '' }}
uses: actions/github-script@v9
env:
ACTION_PATH: ${{ github.action_path }}
COMMENT_FILE: ${{ inputs.comment-file }}
COMMENT_MARKER: ${{ inputs.comment-marker || format('<!-- plugin-check:{0} -->', github.repository) }}
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
with:
script: |
const { runCouldNotRun } = require(`${process.env.ACTION_PATH}/plugin-check-report.js`)
process.exitCode = runCouldNotRun({ core, env: process.env })
46 changes: 46 additions & 0 deletions .github/actions/plugin-check-report/exclude-checks/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Works out which Plugin Check checks to skip: the workflow's `exclude-checks` input when it names
# any, else the `exclude-checks` list in the repository's .plugin-check.json. The result is in the
# format wordpress/plugin-check-action takes for its own `exclude-checks` input: one check per
# line. A bad file fails the step with a message that says what to fix.
#
# The work is in plugin-check-report.js, one folder up, which also prints the same list as the
# `--exclude-checks=a,b` flag of `wp plugin check` for a local run. See the README of
# plugin-check-report.
name: Plugin Check excluded checks
description: Lists the checks to skip, from the exclude-checks input or the repository's .plugin-check.json

inputs:
exclude-checks:
description: >-
Checks to skip, one per line. When it names any check, it replaces the file: the file is not
even read.
required: false
default: ''
config-file:
description: >-
Path of the repository's config file, relative to the workspace. A missing file means no
checks are skipped.
required: false
default: '.plugin-check.json'

outputs:
checks:
description: 'The checks to skip, one per line. Empty when there are none.'
value: ${{ steps.list.outputs.checks }}

runs:
using: 'composite'
steps:
- name: List the excluded checks
id: list
uses: actions/github-script@v9
env:
# github-script's require() resolves against the workspace of the repository being built,
# not this action's directory, so the path has to be passed in.
ACTION_PATH: ${{ github.action_path }}
EXCLUDE_CHECKS: ${{ inputs.exclude-checks }}
CONFIG_FILE: ${{ inputs.config-file }}
with:
script: |
const { runExcludeChecks } = require(`${process.env.ACTION_PATH}/../plugin-check-report.js`)
process.exitCode = runExcludeChecks({ core, env: process.env })
Loading
Loading