Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
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
101 changes: 101 additions & 0 deletions .github/actions/plugin-check/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
name: 'WordPress Plugin Check (pinned wp-env)'
description: >-
Drop-in replacement for wordpress/plugin-check-action@v1 that pins
@wordpress/env to a working release. The upstream action force-installs the
latest @wordpress/env at runtime, and 11.8.0 silently exits 0 from
`wp-env start` without bringing up Docker. Remove this action and switch the
workflow back to wordpress/plugin-check-action@v1 once upstream is fixed.

inputs:
build-dir:
description: 'Path to the built plugin directory to check.'
required: true
categories:
description: 'Check categories (newline- or comma-separated).'
required: false
default: ''
checks:
description: 'Checks to run (newline- or comma-separated).'
required: false
default: ''
exclude-directories:
description: 'Directories to exclude (newline- or comma-separated).'
required: false
default: ''
ignore-warnings:
description: 'Only fail on errors; do not report warnings.'
required: false
default: 'false'
wp-env-version:
description: 'Pinned @wordpress/env version (workaround for the 11.8.0 Docker regression).'
required: false
default: '11.7.0'

runs:
using: 'composite'
steps:
- name: Start WordPress environment (pinned wp-env)
shell: bash
env:
BUILD_DIR: ${{ inputs.build-dir }}
WP_ENV_VERSION: ${{ inputs.wp-env-version }}
run: |
PLUGIN_SLUG="$(basename "$BUILD_DIR")"
echo "PLUGIN_SLUG=$PLUGIN_SLUG" >> "$GITHUB_ENV"

npm install -g "@wordpress/env@${WP_ENV_VERSION}"

cat > .wp-env.json <<JSON
{
"core": null,
"testsEnvironment": false,
"plugins": [ "https://downloads.wordpress.org/plugin/plugin-check.zip" ],
"mappings": {
"wp-content/plugins/${PLUGIN_SLUG}": "${BUILD_DIR}"
}
}
JSON

wp-env start

- name: Run Plugin Check
shell: bash
env:
CATEGORIES: ${{ inputs.categories }}
CHECKS: ${{ inputs.checks }}
EXCLUDE_DIRECTORIES: ${{ inputs.exclude-directories }}
IGNORE_WARNINGS: ${{ inputs.ignore-warnings }}
run: |
# Normalise newline-separated workflow inputs to comma-separated CLI args.
csv() { printf '%s' "$1" | tr -s '[:space:]' ',' | sed 's/^,//;s/,$//'; }

args=()
[ -n "$(csv "$CATEGORIES")" ] && args+=("--categories=$(csv "$CATEGORIES")")
[ -n "$(csv "$CHECKS")" ] && args+=("--checks=$(csv "$CHECKS")")
[ -n "$(csv "$EXCLUDE_DIRECTORIES")" ] && args+=("--exclude-directories=$(csv "$EXCLUDE_DIRECTORIES")")
[ "$IGNORE_WARNINGS" = "true" ] && args+=("--ignore-warnings")

wp-env run cli wp plugin activate "$PLUGIN_SLUG"

# WP-CLI `plugin check` exits 0 even with findings, so we render + gate
# ourselves. 2>/dev/null drops the cli container's bootstrap notices; the
# sed strips a stray wpdb error banner the plugin prints on a fresh
# (table-less) install, keeping the JSON clean for the artifact.
wp-env run cli wp plugin check "$PLUGIN_SLUG" \
--format=json \
"${args[@]}" \
--require=./wp-content/plugins/plugin-check/cli.php \
2>/dev/null | sed 's#<div id="error">.*</div>##' \
> plugin-check-results.json || true

# Render the results (aligned log table + Markdown job summary) and exit
# non-zero on blocking errors.
php "${GITHUB_ACTION_PATH}/format-results.php" plugin-check-results.json "$IGNORE_WARNINGS"

- name: Upload Plugin Check results
if: ${{ always() }}
uses: actions/upload-artifact@v7
with:
name: plugin-check-results
path: plugin-check-results.json
if-no-files-found: ignore
109 changes: 109 additions & 0 deletions .github/actions/plugin-check/format-results.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
<?php
/**
* Render WordPress Plugin Check JSON results for GitHub Actions.
*
* Prints an aligned, file-grouped table to the log, writes a Markdown table to
* the job summary, and exits non-zero when blocking findings are present.
*
* Usage: php format-results.php <results.json> [ignore-warnings]
*
* The input is WP-CLI `plugin check --format=json` output: a "FILE: <path>"
* line followed by a JSON array of findings, repeated per file.
*/

$path = $argv[1] ?? '';
$ignoreWarnings = filter_var($argv[2] ?? 'false', FILTER_VALIDATE_BOOLEAN);

$raw = ($path !== '' && is_readable($path)) ? (string) file_get_contents($path) : '';

$findings = [];
$file = '';
foreach (preg_split('/\R/', $raw) as $line) {
if (preg_match('/^FILE:\s*(.+)$/', $line, $m)) {
$file = trim($m[1]);
continue;
}
$line = trim($line);
if ($line === '' || $line[0] !== '[') {
continue;
}
$rows = json_decode($line, true);
if (!is_array($rows)) {
continue;
}
foreach ($rows as $row) {
$row['file'] = $file;
// With --ignore-warnings the tool omits the type field; all rows are errors.
$row['type'] = $row['type'] ?? 'ERROR';
$findings[] = $row;
}
}

$errors = count(array_filter($findings, static fn ($f) => $f['type'] === 'ERROR'));
$warnings = count(array_filter($findings, static fn ($f) => $f['type'] === 'WARNING'));

// --- Log output: aligned columns, grouped by file ---
echo "::group::Plugin Check results\n";
if (!$findings) {
echo "No issues found.\n";
}
$grouped = [];
foreach ($findings as $f) {
$grouped[$f['file']][] = $f;
}
foreach ($grouped as $file => $rows) {
$wLine = $wCol = $wType = 0;
foreach ($rows as $r) {
$wLine = max($wLine, strlen((string) $r['line']));
$wCol = max($wCol, strlen((string) $r['column']));
$wType = max($wType, strlen($r['type']));
}
echo "\nFILE: {$file}\n";
foreach ($rows as $r) {
$message = preg_replace('/\s+/', ' ', (string) $r['message']);
printf(
" %-{$wLine}s %-{$wCol}s %-{$wType}s %s — %s\n",
$r['line'],
$r['column'],
$r['type'],
$r['code'],
$message
);
}
}
echo "::endgroup::\n";

// --- Job summary: Markdown ---
$summaryFile = getenv('GITHUB_STEP_SUMMARY');
if ($summaryFile) {
$md = "## WordPress Plugin Check\n\n";
if (!$findings) {
$md .= "✅ No issues found.\n";
} else {
$md .= sprintf("**%d error(s), %d warning(s)**\n\n", $errors, $warnings);
$md .= "| File | Line | Col | Type | Code | Message |\n";
$md .= "| --- | --- | --- | --- | --- | --- |\n";
foreach ($findings as $f) {
$message = preg_replace('/\s+/', ' ', (string) $f['message']);
$message = str_replace('|', '\\|', $message);
$md .= sprintf(
"| %s | %s | %s | %s | %s | %s |\n",
$f['file'],
$f['line'],
$f['column'],
$f['type'],
$f['code'],
$message
);
}
}
file_put_contents($summaryFile, $md . "\n", FILE_APPEND);
}

// --- Gate: errors block; with --ignore-warnings every reported finding is an error ---
$blocking = $ignoreWarnings ? count($findings) : $errors;
if ($blocking > 0) {
echo "::error::Plugin Check reported {$blocking} blocking issue(s). See the job summary or the uploaded artifact.\n";
exit(1);
}
exit(0);
16 changes: 6 additions & 10 deletions .github/workflows/plugin-check.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
name: WordPress Plugin Check

on:
push:
branches:
- main
pull_request:
branches:
- main
Expand Down Expand Up @@ -69,15 +66,14 @@ jobs:
run: |
bash .github/build

- name: Start WordPress Environment
run: |
npm install -g @wordpress/env
wp-env start

# Local pinned-wp-env action — workaround for the @wordpress/env 11.8.0
# Docker regression. Toggle back to the upstream action (identical `with:`)
# once it is fixed by swapping the two `uses:` lines below.
- name: WordPress Plugin Check
uses: wordpress/plugin-check-action@v1
uses: ./.github/actions/plugin-check
# uses: wordpress/plugin-check-action@v1
with:
build-dir: './build/${{ env.PLUGIN_SLUG }}'
build-dir: ./build/${{ env.PLUGIN_SLUG }}
exclude-directories: |
vendor
node_modules
Expand Down
4 changes: 2 additions & 2 deletions backend/Actions/WooCommerce/RecordApiHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,7 @@ public function upload_attachment($product_id, $url)
return false;
}

$filename = basename(parse_url($url, PHP_URL_PATH));
$filename = basename(wp_parse_url($url, PHP_URL_PATH));
$tmp = wp_tempnam($filename);
if (!$tmp || file_put_contents($tmp, $image_data) === false) {
return false;
Expand All @@ -651,7 +651,7 @@ public function upload_attachment($product_id, $url)
$attach_id = media_handle_sideload($file_array, $product_id);

if (is_wp_error($attach_id)) {
@unlink($tmp);
wp_delete_file($tmp);

return false;
}
Expand Down