diff --git a/.editorconfig b/.editorconfig index 34ef2fd6f4..1f1ba7e122 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,39 +1,24 @@ +# This file is for unifying the coding style for different editors and IDEs +# editorconfig.org + # WordPress Coding Standards -# https://make.wordpress.org/core/handbook/best-practices/coding-standards/ +# https://developer.wordpress.org/coding-standards/wordpress-coding-standards/ root = true [*] charset = utf-8 end_of_line = lf -indent_size = 4 -tab_width = 4 -indent_style = tab insert_final_newline = true trim_trailing_whitespace = true +indent_style = tab -[*.md] -trim_trailing_whitespace = false +[*.{yml,yaml}] indent_style = space indent_size = 2 -[*.txt] +[*.md] trim_trailing_whitespace = false -[*.json] -indent_style = space -indent_size = 2 - -[.*rc] -insert_final_newline = false -indent_style = space -indent_size = 2 - -[*.yml] -insert_final_newline = false -quote_type = single -indent_style = space -indent_size = 2 - -[.github/CODEOWNERS] -indent_style = space +[*.txt] +end_of_line = crlf diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 7e6228d65a..d654cca54e 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,31 +1,31 @@ version: 2 updates: - - package-ecosystem: github-actions - directory: '/' - schedule: - interval: weekly - open-pull-requests-limit: 10 - labels: - - "no milestone" - - "[Type] Enhancement" - - "github_actions" + - package-ecosystem: github-actions + directory: '/' + schedule: + interval: weekly + open-pull-requests-limit: 10 + labels: + - 'no milestone' + - '[Type] Enhancement' + - 'github_actions' - - package-ecosystem: npm - directory: '/' - schedule: - interval: weekly - open-pull-requests-limit: 10 - labels: - - "no milestone" - - "[Type] Enhancement" - - "javascript" + - package-ecosystem: npm + directory: '/' + schedule: + interval: weekly + open-pull-requests-limit: 10 + labels: + - 'no milestone' + - '[Type] Enhancement' + - 'javascript' - - package-ecosystem: composer - directory: '/' - schedule: - interval: weekly - open-pull-requests-limit: 10 - labels: - - "no milestone" - - "[Type] Enhancement" - - "php" + - package-ecosystem: composer + directory: '/' + schedule: + interval: weekly + open-pull-requests-limit: 10 + labels: + - 'no milestone' + - '[Type] Enhancement' + - 'php' diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 3f8bbc4b6d..008c5580d6 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -3,42 +3,42 @@ name: CodeQL # Cancel previous workflow run groups that have not completed. concurrency: - # Group workflow runs by workflow name, along with the head branch ref of the pull request - # or otherwise the branch or tag ref. - group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.ref }} - cancel-in-progress: true + # Group workflow runs by workflow name, along with the head branch ref of the pull request + # or otherwise the branch or tag ref. + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.ref }} + cancel-in-progress: true # Disable permissions for all available scopes. # Enable permissions for specific scopes as needed on job level. permissions: {} on: - push: - # Only run if JS files changed. - paths: - - '**.js' - branches: - - trunk - - 'release/**' - pull_request: - # Only run if JS files changed. - paths: - - '**.js' + push: + # Only run if JS files changed. + paths: + - '**.js' + branches: + - trunk + - 'release/**' + pull_request: + # Only run if JS files changed. + paths: + - '**.js' jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - permissions: - security-events: write - steps: - - name: Checkout - uses: actions/checkout@v4 + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + security-events: write + steps: + - name: Checkout + uses: actions/checkout@v4 - - name: Initialize CodeQL - uses: github/codeql-action/init@v3 - with: - languages: javascript + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: javascript - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/deploy-plugins.yml b/.github/workflows/deploy-plugins.yml index 7a3c286d39..1033b3234e 100644 --- a/.github/workflows/deploy-plugins.yml +++ b/.github/workflows/deploy-plugins.yml @@ -2,203 +2,203 @@ name: Deploy Standalone Plugin(s) to WordPress.org on: - release: - types: - - published - workflow_dispatch: - inputs: - plugin: - type: string - description: 'The slug of the plugin to deploy' - required: true - dry-run: - type: boolean - description: 'Debug mode (run without publishing).' - default: false + release: + types: + - published + workflow_dispatch: + inputs: + plugin: + type: string + description: 'The slug of the plugin to deploy' + required: true + dry-run: + type: boolean + description: 'Debug mode (run without publishing).' + default: false permissions: {} jobs: - pre-run: - name: Pre-run - runs-on: ubuntu-latest - outputs: - matrix: ${{ steps.set-matrix.outputs.plugins }} - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Set matrix - id: set-matrix - run: | - PLUGINS=$(jq -r '.plugins' plugins.json) - if ${{ github.event_name == 'workflow_dispatch' }}; then - SLUG=${{ inputs.plugin }} - if echo $PLUGINS | jq -e '.[] | select(. == "'$SLUG'")' > /dev/null; then - PLUGINS="[ \"$SLUG\" ]" - else - echo "::error::The plugin $SLUG is not in the list of plugins to deploy." - exit 1 - fi - fi - - # Set the matrix. - echo "::notice::Deploying the following plugins: $(echo ${PLUGINS[@]})" - echo "plugins=$(echo $PLUGINS | jq -c .)" >> $GITHUB_OUTPUT - - deploy: - name: "Deploy Plugin: ${{ matrix.plugin }}" - needs: pre-run - runs-on: ubuntu-latest - permissions: - actions: write - deployments: write - strategy: - matrix: - plugin: ${{ fromJSON(needs.pre-run.outputs.matrix) }} - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup Node.js (.nvmrc) - uses: actions/setup-node@v4 - with: - node-version-file: '.nvmrc' - cache: npm - - - name: Install npm dependencies - run: npm ci - - - name: Check plugin versions - run: npm run versions -- --plugin=${{ matrix.plugin }} - - - name: Build plugin - run: npm run build:plugin:${{ matrix.plugin }} - - - name: Set plugin version - working-directory: ./build - run: | - echo "PLUGIN_VERSION=$(jq -r '."${{ matrix.plugin }}"' manifest.json)" >> $GITHUB_ENV - - - name: Check if deployment is needed - id: check-deployment - run: | - PLUGIN_VERSION_WPORG=$(curl -sSL https://api.wordpress.org/plugins/info/1.0/${{ matrix.plugin }}.json --retry 3 --retry-delay 5 --retry-all-errors --fail | jq -r '.version') - - echo "::debug::The ${{ matrix.plugin }} plugin is currently at version $PLUGIN_VERSION_WPORG on WordPress.org." - - # Bail if the plugin version is not found. - if [ -z "$PLUGIN_VERSION_WPORG" ]; then - echo "::error::Could not retrieve ${{ matrix.plugin }} information from WordPress.org. The plugin may not exist or the API may be down." - exit 1 - fi - - # Bail if the plugin is already up to date. - if [ "$PLUGIN_VERSION_WPORG" = "$PLUGIN_VERSION" ]; then - echo "::notice::The ${{ matrix.plugin }} plugin is already up to date on WordPress.org. Halting deployment." - exit 0 - fi - - echo "deploy=true" >> $GITHUB_OUTPUT - - - name: Create zip file - if: steps.check-deployment.outputs.deploy == 'true' - run: | - mkdir -p ./build/dist - cd ./build/${{ matrix.plugin }} - zip -r ../dist/${{ matrix.plugin }}.zip . - - - name: Generate checksum - if: steps.check-deployment.outputs.deploy == 'true' - working-directory: ./build/dist - run: | - mkdir -p $RUNNER_TEMP/plugin-checksums - find . -type f -print0 | sort -z | xargs -r0 shasum -a 256 -b | sed 's# \*\./# *#' > $RUNNER_TEMP/plugin-checksums/checksums.txt - shasum -a 256 -U -c $RUNNER_TEMP/plugin-checksums/checksums.txt - cat $RUNNER_TEMP/plugin-checksums/checksums.txt | while read sum file; do echo "$sum $file" > ${file#\*}.sha256; done - - - name: Upload artifact - if: steps.check-deployment.outputs.deploy == 'true' - uses: actions/upload-artifact@v4 - with: - name: ${{ matrix.plugin }} - path: ./build/dist - - - name: Start deployment - if: steps.check-deployment.outputs.deploy == 'true' - uses: bobheadxi/deployments@v1 - id: wporg-deployment - with: - step: start - token: ${{ secrets.GITHUB_TOKEN }} - env: "wp.org plugin: ${{ matrix.plugin }}" - - - name: Deploy Plugin - ${{ matrix.plugin }} - if: steps.check-deployment.outputs.deploy == 'true' - uses: 10up/action-wordpress-plugin-deploy@stable - with: - dry-run: ${{ github.event_name == 'workflow_dispatch' && inputs.dry-run || false }} - env: - SLUG: ${{ matrix.plugin }} - VERSION: ${{ env.PLUGIN_VERSION }} - SVN_USERNAME: ${{ secrets.SVN_USERNAME }} - SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }} - BUILD_DIR: ./build/${{ matrix.plugin }} - ASSETS_DIR: ./plugins/${{ matrix.plugin }}/.wordpress-org - - - name: Finish deployment - if: ${{ steps.wporg-deployment.outputs.deployment_id && always() }} - uses: bobheadxi/deployments@v1 - with: - step: finish - token: ${{ secrets.GITHUB_TOKEN }} - status: ${{ job.status }} - deployment_id: ${{ steps.wporg-deployment.outputs.deployment_id }} - env: "wp.org plugin: ${{ matrix.plugin }}" - env_url: "https://wordpress.org/plugins/${{ matrix.plugin }}/" - - release-assets: - name: Add release assets - needs: [ pre-run, deploy ] - runs-on: ubuntu-latest - permissions: - actions: read - contents: write - if: github.event_name == 'release' - strategy: - matrix: - plugin: ${{ fromJSON(needs.pre-run.outputs.matrix) }} - steps: - - name: Check artifact existence - id: artifact-existence - uses: actions/github-script@v7 - with: - script: | - const getArtifact = await github.request('GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts{?name}', { - owner: context.repo.owner, - repo: context.repo.repo, - run_id: context.runId, - name: "${{ matrix.plugin }}" - }); - - if (getArtifact.status !== 200) { - throw new Error(`Invalid response from GitHub API: ${getArtifact.status}`); - } - - core.setOutput('exists', getArtifact.data.artifacts.length > 0); - core.debug(`Artifact for ${{ matrix.plugin }} exists: ${core.getInput('exists')} ? "true" : "false"`); - - - name: Download artifact - if: steps.artifact-existence.outputs.exists == 'true' - uses: actions/download-artifact@v4 - with: - name: ${{ matrix.plugin }} - path: ./build/dist - - - name: Upload release assets - if: steps.artifact-existence.outputs.exists == 'true' - uses: softprops/action-gh-release@v2 - with: - files: | - ./build/dist/${{ matrix.plugin }}.zip - ./build/dist/${{ matrix.plugin }}.zip.sha256 + pre-run: + name: Pre-run + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.set-matrix.outputs.plugins }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set matrix + id: set-matrix + run: | + PLUGINS=$(jq -r '.plugins' plugins.json) + if ${{ github.event_name == 'workflow_dispatch' }}; then + SLUG=${{ inputs.plugin }} + if echo $PLUGINS | jq -e '.[] | select(. == "'$SLUG'")' > /dev/null; then + PLUGINS="[ \"$SLUG\" ]" + else + echo "::error::The plugin $SLUG is not in the list of plugins to deploy." + exit 1 + fi + fi + + # Set the matrix. + echo "::notice::Deploying the following plugins: $(echo ${PLUGINS[@]})" + echo "plugins=$(echo $PLUGINS | jq -c .)" >> $GITHUB_OUTPUT + + deploy: + name: 'Deploy Plugin: ${{ matrix.plugin }}' + needs: pre-run + runs-on: ubuntu-latest + permissions: + actions: write + deployments: write + strategy: + matrix: + plugin: ${{ fromJSON(needs.pre-run.outputs.matrix) }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Node.js (.nvmrc) + uses: actions/setup-node@v4 + with: + node-version-file: '.nvmrc' + cache: npm + + - name: Install npm dependencies + run: npm ci + + - name: Check plugin versions + run: npm run versions -- --plugin=${{ matrix.plugin }} + + - name: Build plugin + run: npm run build:plugin:${{ matrix.plugin }} + + - name: Set plugin version + working-directory: ./build + run: | + echo "PLUGIN_VERSION=$(jq -r '."${{ matrix.plugin }}"' manifest.json)" >> $GITHUB_ENV + + - name: Check if deployment is needed + id: check-deployment + run: | + PLUGIN_VERSION_WPORG=$(curl -sSL https://api.wordpress.org/plugins/info/1.0/${{ matrix.plugin }}.json --retry 3 --retry-delay 5 --retry-all-errors --fail | jq -r '.version') + + echo "::debug::The ${{ matrix.plugin }} plugin is currently at version $PLUGIN_VERSION_WPORG on WordPress.org." + + # Bail if the plugin version is not found. + if [ -z "$PLUGIN_VERSION_WPORG" ]; then + echo "::error::Could not retrieve ${{ matrix.plugin }} information from WordPress.org. The plugin may not exist or the API may be down." + exit 1 + fi + + # Bail if the plugin is already up to date. + if [ "$PLUGIN_VERSION_WPORG" = "$PLUGIN_VERSION" ]; then + echo "::notice::The ${{ matrix.plugin }} plugin is already up to date on WordPress.org. Halting deployment." + exit 0 + fi + + echo "deploy=true" >> $GITHUB_OUTPUT + + - name: Create zip file + if: steps.check-deployment.outputs.deploy == 'true' + run: | + mkdir -p ./build/dist + cd ./build/${{ matrix.plugin }} + zip -r ../dist/${{ matrix.plugin }}.zip . + + - name: Generate checksum + if: steps.check-deployment.outputs.deploy == 'true' + working-directory: ./build/dist + run: | + mkdir -p $RUNNER_TEMP/plugin-checksums + find . -type f -print0 | sort -z | xargs -r0 shasum -a 256 -b | sed 's# \*\./# *#' > $RUNNER_TEMP/plugin-checksums/checksums.txt + shasum -a 256 -U -c $RUNNER_TEMP/plugin-checksums/checksums.txt + cat $RUNNER_TEMP/plugin-checksums/checksums.txt | while read sum file; do echo "$sum $file" > ${file#\*}.sha256; done + + - name: Upload artifact + if: steps.check-deployment.outputs.deploy == 'true' + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.plugin }} + path: ./build/dist + + - name: Start deployment + if: steps.check-deployment.outputs.deploy == 'true' + uses: bobheadxi/deployments@v1 + id: wporg-deployment + with: + step: start + token: ${{ secrets.GITHUB_TOKEN }} + env: 'wp.org plugin: ${{ matrix.plugin }}' + + - name: Deploy Plugin - ${{ matrix.plugin }} + if: steps.check-deployment.outputs.deploy == 'true' + uses: 10up/action-wordpress-plugin-deploy@stable + with: + dry-run: ${{ github.event_name == 'workflow_dispatch' && inputs.dry-run || false }} + env: + SLUG: ${{ matrix.plugin }} + VERSION: ${{ env.PLUGIN_VERSION }} + SVN_USERNAME: ${{ secrets.SVN_USERNAME }} + SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }} + BUILD_DIR: ./build/${{ matrix.plugin }} + ASSETS_DIR: ./plugins/${{ matrix.plugin }}/.wordpress-org + + - name: Finish deployment + if: ${{ steps.wporg-deployment.outputs.deployment_id && always() }} + uses: bobheadxi/deployments@v1 + with: + step: finish + token: ${{ secrets.GITHUB_TOKEN }} + status: ${{ job.status }} + deployment_id: ${{ steps.wporg-deployment.outputs.deployment_id }} + env: 'wp.org plugin: ${{ matrix.plugin }}' + env_url: 'https://wordpress.org/plugins/${{ matrix.plugin }}/' + + release-assets: + name: Add release assets + needs: [pre-run, deploy] + runs-on: ubuntu-latest + permissions: + actions: read + contents: write + if: github.event_name == 'release' + strategy: + matrix: + plugin: ${{ fromJSON(needs.pre-run.outputs.matrix) }} + steps: + - name: Check artifact existence + id: artifact-existence + uses: actions/github-script@v7 + with: + script: | + const getArtifact = await github.request('GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts{?name}', { + owner: context.repo.owner, + repo: context.repo.repo, + run_id: context.runId, + name: "${{ matrix.plugin }}" + }); + + if (getArtifact.status !== 200) { + throw new Error(`Invalid response from GitHub API: ${getArtifact.status}`); + } + + core.setOutput('exists', getArtifact.data.artifacts.length > 0); + core.debug(`Artifact for ${{ matrix.plugin }} exists: ${core.getInput('exists')} ? "true" : "false"`); + + - name: Download artifact + if: steps.artifact-existence.outputs.exists == 'true' + uses: actions/download-artifact@v4 + with: + name: ${{ matrix.plugin }} + path: ./build/dist + + - name: Upload release assets + if: steps.artifact-existence.outputs.exists == 'true' + uses: softprops/action-gh-release@v2 + with: + files: | + ./build/dist/${{ matrix.plugin }}.zip + ./build/dist/${{ matrix.plugin }}.zip.sha256 diff --git a/.github/workflows/js-lint.yml b/.github/workflows/js-lint.yml index 365d32b9d6..545a95cdaa 100644 --- a/.github/workflows/js-lint.yml +++ b/.github/workflows/js-lint.yml @@ -1,52 +1,52 @@ name: JS Code Linting on: - push: - branches: - - trunk - - 'release/**' - # Only run if JS/JSON/Lint/NVM files changed. - paths: - - '.github/workflows/js-lint.yml' - - '**.js' - - '**.json' - - '.eslint*' - - '.nvmrc' - - '.wp-env.json' - - '**/package.json' - - 'package-lock.json' - pull_request: - # Only run if JS/JSON/Lint/NVM files changed. - paths: - - '.github/workflows/js-lint.yml' - - '**.js' - - '**.json' - - '.eslint*' - - '.nvmrc' - - '.wp-env.json' - - '**/package.json' - - 'package-lock.json' - types: - - opened - - reopened - - synchronize + push: + branches: + - trunk + - 'release/**' + # Only run if JS/JSON/Lint/NVM files changed. + paths: + - '.github/workflows/js-lint.yml' + - '**.js' + - '**.json' + - '.eslint*' + - '.nvmrc' + - '.wp-env.json' + - '**/package.json' + - 'package-lock.json' + pull_request: + # Only run if JS/JSON/Lint/NVM files changed. + paths: + - '.github/workflows/js-lint.yml' + - '**.js' + - '**.json' + - '.eslint*' + - '.nvmrc' + - '.wp-env.json' + - '**/package.json' + - 'package-lock.json' + types: + - opened + - reopened + - synchronize jobs: - js-lint: - name: JS Lint - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: styfle/cancel-workflow-action@0.12.1 - - uses: actions/checkout@v4 - - name: Setup Node.js (via .nvmrc) - uses: actions/setup-node@v4 - with: - node-version-file: '.nvmrc' - cache: npm - - name: npm install - run: npm ci - - name: JS Lint - run: npm run lint-js - - name: TypeScript compile - run: npm run tsc + js-lint: + name: JS Lint + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - uses: styfle/cancel-workflow-action@0.12.1 + - uses: actions/checkout@v4 + - name: Setup Node.js (via .nvmrc) + uses: actions/setup-node@v4 + with: + node-version-file: '.nvmrc' + cache: npm + - name: npm install + run: npm ci + - name: JS Lint + run: npm run lint-js + - name: TypeScript compile + run: npm run tsc diff --git a/.github/workflows/php-lint.yml b/.github/workflows/php-lint.yml index 187c61607c..5121c56301 100644 --- a/.github/workflows/php-lint.yml +++ b/.github/workflows/php-lint.yml @@ -1,58 +1,58 @@ name: Code Linting on: - push: - branches: - - trunk - - 'release/**' - # Only run if PHP-related files changed. - paths: - - '.github/workflows/php-lint.yml' - - '**.php' - - 'phpcs.xml.dist' - - 'phpstan.neon.dist' - - 'composer.json' - - 'composer.lock' - pull_request: - # Only run if PHP-related files changed. - paths: - - '.github/workflows/php-lint.yml' - - '**.php' - - 'phpcs.xml.dist' - - 'phpstan.neon.dist' - - 'composer.json' - - 'composer.lock' - types: - - opened - - reopened - - synchronize + push: + branches: + - trunk + - 'release/**' + # Only run if PHP-related files changed. + paths: + - '.github/workflows/php-lint.yml' + - '**.php' + - 'phpcs.xml.dist' + - 'phpstan.neon.dist' + - 'composer.json' + - 'composer.lock' + pull_request: + # Only run if PHP-related files changed. + paths: + - '.github/workflows/php-lint.yml' + - '**.php' + - 'phpcs.xml.dist' + - 'phpstan.neon.dist' + - 'composer.json' + - 'composer.lock' + types: + - opened + - reopened + - synchronize jobs: - php-lint: - name: PHP - runs-on: ubuntu-latest - timeout-minutes: 20 - steps: - - uses: styfle/cancel-workflow-action@0.12.1 - - uses: actions/checkout@v4 - - uses: shivammathur/setup-php@v2 - with: - php-version: latest - - name: Get Composer Cache Directory - id: composer-cache - run: | - echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - uses: actions/cache@v4 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: | - ${{ runner.os }}-composer- - - name: Validate Composer configuration - run: composer validate --strict - - name: Composer Install - run: composer install --no-interaction --no-progress - - name: PHP Lint - run: composer lint:all - - name: PHPStan - run: composer phpstan + php-lint: + name: PHP + runs-on: ubuntu-latest + timeout-minutes: 20 + steps: + - uses: styfle/cancel-workflow-action@0.12.1 + - uses: actions/checkout@v4 + - uses: shivammathur/setup-php@v2 + with: + php-version: latest + - name: Get Composer Cache Directory + id: composer-cache + run: | + echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + - uses: actions/cache@v4 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-composer- + - name: Validate Composer configuration + run: composer validate --strict + - name: Composer Install + run: composer install --no-interaction --no-progress + - name: PHP Lint + run: composer lint:all + - name: PHPStan + run: composer phpstan diff --git a/.github/workflows/php-test-plugins.yml b/.github/workflows/php-test-plugins.yml index 3594515140..797b02362f 100644 --- a/.github/workflows/php-test-plugins.yml +++ b/.github/workflows/php-test-plugins.yml @@ -1,105 +1,105 @@ name: Unit Testing for Plugins on: - push: - branches: - - trunk - - 'release/**' - # Only run if PHP-related files changed. - paths: - - '.github/workflows/php-test-plugins.yml' - - 'plugins/**.php' - - '.wp-env.json' - - '**/package.json' - - 'package-lock.json' - - 'phpunit.xml.dist' - - 'tests/multisite.xml' - - 'composer.json' - - 'composer.lock' - pull_request: - # Only run if PHP-related files changed. - paths: - - '.github/workflows/php-test-plugins.yml' - - 'plugins/**.php' - - '.wp-env.json' - - '**/package.json' - - 'package-lock.json' - - 'phpunit.xml.dist' - - 'tests/multisite.xml' - - 'composer.json' - - 'composer.lock' - types: - - opened - - reopened - - synchronize + push: + branches: + - trunk + - 'release/**' + # Only run if PHP-related files changed. + paths: + - '.github/workflows/php-test-plugins.yml' + - 'plugins/**.php' + - '.wp-env.json' + - '**/package.json' + - 'package-lock.json' + - 'phpunit.xml.dist' + - 'tests/multisite.xml' + - 'composer.json' + - 'composer.lock' + pull_request: + # Only run if PHP-related files changed. + paths: + - '.github/workflows/php-test-plugins.yml' + - 'plugins/**.php' + - '.wp-env.json' + - '**/package.json' + - 'package-lock.json' + - 'phpunit.xml.dist' + - 'tests/multisite.xml' + - 'composer.json' + - 'composer.lock' + types: + - opened + - reopened + - synchronize jobs: - php-test-plugins: - name: "PHP ${{ matrix.php }} / WP ${{ matrix.wp }}" - runs-on: ubuntu-latest - timeout-minutes: 20 - strategy: - fail-fast: false - matrix: - php: ['8.1', '8.0', '7.4', '7.3', '7.2'] - wp: [ 'latest' ] - coverage: [false] - include: - - php: '7.4' - wp: '6.5' - - php: '8.3' - wp: 'trunk' - - php: '8.2' - wp: 'latest' - # coverage: true # TODO: Uncomment once coverage reports are fixed. See . - env: - WP_ENV_PHP_VERSION: ${{ matrix.php }} - WP_ENV_CORE: ${{ matrix.wp == 'trunk' && 'WordPress/WordPress' || format( 'https://wordpress.org/wordpress-{0}.zip', matrix.wp ) }} - steps: - - uses: styfle/cancel-workflow-action@0.12.1 - - uses: actions/checkout@v4 - - name: Setup Node.js (.nvmrc) - uses: actions/setup-node@v4 - with: - node-version-file: '.nvmrc' - cache: npm - - name: npm install - run: npm ci - - name: Build assets - run: npm run build - - name: Install WordPress - run: npm run wp-env start - - name: Composer Install - run: npm run wp-env run tests-cli -- --env-cwd="wp-content/plugins/$(basename $(pwd))" composer install --no-interaction --no-progress - - name: Running single site unit tests - run: | - if [ "${{ matrix.coverage }}" == "true" ]; then - npm run test-php -- --coverage-clover=coverage-${{ github.sha }}.xml - else - npm run test-php - fi - - name: Running multisite unit tests - run: | - if [ "${{ matrix.coverage }}" == "true" ]; then - npm run test-php-multisite -- --coverage-clover=coverage-multisite-${{ github.sha }}.xml - else - npm run test-php-multisite - fi - - name: Upload single site coverage reports to Codecov - if: ${{ matrix.coverage == true }} - uses: codecov/codecov-action@v5 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: coverage-${{ github.sha }}.xml - flags: single - name: ${{ matrix.php }}-single-site-coverage - fail_ci_if_error: true - - name: Upload multisite coverage reports to Codecov - if: ${{ matrix.coverage == true }} - uses: codecov/codecov-action@v5 - with: - token: ${{ secrets.CODECOV_TOKEN }} - files: coverage-multisite-${{ github.sha }}.xml - flags: multisite - name: ${{ matrix.php }}-multisite-coverage - fail_ci_if_error: true + php-test-plugins: + name: 'PHP ${{ matrix.php }} / WP ${{ matrix.wp }}' + runs-on: ubuntu-latest + timeout-minutes: 20 + strategy: + fail-fast: false + matrix: + php: ['8.1', '8.0', '7.4', '7.3', '7.2'] + wp: ['latest'] + coverage: [false] + include: + - php: '7.4' + wp: '6.5' + - php: '8.3' + wp: 'trunk' + - php: '8.2' + wp: 'latest' + # coverage: true # TODO: Uncomment once coverage reports are fixed. See . + env: + WP_ENV_PHP_VERSION: ${{ matrix.php }} + WP_ENV_CORE: ${{ matrix.wp == 'trunk' && 'WordPress/WordPress' || format( 'https://wordpress.org/wordpress-{0}.zip', matrix.wp ) }} + steps: + - uses: styfle/cancel-workflow-action@0.12.1 + - uses: actions/checkout@v4 + - name: Setup Node.js (.nvmrc) + uses: actions/setup-node@v4 + with: + node-version-file: '.nvmrc' + cache: npm + - name: npm install + run: npm ci + - name: Build assets + run: npm run build + - name: Install WordPress + run: npm run wp-env start + - name: Composer Install + run: npm run wp-env run tests-cli -- --env-cwd="wp-content/plugins/$(basename $(pwd))" composer install --no-interaction --no-progress + - name: Running single site unit tests + run: | + if [ "${{ matrix.coverage }}" == "true" ]; then + npm run test-php -- --coverage-clover=coverage-${{ github.sha }}.xml + else + npm run test-php + fi + - name: Running multisite unit tests + run: | + if [ "${{ matrix.coverage }}" == "true" ]; then + npm run test-php-multisite -- --coverage-clover=coverage-multisite-${{ github.sha }}.xml + else + npm run test-php-multisite + fi + - name: Upload single site coverage reports to Codecov + if: ${{ matrix.coverage == true }} + uses: codecov/codecov-action@v5 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: coverage-${{ github.sha }}.xml + flags: single + name: ${{ matrix.php }}-single-site-coverage + fail_ci_if_error: true + - name: Upload multisite coverage reports to Codecov + if: ${{ matrix.coverage == true }} + uses: codecov/codecov-action@v5 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: coverage-multisite-${{ github.sha }}.xml + flags: multisite + name: ${{ matrix.php }}-multisite-coverage + fail_ci_if_error: true diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/pr-validation.yml index 6cd330de83..c4c6ed5389 100644 --- a/.github/workflows/pr-validation.yml +++ b/.github/workflows/pr-validation.yml @@ -1,32 +1,32 @@ name: Pull Request Validation on: - pull_request: - branches: - - trunk - - 'release/**' - - 'feature/**' - types: - - labeled - - unlabeled - - opened - - reopened - - synchronize - - edited + pull_request: + branches: + - trunk + - 'release/**' + - 'feature/**' + types: + - labeled + - unlabeled + - opened + - reopened + - synchronize + - edited env: - LABELS: ${{ join( github.event.pull_request.labels.*.name, ' ' ) }} + LABELS: ${{ join( github.event.pull_request.labels.*.name, ' ' ) }} jobs: - check-type-label: - name: Check [Type] Label - runs-on: ubuntu-latest - steps: - - if: contains( env.LABELS, '[Type]' ) == false - run: exit 1 - check-milestone: - name: Check Milestone - runs-on: ubuntu-latest - steps: - - if: github.event.pull_request.milestone == null && contains( env.LABELS, 'no milestone' ) == false - run: exit 1 + check-type-label: + name: Check [Type] Label + runs-on: ubuntu-latest + steps: + - if: contains( env.LABELS, '[Type]' ) == false + run: exit 1 + check-milestone: + name: Check Milestone + runs-on: ubuntu-latest + steps: + - if: github.event.pull_request.milestone == null && contains( env.LABELS, 'no milestone' ) == false + run: exit 1 diff --git a/.github/workflows/props-bot.yml b/.github/workflows/props-bot.yml index 806ca19583..0f21f47ef1 100644 --- a/.github/workflows/props-bot.yml +++ b/.github/workflows/props-bot.yml @@ -1,88 +1,88 @@ name: Props Bot on: - # This event runs anytime a PR is (re)opened, updated, marked ready for review, or labeled. - # GitHub does not allow filtering the `labeled` event by a specific label. - # However, the logic below will short-circuit the workflow when the `props-bot` label is not the one being added. - # Note: The pull_request_target event is used instead of pull_request because this workflow needs permission to comment - # on the pull request. Because this event grants extra permissions to `GITHUB_TOKEN`, any code changes within the PR - # should be considered untrusted. See https://securitylab.github.com/research/github-actions-preventing-pwn-requests/. - pull_request_target: - types: - - opened - - synchronize - - reopened - - labeled - - ready_for_review - # This event runs anytime a comment is added or deleted. - # You cannot filter this event for PR comments only. - # However, the logic below does short-circuit the workflow for issues. - issue_comment: - type: - - created - # This event will run everytime a new PR review is initially submitted. - pull_request_review: - types: - - submitted - # This event runs anytime a PR review comment is created or deleted. - pull_request_review_comment: - types: - - created + # This event runs anytime a PR is (re)opened, updated, marked ready for review, or labeled. + # GitHub does not allow filtering the `labeled` event by a specific label. + # However, the logic below will short-circuit the workflow when the `props-bot` label is not the one being added. + # Note: The pull_request_target event is used instead of pull_request because this workflow needs permission to comment + # on the pull request. Because this event grants extra permissions to `GITHUB_TOKEN`, any code changes within the PR + # should be considered untrusted. See https://securitylab.github.com/research/github-actions-preventing-pwn-requests/. + pull_request_target: + types: + - opened + - synchronize + - reopened + - labeled + - ready_for_review + # This event runs anytime a comment is added or deleted. + # You cannot filter this event for PR comments only. + # However, the logic below does short-circuit the workflow for issues. + issue_comment: + type: + - created + # This event will run everytime a new PR review is initially submitted. + pull_request_review: + types: + - submitted + # This event runs anytime a PR review comment is created or deleted. + pull_request_review_comment: + types: + - created # Cancels all previous workflow runs for pull requests that have not completed. concurrency: - # The concurrency group contains the workflow name and the branch name for pull requests - # or the commit hash for any other events. - group: ${{ github.workflow }}-${{ contains( fromJSON( '["pull_request_target", "pull_request_review", "pull_request_review_comment"]' ), github.event_name ) && github.head_ref || github.sha }} - cancel-in-progress: true + # The concurrency group contains the workflow name and the branch name for pull requests + # or the commit hash for any other events. + group: ${{ github.workflow }}-${{ contains( fromJSON( '["pull_request_target", "pull_request_review", "pull_request_review_comment"]' ), github.event_name ) && github.head_ref || github.sha }} + cancel-in-progress: true # Disable permissions for all available scopes by default. # Any needed permissions should be configured at the job level. permissions: {} jobs: - # Compiles a list of props for a pull request. - # - # Performs the following steps: - # - Collects a list of contributor props and leaves a comment. - # - Removes the props-bot label, if necessary. - props-bot: - name: Generate a list of props - runs-on: ubuntu-latest - permissions: - # The action needs permission `write` permission for PRs in order to add a comment. - pull-requests: write - contents: read - timeout-minutes: 20 - # The job will run when pull requests are open, ready for review and: + # Compiles a list of props for a pull request. # - # - A comment is added to the pull request. - # - A review is created or commented on. - # - The pull request is opened, synchronized, marked ready for review, or reopened. - # - The `props-bot` label is added to the pull request. - if: | - ( - github.event_name == 'issue_comment' && github.event.issue.pull_request || - contains( fromJSON( '["pull_request_review", "pull_request_review_comment"]' ), github.event_name ) || - github.event_name == 'pull_request_target' && github.event.action != 'labeled' || - 'props-bot' == github.event.label.name - ) && - ( ! github.event.pull_request.draft && github.event.pull_request.state == 'open' || ! github.event.issue.draft && github.event.issue.state == 'open' ) + # Performs the following steps: + # - Collects a list of contributor props and leaves a comment. + # - Removes the props-bot label, if necessary. + props-bot: + name: Generate a list of props + runs-on: ubuntu-latest + permissions: + # The action needs permission `write` permission for PRs in order to add a comment. + pull-requests: write + contents: read + timeout-minutes: 20 + # The job will run when pull requests are open, ready for review and: + # + # - A comment is added to the pull request. + # - A review is created or commented on. + # - The pull request is opened, synchronized, marked ready for review, or reopened. + # - The `props-bot` label is added to the pull request. + if: | + ( + github.event_name == 'issue_comment' && github.event.issue.pull_request || + contains( fromJSON( '["pull_request_review", "pull_request_review_comment"]' ), github.event_name ) || + github.event_name == 'pull_request_target' && github.event.action != 'labeled' || + 'props-bot' == github.event.label.name + ) && + ( ! github.event.pull_request.draft && github.event.pull_request.state == 'open' || ! github.event.issue.draft && github.event.issue.state == 'open' ) - steps: - - name: Gather a list of contributors - uses: WordPress/props-bot-action@trunk + steps: + - name: Gather a list of contributors + uses: WordPress/props-bot-action@trunk - - name: Remove the props-bot label - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 - if: ${{ github.event.action == 'labeled' && 'props-bot' == github.event.label.name }} - with: - retries: 2 - retry-exempt-status-codes: 418 - script: | - github.rest.issues.removeLabel({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: '${{ github.event.number }}', - name: 'props-bot' - }); + - name: Remove the props-bot label + uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + if: ${{ github.event.action == 'labeled' && 'props-bot' == github.event.label.name }} + with: + retries: 2 + retry-exempt-status-codes: 418 + script: | + github.rest.issues.removeLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: '${{ github.event.number }}', + name: 'props-bot' + }); diff --git a/.github/workflows/spell-check.yml b/.github/workflows/spell-check.yml index 701b4fbfdd..4b1784d198 100644 --- a/.github/workflows/spell-check.yml +++ b/.github/workflows/spell-check.yml @@ -3,12 +3,12 @@ name: Spell Check on: [pull_request] jobs: - spell-checker: - name: Spell Check with Typos - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Search for misspellings - uses: crate-ci/typos@master - with: - config: ./.github/typos.toml + spell-checker: + name: Spell Check with Typos + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Search for misspellings + uses: crate-ci/typos@master + with: + config: ./.github/typos.toml diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000000..8061c69ade --- /dev/null +++ b/.prettierignore @@ -0,0 +1,14 @@ +# Files and folders related to build +/build +/node_modules +/vendor +/dist + +# Minified files +/*.min.js + +# Ignore Composer lock file +composer.lock + +# Ignore npm package lock file +package-lock.json diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 235376574a..0000000000 --- a/.prettierrc +++ /dev/null @@ -1 +0,0 @@ -"@wordpress/prettier-config" diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000000..6061cf693d --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,7 @@ +// Import the default config file and expose it in the project root. +// Useful for editor integrations. +const wpPrettierConfig = require( '@wordpress/prettier-config' ); + +module.exports = { + ...wpPrettierConfig, +}; diff --git a/.wp-env.json b/.wp-env.json index 2c652e636f..9e5d6dec6a 100644 --- a/.wp-env.json +++ b/.wp-env.json @@ -1,24 +1,24 @@ { - "core": null, - "plugins": [ - "./plugins/optimization-detective", - "./plugins/auto-sizes", - "./plugins/dominant-color-images", - "./plugins/embed-optimizer", - "./plugins/image-prioritizer", - "./plugins/performance-lab", - "./plugins/speculation-rules", - "./plugins/web-worker-offloading", - "./plugins/webp-uploads" - ], - "env": { - "tests": { - "config": { - "FS_METHOD": "direct" - }, - "mappings": { - "/wp-content/plugins/performance": "." - } - } - } + "core": null, + "plugins": [ + "./plugins/optimization-detective", + "./plugins/auto-sizes", + "./plugins/dominant-color-images", + "./plugins/embed-optimizer", + "./plugins/image-prioritizer", + "./plugins/performance-lab", + "./plugins/speculation-rules", + "./plugins/web-worker-offloading", + "./plugins/webp-uploads" + ], + "env": { + "tests": { + "config": { + "FS_METHOD": "direct" + }, + "mappings": { + "/wp-content/plugins/performance": "." + } + } + } } diff --git a/codecov.yml b/codecov.yml index 94ce322661..e18753db29 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,15 +1,15 @@ codecov: - notify: - require_ci_to_pass: yes + notify: + require_ci_to_pass: yes coverage: - status: - project: - default: - target: auto - threshold: 80% - base: auto - informational: true - patch: - default: - threshold: 80% - informational: true + status: + project: + default: + target: auto + threshold: 80% + base: auto + informational: true + patch: + default: + threshold: 80% + informational: true diff --git a/composer.json b/composer.json index 1503fcf405..00f4d7bf3d 100644 --- a/composer.json +++ b/composer.json @@ -1,137 +1,137 @@ { - "name": "wordpress/performance", - "description": "Performance plugin from the WordPress Performance Team, which is a collection of standalone performance features.", - "license": "GPL-2.0-or-later", - "type": "wordpress-plugin", - "keywords": [ - "performance", - "wordpress" - ], - "homepage": "https://wordpress.org/plugins/performance-lab/", - "support": { - "issues": "https://github.com/WordPress/performance/issues" - }, - "require": { - "php": "^7.2 || ^8.0", - "ext-json": "*" - }, - "suggest": { - "ext-imagick": "Required to use Modern Image Format's Dominant_Color_Image_Editor_Imagick class", - "ext-gd": "Required to use Modern Image Format's Dominant_Color_Image_Editor_GD class" - }, - "require-dev": { - "phpcompatibility/php-compatibility": "^9.3", - "phpstan/extension-installer": "^1.3", - "phpstan/phpstan": "^1.11", - "phpstan/phpstan-deprecation-rules": "^1.1", - "phpstan/phpstan-phpunit": "^1.3", - "slevomat/coding-standard": "^8.0", - "squizlabs/php_codesniffer": "^3.9", - "szepeviktor/phpstan-wordpress": "^1.3", - "wp-coding-standards/wpcs": "^3.1", - "wp-phpunit/wp-phpunit": "^6.5", - "yoast/phpunit-polyfills": "^2.0", - "phpstan/php-8-stubs": "^0.4.0", - "phpstan/phpstan-strict-rules": "^1.6" - }, - "config": { - "allow-plugins": { - "dealerdirect/phpcodesniffer-composer-installer": true, - "phpstan/extension-installer": true - }, - "platform": { - "php": "7.2" - } - }, - "scripts": { - "format": "phpcbf --report-summary --report-source", - "format:all": [ - "@format", - "@format:auto-sizes", - "@format:dominant-color-images", - "@format:embed-optimizer", - "@format:image-prioritizer", - "@format:optimization-detective", - "@format:performance-lab", - "@format:speculation-rules", - "@format:web-worker-offloading", - "@format:webp-uploads" - ], - "format:auto-sizes": "@format -- ./plugins/auto-sizes --standard=./plugins/auto-sizes/phpcs.xml.dist", - "format:dominant-color-images": "@format -- ./plugins/dominant-color-images --standard=./plugins/dominant-color-images/phpcs.xml.dist", - "format:embed-optimizer": "@format -- ./plugins/embed-optimizer --standard=./plugins/embed-optimizer/phpcs.xml.dist", - "format:image-prioritizer": "@format -- ./plugins/image-prioritizer --standard=./plugins/image-prioritizer/phpcs.xml.dist", - "format:optimization-detective": "@format -- ./plugins/optimization-detective --standard=./plugins/optimization-detective/phpcs.xml.dist", - "format:performance-lab": "@format -- ./plugins/performance-lab --standard=./plugins/performance-lab/phpcs.xml.dist", - "format:speculation-rules": "@format -- ./plugins/speculation-rules --standard=./plugins/speculation-rules/phpcs.xml.dist", - "format:web-worker-offloading": "@format -- ./plugins/web-worker-offloading --standard=./plugins/web-worker-offloading/phpcs.xml.dist", - "format:webp-uploads": "@format -- ./plugins/webp-uploads --standard=./plugins/webp-uploads/phpcs.xml.dist", - "lint": "phpcs", - "lint:all": [ - "@lint", - "@lint:auto-sizes", - "@lint:dominant-color-images", - "@lint:embed-optimizer", - "@lint:image-prioritizer", - "@lint:optimization-detective", - "@lint:performance-lab", - "@lint:speculation-rules", - "@lint:web-worker-offloading", - "@lint:webp-uploads" - ], - "lint:auto-sizes": "@lint -- ./plugins/auto-sizes --standard=./plugins/auto-sizes/phpcs.xml.dist", - "lint:dominant-color-images": "@lint -- ./plugins/dominant-color-images --standard=./plugins/dominant-color-images/phpcs.xml.dist", - "lint:embed-optimizer": "@lint -- ./plugins/embed-optimizer --standard=./plugins/embed-optimizer/phpcs.xml.dist", - "lint:image-prioritizer": "@lint -- ./plugins/image-prioritizer --standard=./plugins/image-prioritizer/phpcs.xml.dist", - "lint:optimization-detective": "@lint -- ./plugins/optimization-detective --standard=./plugins/optimization-detective/phpcs.xml.dist", - "lint:performance-lab": "@lint -- ./plugins/performance-lab --standard=./plugins/performance-lab/phpcs.xml.dist", - "lint:speculation-rules": "@lint -- ./plugins/speculation-rules --standard=./plugins/speculation-rules/phpcs.xml.dist", - "lint:web-worker-offloading": "@lint -- ./plugins/web-worker-offloading --standard=./plugins/web-worker-offloading/phpcs.xml.dist", - "lint:webp-uploads": "@lint -- ./plugins/webp-uploads --standard=./plugins/webp-uploads/phpcs.xml.dist", - "phpstan": "phpstan analyse --memory-limit=2048M", - "test": "phpunit --strict-coverage", - "test-multisite": [ - "WP_MULTISITE=1 phpunit --exclude-group=ms-excluded" - ], - "test-multisite:plugins": [ - "@test-multisite:auto-sizes", - "@test-multisite:dominant-color-images", - "@test-multisite:embed-optimizer", - "@test-multisite:image-prioritizer", - "@test-multisite:optimization-detective", - "@test-multisite:performance-lab", - "@test-multisite:speculation-rules", - "@test-multisite:web-worker-offloading", - "@test-multisite:webp-uploads" - ], - "test-multisite:auto-sizes": "@test-multisite --verbose --testsuite auto-sizes", - "test-multisite:dominant-color-images": "@test-multisite --verbose --testsuite dominant-color-images", - "test-multisite:embed-optimizer": "@test-multisite --verbose --testsuite embed-optimizer", - "test-multisite:image-prioritizer": "@test-multisite --verbose --testsuite image-prioritizer", - "test-multisite:optimization-detective": "@test-multisite --verbose --testsuite optimization-detective", - "test-multisite:performance-lab": "@test-multisite --verbose --testsuite performance-lab", - "test-multisite:speculation-rules": "@test-multisite --verbose --testsuite speculation-rules", - "test-multisite:web-worker-offloading": "@test-multisite --verbose --testsuite web-worker-offloading", - "test-multisite:webp-uploads": "@test-multisite --verbose --testsuite webp-uploads", - "test:plugins": [ - "@test:auto-sizes", - "@test:dominant-color-images", - "@test:embed-optimizer", - "@test:image-prioritizer", - "@test:optimization-detective", - "@test:performance-lab", - "@test:speculation-rules", - "@test:web-worker-offloading", - "@test:webp-uploads" - ], - "test:auto-sizes": "@test --verbose --testsuite auto-sizes", - "test:dominant-color-images": "@test --verbose --testsuite dominant-color-images", - "test:embed-optimizer": "@test --verbose --testsuite embed-optimizer", - "test:image-prioritizer": "@test --verbose --testsuite image-prioritizer", - "test:optimization-detective": "@test --verbose --testsuite optimization-detective", - "test:performance-lab": "@test --verbose --testsuite performance-lab", - "test:speculation-rules": "@test --verbose --testsuite speculation-rules", - "test:web-worker-offloading": "@test --verbose --testsuite web-worker-offloading", - "test:webp-uploads": "@test --verbose --testsuite webp-uploads" - } + "name": "wordpress/performance", + "description": "Performance plugin from the WordPress Performance Team, which is a collection of standalone performance features.", + "license": "GPL-2.0-or-later", + "type": "wordpress-plugin", + "keywords": [ + "performance", + "wordpress" + ], + "homepage": "https://wordpress.org/plugins/performance-lab/", + "support": { + "issues": "https://github.com/WordPress/performance/issues" + }, + "require": { + "php": "^7.2 || ^8.0", + "ext-json": "*" + }, + "suggest": { + "ext-imagick": "Required to use Modern Image Format's Dominant_Color_Image_Editor_Imagick class", + "ext-gd": "Required to use Modern Image Format's Dominant_Color_Image_Editor_GD class" + }, + "require-dev": { + "phpcompatibility/php-compatibility": "^9.3", + "phpstan/extension-installer": "^1.3", + "phpstan/phpstan": "^1.11", + "phpstan/phpstan-deprecation-rules": "^1.1", + "phpstan/phpstan-phpunit": "^1.3", + "slevomat/coding-standard": "^8.0", + "squizlabs/php_codesniffer": "^3.9", + "szepeviktor/phpstan-wordpress": "^1.3", + "wp-coding-standards/wpcs": "^3.1", + "wp-phpunit/wp-phpunit": "^6.5", + "yoast/phpunit-polyfills": "^2.0", + "phpstan/php-8-stubs": "^0.4.0", + "phpstan/phpstan-strict-rules": "^1.6" + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true, + "phpstan/extension-installer": true + }, + "platform": { + "php": "7.2" + } + }, + "scripts": { + "format": "phpcbf --report-summary --report-source", + "format:all": [ + "@format", + "@format:auto-sizes", + "@format:dominant-color-images", + "@format:embed-optimizer", + "@format:image-prioritizer", + "@format:optimization-detective", + "@format:performance-lab", + "@format:speculation-rules", + "@format:web-worker-offloading", + "@format:webp-uploads" + ], + "format:auto-sizes": "@format -- ./plugins/auto-sizes --standard=./plugins/auto-sizes/phpcs.xml.dist", + "format:dominant-color-images": "@format -- ./plugins/dominant-color-images --standard=./plugins/dominant-color-images/phpcs.xml.dist", + "format:embed-optimizer": "@format -- ./plugins/embed-optimizer --standard=./plugins/embed-optimizer/phpcs.xml.dist", + "format:image-prioritizer": "@format -- ./plugins/image-prioritizer --standard=./plugins/image-prioritizer/phpcs.xml.dist", + "format:optimization-detective": "@format -- ./plugins/optimization-detective --standard=./plugins/optimization-detective/phpcs.xml.dist", + "format:performance-lab": "@format -- ./plugins/performance-lab --standard=./plugins/performance-lab/phpcs.xml.dist", + "format:speculation-rules": "@format -- ./plugins/speculation-rules --standard=./plugins/speculation-rules/phpcs.xml.dist", + "format:web-worker-offloading": "@format -- ./plugins/web-worker-offloading --standard=./plugins/web-worker-offloading/phpcs.xml.dist", + "format:webp-uploads": "@format -- ./plugins/webp-uploads --standard=./plugins/webp-uploads/phpcs.xml.dist", + "lint": "phpcs", + "lint:all": [ + "@lint", + "@lint:auto-sizes", + "@lint:dominant-color-images", + "@lint:embed-optimizer", + "@lint:image-prioritizer", + "@lint:optimization-detective", + "@lint:performance-lab", + "@lint:speculation-rules", + "@lint:web-worker-offloading", + "@lint:webp-uploads" + ], + "lint:auto-sizes": "@lint -- ./plugins/auto-sizes --standard=./plugins/auto-sizes/phpcs.xml.dist", + "lint:dominant-color-images": "@lint -- ./plugins/dominant-color-images --standard=./plugins/dominant-color-images/phpcs.xml.dist", + "lint:embed-optimizer": "@lint -- ./plugins/embed-optimizer --standard=./plugins/embed-optimizer/phpcs.xml.dist", + "lint:image-prioritizer": "@lint -- ./plugins/image-prioritizer --standard=./plugins/image-prioritizer/phpcs.xml.dist", + "lint:optimization-detective": "@lint -- ./plugins/optimization-detective --standard=./plugins/optimization-detective/phpcs.xml.dist", + "lint:performance-lab": "@lint -- ./plugins/performance-lab --standard=./plugins/performance-lab/phpcs.xml.dist", + "lint:speculation-rules": "@lint -- ./plugins/speculation-rules --standard=./plugins/speculation-rules/phpcs.xml.dist", + "lint:web-worker-offloading": "@lint -- ./plugins/web-worker-offloading --standard=./plugins/web-worker-offloading/phpcs.xml.dist", + "lint:webp-uploads": "@lint -- ./plugins/webp-uploads --standard=./plugins/webp-uploads/phpcs.xml.dist", + "phpstan": "phpstan analyse --memory-limit=2048M", + "test": "phpunit --strict-coverage", + "test-multisite": [ + "WP_MULTISITE=1 phpunit --exclude-group=ms-excluded" + ], + "test-multisite:plugins": [ + "@test-multisite:auto-sizes", + "@test-multisite:dominant-color-images", + "@test-multisite:embed-optimizer", + "@test-multisite:image-prioritizer", + "@test-multisite:optimization-detective", + "@test-multisite:performance-lab", + "@test-multisite:speculation-rules", + "@test-multisite:web-worker-offloading", + "@test-multisite:webp-uploads" + ], + "test-multisite:auto-sizes": "@test-multisite --verbose --testsuite auto-sizes", + "test-multisite:dominant-color-images": "@test-multisite --verbose --testsuite dominant-color-images", + "test-multisite:embed-optimizer": "@test-multisite --verbose --testsuite embed-optimizer", + "test-multisite:image-prioritizer": "@test-multisite --verbose --testsuite image-prioritizer", + "test-multisite:optimization-detective": "@test-multisite --verbose --testsuite optimization-detective", + "test-multisite:performance-lab": "@test-multisite --verbose --testsuite performance-lab", + "test-multisite:speculation-rules": "@test-multisite --verbose --testsuite speculation-rules", + "test-multisite:web-worker-offloading": "@test-multisite --verbose --testsuite web-worker-offloading", + "test-multisite:webp-uploads": "@test-multisite --verbose --testsuite webp-uploads", + "test:plugins": [ + "@test:auto-sizes", + "@test:dominant-color-images", + "@test:embed-optimizer", + "@test:image-prioritizer", + "@test:optimization-detective", + "@test:performance-lab", + "@test:speculation-rules", + "@test:web-worker-offloading", + "@test:webp-uploads" + ], + "test:auto-sizes": "@test --verbose --testsuite auto-sizes", + "test:dominant-color-images": "@test --verbose --testsuite dominant-color-images", + "test:embed-optimizer": "@test --verbose --testsuite embed-optimizer", + "test:image-prioritizer": "@test --verbose --testsuite image-prioritizer", + "test:optimization-detective": "@test --verbose --testsuite optimization-detective", + "test:performance-lab": "@test --verbose --testsuite performance-lab", + "test:speculation-rules": "@test --verbose --testsuite speculation-rules", + "test:web-worker-offloading": "@test --verbose --testsuite web-worker-offloading", + "test:webp-uploads": "@test --verbose --testsuite webp-uploads" + } } diff --git a/package.json b/package.json index 453988c59e..f2f9fabe1c 100644 --- a/package.json +++ b/package.json @@ -1,69 +1,69 @@ { - "name": "performance", - "license": "GPL-2.0-or-later", - "repository": "git+https://github.com/WordPress/performance.git", - "engines": { - "node": ">=20.10.0", - "npm": ">=10.2.3" - }, - "dependencies": { - "@builder.io/partytown": "github:westonruter/partytown#add/wp-i18n-workaround", - "web-vitals": "4.2.4" - }, - "devDependencies": { - "@octokit/rest": "^21.0.2", - "@wordpress/env": "^10.12.0", - "@wordpress/prettier-config": "^4.12.0", - "@wordpress/scripts": "^30.5.1", - "commander": "12.1.0", - "copy-webpack-plugin": "^12.0.2", - "fast-glob": "^3.3.2", - "fs-extra": "^11.2.0", - "husky": "^9.1.7", - "lint-staged": "^15.2.10", - "lodash": "4.17.21", - "micromatch": "^4.0.8", - "npm-run-all": "^4.1.5", - "typescript": "^5.6.3", - "webpackbar": "^7.0.0" - }, - "scripts": { - "changelog": "./bin/plugin/cli.js changelog", - "since": "./bin/plugin/cli.js since", - "readme": "./bin/plugin/cli.js readme", - "versions": "./bin/plugin/cli.js versions", - "build": "wp-scripts build", - "build-plugins": "npm-run-all 'build:plugin:*'", - "build-plugins:zip": "npm-run-all 'build:plugin:* --env zip=true'", - "build:plugin:performance-lab": "webpack --mode production --env plugin=performance-lab", - "build:plugin:auto-sizes": "webpack --mode production --env plugin=auto-sizes", - "build:plugin:dominant-color-images": "webpack --mode production --env plugin=dominant-color-images", - "build:plugin:embed-optimizer": "webpack --mode production --env plugin=embed-optimizer", - "build:plugin:image-prioritizer": "webpack --mode production --env plugin=image-prioritizer", - "build:plugin:optimization-detective": "webpack --mode production --env plugin=optimization-detective", - "build:plugin:speculation-rules": "webpack --mode production --env plugin=speculation-rules", - "build:plugin:web-worker-offloading": "webpack --mode production --env plugin=web-worker-offloading", - "build:plugin:webp-uploads": "webpack --mode production --env plugin=webp-uploads", - "generate-pending-release-diffs": "bin/generate-pending-release-diffs.sh", - "format-js": "wp-scripts format", - "lint-js": "wp-scripts lint-js", - "tsc": "tsc", - "format-php": "composer format:all", - "phpstan": "composer phpstan", - "lint-php": "composer lint:all", - "test-php": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test:plugins", - "test-php-watch": "./bin/test-php-watch.sh", - "test-php-multisite": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test-multisite:plugins", - "test-php:performance-lab": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test:performance-lab", - "test-php:auto-sizes": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test:auto-sizes", - "test-php:dominant-color-images": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test:dominant-color-images", - "test-php:embed-optimizer": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test:embed-optimizer", - "test-php:image-prioritizer": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test:image-prioritizer", - "test-php:optimization-detective": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test:optimization-detective", - "test-php:speculation-rules": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test:speculation-rules", - "test-php:web-worker-offloading": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test:web-worker-offloading", - "test-php:webp-uploads": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test:webp-uploads", - "wp-env": "wp-env", - "prepare": "husky" - } + "name": "performance", + "license": "GPL-2.0-or-later", + "repository": "git+https://github.com/WordPress/performance.git", + "engines": { + "node": ">=20.10.0", + "npm": ">=10.2.3" + }, + "dependencies": { + "@builder.io/partytown": "github:westonruter/partytown#add/wp-i18n-workaround", + "web-vitals": "4.2.4" + }, + "devDependencies": { + "@octokit/rest": "^21.0.2", + "@wordpress/env": "^10.12.0", + "@wordpress/prettier-config": "^4.12.0", + "@wordpress/scripts": "^30.5.1", + "commander": "12.1.0", + "copy-webpack-plugin": "^12.0.2", + "fast-glob": "^3.3.2", + "fs-extra": "^11.2.0", + "husky": "^9.1.7", + "lint-staged": "^15.2.10", + "lodash": "4.17.21", + "micromatch": "^4.0.8", + "npm-run-all": "^4.1.5", + "typescript": "^5.6.3", + "webpackbar": "^7.0.0" + }, + "scripts": { + "changelog": "./bin/plugin/cli.js changelog", + "since": "./bin/plugin/cli.js since", + "readme": "./bin/plugin/cli.js readme", + "versions": "./bin/plugin/cli.js versions", + "build": "wp-scripts build", + "build-plugins": "npm-run-all 'build:plugin:*'", + "build-plugins:zip": "npm-run-all 'build:plugin:* --env zip=true'", + "build:plugin:performance-lab": "webpack --mode production --env plugin=performance-lab", + "build:plugin:auto-sizes": "webpack --mode production --env plugin=auto-sizes", + "build:plugin:dominant-color-images": "webpack --mode production --env plugin=dominant-color-images", + "build:plugin:embed-optimizer": "webpack --mode production --env plugin=embed-optimizer", + "build:plugin:image-prioritizer": "webpack --mode production --env plugin=image-prioritizer", + "build:plugin:optimization-detective": "webpack --mode production --env plugin=optimization-detective", + "build:plugin:speculation-rules": "webpack --mode production --env plugin=speculation-rules", + "build:plugin:web-worker-offloading": "webpack --mode production --env plugin=web-worker-offloading", + "build:plugin:webp-uploads": "webpack --mode production --env plugin=webp-uploads", + "generate-pending-release-diffs": "bin/generate-pending-release-diffs.sh", + "format-js": "wp-scripts format", + "lint-js": "wp-scripts lint-js", + "tsc": "tsc", + "format-php": "composer format:all", + "phpstan": "composer phpstan", + "lint-php": "composer lint:all", + "test-php": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test:plugins", + "test-php-watch": "./bin/test-php-watch.sh", + "test-php-multisite": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test-multisite:plugins", + "test-php:performance-lab": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test:performance-lab", + "test-php:auto-sizes": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test:auto-sizes", + "test-php:dominant-color-images": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test:dominant-color-images", + "test-php:embed-optimizer": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test:embed-optimizer", + "test-php:image-prioritizer": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test:image-prioritizer", + "test-php:optimization-detective": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test:optimization-detective", + "test-php:speculation-rules": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test:speculation-rules", + "test-php:web-worker-offloading": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test:web-worker-offloading", + "test-php:webp-uploads": "wp-env run tests-cli --env-cwd=/var/www/html/wp-content/plugins/performance composer test:webp-uploads", + "wp-env": "wp-env", + "prepare": "husky" + } } diff --git a/plugins.json b/plugins.json index 9fa07ba6e7..281e5d3863 100644 --- a/plugins.json +++ b/plugins.json @@ -1,13 +1,13 @@ { - "plugins": [ - "auto-sizes", - "dominant-color-images", - "embed-optimizer", - "image-prioritizer", - "optimization-detective", - "performance-lab", - "speculation-rules", - "web-worker-offloading", - "webp-uploads" - ] + "plugins": [ + "auto-sizes", + "dominant-color-images", + "embed-optimizer", + "image-prioritizer", + "optimization-detective", + "performance-lab", + "speculation-rules", + "web-worker-offloading", + "webp-uploads" + ] } diff --git a/plugins/performance-lab/.wordpress-org/blueprints/blueprint.json b/plugins/performance-lab/.wordpress-org/blueprints/blueprint.json index 01d0ee6f97..9dddee1e20 100644 --- a/plugins/performance-lab/.wordpress-org/blueprints/blueprint.json +++ b/plugins/performance-lab/.wordpress-org/blueprints/blueprint.json @@ -1,24 +1,22 @@ { - "$schema": "https://playground.wordpress.net/blueprint-schema.json", - "landingPage": "\/wp-admin\/admin.php?page=perflab-modules", - "phpExtensionBundles": [ - "kitchen-sink" - ], - "steps": [ - { - "step": "login", - "username": "admin", - "password": "password" - }, - { - "step": "installPlugin", - "pluginZipFile": { - "resource": "wordpress.org\/plugins", - "slug": "performance-lab" - }, - "options": { - "activate": true - } - } - ] + "$schema": "https://playground.wordpress.net/blueprint-schema.json", + "landingPage": "/wp-admin/admin.php?page=perflab-modules", + "phpExtensionBundles": [ "kitchen-sink" ], + "steps": [ + { + "step": "login", + "username": "admin", + "password": "password" + }, + { + "step": "installPlugin", + "pluginZipFile": { + "resource": "wordpress.org/plugins", + "slug": "performance-lab" + }, + "options": { + "activate": true + } + } + ] } diff --git a/tsconfig.json b/tsconfig.json index 137042b518..9c9a169614 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,18 +1,13 @@ { - "compilerOptions": { - "checkJs": true, - "noEmit": true, - "allowJs": true, - "target": "es2020", - "moduleResolution": "node", - "module": "esnext", - "skipLibCheck": true - }, - "include": [ - "plugins/**/*.js", - "plugins/**/*.ts", - ], - "exclude": [ - "plugins/*/build/*" - ] + "compilerOptions": { + "checkJs": true, + "noEmit": true, + "allowJs": true, + "target": "es2020", + "moduleResolution": "node", + "module": "esnext", + "skipLibCheck": true + }, + "include": [ "plugins/**/*.js", "plugins/**/*.ts" ], + "exclude": [ "plugins/*/build/*" ] }