Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
1b597ac
Update packages
ahegyes Nov 6, 2026
97af6ba
Test the release, audit and workflow-check gaps the audit found
ahegyes Nov 6, 2026
f624ee7
Release prerelease tags as GitHub prereleases
ahegyes Nov 6, 2026
1401692
Check the changelog section in the release build
ahegyes Nov 6, 2026
3fca6f7
Hold the release headers to WooCommerce and vendor-dir floors
ahegyes Nov 6, 2026
285d5db
Tighten the release archive's shipped and forbidden files
ahegyes Nov 6, 2026
385f03a
Merge the artifact test's redirect into the project's wp-env override
ahegyes Nov 6, 2026
ff19ff5
Attest the release zip's build provenance
ahegyes Nov 6, 2026
b35c0b2
Keep a pinned site's PHP in the end-to-end workflow
ahegyes Nov 6, 2026
18525da
Count cooldown findings and default npm audits to production
ahegyes Nov 6, 2026
093da39
Lint extra workflow files and pin actionlint in Workflow Checks
ahegyes Nov 6, 2026
8fd8016
Audit the release tools' lock in configs' Quality
ahegyes Nov 6, 2026
b832545
Validate block.json files with a locked ajv-cli
ahegyes Nov 6, 2026
90e8d00
Skip CodeQL analysis where Advanced Security is off
ahegyes Nov 6, 2026
284e4e6
Check PHP syntax on 8.6 by default
ahegyes Nov 6, 2026
e4baaa6
Declare the php-scoper range and the stubs the pipeline reads
ahegyes Nov 6, 2026
6b41179
Simplify the release workflow's shell
ahegyes Nov 6, 2026
0774e47
Write the workflows' inline PHP in the repository's style
ahegyes Nov 6, 2026
07a6447
Simplify the supply-chain audit's exit handling
ahegyes Nov 6, 2026
dc267a5
Exclude every file the release forbids from the baseline .distignore
ahegyes Nov 6, 2026
d3c4033
Read the artifact test's port raw and state what the deploy checks
ahegyes Nov 6, 2026
4ab1f38
Separate a test's statements and drop a comment narrating a fake
ahegyes Nov 6, 2026
ad9b98c
Let a wp.org plugin's prerelease pass Plugin Check's readme check
ahegyes Nov 6, 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
13 changes: 9 additions & 4 deletions .distignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
.gitattributes
.gitignore
.distignore
AGENTS.md
CLAUDE.md
/changelog
node_modules
tests
vendor/bin
Expand All @@ -18,9 +21,11 @@ package.json
package-lock.json
.phpcs*.xml*
phpcs*.xml*
.phpstan.neon
phpstan.dist.neon
.phpstan*.neon*
phpstan*.neon*
phpunit*.xml*
.phpunit.result.cache
.phpunit.cache
infection.json*
eslint.config.*
stylelint.config.*
Expand All @@ -31,10 +36,10 @@ scoper.inc.php
.wordpress-org

# Secret material — never ship, even when a consumer forgets to list it.
# .pem/.key are root-anchored (leading /) so certs bundled under vendor/ (e.g. CA bundles) still ship.
# .pem is root-anchored (leading /) so certs bundled under vendor/ (e.g. CA bundles) still ship.
.env*
/*.pem
/*.key
*.key
id_rsa*
.npmrc
auth.json
5 changes: 5 additions & 0 deletions .github/actionlint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# actionlint does not know the job context's workflow_repository and workflow_sha yet, which GitHub documents for a reusable workflow's own commit.
paths:
.github/workflows/reusable-block-json-check.yml:
ignore:
- 'property "workflow_(repository|sha)" is not defined'
15 changes: 15 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,21 @@ updates:
patterns:
- '*'

- package-ecosystem: npm
directory: /node/block-json
schedule:
interval: weekly
day: monday
time: '06:00'
timezone: UTC
open-pull-requests-limit: 5
cooldown:
default-days: 7
groups:
block-json-tools:
patterns:
- '*'

- package-ecosystem: github-actions
directory: /
schedule:
Expand Down
20 changes: 17 additions & 3 deletions .github/workflows/quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ jobs:
- name: Scan fixture with php/quality-assurance/phpcs.dist.xml
shell: bash
run: |
set -e -o pipefail
# The production profile skips */tests/*, so a temp copy is scanned outside that path.
cp -R tests/fixtures/plugin-stub "$RUNNER_TEMP/plugin-stub"
vendor/bin/phpcs -v --standard=php/quality-assurance/phpcs.dist.xml "$RUNNER_TEMP/plugin-stub" | tee phpcs-scan.log
Expand All @@ -90,12 +89,27 @@ jobs:

supply-chain:
name: Supply-chain audit
# npm gate audits production deps only — the dev-tooling graph (wp-scripts/playwright trees) is advisory via dependabot alerts.
permissions:
contents: read
uses: ./.github/workflows/reusable-supply-chain-audit.yml

supply-chain-release-tools:
name: Supply-chain audit (release tools)
permissions:
contents: read
uses: ./.github/workflows/reusable-supply-chain-audit.yml
with:
project-path: php/release
npm-audit: false

supply-chain-block-json-tools:
name: Supply-chain audit (block.json tools)
permissions:
contents: read
uses: ./.github/workflows/reusable-supply-chain-audit.yml
with:
npm-audit-flags: '--omit=dev --audit-level=high'
project-path: node/block-json
composer-audit: false

block-json:
name: block.json schema check
Expand Down
20 changes: 18 additions & 2 deletions .github/workflows/reusable-block-json-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,32 @@ jobs:
with:
persist-credentials: false

# The validator installs from this workflow's own commit of configs, whose lock Dependabot keeps current.
- name: Check out the block.json tools
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: ${{ job.workflow_repository }}
ref: ${{ job.workflow_sha }}
path: .block-json-tools
sparse-checkout: node/block-json
persist-credentials: false

- name: Setup Node.js
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: '26'

- name: Install ajv-cli
working-directory: .block-json-tools/node/block-json
run: npm ci --ignore-scripts --no-audit --no-fund

- name: Validate block.json files against the WordPress schema
working-directory: ${{ inputs.project-path }}
env:
AJV: ${{ github.workspace }}/.block-json-tools/node/block-json/node_modules/.bin/ajv
run: |
# Validate one file per -d invocation; a single joined string breaks multi-block plugins.
mapfile -d '' files < <(find . -path ./node_modules -prune -o -path ./vendor -prune -o -name 'block.json' -print0)
mapfile -d '' files < <(find . -path ./node_modules -prune -o -path ./vendor -prune -o -path ./.block-json-tools -prune -o -name 'block.json' -print0)
if [ "${#files[@]}" -eq 0 ]; then
echo "No block.json files found — nothing to validate."
exit 0
Expand All @@ -43,7 +59,7 @@ jobs:
curl -fsSL https://schemas.wp.org/trunk/block.json -o "$schema"
for file in "${files[@]}"; do
echo "Validating $file"
npx --yes ajv-cli@5.0.0 validate \
"$AJV" validate \
-s "$schema" \
-d "$file" \
--strict=false
Expand Down
52 changes: 51 additions & 1 deletion .github/workflows/reusable-codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,59 @@ jobs:
exit 1
fi

detect-ghas:
name: Detect GHAS availability
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
security-events: read
outputs:
ghas-available: ${{ steps.detect.outputs.ghas-available }}
steps:
- name: Detect GitHub Advanced Security availability
id: detect
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
run: |
# The code-scanning alerts endpoint answers 403 naming Advanced Security exactly where analyze would fail, and an unclear answer is retried and then read as available, because a skipped analyze passes as a green check.
probe_body="${RUNNER_TEMP}/ghas-probe.json"
max_attempts=3
retry_sleep_seconds=5
attempt=1
while :; do
http_code=$(curl -s --max-time 15 -o "$probe_body" -w '%{http_code}' \
-H "Authorization: Bearer ${GH_TOKEN}" \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"https://api.github.com/repos/${REPO}/code-scanning/alerts?per_page=1") || http_code="curl-error"

if [ "$http_code" = "200" ]; then
echo "ghas-available=true" >> "$GITHUB_OUTPUT"
break
fi

if [ "$http_code" = "403" ] && grep -q 'Advanced Security must be enabled' "$probe_body" 2>/dev/null; then
echo "::notice::GitHub Advanced Security is unavailable on this repository — CodeQL analyze is skipped."
echo "ghas-available=false" >> "$GITHUB_OUTPUT"
break
fi

if [ "$attempt" -lt "$max_attempts" ]; then
attempt=$((attempt + 1))
sleep "$retry_sleep_seconds"
continue
fi

echo "::warning::GHAS availability probe was ambiguous after $max_attempts attempts (last status '$http_code') — assuming GHAS is available so analyze runs and a genuine absence fails visibly."
echo "ghas-available=true" >> "$GITHUB_OUTPUT"
break
done

analyze:
name: Analyze (${{ matrix.language }})
needs: validate-inputs
needs: [validate-inputs, detect-ghas]
if: needs.detect-ghas.outputs.ghas-available == 'true'
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/reusable-php-syntax-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ on:
description: 'Non-empty JSON array of PHP versions to check (e.g. [\"8.5\",\"8.6\"])'
type: string
required: false
default: '["8.5"]'
default: '["8.5", "8.6"]'
paths:
description: 'Non-empty JSON array of files and directories to check, relative to project-path. Directories are searched for *.php files, skipping any vendor/ and node_modules/ inside them.'
type: string
Expand Down
26 changes: 21 additions & 5 deletions .github/workflows/reusable-playwright-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ on:
type: string
required: true
php-version:
description: 'PHP version for Composer, and for wp-env through WP_ENV_PHP_VERSION, which wins over the phpVersion of its config files.'
description: 'PHP version for Composer and any suite outside wp-env, and for the site in wp-env when its config and override file pin no phpVersion.'
type: string
required: false
default: '8.5'
Expand Down Expand Up @@ -58,9 +58,8 @@ jobs:
permissions:
contents: read
env:
# Job-level wp-env variables give a consumer script that starts wp-env again the same WordPress and PHP.
# A job-level WP_ENV_CORE gives a consumer script that starts wp-env again the same WordPress.
WP_ENV_CORE: ${{ inputs.wp-env-core != '' && inputs.wp-env-core || (inputs.wp-version != '' && format('WordPress/WordPress#tags/{0}', inputs.wp-version)) || '' }}
WP_ENV_PHP_VERSION: ${{ inputs.php-version }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
Expand Down Expand Up @@ -114,7 +113,9 @@ jobs:
- name: Resolve Playwright version
id: playwright
working-directory: ${{ inputs.project-path }}
run: echo "version=$(node -p "require('@playwright/test/package.json').version")" >> "$GITHUB_OUTPUT"
run: |
version=$(node -p "require('@playwright/test/package.json').version") || { echo "::error::@playwright/test is not installed in this project — add it to devDependencies."; exit 1; }
echo "version=$version" >> "$GITHUB_OUTPUT"

- name: Cache Playwright browsers
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
Expand All @@ -124,7 +125,22 @@ jobs:

- name: Install Playwright browsers
working-directory: ${{ inputs.project-path }}
run: npx playwright install --with-deps chromium
run: npx --no-install playwright install --with-deps chromium

# wp-env applies WP_ENV_PHP_VERSION over a config's phpVersion, so a pinned site keeps its PHP while Composer and the suite run on php-version.
- name: Resolve the site's PHP
working-directory: ${{ inputs.project-path }}
env:
PHP_VERSION: ${{ inputs.php-version }}
WP_ENV_CONFIG_FILE: ${{ inputs.wp-env-config-file }}
run: |
config="${WP_ENV_CONFIG_FILE:-.wp-env.json}"
for file in "$config" "${config%.json}.override.json"; do
if [ -f "$file" ] && jq -e '[.phpVersion, (.env // {} | .[] | .phpVersion?)] | map(select(. != null)) | length > 0' "$file" > /dev/null; then
exit 0
fi
done
echo "WP_ENV_PHP_VERSION=$PHP_VERSION" >> "$GITHUB_ENV"

- name: Start wp-env
working-directory: ${{ inputs.project-path }}
Expand Down
Loading
Loading