From ab0975c08b047da1c4f78894b723f42f23f26da9 Mon Sep 17 00:00:00 2001 From: Abu Hurayra Date: Tue, 24 Mar 2026 08:05:39 +0600 Subject: [PATCH 1/5] refactor: Add new workflows for PCP, PHP syntax, and version consistency checks, and a dedicated plugin zip creation workflow, replacing older distribution and plugin check workflows. --- .github/workflows/create-plugin-zip.yml | 37 +++++ .github/workflows/dist-archive.yml | 22 --- .../embedpress-compatibility-test.yml | 153 ++++++----------- .github/workflows/pcp-plugin-check.yml | 155 ++++++++++++++++++ .github/workflows/php-syntax-check.yml | 49 ++++++ .github/workflows/plugin-check.yml | 94 ----------- .../workflows/plugin-version-verification.yml | 38 +++++ .github/workflows/qa.yml | 35 ++++ 8 files changed, 364 insertions(+), 219 deletions(-) create mode 100644 .github/workflows/create-plugin-zip.yml delete mode 100644 .github/workflows/dist-archive.yml create mode 100644 .github/workflows/pcp-plugin-check.yml create mode 100644 .github/workflows/php-syntax-check.yml delete mode 100644 .github/workflows/plugin-check.yml create mode 100644 .github/workflows/plugin-version-verification.yml create mode 100644 .github/workflows/qa.yml diff --git a/.github/workflows/create-plugin-zip.yml b/.github/workflows/create-plugin-zip.yml new file mode 100644 index 00000000..f1710320 --- /dev/null +++ b/.github/workflows/create-plugin-zip.yml @@ -0,0 +1,37 @@ +# Reusable workflow: builds the EmbedPress plugin zip using the 10up action +# and uploads it as a short-lived artifact. Called by qa.yml so the zip is +# built once and shared across all QA jobs. Also runnable standalone via +# workflow_dispatch for a one-off build. + +name: QA - Create Plugin Zip + +on: + workflow_dispatch: # Manual trigger only + workflow_call: + outputs: + artifact-name: + description: "The name of the uploaded artifact" + value: ${{ jobs.build.outputs.artifact-name }} + +jobs: + build: + name: Build plugin zip + runs-on: ubuntu-24.04 + timeout-minutes: 5 + outputs: + artifact-name: ${{ steps.upload-plugin-artifact.outputs.artifact-name }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + # - name: Build plugin # Remove or modify this step as needed + # run: | + # composer install --no-dev + # npm install + # npm run build + + - name: Generate zip + id: upload-plugin-artifact + uses: 10up/action-wordpress-plugin-build-zip@stable + with: + retention-days: 3 # Optional; defaults to 5 \ No newline at end of file diff --git a/.github/workflows/dist-archive.yml b/.github/workflows/dist-archive.yml deleted file mode 100644 index c3accfe7..00000000 --- a/.github/workflows/dist-archive.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: Generate WordPress Archive -on: - workflow_dispatch: - workflow_call: - # This allows other workflows to call this and get the zip - outputs: - artifact-name: - description: 'The name of the uploaded artifact' - value: ${{ github.event.repository.name }} - -jobs: - generate-archive: - runs-on: ubuntu-24.04 - steps: - - name: Checkout repository - uses: actions/checkout@v4 # Updated to v4 for better performance - - - name: Generating zip - uses: rudlinkon/action-wordpress-build-zip@master - with: - # npm-run-build: true - install-composer: false diff --git a/.github/workflows/embedpress-compatibility-test.yml b/.github/workflows/embedpress-compatibility-test.yml index 227c3949..28f34ef5 100644 --- a/.github/workflows/embedpress-compatibility-test.yml +++ b/.github/workflows/embedpress-compatibility-test.yml @@ -1,114 +1,41 @@ +# Reusable workflow: installs EmbedPress on a matrix of WordPress + PHP +# version combinations and runs a suite of activation and integrity checks +# (constants, DB options, CPTs, taxonomies, shortcodes, REST routes, DB +# tables, CRUD, and WP_DEBUG log inspection). Called by qa.yml after the +# build job provides the plugin zip artifact. Version consistency and PHP +# syntax checks run as separate parallel jobs in qa.yml. + name: QA - EmbedPress Compatibility Testing on: workflow_dispatch: # Manual trigger -# pull_request: -# branches: ["main", "dev"] -# push: -# branches: ["main"] + workflow_call: + inputs: + artifact-name: + required: true + type: string env: - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true jobs: - # ────────────────────────────────────────────────────────────────────────── - # Job 0: Version consistency (fast, no server required, runs before matrix) - # ────────────────────────────────────────────────────────────────────────── - version-check: - runs-on: ubuntu-24.04 - name: Version Consistency Check - steps: - - uses: actions/checkout@v4 - - - name: Check all version numbers are consistent - run: | - # Extract each version string from its canonical location - V_HEADER=$(grep -oP "^\s*\*\s*Version:\s*\K[\d.]+" embedpress.php | head -1) - V_CONST=$(grep -oP "define\('EMBEDPRESS_VERSION',\s*\"?\K[\d.]+" includes.php | head -1) - V_PLG=$(grep -oP "define\('EMBEDPRESS_PLUGIN_VERSION',\s*'?\K[\d.]+" embedpress.php | head -1) - V_README=$(grep -oP "Stable tag:\s*\K[\d.]+" readme.txt | head -1) - - echo "Plugin header (Version:): $V_HEADER" - echo "EMBEDPRESS_VERSION (includes): $V_CONST" - echo "EMBEDPRESS_PLUGIN_VERSION (main): $V_PLG" - echo "readme.txt Stable tag: $V_README" - - MISMATCH=0 - [ "$V_HEADER" != "$V_CONST" ] && echo "::error::MISMATCH: Plugin header ($V_HEADER) ≠ EMBEDPRESS_VERSION ($V_CONST)" && MISMATCH=1 - [ "$V_HEADER" != "$V_PLG" ] && echo "::error::MISMATCH: Plugin header ($V_HEADER) ≠ EMBEDPRESS_PLUGIN_VERSION ($V_PLG)" && MISMATCH=1 - [ "$V_HEADER" != "$V_README" ] && echo "::error::MISMATCH: Plugin header ($V_HEADER) ≠ readme.txt Stable tag ($V_README)" && MISMATCH=1 - [ "$MISMATCH" -eq 1 ] && exit 1 - - echo "✅ All version numbers are consistent: $V_HEADER" - - # ────────────────────────────────────────────────────────────────────────── - # Job 1: PHP syntax lint (fast, no server, runs in parallel with version-check) - # ────────────────────────────────────────────────────────────────────────── - php-syntax-check: - runs-on: ubuntu-24.04 - strategy: - fail-fast: false - matrix: - php-version: ["7.4", "8.0", "8.1", "8.2", "8.3", "8.4", "8.5"] - name: PHP Syntax (${{ matrix.php-version }}) - steps: - - uses: actions/checkout@v4 - - - name: Setup PHP ${{ matrix.php-version }} - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-version }} - - - name: Lint all PHP files - run: | - # Find every .php file, excluding vendor (third-party) and node_modules - FILES=$(find . -name "*.php" \ - -not -path "./vendor/*" \ - -not -path "./node_modules/*" \ - -not -path "./.git/*") - - ERRORS=0 - while IFS= read -r file; do - OUTPUT=$(php -l "$file" 2>&1) - if [ $? -ne 0 ]; then - echo "::error file=$file::$OUTPUT" - ERRORS=$((ERRORS + 1)) - fi - done <<< "$FILES" - - TOTAL=$(echo "$FILES" | wc -l | tr -d ' ') - if [ "$ERRORS" -gt 0 ]; then - echo "::error::PHP syntax errors found in $ERRORS / $TOTAL file(s) on PHP ${{ matrix.php-version }}" - exit 1 - fi - echo "✅ All $TOTAL PHP files passed syntax check on PHP ${{ matrix.php-version }}" - - # ────────────────────────────────────────────────────────────────────────── - # Job 2: Build the plugin zip - # ────────────────────────────────────────────────────────────────────────── - build: - uses: ./.github/workflows/dist-archive.yml - - # ────────────────────────────────────────────────────────────────────────── - # Job 2: Matrix compatibility tests - # ────────────────────────────────────────────────────────────────────────── compatibility-test: - needs: [version-check, php-syntax-check, build] runs-on: ubuntu-24.04 + timeout-minutes: 10 strategy: fail-fast: false matrix: include: - wp-version: "6.9.4" - php-version: "7.4" + php-version: "8.5" - wp-version: "6.9.4" - php-version: "8.0" + php-version: "8.4" - wp-version: "6.9.4" php-version: "8.2" - wp-version: "6.9.4" - php-version: "8.4" + php-version: "8.0" - wp-version: "6.9.4" - php-version: "8.5" + php-version: "7.4" - wp-version: "6.5.5" php-version: "8.1" - wp-version: "6.0.9" @@ -117,19 +44,19 @@ jobs: name: WP ${{ matrix.wp-version }} / PHP ${{ matrix.php-version }} steps: - # Setup PHP environment - - name: Setup PHP Runtime + # Setup PHP + WP-CLI via shivammathur (handles WP-CLI install automatically) + - name: Setup PHP ${{ matrix.php-version }} + WP-CLI uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php-version }} - extensions: mysqli, mbstring, xml, gd + extensions: mysqli, mbstring, xml, gd, zip tools: wp-cli # Download the built artifact from the 'build' job - name: Download Built EmbedPress uses: actions/download-artifact@v4 with: - name: ${{ needs.build.outputs.artifact-name }} + name: ${{ inputs.artifact-name }} path: ./embedpress-dist - name: Start Database @@ -140,17 +67,37 @@ jobs: - name: Install WordPress Core run: | wp core download --version=${{ matrix.wp-version }} --path=./test-site --allow-root - cd test-site + cd test-site wp config create --dbname=wordpress_test --dbuser=root --dbpass=root --dbhost=127.0.0.1 --allow-root - wp core install --url=http://localhost:8080 --title="EmbedPress Test" --admin_user=admin --admin_password=password --admin_email=hurayra@wpdeveloper.com --allow-root + wp core install \ + --url=http://localhost:8080 \ + --title="EmbedPress Test" \ + --admin_user=admin \ + --admin_password=password \ + --admin_email=hurayra@wpdeveloper.com \ + --allow-root + + # Install from zip (10up action uploads the plugin as a zip artifact) + - name: Install EmbedPress + run: | + ZIP_FILE=$(find ./embedpress-dist -maxdepth 2 -name "*.zip" | head -n 1) + + if [ -n "$ZIP_FILE" ]; then + echo "Installing from zip: $ZIP_FILE" + wp plugin install "$(realpath "$ZIP_FILE")" --path=./test-site --allow-root + else + echo "No zip found — falling back to directory copy" + PLUGIN_SRC=$(find ./embedpress-dist -maxdepth 1 -mindepth 1 -type d | head -n 1) + [ -z "$PLUGIN_SRC" ] && PLUGIN_SRC="./embedpress-dist" + mkdir -p ./test-site/wp-content/plugins/embedpress + cp -r "$PLUGIN_SRC/." ./test-site/wp-content/plugins/embedpress/ + fi + + echo "Plugin directory contents:" + ls ./test-site/wp-content/plugins/embedpress | head -n 15 - # Move the built plugin to the WP folder and activate - - name: Install and Activate EmbedPress + - name: Activate EmbedPress run: | - mkdir -p ./test-site/wp-content/plugins/embedpress - cp -r ./embedpress-dist/embedpress/. ./test-site/wp-content/plugins/embedpress/ - echo "Checking plugin directory structure:" - ls ./test-site/wp-content/plugins/embedpress | head -n 10 cd test-site wp plugin activate embedpress --allow-root diff --git a/.github/workflows/pcp-plugin-check.yml b/.github/workflows/pcp-plugin-check.yml new file mode 100644 index 00000000..dbb9ca77 --- /dev/null +++ b/.github/workflows/pcp-plugin-check.yml @@ -0,0 +1,155 @@ +# Reusable workflow: downloads the plugin zip artifact, installs it into a +# fresh WordPress (latest) environment, activates the plugin, and runs the +# WordPress Plugin Checker (PCP) against it. Called by qa.yml after the +# build job completes. Also runnable standalone via workflow_dispatch. + +name: QA - PCP Plugin Check + +on: + workflow_dispatch: # Manual trigger + workflow_call: + inputs: + artifact-name: + required: true + type: string + +jobs: + plugin-check: + runs-on: ubuntu-24.04 + name: PCP Plugin Check + timeout-minutes: 10 + + steps: + # 0. Install WP-CLI (not pre-installed on ubuntu-24.04 runners) + - name: Install WP-CLI + run: | + curl -sS -o /tmp/wp-cli.phar \ + https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar + chmod +x /tmp/wp-cli.phar + sudo mv /tmp/wp-cli.phar /usr/local/bin/wp + wp --info + + # 1. Download the built EmbedPress artifact (contains the plugin zip) + - name: Download Built EmbedPress + uses: actions/download-artifact@v4 + with: + name: ${{ inputs.artifact-name }} + path: ./embedpress-dist + + # 2. Verify the downloaded plugin contents + - name: Verify downloaded plugin contents + run: | + echo "Downloaded artifact contents:" + ls ./embedpress-dist | head -n 15 + + # 3. Start MySQL and create the database + - name: Start Database + run: | + sudo systemctl start mysql + mysql -u root -proot -e "CREATE DATABASE wordpress_test;" + + # 4. Download and configure WordPress (latest) + - name: Install WordPress Core + run: | + wp core download --path=./test-site --allow-root + cd test-site + wp config create --dbname=wordpress_test --dbuser=root --dbpass=root --dbhost=127.0.0.1 --allow-root + + # Enable WP_DEBUG and logging so we can capture PHP fatal errors + wp config set WP_DEBUG true --raw --allow-root + wp config set WP_DEBUG_LOG true --raw --allow-root + wp config set WP_DEBUG_DISPLAY false --raw --allow-root + + wp core install \ + --url=http://localhost:8080 \ + --title="EmbedPress Plugin Check" \ + --admin_user=admin \ + --admin_password=password \ + --admin_email=hurayra@wpdeveloper.com \ + --allow-root + + # 5. Copy the built plugin into the WP plugins directory + - name: Install EmbedPress from built zip + run: | + # The 10up build action uploads the plugin as a zip artifact. + # download-artifact extracts the artifact contents, so embedpress-dist + # will contain the zip file (e.g. embedpress.zip). + ZIP_FILE=$(find ./embedpress-dist -maxdepth 2 -name "*.zip" | head -n 1) + + if [ -n "$ZIP_FILE" ]; then + echo "Found zip: $ZIP_FILE — installing via WP-CLI" + wp plugin install "$(realpath "$ZIP_FILE")" --path=./test-site --allow-root + else + echo "No zip found — treating artifact as an already-extracted directory" + PLUGIN_SRC=$(find ./embedpress-dist -maxdepth 1 -mindepth 1 -type d | head -n 1) + [ -z "$PLUGIN_SRC" ] && PLUGIN_SRC="./embedpress-dist" + mkdir -p ./test-site/wp-content/plugins/embedpress + cp -r "$PLUGIN_SRC/." ./test-site/wp-content/plugins/embedpress/ + fi + + echo "Plugin directory contents:" + ls ./test-site/wp-content/plugins/embedpress | head -n 15 + + # 6. Activate EmbedPress and check for PHP fatal errors + - name: Activate EmbedPress & Check for Fatal Errors + run: | + cd test-site + + # Activate; capture output AND exit status separately + ACTIVATE_OUTPUT=$(wp plugin activate embedpress --allow-root 2>&1) || ACTIVATE_STATUS=$? + echo "$ACTIVATE_OUTPUT" + + # Fail immediately if WP-CLI itself reported an error during activation + if echo "$ACTIVATE_OUTPUT" | grep -qiE "Error:|fatal error|plugin could not be activated"; then + echo "❌ Plugin activation failed:" + echo "$ACTIVATE_OUTPUT" + exit 1 + fi + + # Trigger a full WordPress bootstrap so any lazy-loaded code runs + wp eval 'echo "Bootstrap OK\n";' --allow-root 2>&1 || true + + # Inspect the WP debug log for PHP fatal errors written during activation + DEBUG_LOG="./wp-content/debug.log" + if [ -f "$DEBUG_LOG" ]; then + echo "--- WP Debug Log ---" + cat "$DEBUG_LOG" + echo "--- End Debug Log ---" + + if grep -qiE "PHP Fatal error|PHP Parse error" "$DEBUG_LOG"; then + echo "❌ PHP Fatal/Parse error detected in WP debug log after activation:" + grep -iE "PHP Fatal error|PHP Parse error" "$DEBUG_LOG" + exit 1 + fi + else + echo "ℹ️ No debug.log found (no fatal errors logged)." + fi + + echo "✅ Plugin activated successfully with no PHP fatal errors." + + # 7. Install and activate the Plugin Check plugin from WordPress.org + - name: Install Plugin Check Plugin + run: | + cd test-site + wp plugin install plugin-check --activate --allow-root + + # 8. Run Plugin Check against EmbedPress + # NOTE: We are only checking errors for now. + # We will also address warnings once all errors are resolved. + - name: Run Plugin Check + run: | + cd test-site + + # Redirect full output to a file — errors can be large (thousands of lines) + wp plugin check embedpress --ignore-warnings --allow-root 2>&1 | tee /tmp/pcp-output.txt || true + + # Pass only if the output contains the exact success message + if grep -qF "Success: Checks complete. No errors found." /tmp/pcp-output.txt; then + echo "✅ Plugin Check passed — no errors found." + else + echo "❌ Plugin Check found errors:" + echo "------------------------------------------------------------" + cat /tmp/pcp-output.txt + echo "------------------------------------------------------------" + exit 1 + fi \ No newline at end of file diff --git a/.github/workflows/php-syntax-check.yml b/.github/workflows/php-syntax-check.yml new file mode 100644 index 00000000..aadb9ceb --- /dev/null +++ b/.github/workflows/php-syntax-check.yml @@ -0,0 +1,49 @@ +# Reusable workflow: runs `php -l` on every PHP source file across a matrix +# of all supported PHP versions. Catches parse errors before any runtime +# testing. No artifact needed — only requires a source checkout. Runs in +# parallel with the build job in qa.yml. + +name: QA - PHP Syntax Check + +on: + workflow_dispatch: + workflow_call: + +jobs: + php-syntax-check: + runs-on: ubuntu-24.04 + strategy: + fail-fast: false + matrix: + php-version: ["7.4", "8.2", "8.5"] + name: PHP ${{ matrix.php-version }} Syntax Check + steps: + - uses: actions/checkout@v4 + + - name: Setup PHP ${{ matrix.php-version }} + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php-version }} + + - name: PHP Syntax Check (PHP ${{ matrix.php-version }}) + run: | + FILES=$(find . -name "*.php" \ + -not -path "./vendor/*" \ + -not -path "./node_modules/*" \ + -not -path "./.git/*") + + ERRORS=0 + while IFS= read -r file; do + OUTPUT=$(php -l "$file" 2>&1) + if [ $? -ne 0 ]; then + echo "::error file=$file::$OUTPUT" + ERRORS=$((ERRORS + 1)) + fi + done <<< "$FILES" + + TOTAL=$(echo "$FILES" | wc -l | tr -d ' ') + if [ "$ERRORS" -gt 0 ]; then + echo "::error::PHP syntax errors found in $ERRORS / $TOTAL file(s) on PHP ${{ matrix.php-version }}" + exit 1 + fi + echo "✅ All $TOTAL PHP files passed syntax check on PHP ${{ matrix.php-version }}" \ No newline at end of file diff --git a/.github/workflows/plugin-check.yml b/.github/workflows/plugin-check.yml deleted file mode 100644 index e0897913..00000000 --- a/.github/workflows/plugin-check.yml +++ /dev/null @@ -1,94 +0,0 @@ -name: QA - Plugin Check (PCP) - -on: - workflow_dispatch: # Manual trigger - # push: - # branches: ["main"] - -env: - FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true - -jobs: - # 1. Build the plugin zip using the existing dist-archive workflow - build: - uses: ./.github/workflows/dist-archive.yml - - plugin-check: - needs: build - runs-on: ubuntu-latest - name: Plugin Check - WP Latest / PHP 8.4 - - steps: - # 2. Setup PHP 8.4 + WP-CLI - - name: Setup PHP Runtime - uses: shivammathur/setup-php@v2 - with: - php-version: "8.4" - extensions: mysqli, mbstring, xml, gd - tools: wp-cli - - # 3. Download the built EmbedPress zip artifact - - name: Download Built EmbedPress - uses: actions/download-artifact@v4 - with: - name: ${{ needs.build.outputs.artifact-name }} - path: ./embedpress-dist - - # 4. Start MySQL and create the database - - name: Start Database - run: | - sudo systemctl start mysql - mysql -u root -proot -e "CREATE DATABASE wordpress_test;" - - # 5. Download and configure WordPress (latest) - - name: Install WordPress Core - run: | - wp core download --path=./test-site --allow-root - cd test-site - wp config create --dbname=wordpress_test --dbuser=root --dbpass=root --dbhost=127.0.0.1 --allow-root - wp core install \ - --url=http://localhost:8080 \ - --title="EmbedPress Plugin Check" \ - --admin_user=admin \ - --admin_password=password \ - --admin_email=test@example.com \ - --allow-root - - # 6. Install and activate EmbedPress from the built dist zip - - name: Install and Activate EmbedPress - run: | - mkdir -p ./test-site/wp-content/plugins/embedpress - cp -r ./embedpress-dist/embedpress/. ./test-site/wp-content/plugins/embedpress/ - - echo "Plugin directory contents:" - ls ./test-site/wp-content/plugins/embedpress | head -n 15 - - cd test-site - wp plugin activate embedpress --allow-root - - # 7. Install and activate the Plugin Check plugin from WordPress.org - - name: Install Plugin Check Plugin - run: | - cd test-site - wp plugin install plugin-check --activate --allow-root - - # 8. Run Plugin Check against EmbedPress - # NOTE: We are only checking errors for now. - # We will also address warnings once all errors are resolved. - - name: Run Plugin Check - run: | - cd test-site - - # Redirect full output to a file — errors can be large (thousands of lines) - wp plugin check embedpress --ignore-warnings --allow-root 2>&1 | tee /tmp/pcp-output.txt || true - - # Pass only if the output contains the exact success message - if grep -qF "Success: Checks complete. No errors found." /tmp/pcp-output.txt; then - echo "✅ Plugin Check passed — no errors found." - else - echo "❌ Plugin Check found errors:" - echo "------------------------------------------------------------" - cat /tmp/pcp-output.txt - echo "------------------------------------------------------------" - exit 1 - fi diff --git a/.github/workflows/plugin-version-verification.yml b/.github/workflows/plugin-version-verification.yml new file mode 100644 index 00000000..6e68d5c7 --- /dev/null +++ b/.github/workflows/plugin-version-verification.yml @@ -0,0 +1,38 @@ +# Reusable workflow: verifies that the version string is identical across +# embedpress.php (plugin header), includes/Plugin.php ($version property), +# and readme.txt (Stable tag, if the file exists). Fast, no server required +# — runs in parallel with the build job in qa.yml. + +name: QA - Plugin Version Verification + +on: + workflow_dispatch: + workflow_call: + +jobs: + version-check: + runs-on: ubuntu-24.04 + name: Version Consistency Check + steps: + - uses: actions/checkout@v4 + + - name: Check all version numbers are consistent + run: | + # Extract each version string from its canonical location + V_HEADER=$(grep -oP "^\s*\*\s*Version:\s*\K[\d.]+" embedpress.php | head -1) + V_CONST=$(grep -oP "define\('EMBEDPRESS_VERSION',\s*\"?\K[\d.]+" includes.php | head -1) + V_PLG=$(grep -oP "define\('EMBEDPRESS_PLUGIN_VERSION',\s*'?\K[\d.]+" embedpress.php | head -1) + V_README=$(grep -oP "Stable tag:\s*\K[\d.]+" readme.txt | head -1) + + echo "Plugin header (Version:): $V_HEADER" + echo "EMBEDPRESS_VERSION (includes): $V_CONST" + echo "EMBEDPRESS_PLUGIN_VERSION (main): $V_PLG" + echo "readme.txt Stable tag: $V_README" + + MISMATCH=0 + [ "$V_HEADER" != "$V_CONST" ] && echo "::error::MISMATCH: Plugin header ($V_HEADER) ≠ EMBEDPRESS_VERSION ($V_CONST)" && MISMATCH=1 + [ "$V_HEADER" != "$V_PLG" ] && echo "::error::MISMATCH: Plugin header ($V_HEADER) ≠ EMBEDPRESS_PLUGIN_VERSION ($V_PLG)" && MISMATCH=1 + [ "$V_HEADER" != "$V_README" ] && echo "::error::MISMATCH: Plugin header ($V_HEADER) ≠ readme.txt Stable tag ($V_README)" && MISMATCH=1 + [ "$MISMATCH" -eq 1 ] && exit 1 + + echo "✅ All version numbers are consistent: $V_HEADER" \ No newline at end of file diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml new file mode 100644 index 00000000..ef202754 --- /dev/null +++ b/.github/workflows/qa.yml @@ -0,0 +1,35 @@ +# Orchestrator workflow: builds the plugin zip once, then fans out to all QA +# checks in parallel. Version verification and PHP syntax checks run alongside +# the build (no artifact needed). Plugin Check and compatibility tests run +# after the build completes and receive the artifact name via workflow inputs. + +name: QA + +on: + workflow_dispatch: + pull_request: + push: + tags: + - "*" + +jobs: + build: + uses: ./.github/workflows/create-plugin-zip.yml + + plugin-version-check: + uses: ./.github/workflows/plugin-version-verification.yml + + php-syntax-check: + uses: ./.github/workflows/php-syntax-check.yml + + pcp-plugin-check: + needs: build + uses: ./.github/workflows/pcp-plugin-check.yml + with: + artifact-name: ${{ needs.build.outputs.artifact-name }} + + compatibility-test: + needs: [build, plugin-version-check, php-syntax-check] + uses: ./.github/workflows/embedpress-compatibility-test.yml + with: + artifact-name: ${{ needs.build.outputs.artifact-name }} \ No newline at end of file From 8d19d97e6c95aee4b9fc3f90d21d198879b1054e Mon Sep 17 00:00:00 2001 From: Abu Hurayra Date: Tue, 24 Mar 2026 08:29:06 +0600 Subject: [PATCH 2/5] chore: Add `read-all` permissions to all workflows, enable plugin build step, adjust QA workflow triggers and concurrency, and add artifact input to compatibility and PCP checks. --- .github/workflows/create-plugin-zip.yml | 12 +++++++----- .github/workflows/embedpress-compatibility-test.yml | 8 +++++++- .github/workflows/pcp-plugin-check.yml | 8 +++++++- .github/workflows/php-syntax-check.yml | 2 ++ .github/workflows/plugin-version-verification.yml | 2 ++ .github/workflows/qa.yml | 10 ++++++---- 6 files changed, 31 insertions(+), 11 deletions(-) diff --git a/.github/workflows/create-plugin-zip.yml b/.github/workflows/create-plugin-zip.yml index f1710320..bc3919b1 100644 --- a/.github/workflows/create-plugin-zip.yml +++ b/.github/workflows/create-plugin-zip.yml @@ -5,6 +5,8 @@ name: QA - Create Plugin Zip +permissions: read-all + on: workflow_dispatch: # Manual trigger only workflow_call: @@ -24,11 +26,11 @@ jobs: - name: Checkout uses: actions/checkout@v4 - # - name: Build plugin # Remove or modify this step as needed - # run: | - # composer install --no-dev - # npm install - # npm run build + - name: Build plugin + run: | + composer install --no-dev + npm install + npm run build - name: Generate zip id: upload-plugin-artifact diff --git a/.github/workflows/embedpress-compatibility-test.yml b/.github/workflows/embedpress-compatibility-test.yml index 28f34ef5..5715eb3e 100644 --- a/.github/workflows/embedpress-compatibility-test.yml +++ b/.github/workflows/embedpress-compatibility-test.yml @@ -7,8 +7,14 @@ name: QA - EmbedPress Compatibility Testing +permissions: read-all + on: - workflow_dispatch: # Manual trigger + workflow_dispatch: + inputs: + artifact-name: + required: true + type: string workflow_call: inputs: artifact-name: diff --git a/.github/workflows/pcp-plugin-check.yml b/.github/workflows/pcp-plugin-check.yml index dbb9ca77..690f8844 100644 --- a/.github/workflows/pcp-plugin-check.yml +++ b/.github/workflows/pcp-plugin-check.yml @@ -5,8 +5,14 @@ name: QA - PCP Plugin Check +permissions: read-all + on: - workflow_dispatch: # Manual trigger + workflow_dispatch: + inputs: + artifact-name: + required: true + type: string workflow_call: inputs: artifact-name: diff --git a/.github/workflows/php-syntax-check.yml b/.github/workflows/php-syntax-check.yml index aadb9ceb..d82468e7 100644 --- a/.github/workflows/php-syntax-check.yml +++ b/.github/workflows/php-syntax-check.yml @@ -5,6 +5,8 @@ name: QA - PHP Syntax Check +permissions: read-all + on: workflow_dispatch: workflow_call: diff --git a/.github/workflows/plugin-version-verification.yml b/.github/workflows/plugin-version-verification.yml index 6e68d5c7..51fcd081 100644 --- a/.github/workflows/plugin-version-verification.yml +++ b/.github/workflows/plugin-version-verification.yml @@ -5,6 +5,8 @@ name: QA - Plugin Version Verification +permissions: read-all + on: workflow_dispatch: workflow_call: diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index ef202754..2af95071 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -6,11 +6,13 @@ name: QA on: - workflow_dispatch: pull_request: - push: - tags: - - "*" + +permissions: read-all + +concurrency: + group: qa-${{ github.ref }} + cancel-in-progress: true jobs: build: From 1ee0737139e2fd38eee10b56f6b09b57b30998ac Mon Sep 17 00:00:00 2001 From: Abu Hurayra Date: Tue, 24 Mar 2026 08:31:35 +0600 Subject: [PATCH 3/5] feat: enable manual triggering of the QA workflow --- .github/workflows/qa.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index 2af95071..ae6038b6 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -6,6 +6,7 @@ name: QA on: + workflow_dispatch: pull_request: permissions: read-all From 0340df9c6371ece6a04edd1692c1f3ad1c8724e4 Mon Sep 17 00:00:00 2001 From: Abu Hurayra Date: Tue, 24 Mar 2026 08:33:08 +0600 Subject: [PATCH 4/5] ci: comment out plugin build step in workflow. --- .github/workflows/create-plugin-zip.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/create-plugin-zip.yml b/.github/workflows/create-plugin-zip.yml index bc3919b1..4c9eff82 100644 --- a/.github/workflows/create-plugin-zip.yml +++ b/.github/workflows/create-plugin-zip.yml @@ -26,11 +26,11 @@ jobs: - name: Checkout uses: actions/checkout@v4 - - name: Build plugin - run: | - composer install --no-dev - npm install - npm run build + # - name: Build plugin + # run: | + # composer install --no-dev + # npm install + # npm run build - name: Generate zip id: upload-plugin-artifact From 0b96c0b2c1ae3c4e8dd7084bf8b4b828032ac0b1 Mon Sep 17 00:00:00 2001 From: Abu Hurayra Date: Tue, 24 Mar 2026 08:47:42 +0600 Subject: [PATCH 5/5] feat: make `readme.txt` version verification conditional and update version constant descriptions in the plugin version verification workflow. --- .github/workflows/php-syntax-check.yml | 83 ++++++++++++++----- .../workflows/plugin-version-verification.yml | 27 ++++-- 2 files changed, 82 insertions(+), 28 deletions(-) diff --git a/.github/workflows/php-syntax-check.yml b/.github/workflows/php-syntax-check.yml index d82468e7..a90ae1e6 100644 --- a/.github/workflows/php-syntax-check.yml +++ b/.github/workflows/php-syntax-check.yml @@ -1,7 +1,7 @@ -# Reusable workflow: runs `php -l` on every PHP source file across a matrix -# of all supported PHP versions. Catches parse errors before any runtime -# testing. No artifact needed — only requires a source checkout. Runs in -# parallel with the build job in qa.yml. +# Reusable workflow: runs `php -l` on every PHP source file for all supported +# PHP versions in a single job (sequential). Catches parse errors before any +# runtime testing. No artifact needed — only requires a source checkout. +# Single job eliminates per-version runner startup overhead vs. a matrix. name: QA - PHP Syntax Check @@ -14,26 +14,51 @@ on: jobs: php-syntax-check: runs-on: ubuntu-24.04 - strategy: - fail-fast: false - matrix: - php-version: ["7.4", "8.2", "8.5"] - name: PHP ${{ matrix.php-version }} Syntax Check + name: PHP Syntax Check (7.4, 8.2, 8.5) steps: - uses: actions/checkout@v4 - - name: Setup PHP ${{ matrix.php-version }} - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php-version }} - - - name: PHP Syntax Check (PHP ${{ matrix.php-version }}) + - name: Find PHP files + id: find run: | FILES=$(find . -name "*.php" \ -not -path "./vendor/*" \ -not -path "./node_modules/*" \ -not -path "./.git/*") + echo "TOTAL=$(echo "$FILES" | wc -l | tr -d ' ')" >> "$GITHUB_ENV" + # Write file list to a temp file so all steps share it + echo "$FILES" > /tmp/php_files.txt + + # ── PHP 7.4 ──────────────────────────────────────────────────────────── + - name: Setup PHP 7.4 + uses: shivammathur/setup-php@v2 + with: + php-version: "7.4" + + - name: PHP Syntax Check (PHP 7.4) + run: | + ERRORS=0 + while IFS= read -r file; do + OUTPUT=$(php -l "$file" 2>&1) + if [ $? -ne 0 ]; then + echo "::error file=$file::$OUTPUT" + ERRORS=$((ERRORS + 1)) + fi + done < /tmp/php_files.txt + if [ "$ERRORS" -gt 0 ]; then + echo "::error::PHP syntax errors found in $ERRORS / $TOTAL file(s) on PHP 7.4" + exit 1 + fi + echo "✅ All $TOTAL PHP files passed syntax check on PHP 7.4" + # ── PHP 8.2 ──────────────────────────────────────────────────────────── + - name: Setup PHP 8.2 + uses: shivammathur/setup-php@v2 + with: + php-version: "8.2" + + - name: PHP Syntax Check (PHP 8.2) + run: | ERRORS=0 while IFS= read -r file; do OUTPUT=$(php -l "$file" 2>&1) @@ -41,11 +66,31 @@ jobs: echo "::error file=$file::$OUTPUT" ERRORS=$((ERRORS + 1)) fi - done <<< "$FILES" + done < /tmp/php_files.txt + if [ "$ERRORS" -gt 0 ]; then + echo "::error::PHP syntax errors found in $ERRORS / $TOTAL file(s) on PHP 8.2" + exit 1 + fi + echo "✅ All $TOTAL PHP files passed syntax check on PHP 8.2" + + # ── PHP 8.5 ──────────────────────────────────────────────────────────── + - name: Setup PHP 8.5 + uses: shivammathur/setup-php@v2 + with: + php-version: "8.5" - TOTAL=$(echo "$FILES" | wc -l | tr -d ' ') + - name: PHP Syntax Check (PHP 8.5) + run: | + ERRORS=0 + while IFS= read -r file; do + OUTPUT=$(php -l "$file" 2>&1) + if [ $? -ne 0 ]; then + echo "::error file=$file::$OUTPUT" + ERRORS=$((ERRORS + 1)) + fi + done < /tmp/php_files.txt if [ "$ERRORS" -gt 0 ]; then - echo "::error::PHP syntax errors found in $ERRORS / $TOTAL file(s) on PHP ${{ matrix.php-version }}" + echo "::error::PHP syntax errors found in $ERRORS / $TOTAL file(s) on PHP 8.5" exit 1 fi - echo "✅ All $TOTAL PHP files passed syntax check on PHP ${{ matrix.php-version }}" \ No newline at end of file + echo "✅ All $TOTAL PHP files passed syntax check on PHP 8.5" diff --git a/.github/workflows/plugin-version-verification.yml b/.github/workflows/plugin-version-verification.yml index 51fcd081..66fd6d0a 100644 --- a/.github/workflows/plugin-version-verification.yml +++ b/.github/workflows/plugin-version-verification.yml @@ -1,6 +1,7 @@ # Reusable workflow: verifies that the version string is identical across -# embedpress.php (plugin header), includes/Plugin.php ($version property), -# and readme.txt (Stable tag, if the file exists). Fast, no server required +# embedpress.php (plugin header), includes.php (EMBEDPRESS_VERSION constant), +# embedpress.php (EMBEDPRESS_PLUGIN_VERSION constant), and readme.txt +# (Stable tag, checked only if the file exists). Fast, no server required # — runs in parallel with the build job in qa.yml. name: QA - Plugin Version Verification @@ -23,18 +24,26 @@ jobs: # Extract each version string from its canonical location V_HEADER=$(grep -oP "^\s*\*\s*Version:\s*\K[\d.]+" embedpress.php | head -1) V_CONST=$(grep -oP "define\('EMBEDPRESS_VERSION',\s*\"?\K[\d.]+" includes.php | head -1) - V_PLG=$(grep -oP "define\('EMBEDPRESS_PLUGIN_VERSION',\s*'?\K[\d.]+" embedpress.php | head -1) - V_README=$(grep -oP "Stable tag:\s*\K[\d.]+" readme.txt | head -1) + # Anchor to the quoted production string to avoid matching the time() dev-mode line + V_PLG=$(grep -oP "define\('EMBEDPRESS_PLUGIN_VERSION',\s*'\K[\d.]+" embedpress.php | head -1) + # V_PKG=$(grep -oP '"version":\s*"\K[\d.]+' package.json | head -1) echo "Plugin header (Version:): $V_HEADER" echo "EMBEDPRESS_VERSION (includes): $V_CONST" echo "EMBEDPRESS_PLUGIN_VERSION (main): $V_PLG" - echo "readme.txt Stable tag: $V_README" MISMATCH=0 - [ "$V_HEADER" != "$V_CONST" ] && echo "::error::MISMATCH: Plugin header ($V_HEADER) ≠ EMBEDPRESS_VERSION ($V_CONST)" && MISMATCH=1 - [ "$V_HEADER" != "$V_PLG" ] && echo "::error::MISMATCH: Plugin header ($V_HEADER) ≠ EMBEDPRESS_PLUGIN_VERSION ($V_PLG)" && MISMATCH=1 - [ "$V_HEADER" != "$V_README" ] && echo "::error::MISMATCH: Plugin header ($V_HEADER) ≠ readme.txt Stable tag ($V_README)" && MISMATCH=1 + [ "$V_HEADER" != "$V_CONST" ] && echo "::error::MISMATCH: Plugin header ($V_HEADER) ≠ EMBEDPRESS_VERSION ($V_CONST)" && MISMATCH=1 + [ "$V_HEADER" != "$V_PLG" ] && echo "::error::MISMATCH: Plugin header ($V_HEADER) ≠ EMBEDPRESS_PLUGIN_VERSION ($V_PLG)" && MISMATCH=1 + # [ "$V_HEADER" != "$V_PKG" ] && echo "::error::MISMATCH: Plugin header ($V_HEADER) ≠ package.json version ($V_PKG)" && MISMATCH=1 + + # readme.txt is optional — only check if present + if [ -f readme.txt ]; then + V_README=$(grep -oP "Stable tag:\s*\K[\d.]+" readme.txt | head -1) + echo "readme.txt Stable tag: $V_README" + [ "$V_HEADER" != "$V_README" ] && echo "::error::MISMATCH: Plugin header ($V_HEADER) ≠ readme.txt Stable tag ($V_README)" && MISMATCH=1 + fi + [ "$MISMATCH" -eq 1 ] && exit 1 - echo "✅ All version numbers are consistent: $V_HEADER" \ No newline at end of file + echo "✅ All version numbers are consistent: $V_HEADER"