Plugin Check lokalnie i w CI: błędy wykryte przed recenzją

Spis treści
Każda wtyczka zgłoszona do katalogu WordPress.org przechodzi najpierw automatyczne skanowanie, a dopiero potem jej kod czyta ktoś z Plugins Team. Część uwag z recenzji da się wykryć maszynowo: brak nagłówka z licencją, dane wypisywane bez escapowania, skrypt ładowany z publicznego CDN, Text Domain niezgodna ze slugiem. Plugin Check, w skrócie PCP, to narzędzie, które WordPress.org publikuje właśnie w tym celu. Według opisu uruchamia większość testów stosowanych przy nowych zgłoszeniach, i to na dowolnej instalacji WordPressa, zanim cokolwiek trafi do katalogu.
Artykuł pokazuje Plugin Check 2.1.0 w trzech miejscach: w panelu administracyjnym, w wierszu poleceń z WP-CLI oraz w workflow GitHub Actions opartym na oficjalnej akcji. Obiektem testu jest mała wtyczka z celowo wprowadzonymi błędami. Przy każdym błędzie podano test i kod wyniku zgłoszony przez przebieg Plugin Check 2.1.0 w WordPressie 7.1.2, a następnie pokazano poprawioną wersję.
Co sprawdza Plugin Check
Aktualna wersja w katalogu to 2.1.0 z 16 sierpnia 2026 roku. Wymaga WordPressa 6.3 i PHP 7.4; strona wtyczki podaje „Tested up to” 7.0.6, podczas gdy bieżące wydanie WordPressa to 7.1.2. Wersja 2.1.0 wprowadziła między innymi test wykrywający zmiany raportowania błędów PHP w czasie działania.
W kodzie wersji 2.1.0 klasa Default_Check_Repository rejestruje 34 testy. Każdy ma slug, na przykład late_escaping, i należy do jednej lub kilku kategorii. Istnieją dwa rodzaje testów. Testy statyczne czytają kod bez jego wykonywania, najczęściej za pomocą sniffów PHP_CodeSniffer z WordPress Coding Standards lub z własnego zestawu Plugin Check, a częściowo za pomocą własnej logiki. Testy uruchomieniowe wykonują wtyczkę, która musi być aktywna, na wydzielonym zestawie tabel bazy danych i obserwują jej działanie; w 2.1.0 jest to pięć testów wydajności dotyczących zasięgu i rozmiaru skryptów oraz arkuszy stylów, a także strategii ładowania.
| Kategoria (slug) | Przykładowe testy w 2.1.0 |
|---|---|
General (general) |
i18n_usage, php_error_reporting, ai_provider |
Plugin Repo (plugin_repo) |
plugin_readme, plugin_header_fields, file_type, offloading_files, setting_sanitization, prefixing, plugin_review_phpcs, trademarks |
Security (security) |
late_escaping, direct_file_access, safe_redirect, direct_db_queries, direct_db |
Performance (performance) |
enqueued_scripts_in_footer, performant_wp_query_params, enqueued_scripts_scope, non_blocking_scripts |
Accessibility (accessibility) |
brak: kategoria jest zdefiniowana, ale żaden wbudowany test wersji 2.1.0 nie jest do niej przypisany |
Wszystkie testy bezpieczeństwa zarejestrowane w 2.1.0 mają dodatkowo kategorię plugin_repo, więc przebieg ograniczony do Plugin Repo obejmuje już escapowanie i bezpośredni dostęp do plików. Ma to znaczenie, bo FAQ wtyczki stwierdza, że do przyjęcia do katalogu wtyczka zazwyczaj musi przejść wszystkie testy kategorii Plugin Repo. Pozostałe kategorie opisano jako dodatkowe.
Każdy wynik ma typ ERROR albo WARNING oraz wagę (severity); domyślnie wynosi ona 5, a brak licencji w nagłówku wtyczki test zgłasza z wagą 9. Błędy oznaczają naruszenie wymagań katalogu. Ostrzeżenia wskazują kod, który często, choć nie zawsze, stanowi problem: odczyt $_GET bez Nonce jest nieszkodliwy przy parametrze służącym tylko do wyświetlenia, a w obsłudze formularza oznacza realną lukę. Typ ustala sam test. Zestaw reguł PHPCS w Plugin Check celowo obniża niektóre sniffy do ostrzeżeń, na przykład weryfikację Nonce i sanityzację danych wejściowych.
Uruchamianie lokalne: panel i WP-CLI
Plugin Check jest instalowany tak jak każda inna wtyczka. README projektu odradza używanie go na stronie produkcyjnej, ponieważ testy uruchomieniowe faktycznie wykonują sprawdzaną wtyczkę. Po aktywacji w menu Narzędzia → Plugin Check pojawia się ekran dostępny dla użytkowników z prawem zarządzania wtyczkami. Zawiera listę wyboru wtyczki oraz pola wyboru kategorii i typów wyników. Wyniki są grupowane według plików, z wierszem, kolumną, typem, kodem i komunikatem; od wersji 1.8.0 da się je wyeksportować do CSV, JSON lub Markdown.
Przy częstych przebiegach wygodniejsze jest polecenie WP-CLI. Jako argument przyjmuje slug wtyczki, ścieżkę albo adres URL pliku ZIP. Domyślnie uruchamia tylko testy statyczne. Dla testów uruchomieniowych README opisuje obejście: --require wczytuje plik cli.php z Plugin Check, zanim wystartuje WordPress. Ponadto sprawdzana wtyczka musi być aktywna; przy nieaktywnej wtyczce Plugin Check bez żadnego komunikatu pomija testy uruchomieniowe, a --checks=enqueued_scripts_scope kończy się wtedy komunikatem „does not exist”.
# Install and activate Plugin Check (2.1.0 at the time of writing).
wp plugin install plugin-check --activate
# All static checks for wp-content/plugins/lw-hello-banner.
wp plugin check lw-hello-banner
# Include runtime checks (plugin must be active): load cli.php before WordPress boots.
wp plugin check lw-hello-banner --require=./wp-content/plugins/plugin-check/cli.php
# Limit the run to categories or to single checks.
wp plugin check lw-hello-banner --categories=plugin_repo,security
wp plugin check lw-hello-banner --checks=late_escaping,i18n_usage
# Errors only, as one JSON array for scripts.
wp plugin check lw-hello-banner --ignore-warnings --format=strict-json
# Show result codes, then ignore one specific code.
wp plugin check lw-hello-banner --format=csv --fields=code,message
wp plugin check lw-hello-banner --ignore-codes=textdomain_mismatch
# Checks for an update of an existing directory plugin.
wp plugin check lw-hello-banner --mode=update
# What is available in the installed version.
wp plugin list-checks --format=csv
wp plugin list-check-categories
Najważniejsze opcje wp plugin check w wersji 2.1.0:
| Opcja | Działanie |
|---|---|
--checks=, --exclude-checks= |
uruchamia tylko wymienione testy albo je pomija |
--categories= |
ogranicza przebieg do kategorii, rozdzielonych przecinkami |
--ignore-codes= |
ukrywa pojedyncze kody wyników, np. textdomain_mismatch |
--ignore-warnings, --ignore-errors |
ukrywa jeden z dwóch typów wyników |
--format= |
table (domyślnie), csv, json, ctrf oraz strict-table, strict-csv, strict-json, strict-ctrf |
--fields= |
wybór kolumn, np. code,message |
--exclude-directories=, --exclude-files= |
pomija ścieżki przy skanowaniu plików; .git, vendor, vendor_prefixed, vendor-prefixed i node_modules są wykluczone domyślnie |
--severity=, --error-severity=, --warning-severity= |
pokazuje tylko wyniki od określonej wagi |
--mode= |
new (domyślnie) lub update; w trybie aktualizacji nieaktualne „Tested up to” jest ostrzeżeniem, a nie błędem |
--slug= |
nadpisuje slug, z którym porównywane są Text Domain i readme |
Slugi testów i kody wyników to dwie różne rzeczy. --checks=i18n_usage wybiera test, a --ignore-codes=WordPress.WP.I18n.TextDomainMismatch ukrywa pojedyncze zgłoszenie z tego testu. Do wyszukiwania kodów dokumentacja CLI zaleca --format=csv --fields=code,message. Dla skryptów ważny jest jeszcze jeden szczegół: w kodzie wersji 2.1.0 polecenie wypisuje wyniki, ale z ich powodu nie ustawia kodu wyjścia oznaczającego błąd. Skrypt powłoki, który ma się zatrzymać przy zgłoszeniach, musi więc sam przeanalizować wynik; w teście polecenie zgłosiło dla błędnego przykładu dwanaście błędów i mimo to zakończyło się kodem wyjścia 0. Akcja dla GitHuba robi dokładnie to. Przy --format=json przed każdym plikiem stoi wiersz FILE: … z osobną tablicą JSON, więc całość nie jest poprawnym JSON-em; --format=strict-json zwraca jedną tablicę, ale bez nazw plików. Bez zgłoszeń oba formaty wypisują tylko wiersz o powodzeniu.
Przykładowa wtyczka z wbudowanymi błędami
Przykład to jeden plik w katalogu wp-content/plugins/lw-hello-banner/, więc slug brzmi lw-hello-banner. Wtyczka wyświetla powitanie u góry strony, odczytuje opcjonalne imię z adresu URL, dodaje pole notatki w Ustawienia → Ogólne i ładuje ozdobny skrypt. Zawiera dziewięć celowych błędów: brak readme.txt, brak nagłówka licencji, Text Domain inną niż slug, brak ochrony przed bezpośrednim wywołaniem pliku, wywołanie error_reporting(), register_setting() bez sanityzacji, wypisywanie danych bez escapowania, tłumaczony tekst z symbolem zastępczym, ale bez komentarza dla tłumaczy, oraz skrypt z CDN bez wersji i bez argumentów ładowania.
<?php
/**
* Plugin Name: LW Hello Banner
* Description: Shows a greeting banner at the top of the front page.
* Version: 0.1.0
* Author: Lukas Wojcik
* Text Domain: hello-banner
*/
// Intentionally faulty example for Plugin Check. Do not use on a live site.
error_reporting( E_ALL );
function lw_hello_banner_register_setting() {
register_setting( 'general', 'lw_hello_banner_note' );
add_settings_field(
'lw_hello_banner_note',
__( 'Banner note', 'hello-banner' ),
'lw_hello_banner_field',
'general'
);
}
add_action( 'admin_init', 'lw_hello_banner_register_setting' );
function lw_hello_banner_field() {
echo '<input type="text" name="lw_hello_banner_note" value="' . get_option( 'lw_hello_banner_note' ) . '">';
}
function lw_hello_banner_assets() {
wp_enqueue_script( 'lw-hello-banner', 'https://cdn.jsdelivr.net/npm/canvas-confetti@1.9.3/dist/confetti.browser.min.js' );
}
add_action( 'wp_enqueue_scripts', 'lw_hello_banner_assets' );
function lw_hello_banner_render() {
$name = isset( $_GET['lw_name'] ) ? $_GET['lw_name'] : 'Guest';
$note = get_option( 'lw_hello_banner_note', '' );
echo '<div class="lw-hello-banner"><p>' . sprintf( __( 'Hello, %s!', 'hello-banner' ), $name ) . ' ' . $note . '</p></div>';
}
add_action( 'wp_body_open', 'lw_hello_banner_render' );
Co zgłasza Plugin Check
Tabela zawiera zgłoszenia, które wp plugin check lw-hello-banner z Plugin Check 2.1.0 w WordPressie 7.1.2 wypisuje dla tego przykładu, łącznie dwanaście błędów i dziewięć ostrzeżeń; przebieg z --require daje tę samą listę. Numery wierszy pominięto; OutputNotEscaped pojawia się cztery razy, TextDomainMismatch i NonceVerification.Recommended po dwa razy.
| Kod wyniku | Test (kategoria) | Typ | Przyczyna w przykładzie |
|---|---|---|---|
no_plugin_readme |
plugin_readme (plugin_repo) |
ERROR | brak readme.txt |
plugin_header_no_license |
plugin_header_fields (plugin_repo) |
ERROR | brak nagłówka License |
textdomain_mismatch |
plugin_header_fields (plugin_repo) |
WARNING | nagłówek podaje hello-banner, slug to lw-hello-banner |
missing_direct_file_access_protection |
direct_file_access (security, plugin_repo) |
ERROR | funkcje i Hooki bez warunku ABSPATH |
WordPress.WP.I18n.TextDomainMismatch |
i18n_usage (general, plugin_repo) |
ERROR | wywołania __() z niewłaściwą Text Domain |
WordPress.WP.I18n.MissingTranslatorsComment |
i18n_usage (general, plugin_repo) |
ERROR | %s bez komentarza translators: |
PluginCheck.CodeAnalysis.PHPErrorReporting.DirectErrorReportingCall |
php_error_reporting (general) |
WARNING | error_reporting( E_ALL ) |
WordPress.PHP.DevelopmentFunctions.prevent_path_disclosure_error_reporting |
plugin_review_phpcs (plugin_repo) |
WARNING | error_reporting( E_ALL ) |
PluginCheck.CodeAnalysis.SettingSanitization.register_settingMissing |
setting_sanitization (plugin_repo) |
ERROR | register_setting() bez trzeciego argumentu |
WordPress.Security.EscapeOutput.OutputNotEscaped |
late_escaping (security, plugin_repo) |
ERROR | get_option(), __(), $name i $note w echo |
PluginCheck.CodeAnalysis.EnqueuedResourceOffloading.OffloadedContent |
offloading_files (plugin_repo) |
ERROR | adres skryptu na cdn.jsdelivr.net |
WordPress.WP.EnqueuedResourceParameters.MissingVersion, .NotInFooter |
enqueued_scripts_in_footer (performance) |
WARNING | brak wersji i piątego argumentu |
WordPress.Security.NonceVerification.Recommended |
plugin_review_phpcs (plugin_repo) |
WARNING | $_GET['lw_name'] bez weryfikacji Nonce |
WordPress.Security.ValidatedSanitizedInput.MissingUnslash, .InputNotSanitized |
plugin_review_phpcs (plugin_repo) |
WARNING | $_GET['lw_name'] użyte bez obróbki |

Z tabeli wynikają trzy obserwacje. Po pierwsze, Text Domain jest zgłaszana dwukrotnie, przez dwa różne testy: test nagłówka porównuje pole Text Domain ze slugiem i zgłasza ostrzeżenie, a sniff i18n porównuje ze slugiem każde wywołanie funkcji tłumaczącej i zgłasza błąd. Po drugie, zgłoszenia dotyczące Nonce i sanityzacji nie pochodzą z kategorii Security, lecz z plugin_review_phpcs, czyli przebiegu PHPCS z zestawem reguł recenzji Plugin Check; przebieg z --categories=security ich nie pokaże. Po trzecie, zestaw reguł zawiera również grupę sniffów WordPress.PHP.DevelopmentFunctions jako ostrzeżenie. Rzeczywiście zgłasza ona wiersz z error_reporting() po raz drugi, jako prevent_path_disclosure_error_reporting.
Skrypt z CDN prowadzi do jeszcze jednej kwestii: testy uruchomieniowe zasięgu i strategii ładowania skryptów oceniają wyłącznie skrypty, których adres URL leży w katalogu wtyczki. Skrypt z CDN zgłaszają więc tylko testy statyczne, a przebieg z --require daje tę samą listę co przebieg bez niego. Testy uruchomieniowe mają znaczenie dopiero dla poprawionej wersji z dołączonym skryptem: bez warunku is_front_page() Plugin Check zgłasza go jako EnqueuedScriptsScope („This script is being loaded in all frontend contexts.”), ale tylko w przebiegu z --require.
Poprawiona wersja
Poprawiona wtyczka składa się z trzech plików: pliku głównego, readme.txt i małego lokalnego skryptu w assets/. Plik główny dostaje pełny nagłówek z licencją, Requires at least i Text Domain lw-hello-banner, a także warunek ABSPATH. Wywołanie error_reporting() znika. register_setting() otrzymuje typ, sanitize_callback i wartość domyślną. Dane są escapowane dopiero w miejscu wypisania, za pomocą esc_attr(), esc_html() i esc_html__(). Skrypt jest dołączony do wtyczki, ma wersję i ładuje się tylko na stronie głównej z in_footer i strategy. Tablicowa postać piątego argumentu wp_enqueue_script() istnieje od WordPressa 6.3, co zgadza się z zadeklarowaną wersją minimalną.
<?php
/**
* Plugin Name: LW Hello Banner
* Description: Shows a greeting banner at the top of the front page.
* Version: 0.2.0
* Requires at least: 6.3
* Requires PHP: 7.4
* Author: Lukas Wojcik
* License: GPLv2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: lw-hello-banner
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
define( 'LW_HELLO_BANNER_VERSION', '0.2.0' );
/**
* Registers the banner note setting and its field on Settings > General.
*/
function lw_hello_banner_register_setting() {
register_setting(
'general',
'lw_hello_banner_note',
array(
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
'default' => '',
)
);
add_settings_field(
'lw_hello_banner_note',
__( 'Banner note', 'lw-hello-banner' ),
'lw_hello_banner_field',
'general',
'default',
array( 'label_for' => 'lw_hello_banner_note' )
);
}
add_action( 'admin_init', 'lw_hello_banner_register_setting' );
/**
* Prints the input field for the banner note.
*/
function lw_hello_banner_field() {
printf(
'<input type="text" class="regular-text" id="lw_hello_banner_note" name="lw_hello_banner_note" value="%s">',
esc_attr( get_option( 'lw_hello_banner_note', '' ) )
);
}
/**
* Loads the bundled script on the front page only.
*/
function lw_hello_banner_assets() {
if ( ! is_front_page() ) {
return;
}
wp_enqueue_script(
'lw-hello-banner',
plugins_url( 'assets/lw-hello-banner.js', __FILE__ ),
array(),
LW_HELLO_BANNER_VERSION,
array(
'in_footer' => true,
'strategy' => 'defer',
)
);
}
add_action( 'wp_enqueue_scripts', 'lw_hello_banner_assets' );
/**
* Prints the banner on the front page.
*/
function lw_hello_banner_render() {
if ( ! is_front_page() ) {
return;
}
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only display value, nothing is stored.
$name = isset( $_GET['lw_name'] ) ? sanitize_text_field( wp_unslash( $_GET['lw_name'] ) ) : '';
if ( '' === $name ) {
$name = __( 'Guest', 'lw-hello-banner' );
}
$greeting = sprintf(
/* translators: %s: visitor name */
__( 'Hello, %s!', 'lw-hello-banner' ),
$name
);
$note = get_option( 'lw_hello_banner_note', '' );
echo '<div class="lw-hello-banner"><p>' . esc_html( $greeting );
if ( '' !== $note ) {
echo ' ' . esc_html( $note );
}
echo '</p><button type="button">' . esc_html__( 'Dismiss', 'lw-hello-banner' ) . '</button></div>';
}
add_action( 'wp_body_open', 'lw_hello_banner_render' );
Imię z adresu URL pozostało celowo, w parametrze lw_name: WordPress sam odczytuje name jako slug wpisu, więc ?name=Anna zamienia stronę główną w stronę 404, na której is_front_page() zwraca false. Przechodzi przez wp_unslash() i sanitize_text_field(), a pozostałe ostrzeżenie o Nonce wycisza komentarz phpcs:ignore, który wskazuje sniff i podaje uzasadnienie. FAQ Plugin Check opisuje takie adnotacje jako przewidziany sposób obsługi fałszywych alarmów PHPCS w konkretnym wierszu. Uzasadnienie jest tu zasadne tylko dlatego, że wartość niczego nie zmienia: nie jest zapisywana i nie uruchamia żadnej akcji. W formularzu zapisującym dane potrzebne są Nonce oraz sprawdzenie Capability, czym szczegółowo zajmuje się osobny artykuł z tej serii.
=== LW Hello Banner ===
Contributors: lukaswojcik
Tags: banner, greeting
Requires at least: 6.3
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 0.2.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Shows a short, dismissible greeting banner at the top of the front page.
== Description ==
LW Hello Banner prints a greeting on the front page. An optional note can be set under Settings > General.
== Changelog ==
= 0.2.0 =
* Fix all findings reported by Plugin Check.
= 0.1.0 =
* Initial version.
Dwa szczegóły readme wynikają bezpośrednio z kodu testu. „Tested up to” musi odpowiadać bieżącej głównej wersji WordPressa, obecnie 7.1. Starsza wartość to błąd dla nowych wtyczek i ostrzeżenie w trybie aktualizacji, a wartość z numerem poprawki, np. 7.1.2, jest zgłaszana jako invalid_tested_upto_minor. Test porównuje też licencję w readme z licencją w nagłówku wtyczki i zgłasza różnicę jako license_mismatch, dlatego w obu plikach widnieje identyczny zapis. Pola readme i nagłówka wtyczki omawia osobny artykuł z tej serii.
// assets/lw-hello-banner.js
( function () {
const banner = document.querySelector( '.lw-hello-banner' );
if ( ! banner ) {
return;
}
const button = banner.querySelector( 'button' );
if ( button ) {
button.addEventListener( 'click', function () {
banner.hidden = true;
} );
}
} )();
Plugin Check w GitHub Actions
Oficjalną integracją jest repozytorium WordPress/plugin-check-action. Najnowsze wydanie to v1.1.9 z 11 sierpnia 2026 roku, a ruchomy tag v1 wskazuje obecnie na ten sam commit. To akcja typu composite. Kolejno konfiguruje Node 24, instaluje @wordpress/env, uruchamia instancję WordPressa z katalogiem wtyczki zmapowanym do wp-content/plugins, instaluje Plugin Check z katalogu, a także wtyczki wymienione w Requires Plugins, po czym wywołuje wp plugin check z --format=json i --require=./wp-content/plugins/plugin-check/cli.php. Testy uruchomieniowe są więc uwzględnione. Według dokumentacji wp-env domyślnie działa na Dockerze, dlatego standardowy runner Ubuntu jest naturalnym wyborem.
Plik JSON analizuje skrypt Node. Każdy wynik staje się adnotacją przy pliku, z kodem wyniku jako tytułem. Każdy ERROR ustawia kod wyjścia 1 i kończy zadanie niepowodzeniem, ostrzeżenia pojawiają się tylko jako adnotacje. Przy strict: true każdy wynik liczy się jako błąd. W pull requestach akcja dodaje lub aktualizuje komentarz z podsumowaniem, a surowy wynik zapisuje jako artefakt plugin-check-results.
Parametry wejściowe w v1.1.9: build-dir (domyślnie ./), checks, exclude-checks, categories, exclude-files, exclude-directories, ignore-codes, ignore-warnings, ignore-errors, include-experimental, wp-version (latest lub trunk), severity, error-severity, warning-severity, include-low-severity-errors, include-low-severity-warnings, slug, strict i repo-token. Parametry listowe przyjmują jeden wpis w wierszu.
O sensowności wyników decydują dwa szczegóły. Akcja wyprowadza slug z ostatniego członu build-dir. Przy domyślnym ./ jest to nazwa katalogu roboczego, która według dokumentacji GitHuba odpowiada nazwie repozytorium, np. /home/runner/work/my-repo-name/my-repo-name. Jeśli repozytorium nazywa się inaczej niż wtyczka, każde wywołanie funkcji tłumaczącej zostanie zgłoszone. Ponadto test file_type w 2.1.0 ostrzega przed katalogiem .github wewnątrz wtyczki i zgłasza inne ukryte pliki. Sprawdzanie katalogu głównego repozytorium oznacza zatem testowanie plików, które nigdy nie trafią do wydania. Poniższy workflow buduje więc za pomocą git archive katalog, który faktycznie zostałby wysłany, z uwzględnieniem wpisów export-ignore w .gitattributes, i przekazuje go jako build-dir.
# .github/workflows/plugin-check.yml
name: Plugin Check
on:
pull_request:
push:
branches:
- main
permissions:
contents: read
pull-requests: write # only for the summary comment on pull requests
jobs:
plugin-check:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v7
# Build the folder that would be shipped, without .github and other
# development files (see export-ignore in .gitattributes).
- name: Build distributable plugin folder
run: |
mkdir -p build
git archive --format=tar --prefix=lw-hello-banner/ HEAD | tar -x -C build
- name: Run Plugin Check
uses: wordpress/plugin-check-action@v1
with:
# The folder name becomes the slug (text domain check, readme check).
build-dir: ./build/lw-hello-banner
wp-version: latest
# Optional filters, one entry per line:
# categories: |
# plugin_repo
# security
# exclude-checks: |
# enqueued_scripts_scope
# ignore-codes: |
# textdomain_mismatch
# Fail on warnings as well:
# strict: true
# .gitattributes: files that git archive leaves out of the build
/.gitattributes export-ignore
/.github export-ignore
/.gitignore export-ignore
/build export-ignore
Uprawnienie pull-requests: write jest potrzebne tylko do komentarza z podsumowaniem; według tabel uprawnień GitHuba obejmuje ono endpoint komentarzy. Bez niego akcja zapisze w logu ostrzeżenie przy komentowaniu, ale wyniki i tak przeanalizuje. Przy preferencji stałych wersji warto zamiast v1 wskazać wordpress/plugin-check-action@v1.1.9 albo hash jego commitu.
Ograniczenia i otwarte kwestie
- Plugin Check nie zastępuje ręcznej recenzji. Strona wtyczki mówi to wprost, a czysty przebieg nie gwarantuje akceptacji.
- Tabela zgłoszeń dla przykładowej wtyczki pochodzi z lokalnego przebiegu
wp plugin checkw WordPressie 7.1.2. Sam workflow nie był uruchamiany na GitHubie; lokalnie krok zgit archiveutworzył oczekiwany katalog, a skrypt oceniający akcji (v1.1.9) zakończył się kodem wyjścia 1 dla błędnego przykładu i 0 dla poprawionej wersji. - Niektóre testy opierają się na heurystykach. Test prefiksów wyprowadza oczekiwane prefiksy z kodu wtyczki, dlatego liczy się konsekwentny prefiks, taki jak
lw_hello_banner_. - Akcja instaluje tę wersję Plugin Check, którą katalog oferuje w chwili przebiegu, i nie ma parametru, który by ją zamroził. Pipeline może więc zmienić kolor na czerwony po wydaniu nowego Plugin Check, choć we wtyczce nic się nie zmieniło.
- Brak parametru dla wersji PHP, a
wp-versionrozróżnia tylko najnowsze wydanie i trunk. Testy ze starszymi wersjami WordPressa lub PHP wymagają osobnej konfiguracji, np. z wp-env lub Playground, czemu poświęcony jest osobny artykuł z tej serii. - Zgłoszenia wydajnościowe dotyczące zasięgu skryptów zależą od sposobu, w jaki wtyczka dołącza pliki; drugą stronę problemu pokazuje artykuł o selektywnym wyłączaniu skryptów wtyczek.
Pytania i odpowiedzi
Czy przebieg bez zgłoszeń gwarantuje przyjęcie wtyczki do katalogu?
Nie. Według FAQ Plugin Check wtyczka zazwyczaj musi przejść wszystkie testy kategorii plugin_repo, ale akceptacja nadal zależy od ręcznej recenzji. Strona wtyczki wprost zaznacza, że Plugin Check nie zastępuje ręcznej recenzji; czysty przebieg jedynie ją przyspiesza.
Dlaczego akcja GitHub zgłasza więcej niż lokalne wywołanie wp plugin check?
Zwykle z trzech powodów:
- Akcja zawsze wczytuje
cli.phpprzez--requirei aktywuje wtyczkę, a lokalnie bez tego obejścia lub przy nieaktywnej wtyczce działają tylko testy statyczne. - Akcja instaluje bieżącą wersję Plugin Check z katalogu, lokalnie może być aktywna starsza.
- Przy
build-dir: ./sprawdza całe repozytorium, łącznie z.githubi ukrytymi plikami.
Kiedy wyciszenie ostrzeżenia jest uzasadnione?
Gdy zgłoszenie w danym przypadku faktycznie nie stanowi problemu, np. oczyszczony parametr URL, który jest tylko wyświetlany i nigdzie nie zapisywany. Wtedy przy tym wierszu należy umieścić komentarz phpcs:ignore z nazwą sniffa i uzasadnieniem. --ignore-codes lub parametr akcji ignore-codes ukrywają kod w całej wtyczce, a więc także prawdziwe problemy.
Dlaczego ta sama Text Domain jest zgłaszana dwa razy?
Ze slugiem porównują ją dwa testy: plugin_header_fields sprawdza nagłówek Text Domain i zgłasza textdomain_mismatch jako ostrzeżenie, a i18n_usage sprawdza każde wywołanie funkcji tłumaczącej i zgłasza WordPress.WP.I18n.TextDomainMismatch. Slug to nazwa katalogu; w CI da się go ustalić parametrem slug, lokalnie opcją --slug.
Źródła
- Plugin Check (PCP) na WordPress.org, dostęp 29.09.2026
- WordPress/plugin-check, README, dostęp 29.09.2026
- Wydanie Plugin Check 2.1.0, dostęp 29.09.2026
- Plugin Check: dokumentacja WP-CLI (docs/CLI.md), dostęp 29.09.2026
- Plugin Check: dostępne testy (docs/checks.md), dostęp 29.09.2026
- Default_Check_Repository.php (tag 2.1.0), dostęp 29.09.2026
- Check_Categories.php (tag 2.1.0), dostęp 29.09.2026
- Plugin_Check_Command.php (tag 2.1.0), dostęp 29.09.2026
- plugin-check.ruleset.xml (tag 2.1.0), dostęp 29.09.2026
- Kod źródłowy testów (tag 2.1.0), dostęp 29.09.2026
- Testy jednostkowe (tag 2.1.0), dostęp 29.09.2026
- WordPress/plugin-check-action, README, dostęp 29.09.2026
- plugin-check-action: action.yml (v1.1.9), dostęp 29.09.2026
- plugin-check-action: src/main.ts (v1.1.9), dostęp 29.09.2026
- Wydanie plugin-check-action v1.1.9, dostęp 29.09.2026
- wp_enqueue_script() – Developer Resources, dostęp 29.09.2026
- @wordpress/env – Block Editor Handbook, dostęp 29.09.2026
- API wersji WordPress.org (bieżące wydanie 7.1.2), dostęp 29.09.2026
- Wydania actions/checkout (v7.0.1), dostęp 29.09.2026
- GitHub Docs: zmienne (GITHUB_WORKSPACE), dostęp 29.09.2026
- GitHub Docs: uprawnienia dla GitHub Apps, dostęp 29.09.2026