diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 79cc7d8fc98..2f7a7c495e8 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -1,2 +1,5 @@ # Apply Prettier formatting 614e495726bce56983b4c5dc948bac557afb4565 + +# Apply Prettier formatting in .github directory and .md files. +439a249543886306c91aace8a0ab7db2dc70a812 diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 9ea11a6f61b..0d5f4540baa 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,125 +1,125 @@ name: 🐛 Bug report description: Create a report to help us improve. labels: - - Bug + - Bug body: - - type: textarea - attributes: - label: Bug Description - description: Please describe clearly and concisely what the bug is. - validations: - required: true - - - type: textarea - attributes: - label: Expected Behaviour - description: Please describe clearly and concisely what the expected behaviour should be. - validations: - required: true - - - type: textarea - attributes: - label: Screenshots - description: > - Please provide detailed steps on how to reproduce the bug. Provide a URL where the issue can be seen on the - frontend when possible, otherwise go to “View source” in the browser and copy all to paste in a - [Gist](https://gist.github.com/) and share it. - - - type: input - attributes: - label: PHP Version - description: Specify which PHP version the bug occurs on. - placeholder: e.g. 8.1 - validations: - required: false - - - type: input - attributes: - label: Plugin Version - description: Specify which plugin version the bug occurs on. - placeholder: e.g. 2.1.4 - validations: - required: true - - - type: dropdown - attributes: - label: AMP plugin template mode - description: Specify which template mode the bug occurs on. - multiple: true - options: - - Standard - - Transitional - - Reader - validations: - required: true - - - type: input - attributes: - label: WordPress Version - description: If applicable, specify which WordPress version the bug occurs on. - placeholder: e.g. 5.8 - - - type: textarea - attributes: - label: Site Health - description: > - If you would like to, please provide your Site Health information. You can also submit it privately via our - [AMP Plugin Escalations form](https://docs.google.com/forms/d/1JTQmphDlk9YgHpDoFRbHXpkDqv8-QmzTT7MDR4AstyQ). - - - type: input - attributes: - label: Gutenberg Version - description: If applicable, specify which Gutenberg version the bug occurs on. - placeholder: e.g. 11.2.1 - - - type: input - attributes: - label: OS(s) Affected - description: If applicable, specify which operating system(s) are affected. - placeholder: e.g. Windows, Android - - - type: input - attributes: - label: Browser(s) Affected - description: If applicable, specify which browser(s) are affected. - placeholder: e.g. Chrome, Firefox - - - type: input - attributes: - label: Device(s) Affected - description: If applicable, specify which device(s) are affected. - placeholder: e.g. iPhone 12, Pixel 5 - - - type: markdown - attributes: - value: | - --- - _**Do not alter anything below. The following fields will be managed by moderators only.**_ - - - type: textarea - attributes: - label: Acceptance Criteria - description: One or more bullet points for acceptance criteria. - - - type: textarea - attributes: - label: Implementation Brief - description: > - One or more bullet points for how to technically resolve the issue. For significant Implementation Design, - it is ok use a Google document **accessible by anyone**. - - - type: textarea - attributes: - label: QA Testing Instructions - description: One or more bullet points to describe how to test the implementation in QA. - - - type: textarea - attributes: - label: Demo - description: A video or screenshots demoing the implementation. - - - type: textarea - attributes: - label: Changelog Entry - description: One sentence summarizing the PR, to be used in the changelog. + - type: textarea + attributes: + label: Bug Description + description: Please describe clearly and concisely what the bug is. + validations: + required: true + + - type: textarea + attributes: + label: Expected Behaviour + description: Please describe clearly and concisely what the expected behaviour should be. + validations: + required: true + + - type: textarea + attributes: + label: Screenshots + description: > + Please provide detailed steps on how to reproduce the bug. Provide a URL where the issue can be seen on the + frontend when possible, otherwise go to “View source” in the browser and copy all to paste in a + [Gist](https://gist.github.com/) and share it. + + - type: input + attributes: + label: PHP Version + description: Specify which PHP version the bug occurs on. + placeholder: e.g. 8.1 + validations: + required: false + + - type: input + attributes: + label: Plugin Version + description: Specify which plugin version the bug occurs on. + placeholder: e.g. 2.1.4 + validations: + required: true + + - type: dropdown + attributes: + label: AMP plugin template mode + description: Specify which template mode the bug occurs on. + multiple: true + options: + - Standard + - Transitional + - Reader + validations: + required: true + + - type: input + attributes: + label: WordPress Version + description: If applicable, specify which WordPress version the bug occurs on. + placeholder: e.g. 5.8 + + - type: textarea + attributes: + label: Site Health + description: > + If you would like to, please provide your Site Health information. You can also submit it privately via our + [AMP Plugin Escalations form](https://docs.google.com/forms/d/1JTQmphDlk9YgHpDoFRbHXpkDqv8-QmzTT7MDR4AstyQ). + + - type: input + attributes: + label: Gutenberg Version + description: If applicable, specify which Gutenberg version the bug occurs on. + placeholder: e.g. 11.2.1 + + - type: input + attributes: + label: OS(s) Affected + description: If applicable, specify which operating system(s) are affected. + placeholder: e.g. Windows, Android + + - type: input + attributes: + label: Browser(s) Affected + description: If applicable, specify which browser(s) are affected. + placeholder: e.g. Chrome, Firefox + + - type: input + attributes: + label: Device(s) Affected + description: If applicable, specify which device(s) are affected. + placeholder: e.g. iPhone 12, Pixel 5 + + - type: markdown + attributes: + value: | + --- + _**Do not alter anything below. The following fields will be managed by moderators only.**_ + + - type: textarea + attributes: + label: Acceptance Criteria + description: One or more bullet points for acceptance criteria. + + - type: textarea + attributes: + label: Implementation Brief + description: > + One or more bullet points for how to technically resolve the issue. For significant Implementation Design, + it is ok use a Google document **accessible by anyone**. + + - type: textarea + attributes: + label: QA Testing Instructions + description: One or more bullet points to describe how to test the implementation in QA. + + - type: textarea + attributes: + label: Demo + description: A video or screenshots demoing the implementation. + + - type: textarea + attributes: + label: Changelog Entry + description: One sentence summarizing the PR, to be used in the changelog. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index e39bc45f4b2..b123d108c3e 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,11 +1,11 @@ blank_issues_enabled: true contact_links: - - name: ❓ Plugin Support Forum - url: https://wordpress.org/support/plugin/amp/ - about: For plugin usage questions and compatibility issues with other plugins, please use the plugin's support forum. Before opening a new topic, please search the forum for existing topics as someone else has likely reported the issue already. - - name: ℹ️ AMP for WordPress - url: https://amp-wp.org/ - about: Find documentation, a showcase of sites using the official AMP plugin, an ecosystem directory of compatible themes/plugins, and a blog with news on the plugin site. - - name: 📺 Video Series - url: https://www.youtube.com/playlist?list=PLXTOW_XMsIDRGRr5QDffrvND8Qh1RndFb - about: Check out our video series on YouTube for an introduction to the plugin and how you can leverage it on your site. + - name: ❓ Plugin Support Forum + url: https://wordpress.org/support/plugin/amp/ + about: For plugin usage questions and compatibility issues with other plugins, please use the plugin's support forum. Before opening a new topic, please search the forum for existing topics as someone else has likely reported the issue already. + - name: ℹ️ AMP for WordPress + url: https://amp-wp.org/ + about: Find documentation, a showcase of sites using the official AMP plugin, an ecosystem directory of compatible themes/plugins, and a blog with news on the plugin site. + - name: 📺 Video Series + url: https://www.youtube.com/playlist?list=PLXTOW_XMsIDRGRr5QDffrvND8Qh1RndFb + about: Check out our video series on YouTube for an introduction to the plugin and how you can leverage it on your site. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index b7a710abdf5..e88eedf8141 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -1,47 +1,47 @@ name: ✨ Feature request description: Suggest an idea for this project. labels: - - Enhancement + - Enhancement body: - - type: textarea - attributes: - label: Feature Description - description: > - Please describe clear and concisely which problem the feature would solve or which publisher needs - it would address. - validations: - required: true + - type: textarea + attributes: + label: Feature Description + description: > + Please describe clear and concisely which problem the feature would solve or which publisher needs + it would address. + validations: + required: true - - type: markdown - attributes: - value: | - --- - _**Do not alter anything below. The following fields will be managed by moderators only.**_ + - type: markdown + attributes: + value: | + --- + _**Do not alter anything below. The following fields will be managed by moderators only.**_ - - type: textarea - attributes: - label: Acceptance Criteria - description: One or more bullet points for acceptance criteria. + - type: textarea + attributes: + label: Acceptance Criteria + description: One or more bullet points for acceptance criteria. - - type: textarea - attributes: - label: Implementation Brief - description: > - One or more bullet points for how to technically resolve the issue. For significant Implementation Design, - it is ok use a Google document **accessible by anyone**. + - type: textarea + attributes: + label: Implementation Brief + description: > + One or more bullet points for how to technically resolve the issue. For significant Implementation Design, + it is ok use a Google document **accessible by anyone**. - - type: textarea - attributes: - label: QA Testing Instructions - description: One or more bullet points to describe how to test the implementation in QA. + - type: textarea + attributes: + label: QA Testing Instructions + description: One or more bullet points to describe how to test the implementation in QA. - - type: textarea - attributes: - label: Demo - description: A video or screenshots demoing the implementation. + - type: textarea + attributes: + label: Demo + description: A video or screenshots demoing the implementation. - - type: textarea - attributes: - label: Changelog Entry - description: One sentence summarizing the PR, to be used in the changelog. + - type: textarea + attributes: + label: Changelog Entry + description: One sentence summarizing the PR, to be used in the changelog. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 4f08a8ff005..35f0189e241 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,9 +1,10 @@ ## Summary + Fixes # ## Checklist -- [ ] My code is tested and passes existing [tests](https://github.com/ampproject/amp-wp/wiki/Engineering-Guidelines#tests). -- [ ] My code follows the [Engineering Guidelines](https://github.com/ampproject/amp-wp/wiki/Engineering-Guidelines) (updates are often made to the guidelines, check it out periodically). +- [ ] My code is tested and passes existing [tests](https://github.com/ampproject/amp-wp/wiki/Engineering-Guidelines#tests). +- [ ] My code follows the [Engineering Guidelines](https://github.com/ampproject/amp-wp/wiki/Engineering-Guidelines) (updates are often made to the guidelines, check it out periodically). diff --git a/.github/actions/draft-release/.eslintrc b/.github/actions/draft-release/.eslintrc index f7e10048984..b46dd59136e 100644 --- a/.github/actions/draft-release/.eslintrc +++ b/.github/actions/draft-release/.eslintrc @@ -1,23 +1,18 @@ { - "root": true, - "extends": [ - "airbnb", - "prettier" - ], - "env": { - "es6": true, - "node": true - }, - "rules": { - "prettier/prettier": [ - "error", - { - "singleQuote": true, - "printWidth": 120 - } - ] - }, - "plugins": [ - "prettier" - ] + "root": true, + "extends": ["airbnb", "prettier"], + "env": { + "es6": true, + "node": true + }, + "rules": { + "prettier/prettier": [ + "error", + { + "singleQuote": true, + "printWidth": 120 + } + ] + }, + "plugins": ["prettier"] } diff --git a/.github/actions/draft-release/README.md b/.github/actions/draft-release/README.md index f4f317dafbc..1877d63f603 100644 --- a/.github/actions/draft-release/README.md +++ b/.github/actions/draft-release/README.md @@ -19,7 +19,7 @@ The URL for uploading assets to the release. ```yaml uses: ./.github/actions/draft-release env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - milestone: v3.2.1 + milestone: v3.2.1 ``` diff --git a/.github/actions/draft-release/action.yml b/.github/actions/draft-release/action.yml index bde8b1394b3..1ee9b7b5620 100644 --- a/.github/actions/draft-release/action.yml +++ b/.github/actions/draft-release/action.yml @@ -1,15 +1,15 @@ name: 'Draft release' description: 'Drafts a release based on the specified milestone' inputs: - milestone: - description: 'Milestone name' - required: true - release_branch: - description: 'Release branch name' - required: true + milestone: + description: 'Milestone name' + required: true + release_branch: + description: 'Release branch name' + required: true outputs: - asset_upload_url: - description: 'The URL for uploading assets to the release' + asset_upload_url: + description: 'The URL for uploading assets to the release' runs: - using: 'node12' - main: 'dist/index.js' + using: 'node12' + main: 'dist/index.js' diff --git a/.github/actions/draft-release/src/index.js b/.github/actions/draft-release/src/index.js index 3baef3601e8..4f3131a4968 100644 --- a/.github/actions/draft-release/src/index.js +++ b/.github/actions/draft-release/src/index.js @@ -15,16 +15,22 @@ async function main() { } // Get tag name from plugin main PHP file. - const pluginFile = fs.readFileSync(path.resolve(process.cwd(), 'amp.php')).toString(); + const pluginFile = fs + .readFileSync(path.resolve(process.cwd(), 'amp.php')) + .toString(); const matches = /\*\s+Version:\s+(\d+(\.\d+)+-\w+)/.exec(pluginFile); const tagName = matches && matches[1] ? matches[1] : null; if (!tagName) { - throw new Error('Unable to parse Version from plugin bootstrap PHP file.'); + throw new Error( + 'Unable to parse Version from plugin bootstrap PHP file.' + ); } if (!tagName.startsWith(milestone)) { - throw new Error('Milestone mismatch with PHP plugin bootstrap version.'); + throw new Error( + 'Milestone mismatch with PHP plugin bootstrap version.' + ); } // Get target branch. @@ -37,11 +43,15 @@ async function main() { // Generate release changelog. const repo = process.env.GITHUB_REPOSITORY; const token = process.env.GITHUB_TOKEN; - const releaseBody = await new ReleaseChangelog(repo, milestone, token).generate(); + const releaseBody = await new ReleaseChangelog( + repo, + milestone, + token + ).generate(); // Make GitHub release. const { - data: { html_url: htmlUrl, upload_url: assetUploadUrl } + data: { html_url: htmlUrl, upload_url: assetUploadUrl }, } = await makeRelease(tagName, releaseBody, targetBranch); core.info(`Release draft URL: ${htmlUrl}`); diff --git a/.github/actions/draft-release/src/utils/make_release.js b/.github/actions/draft-release/src/utils/make_release.js index bce020e735e..84bcd6108ef 100644 --- a/.github/actions/draft-release/src/utils/make_release.js +++ b/.github/actions/draft-release/src/utils/make_release.js @@ -11,7 +11,7 @@ const makeRelease = async (tagName, body, commitish) => { release = await octokit.rest.repos.getReleaseByTag({ owner, repo, - tag: tagName + tag: tagName, }); } catch (error) { if (error instanceof RequestError && error.status === 404) { @@ -32,12 +32,14 @@ const makeRelease = async (tagName, body, commitish) => { body, draft: true, prerelease: false, - target_commitish: commitish + target_commitish: commitish, }); core.info(`Successfully drafted a release for ${tagName}`); } else { if (release.draft !== true) { - throw new Error(`The ${tagName} release is not a draft. Aborting...`) + throw new Error( + `The ${tagName} release is not a draft. Aborting...` + ); } releaseResponse = await octokit.rest.repos.updateRelease({ @@ -46,7 +48,7 @@ const makeRelease = async (tagName, body, commitish) => { release_id: release.id, tag_name: tagName, name: tagName, - body + body, }); core.info(`Successfully updated the ${tagName} draft release`); } diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 6458f55b2a5..e93aba748b7 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,51 +1,30 @@ version: 2 updates: + # Config for AMP plugin. + - package-ecosystem: composer + directory: '/' + schedule: + interval: weekly + time: '17:00' + timezone: America/Los_Angeles + open-pull-requests-limit: 10 -# Config for AMP plugin. -- package-ecosystem: composer - directory: "/" - schedule: - interval: weekly - time: "17:00" - timezone: America/Los_Angeles - open-pull-requests-limit: 10 + - package-ecosystem: npm + directory: '/' + schedule: + interval: weekly + time: '17:00' + timezone: America/Los_Angeles + open-pull-requests-limit: 10 + ignore: + # Updates are handled via the `gutenberg-packages-update` GHA workflow. + - dependency-name: '@wordpress/*' -- package-ecosystem: npm - directory: "/" - schedule: - interval: weekly - time: "17:00" - timezone: America/Los_Angeles - open-pull-requests-limit: 10 - ignore: - # Cannot upgrade until @wordpress/scripts supports webpack v5. - - dependency-name: postcss-loader - versions: - - ">= 5" - # Cannot be updated at the moment due to an incompatibility with `postcss-preset-env`. See https://github.com/ampproject/amp-wp/pull/5675#issuecomment-769197753. - - dependency-name: postcss-nested - versions: - - "> 5.0.1" - # Cannot upgrade until @wordpress/element supports react v17. - - dependency-name: react - versions: - - ">= 17" - # Cannot upgrade until @wordpress/scripts supports webpack v5. - - dependency-name: terser-webpack-plugin - versions: - - ">= 5" - # Cannot upgrade until @wordpress/scripts supports webpack v5. - - dependency-name: copy-webpack-plugin - versions: - - ">= 7" - # Updates are handled via the `gutenberg-packages-update` GHA workflow. - - dependency-name: "@wordpress/*" - -# Config for GitHub Actions. -- package-ecosystem: github-actions - directory: "/" - schedule: - interval: weekly - time: "17:00" - timezone: America/Los_Angeles - open-pull-requests-limit: 10 + # Config for GitHub Actions. + - package-ecosystem: github-actions + directory: '/' + schedule: + interval: weekly + time: '17:00' + timezone: America/Los_Angeles + open-pull-requests-limit: 10 diff --git a/.github/workflows/auto-merge.yml b/.github/workflows/auto-merge.yml index 1389d5f46e1..6d4c0e318db 100644 --- a/.github/workflows/auto-merge.yml +++ b/.github/workflows/auto-merge.yml @@ -3,40 +3,40 @@ name: Dependabot auto-merge # Only trigger, when the build workflow succeeded, per . on: - workflow_run: - workflows: ["Build, test & measure"] - types: - - completed + workflow_run: + workflows: ['Build, test & measure'] + types: + - completed permissions: - pull-requests: write - contents: write + pull-requests: write + contents: write # Cancel previous workflow run groups that have not completed. concurrency: - # Group workflow runs by workflow name and branch name of pull request. - group: ${{ github.workflow }}-${{ github.head_ref }} - cancel-in-progress: true + # Group workflow runs by workflow name and branch name of pull request. + group: ${{ github.workflow }}-${{ github.head_ref }} + cancel-in-progress: true jobs: - dependabot: - runs-on: ubuntu-latest - if: ${{ github.actor == 'dependabot[bot]' }} - steps: - - name: Dependabot metadata - id: metadata - uses: dependabot/fetch-metadata@v1.3.5 - with: - github-token: "${{ secrets.GITHUB_TOKEN }}" - - name: Enable auto-merge for Dependabot PRs - if: ${{ github.event.pull_request.auto_merge == null && ( steps.metadata.outputs.update-type == 'version-update:semver-patch' || steps.metadata.outputs.update-type == 'version-update:semver-minor' ) }} - run: gh pr merge --auto --merge "$PR_URL" - env: - PR_URL: ${{github.event.pull_request.html_url}} - GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} - - name: Approve PR - run: gh pr review --approve "$PR_URL" - if: ${{ steps.metadata.outputs.update-type == 'version-update:semver-patch' || steps.metadata.outputs.update-type == 'version-update:semver-minor' }} - env: - PR_URL: ${{github.event.pull_request.html_url}} - GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} + dependabot: + runs-on: ubuntu-latest + if: ${{ github.actor == 'dependabot[bot]' }} + steps: + - name: Dependabot metadata + id: metadata + uses: dependabot/fetch-metadata@v1.3.5 + with: + github-token: '${{ secrets.GITHUB_TOKEN }}' + - name: Enable auto-merge for Dependabot PRs + if: ${{ github.event.pull_request.auto_merge == null && ( steps.metadata.outputs.update-type == 'version-update:semver-patch' || steps.metadata.outputs.update-type == 'version-update:semver-minor' ) }} + run: gh pr merge --auto --merge "$PR_URL" + env: + PR_URL: ${{github.event.pull_request.html_url}} + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} + - name: Approve PR + run: gh pr review --approve "$PR_URL" + if: ${{ steps.metadata.outputs.update-type == 'version-update:semver-patch' || steps.metadata.outputs.update-type == 'version-update:semver-minor' }} + env: + PR_URL: ${{github.event.pull_request.html_url}} + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} diff --git a/.github/workflows/build-test-measure.yml b/.github/workflows/build-test-measure.yml index a1abd1b067f..b7f07e31130 100644 --- a/.github/workflows/build-test-measure.yml +++ b/.github/workflows/build-test-measure.yml @@ -1,935 +1,935 @@ name: Build, test & measure on: - push: - branches: - - develop - # Include all release branches. - - '[0-9]+.[0-9]+' - pull_request: - # Run workflow whenever a PR is opened, updated (synchronized), or marked ready for review. - types: [opened, synchronize, ready_for_review] + push: + branches: + - develop + # Include all release branches. + - '[0-9]+.[0-9]+' + pull_request: + # Run workflow whenever a PR is opened, updated (synchronized), or marked ready for review. + types: [opened, synchronize, ready_for_review] # 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 jobs: - pre-run: - name: 'Pre run' - runs-on: ubuntu-latest - outputs: - changed-file-count: ${{ steps.determine-file-counts.outputs.count }} - changed-php-count: ${{ steps.determine-file-counts.outputs.php-count }} - changed-css-count: ${{ steps.determine-file-counts.outputs.css-count }} - changed-js-count: ${{ steps.determine-file-counts.outputs.js-count }} - changed-gha-workflow-count: ${{ steps.determine-file-counts.outputs.gha-workflow-count }} - steps: - - name: Checkout including last 2 commits - # Fetch last 2 commits if it's not a PR, so that we can determine the list of modified files. - if: ${{ github.base_ref == null }} - uses: actions/checkout@v3 - with: - fetch-depth: 2 - - - name: Checkout - # Do usual checkout if it's a PR. - if: ${{ github.base_ref != null }} - uses: actions/checkout@v3 - - - name: Fetch base branch - # Only fetch base ref if it's a PR. - if: ${{ github.base_ref != null }} - run: git fetch --depth=1 --no-tags origin ${{ github.base_ref }} - - - name: Determine modified files for PR - if: ${{ github.base_ref != null }} - run: echo "MODIFIED_FILES=$(git diff --name-only FETCH_HEAD HEAD | base64 -w 0)" >> $GITHUB_ENV - - - name: Determine modified files for commit - if: ${{ github.base_ref == null }} - run: echo "MODIFIED_FILES=$(git diff --name-only HEAD~1 HEAD | base64 -w 0)" >> $GITHUB_ENV - - - id: determine-file-counts - name: Determine if modified files should make the workflow run continue - run: | - MODIFIED_FILES=$(echo "$MODIFIED_FILES" | base64 -d) - echo -e "Modified files:\n$MODIFIED_FILES\n" - - FILE_COUNT=$(php -f bin/determine-modified-files-count.php "$IGNORE_PATH_REGEX" "$MODIFIED_FILES" --invert) - PHP_FILE_COUNT=$(php -f bin/determine-modified-files-count.php ".+\.php|composer\.(json|lock)|phpstan\.neon\.dist" "$MODIFIED_FILES") - CSS_FILE_COUNT=$(php -f bin/determine-modified-files-count.php ".+\.s?css|package\.json|package-lock\.json" "$MODIFIED_FILES") - JS_FILE_COUNT=$(php -f bin/determine-modified-files-count.php ".+\.(js|snap)|package\.json|package-lock\.json" "$MODIFIED_FILES") - GHA_WORKFLOW_COUNT=$(php -f bin/determine-modified-files-count.php "(\.github\/workflows\/.+\.yml)" "$MODIFIED_FILES") - - echo "Changed file count: $FILE_COUNT" - echo "Changed PHP file count: $PHP_FILE_COUNT" - echo "Changed CSS file count: $CSS_FILE_COUNT" - echo "Changed JS file count: $JS_FILE_COUNT" - echo "Changed GHA workflow file count: $GHA_WORKFLOW_COUNT" - - echo "count=$FILE_COUNT" >> $GITHUB_OUTPUT - echo "php-count=$PHP_FILE_COUNT" >> $GITHUB_OUTPUT - echo "css-count=$CSS_FILE_COUNT" >> $GITHUB_OUTPUT - echo "js-count=$JS_FILE_COUNT" >> $GITHUB_OUTPUT - echo "gha-workflow-count=$GHA_WORKFLOW_COUNT" >> $GITHUB_OUTPUT + pre-run: + name: 'Pre run' + runs-on: ubuntu-latest + outputs: + changed-file-count: ${{ steps.determine-file-counts.outputs.count }} + changed-php-count: ${{ steps.determine-file-counts.outputs.php-count }} + changed-css-count: ${{ steps.determine-file-counts.outputs.css-count }} + changed-js-count: ${{ steps.determine-file-counts.outputs.js-count }} + changed-gha-workflow-count: ${{ steps.determine-file-counts.outputs.gha-workflow-count }} + steps: + - name: Checkout including last 2 commits + # Fetch last 2 commits if it's not a PR, so that we can determine the list of modified files. + if: ${{ github.base_ref == null }} + uses: actions/checkout@v3 + with: + fetch-depth: 2 + + - name: Checkout + # Do usual checkout if it's a PR. + if: ${{ github.base_ref != null }} + uses: actions/checkout@v3 + + - name: Fetch base branch + # Only fetch base ref if it's a PR. + if: ${{ github.base_ref != null }} + run: git fetch --depth=1 --no-tags origin ${{ github.base_ref }} + + - name: Determine modified files for PR + if: ${{ github.base_ref != null }} + run: echo "MODIFIED_FILES=$(git diff --name-only FETCH_HEAD HEAD | base64 -w 0)" >> $GITHUB_ENV + + - name: Determine modified files for commit + if: ${{ github.base_ref == null }} + run: echo "MODIFIED_FILES=$(git diff --name-only HEAD~1 HEAD | base64 -w 0)" >> $GITHUB_ENV + + - id: determine-file-counts + name: Determine if modified files should make the workflow run continue + run: | + MODIFIED_FILES=$(echo "$MODIFIED_FILES" | base64 -d) + echo -e "Modified files:\n$MODIFIED_FILES\n" + + FILE_COUNT=$(php -f bin/determine-modified-files-count.php "$IGNORE_PATH_REGEX" "$MODIFIED_FILES" --invert) + PHP_FILE_COUNT=$(php -f bin/determine-modified-files-count.php ".+\.php|composer\.(json|lock)|phpstan\.neon\.dist" "$MODIFIED_FILES") + CSS_FILE_COUNT=$(php -f bin/determine-modified-files-count.php ".+\.s?css|package\.json|package-lock\.json" "$MODIFIED_FILES") + JS_FILE_COUNT=$(php -f bin/determine-modified-files-count.php ".+\.(js|snap)|package\.json|package-lock\.json" "$MODIFIED_FILES") + GHA_WORKFLOW_COUNT=$(php -f bin/determine-modified-files-count.php "(\.github\/workflows\/.+\.yml)" "$MODIFIED_FILES") + + echo "Changed file count: $FILE_COUNT" + echo "Changed PHP file count: $PHP_FILE_COUNT" + echo "Changed CSS file count: $CSS_FILE_COUNT" + echo "Changed JS file count: $JS_FILE_COUNT" + echo "Changed GHA workflow file count: $GHA_WORKFLOW_COUNT" + + echo "count=$FILE_COUNT" >> $GITHUB_OUTPUT + echo "php-count=$PHP_FILE_COUNT" >> $GITHUB_OUTPUT + echo "css-count=$CSS_FILE_COUNT" >> $GITHUB_OUTPUT + echo "js-count=$JS_FILE_COUNT" >> $GITHUB_OUTPUT + echo "gha-workflow-count=$GHA_WORKFLOW_COUNT" >> $GITHUB_OUTPUT + env: + # Ignore Paths: + # - .github/ + # - !.github/workflows + # - .wordpress-org/ + # - docs/ + IGNORE_PATH_REGEX: \.github\/(?!workflows)|\.wordpress-org\/|docs\/ + + lint-css: + needs: pre-run + if: needs.pre-run.outputs.changed-css-count > 0 || needs.pre-run.outputs.changed-gha-workflow-count > 0 + name: 'Lint: CSS' + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup Node + uses: actions/setup-node@v3.6.0 + with: + node-version-file: '.nvmrc' + cache: npm + + - name: Install Node dependencies + run: npm ci + env: + CI: true + + - name: Detect coding standard violations (stylelint) + run: npm run lint:css + + #----------------------------------------------------------------------------------------------------------------------- + + lint-js: + name: 'Lint: JS' + needs: pre-run + if: needs.pre-run.outputs.changed-js-count > 0 || needs.pre-run.outputs.changed-gha-workflow-count > 0 + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup Node + uses: actions/setup-node@v3.6.0 + with: + node-version-file: '.nvmrc' + cache: npm + + - name: Install Node dependencies + run: npm ci + env: + CI: true + + - name: Validate package.json + run: npm run lint:pkg-json + + - name: Detect ESLint coding standard violations + if: > + github.event.pull_request.head.repo.fork == true || + github.event.pull_request.user.login == 'dependabot[bot]' + run: npm run lint:js + + - name: Generate ESLint coding standard violations report + # Prevent generating the ESLint report if PR is from a fork or authored by Dependabot. + if: > + ! ( github.event.pull_request.head.repo.fork == true || + github.event.pull_request.user.login == 'dependabot[bot]' ) + run: npm run lint:js:report + continue-on-error: true + + - name: Annotate code linting results + # The action cannot annotate the PR when run from a PR fork or was authored by Dependabot. + if: > + ! ( github.event.pull_request.head.repo.fork == true || + github.event.pull_request.user.login == 'dependabot[bot]' ) + uses: ataylorme/eslint-annotate-action@1.2.0 + with: + repo-token: '${{ secrets.GITHUB_TOKEN }}' + report-json: 'lint-js-report.json' + + #----------------------------------------------------------------------------------------------------------------------- + + lint-php: + name: 'Lint: PHP' + needs: pre-run + if: needs.pre-run.outputs.changed-php-count > 0 || needs.pre-run.outputs.changed-gha-workflow-count > 0 + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.0' + coverage: none + tools: cs2pr + + - name: Get Composer Cache Directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Configure Composer cache + uses: actions/cache@v3.2.3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-composer- + + - name: Install Composer dependencies + run: composer install --prefer-dist --optimize-autoloader --no-progress --no-interaction + + - name: Validate composer.json + run: composer --no-interaction validate --no-check-all + + - name: Detect coding standard violations (PHPCS) + run: vendor/bin/phpcs -q --report=checkstyle --runtime-set ignore_errors_on_exit 1 --runtime-set ignore_warnings_on_exit 1 | cs2pr --graceful-warnings + + - name: Normalize composer.json + run: | + composer config --no-interaction --no-plugins allow-plugins.ergebnis/composer-normalize true + composer require --no-interaction --dev ergebnis/composer-normalize --ignore-platform-reqs + composer --no-interaction normalize --dry-run + + #----------------------------------------------------------------------------------------------------------------------- + + static-analysis-php: + name: 'Static Analysis: PHP' + runs-on: ubuntu-latest + needs: pre-run + if: needs.pre-run.outputs.changed-php-count > 0 || needs.pre-run.outputs.changed-gha-workflow-count > 0 + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + # phpstan requires PHP 7.1+. + php-version: '8.0' + extensions: dom, iconv, json, libxml, zip + tools: phpstan + + - name: Get Composer Cache Directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Configure Composer cache + uses: actions/cache@v3.2.3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-composer- + + - name: Install Composer dependencies + run: composer install + + - name: Static Analysis (PHPStan) + run: | + phpstan --version + phpstan analyse + + #----------------------------------------------------------------------------------------------------------------------- + + unit-test-js: + name: 'Unit test: JS' + runs-on: ubuntu-latest + needs: pre-run + if: needs.pre-run.outputs.changed-js-count > 0 || needs.pre-run.outputs.changed-gha-workflow-count > 0 + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup Node + uses: actions/setup-node@v3.6.0 + with: + node-version-file: '.nvmrc' + cache: npm + + - name: Setup Jest cache + uses: actions/cache@v3.2.3 + with: + path: ~/.jest-cache + key: ${{ runner.os }}-jest + + - name: Install Node dependencies + run: npm ci + env: + CI: true + + - name: Run unit tests (with coverage) + run: npm run test:js -- --ci --cacheDirectory="$HOME/.jest-cache" --collectCoverage + + - name: Upload code coverage report + uses: codecov/codecov-action@v3 + with: + file: build/logs/lcov.info + flags: javascript + fail_ci_if_error: true + + #----------------------------------------------------------------------------------------------------------------------- + + e2e-test-js: + name: 'E2E test: JS' + needs: pre-run + if: needs.pre-run.outputs.changed-file-count > 0 + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.0' + + - name: Setup Node + uses: actions/setup-node@v3.6.0 + with: + node-version-file: '.nvmrc' + cache: npm + + - name: Get Composer Cache Directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Configure Composer cache + uses: actions/cache@v3.2.3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-composer- + + - name: Install Node dependencies + run: npm ci + env: + CI: true + + - name: Install Composer dependencies + run: composer install --prefer-dist --optimize-autoloader --no-progress --no-interaction + + - name: Build plugin + run: npm run build:js + + - name: Start Docker environment + run: npm run env:start:ci + env: + COMPOSE_INTERACTIVE_NO_CLI: true + + - name: Run E2E tests + run: npm run test:e2e:ci + + - name: Stop Docker environment + run: npm run env:stop:ci + if: always() + env: + COMPOSE_INTERACTIVE_NO_CLI: true + + #----------------------------------------------------------------------------------------------------------------------- + + # Adapted from workflow for running PHP unit tests on google/web-stories-wp. + # See https://github.com/google/web-stories-wp/blob/cb2ebada48039171e25c279bdb27d3712dd70b22/.github/workflows/continuous-integration-unit-php.yml + unit-test-php: + name: "Unit test${{ matrix.coverage && ' (with coverage)' || '' }}: PHP ${{ matrix.php }}, WP ${{ matrix.wp }}" + runs-on: ubuntu-latest + needs: pre-run env: - # Ignore Paths: - # - .github/ - # - !.github/workflows - # - .wordpress-org/ - # - docs/ - IGNORE_PATH_REGEX: \.github\/(?!workflows)|\.wordpress-org\/|docs\/ - - lint-css: - needs: pre-run - if: needs.pre-run.outputs.changed-css-count > 0 || needs.pre-run.outputs.changed-gha-workflow-count > 0 - name: 'Lint: CSS' - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Setup Node - uses: actions/setup-node@v3.6.0 - with: - node-version-file: '.nvmrc' - cache: npm - - - name: Install Node dependencies - run: npm ci - env: - CI: true - - - name: Detect coding standard violations (stylelint) - run: npm run lint:css - -#----------------------------------------------------------------------------------------------------------------------- - - lint-js: - name: 'Lint: JS' - needs: pre-run - if: needs.pre-run.outputs.changed-js-count > 0 || needs.pre-run.outputs.changed-gha-workflow-count > 0 - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Setup Node - uses: actions/setup-node@v3.6.0 - with: - node-version-file: '.nvmrc' - cache: npm - - - name: Install Node dependencies - run: npm ci - env: - CI: true - - - name: Validate package.json - run: npm run lint:pkg-json - - - name: Detect ESLint coding standard violations - if: > - github.event.pull_request.head.repo.fork == true || - github.event.pull_request.user.login == 'dependabot[bot]' - run: npm run lint:js - - - name: Generate ESLint coding standard violations report - # Prevent generating the ESLint report if PR is from a fork or authored by Dependabot. - if: > - ! ( github.event.pull_request.head.repo.fork == true || - github.event.pull_request.user.login == 'dependabot[bot]' ) - run: npm run lint:js:report - continue-on-error: true - - - name: Annotate code linting results - # The action cannot annotate the PR when run from a PR fork or was authored by Dependabot. - if: > - ! ( github.event.pull_request.head.repo.fork == true || - github.event.pull_request.user.login == 'dependabot[bot]' ) - uses: ataylorme/eslint-annotate-action@1.2.0 - with: - repo-token: '${{ secrets.GITHUB_TOKEN }}' - report-json: 'lint-js-report.json' - -#----------------------------------------------------------------------------------------------------------------------- - - lint-php: - name: 'Lint: PHP' - needs: pre-run - if: needs.pre-run.outputs.changed-php-count > 0 || needs.pre-run.outputs.changed-gha-workflow-count > 0 - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: '8.0' - coverage: none - tools: cs2pr - - - name: Get Composer Cache Directory - id: composer-cache - run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - - name: Configure Composer cache - uses: actions/cache@v3.2.3 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: | - ${{ runner.os }}-composer- - - - name: Install Composer dependencies - run: composer install --prefer-dist --optimize-autoloader --no-progress --no-interaction - - - name: Validate composer.json - run: composer --no-interaction validate --no-check-all - - - name: Detect coding standard violations (PHPCS) - run: vendor/bin/phpcs -q --report=checkstyle --runtime-set ignore_errors_on_exit 1 --runtime-set ignore_warnings_on_exit 1 | cs2pr --graceful-warnings - - - name: Normalize composer.json - run: | - composer config --no-interaction --no-plugins allow-plugins.ergebnis/composer-normalize true - composer require --no-interaction --dev ergebnis/composer-normalize --ignore-platform-reqs - composer --no-interaction normalize --dry-run - -#----------------------------------------------------------------------------------------------------------------------- - - static-analysis-php: - name: 'Static Analysis: PHP' - runs-on: ubuntu-latest - needs: pre-run - if: needs.pre-run.outputs.changed-php-count > 0 || needs.pre-run.outputs.changed-gha-workflow-count > 0 - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - # phpstan requires PHP 7.1+. - php-version: '8.0' - extensions: dom, iconv, json, libxml, zip - tools: phpstan - - - name: Get Composer Cache Directory - id: composer-cache - run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - - name: Configure Composer cache - uses: actions/cache@v3.2.3 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: | - ${{ runner.os }}-composer- - - - name: Install Composer dependencies - run: composer install - - - name: Static Analysis (PHPStan) - run: | - phpstan --version - phpstan analyse - -#----------------------------------------------------------------------------------------------------------------------- - - unit-test-js: - name: 'Unit test: JS' - runs-on: ubuntu-latest - needs: pre-run - if: needs.pre-run.outputs.changed-js-count > 0 || needs.pre-run.outputs.changed-gha-workflow-count > 0 - - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Setup Node - uses: actions/setup-node@v3.6.0 - with: - node-version-file: '.nvmrc' - cache: npm - - - name: Setup Jest cache - uses: actions/cache@v3.2.3 - with: - path: ~/.jest-cache - key: ${{ runner.os }}-jest - - - name: Install Node dependencies - run: npm ci - env: - CI: true - - - name: Run unit tests (with coverage) - run: npm run test:js -- --ci --cacheDirectory="$HOME/.jest-cache" --collectCoverage - - - name: Upload code coverage report - uses: codecov/codecov-action@v3 - with: - file: build/logs/lcov.info - flags: javascript - fail_ci_if_error: true - -#----------------------------------------------------------------------------------------------------------------------- - - e2e-test-js: - name: 'E2E test: JS' - needs: pre-run - if: needs.pre-run.outputs.changed-file-count > 0 - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: '8.0' - - - name: Setup Node - uses: actions/setup-node@v3.6.0 - with: - node-version-file: '.nvmrc' - cache: npm - - - name: Get Composer Cache Directory - id: composer-cache - run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - - name: Configure Composer cache - uses: actions/cache@v3.2.3 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: | - ${{ runner.os }}-composer- - - - name: Install Node dependencies - run: npm ci - env: - CI: true - - - name: Install Composer dependencies - run: composer install --prefer-dist --optimize-autoloader --no-progress --no-interaction - - - name: Build plugin - run: npm run build:js - - - name: Start Docker environment - run: npm run env:start:ci - env: - COMPOSE_INTERACTIVE_NO_CLI: true - - - name: Run E2E tests - run: npm run test:e2e:ci - - - name: Stop Docker environment - run: npm run env:stop:ci - if: always() - env: - COMPOSE_INTERACTIVE_NO_CLI: true - -#----------------------------------------------------------------------------------------------------------------------- - - # Adapted from workflow for running PHP unit tests on google/web-stories-wp. - # See https://github.com/google/web-stories-wp/blob/cb2ebada48039171e25c279bdb27d3712dd70b22/.github/workflows/continuous-integration-unit-php.yml - unit-test-php: - name: "Unit test${{ matrix.coverage && ' (with coverage)' || '' }}: PHP ${{ matrix.php }}, WP ${{ matrix.wp }}" - runs-on: ubuntu-latest - needs: pre-run - env: - WP_CORE_DIR: /tmp/wordpress - services: - mysql: - image: mariadb:latest - env: - MYSQL_ALLOW_EMPTY_PASSWORD: true - MYSQL_ROOT_PASSWORD: - MYSQL_DATABASE: wordpress_test - ports: - - 3306 - options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 - continue-on-error: ${{ matrix.experimental == true }} - strategy: - fail-fast: false - matrix: - php: ['8.0'] - wp: ['latest'] - external-http: [false] - install-pwa-plugin: [true] - coverage: [false] - include: - - php: '8.0' - wp: 'trunk' - experimental: true - - - php: '8.1' - wp: 'trunk' - experimental: true - - - php: '8.2' - wp: 'trunk' - experimental: true - - - php: '8.0' - wp: 'latest' - coverage: true - - - php: '8.0' - wp: 'latest' - external-http: true - - - php: '7.4' - wp: 'latest' - - - php: '7.4' - wp: 'latest' - external-http: true - - - php: '7.3' - wp: 'latest' - - - php: '7.2' - wp: 'latest' - - - php: '7.1' - wp: 'latest' - - - php: '7.0' - wp: '5.1' - - - php: '7.0' - wp: '5.0' - - - php: '7.0' - wp: '4.9' - external-http: true - - steps: - # Note: The repeated `needs.pre-run.outputs.changed-php-count > 0` checks would be avoided if a step could short- - # circuit per . The reason why the if statement can't be put on the - # job as a whole is because the name is variable based on the matrix, and if the condition is not met then the - # name won't be interpolated in order to match the required jobs set up in branch protection. - - name: Notice - if: needs.pre-run.outputs.changed-php-count == 0 - run: echo "No PHP files were changed so no PHP unit tests will run" - - - name: Checkout - if: needs.pre-run.outputs.changed-php-count > 0 - uses: actions/checkout@v3 - - - name: Setup PHP - if: needs.pre-run.outputs.changed-php-count > 0 - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - extensions: curl, date, dom, gd, iconv, json, libxml, mysql, spl - coverage: ${{ matrix.coverage && 'xdebug' || 'none' }} - - - name: Shutdown default MySQL service - if: needs.pre-run.outputs.changed-php-count > 0 - run: sudo service mysql stop - - - name: Verify MariaDB connection - if: needs.pre-run.outputs.changed-php-count > 0 - run: | - while ! mysqladmin ping -h"127.0.0.1" -P"${{ job.services.mysql.ports[3306] }}" --silent; do - sleep 1 - done - - - name: Setup Node - if: needs.pre-run.outputs.changed-php-count > 0 - uses: actions/setup-node@v3.6.0 - with: - node-version-file: '.nvmrc' - cache: npm - - - name: Get Composer Cache Directory - if: needs.pre-run.outputs.changed-php-count > 0 - id: composer-cache - run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - - name: Configure Composer cache - if: needs.pre-run.outputs.changed-php-count > 0 - uses: actions/cache@v3.2.3 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: | - ${{ runner.os }}-composer- - - - name: Install Composer dependencies - if: needs.pre-run.outputs.changed-php-count > 0 - run: | - # phpdocumentor/reflection has to be removed as it makes use of an outdated dependency. - composer remove --dev phpdocumentor/reflection - composer install --prefer-dist --ignore-platform-reqs --no-progress --no-interaction - - # See https://github.com/wp-cli/wp-cli/issues/5484 - - name: Remove conflicting Requests library + WP_CORE_DIR: /tmp/wordpress + services: + mysql: + image: mariadb:latest + env: + MYSQL_ALLOW_EMPTY_PASSWORD: true + MYSQL_ROOT_PASSWORD: + MYSQL_DATABASE: wordpress_test + ports: + - 3306 + options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 + continue-on-error: ${{ matrix.experimental == true }} + strategy: + fail-fast: false + matrix: + php: ['8.0'] + wp: ['latest'] + external-http: [false] + install-pwa-plugin: [true] + coverage: [false] + include: + - php: '8.0' + wp: 'trunk' + experimental: true + + - php: '8.1' + wp: 'trunk' + experimental: true + + - php: '8.2' + wp: 'trunk' + experimental: true + + - php: '8.0' + wp: 'latest' + coverage: true + + - php: '8.0' + wp: 'latest' + external-http: true + + - php: '7.4' + wp: 'latest' + + - php: '7.4' + wp: 'latest' + external-http: true + + - php: '7.3' + wp: 'latest' + + - php: '7.2' + wp: 'latest' + + - php: '7.1' + wp: 'latest' + + - php: '7.0' + wp: '5.1' + + - php: '7.0' + wp: '5.0' + + - php: '7.0' + wp: '4.9' + external-http: true + + steps: + # Note: The repeated `needs.pre-run.outputs.changed-php-count > 0` checks would be avoided if a step could short- + # circuit per . The reason why the if statement can't be put on the + # job as a whole is because the name is variable based on the matrix, and if the condition is not met then the + # name won't be interpolated in order to match the required jobs set up in branch protection. + - name: Notice + if: needs.pre-run.outputs.changed-php-count == 0 + run: echo "No PHP files were changed so no PHP unit tests will run" + + - name: Checkout + if: needs.pre-run.outputs.changed-php-count > 0 + uses: actions/checkout@v3 + + - name: Setup PHP + if: needs.pre-run.outputs.changed-php-count > 0 + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: curl, date, dom, gd, iconv, json, libxml, mysql, spl + coverage: ${{ matrix.coverage && 'xdebug' || 'none' }} + + - name: Shutdown default MySQL service + if: needs.pre-run.outputs.changed-php-count > 0 + run: sudo service mysql stop + + - name: Verify MariaDB connection + if: needs.pre-run.outputs.changed-php-count > 0 + run: | + while ! mysqladmin ping -h"127.0.0.1" -P"${{ job.services.mysql.ports[3306] }}" --silent; do + sleep 1 + done + + - name: Setup Node + if: needs.pre-run.outputs.changed-php-count > 0 + uses: actions/setup-node@v3.6.0 + with: + node-version-file: '.nvmrc' + cache: npm + + - name: Get Composer Cache Directory + if: needs.pre-run.outputs.changed-php-count > 0 + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Configure Composer cache + if: needs.pre-run.outputs.changed-php-count > 0 + uses: actions/cache@v3.2.3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-composer- + + - name: Install Composer dependencies + if: needs.pre-run.outputs.changed-php-count > 0 + run: | + # phpdocumentor/reflection has to be removed as it makes use of an outdated dependency. + composer remove --dev phpdocumentor/reflection + composer install --prefer-dist --ignore-platform-reqs --no-progress --no-interaction + + # See https://github.com/wp-cli/wp-cli/issues/5484 + - name: Remove conflicting Requests library + if: needs.pre-run.outputs.changed-php-count > 0 + run: composer remove --dev --ignore-platform-reqs --no-interaction --no-scripts roave/security-advisories wp-cli/export-command wp-cli/extension-command wp-cli/wp-cli wp-cli/wp-cli-tests + + # Installs a different PHPUnit version depending on the WP/PHP version combo we're testing against. + # + # | WP / PHP | PHPUnit | + # |-----------|---------| + # | 5.0 / 7.0 | 6 | + # | 5.7 / 7.1 | 7 | + # | 5.9 / 7.2 | 8 | + # | 5.9 / 7.4 | 9 | + # | * / 8 | 9 | + # + # See https://make.wordpress.org/core/handbook/references/phpunit-compatibility-and-wordpress-versions/ + - name: Update PHPUnit + if: needs.pre-run.outputs.changed-php-count > 0 + run: | + if [[ $PHP_VERSION == "7.1" ]]; then + echo "Installing PHPUnit 7.5.x" + composer require --ignore-platform-reqs --no-interaction --no-scripts phpunit/phpunit:^7.5 --with-dependencies + elif [[ $PHP_VERSION == "7.2" ]]; then + echo "Installing PHPUnit 8.5.x" + composer require --ignore-platform-reqs --no-interaction --no-scripts phpunit/phpunit:^8.5 --with-dependencies + echo "Downgrading phpunit/php-token-stream because the latest version requires PHP 7.3" + composer require --ignore-platform-reqs --no-interaction --no-scripts phpunit/php-token-stream:^3.1.3 --with-dependencies + elif [[ $WP_VERSION == "latest" || $WP_VERSION == "trunk" || $PHP_VERSION == "7.4" ]]; then + echo "Installing latest version of PHPUnit" + composer update --ignore-platform-reqs --no-interaction --no-scripts yoast/phpunit-polyfills --with-dependencies + fi + env: + WP_VERSION: ${{ matrix.wp }} + PHP_VERSION: ${{ matrix.php }} + + - name: Install Node dependencies + if: needs.pre-run.outputs.changed-php-count > 0 + run: npm ci + env: + CI: true + + - name: Build plugin + if: needs.pre-run.outputs.changed-php-count > 0 + run: npm run build:js + + # Scan the logs for failing tests and surface that information by creating annotations and log file decorations. + - name: Setup problem matcher to provide annotations for PHPUnit + if: needs.pre-run.outputs.changed-php-count > 0 + # The JSON file is provided by the `shivammathur/setup-php` action. See https://github.com/shivammathur/setup-php#problem-matchers. + run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" + + - name: Install WP tests + if: needs.pre-run.outputs.changed-php-count > 0 + run: bash bin/ci/install-wp-tests.sh wordpress_test root '' 127.0.0.1:${{ job.services.mysql.ports['3306'] }} ${{ matrix.wp }} true + + - name: Post install of WP tests + if: needs.pre-run.outputs.changed-php-count > 0 + run: bash bin/ci/after-wp-install.sh ${{ matrix.wp }} ${{ matrix.install-pwa-plugin == true }} + + - name: Copy plugin to WP plugins directory + if: needs.pre-run.outputs.changed-php-count > 0 + run: cp -r "$PWD" "$WP_CORE_DIR/src/wp-content/plugins/amp" + + - name: Run tests + if: ${{ matrix.coverage == false && needs.pre-run.outputs.changed-php-count > 0 }} + run: vendor/bin/phpunit --verbose + working-directory: ${{ env.WP_CORE_DIR }}/src/wp-content/plugins/amp + env: + WP_TESTS_DIR: /tmp/wordpress-tests-lib + + - name: Run tests with coverage + if: ${{ matrix.coverage == true && needs.pre-run.outputs.changed-php-count > 0 }} + run: vendor/bin/phpunit --verbose --coverage-clover ${{ env.WP_CORE_DIR }}/src/wp-content/plugins/amp/build/logs/clover.xml + working-directory: ${{ env.WP_CORE_DIR }}/src/wp-content/plugins/amp + env: + WP_TESTS_DIR: /tmp/wordpress-tests-lib + + - name: Run external HTTP tests + if: ${{ matrix.external-http == true && needs.pre-run.outputs.changed-php-count > 0 }} + run: vendor/bin/phpunit --testsuite external-http + working-directory: ${{ env.WP_CORE_DIR }}/src/wp-content/plugins/amp + env: + WP_TESTS_DIR: /tmp/wordpress-tests-lib + + - name: Upload code coverage report + if: ${{ matrix.coverage == true && needs.pre-run.outputs.changed-php-count > 0 }} + uses: codecov/codecov-action@v3 + with: + file: ${{ env.WP_CORE_DIR }}/src/wp-content/plugins/amp/build/logs/clover.xml + flags: php,unit + fail_ci_if_error: true + + #----------------------------------------------------------------------------------------------------------------------- + + unit-test-multisite-php: + name: 'Unit Tests Multisite: PHP 7.4, WP Latest' + needs: pre-run + runs-on: ubuntu-latest if: needs.pre-run.outputs.changed-php-count > 0 - run: composer remove --dev --ignore-platform-reqs --no-interaction --no-scripts roave/security-advisories wp-cli/export-command wp-cli/extension-command wp-cli/wp-cli wp-cli/wp-cli-tests - - # Installs a different PHPUnit version depending on the WP/PHP version combo we're testing against. - # - # | WP / PHP | PHPUnit | - # |-----------|---------| - # | 5.0 / 7.0 | 6 | - # | 5.7 / 7.1 | 7 | - # | 5.9 / 7.2 | 8 | - # | 5.9 / 7.4 | 9 | - # | * / 8 | 9 | - # - # See https://make.wordpress.org/core/handbook/references/phpunit-compatibility-and-wordpress-versions/ - - name: Update PHPUnit + strategy: + matrix: + testsuite: ['default', 'external-http'] + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup Node + uses: actions/setup-node@v3.6.0 + with: + node-version-file: '.nvmrc' + cache: npm + + - name: Get Composer Cache Directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Configure Composer cache + uses: actions/cache@v3.2.3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-composer- + + - name: Install Node dependencies + run: npm ci + env: + CI: true + + - name: Install Composer dependencies + run: | + # phpdocumentor/reflection has to be removed as it makes use of an outdated dependency. + composer remove --dev phpdocumentor/reflection + composer install --prefer-dist --ignore-platform-reqs --no-progress --no-interaction + + # See https://github.com/wp-cli/wp-cli/issues/5484 + - name: Remove conflicting Requests library + run: composer remove --dev --ignore-platform-reqs --no-interaction --no-scripts roave/security-advisories wp-cli/export-command wp-cli/extension-command wp-cli/wp-cli wp-cli/wp-cli-tests + + - name: Update PHPUnit + if: needs.pre-run.outputs.changed-php-count > 0 + run: | + # We are using PHP 7.4 and WP Latest. + echo "Installing latest version of PHPUnit" + composer update --ignore-platform-reqs --no-interaction --no-scripts yoast/phpunit-polyfills --with-dependencies + + - name: Build plugin + run: npm run build:js + + - name: Move amp-wp to amp + run: cp -r "$PWD" "/tmp/amp" + + - name: Start wp-env + working-directory: /tmp/amp + run: npm run wp-env start + + - name: Run multisite unit tests + working-directory: /tmp/amp + run: npm run test:php:multisite ${{ matrix.testsuite == 'external-http' && '-- --testsuite external-http' || '' }} + + #----------------------------------------------------------------------------------------------------------------------- + + feature-test-php: + name: "Feature test${{ matrix.coverage && ' (with coverage)' || '' }}: PHP ${{ matrix.php }}, WP ${{ matrix.wp }}" + needs: pre-run if: needs.pre-run.outputs.changed-php-count > 0 - run: | - if [[ $PHP_VERSION == "7.1" ]]; then - echo "Installing PHPUnit 7.5.x" - composer require --ignore-platform-reqs --no-interaction --no-scripts phpunit/phpunit:^7.5 --with-dependencies - elif [[ $PHP_VERSION == "7.2" ]]; then - echo "Installing PHPUnit 8.5.x" - composer require --ignore-platform-reqs --no-interaction --no-scripts phpunit/phpunit:^8.5 --with-dependencies - echo "Downgrading phpunit/php-token-stream because the latest version requires PHP 7.3" - composer require --ignore-platform-reqs --no-interaction --no-scripts phpunit/php-token-stream:^3.1.3 --with-dependencies - elif [[ $WP_VERSION == "latest" || $WP_VERSION == "trunk" || $PHP_VERSION == "7.4" ]]; then - echo "Installing latest version of PHPUnit" - composer update --ignore-platform-reqs --no-interaction --no-scripts yoast/phpunit-polyfills --with-dependencies - fi + runs-on: ubuntu-latest env: - WP_VERSION: ${{ matrix.wp }} - PHP_VERSION: ${{ matrix.php }} - - - name: Install Node dependencies - if: needs.pre-run.outputs.changed-php-count > 0 - run: npm ci - env: - CI: true - - - name: Build plugin - if: needs.pre-run.outputs.changed-php-count > 0 - run: npm run build:js - - # Scan the logs for failing tests and surface that information by creating annotations and log file decorations. - - name: Setup problem matcher to provide annotations for PHPUnit - if: needs.pre-run.outputs.changed-php-count > 0 - # The JSON file is provided by the `shivammathur/setup-php` action. See https://github.com/shivammathur/setup-php#problem-matchers. - run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" - - - name: Install WP tests - if: needs.pre-run.outputs.changed-php-count > 0 - run: bash bin/ci/install-wp-tests.sh wordpress_test root '' 127.0.0.1:${{ job.services.mysql.ports['3306'] }} ${{ matrix.wp }} true - - - name: Post install of WP tests - if: needs.pre-run.outputs.changed-php-count > 0 - run: bash bin/ci/after-wp-install.sh ${{ matrix.wp }} ${{ matrix.install-pwa-plugin == true }} - - - name: Copy plugin to WP plugins directory - if: needs.pre-run.outputs.changed-php-count > 0 - run: cp -r "$PWD" "$WP_CORE_DIR/src/wp-content/plugins/amp" - - - name: Run tests - if: ${{ matrix.coverage == false && needs.pre-run.outputs.changed-php-count > 0 }} - run: vendor/bin/phpunit --verbose - working-directory: ${{ env.WP_CORE_DIR }}/src/wp-content/plugins/amp - env: - WP_TESTS_DIR: /tmp/wordpress-tests-lib - - - name: Run tests with coverage - if: ${{ matrix.coverage == true && needs.pre-run.outputs.changed-php-count > 0 }} - run: vendor/bin/phpunit --verbose --coverage-clover ${{ env.WP_CORE_DIR }}/src/wp-content/plugins/amp/build/logs/clover.xml - working-directory: ${{ env.WP_CORE_DIR }}/src/wp-content/plugins/amp - env: - WP_TESTS_DIR: /tmp/wordpress-tests-lib - - - name: Run external HTTP tests - if: ${{ matrix.external-http == true && needs.pre-run.outputs.changed-php-count > 0 }} - run: vendor/bin/phpunit --testsuite external-http - working-directory: ${{ env.WP_CORE_DIR }}/src/wp-content/plugins/amp - env: - WP_TESTS_DIR: /tmp/wordpress-tests-lib - - - name: Upload code coverage report - if: ${{ matrix.coverage == true && needs.pre-run.outputs.changed-php-count > 0 }} - uses: codecov/codecov-action@v3 - with: - file: ${{ env.WP_CORE_DIR }}/src/wp-content/plugins/amp/build/logs/clover.xml - flags: php,unit - fail_ci_if_error: true - -#----------------------------------------------------------------------------------------------------------------------- - - unit-test-multisite-php: - name: 'Unit Tests Multisite: PHP 7.4, WP Latest' - needs: pre-run - runs-on: ubuntu-latest - if: needs.pre-run.outputs.changed-php-count > 0 - strategy: - matrix: - testsuite: ['default', 'external-http'] - - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Setup Node - uses: actions/setup-node@v3.6.0 - with: - node-version-file: '.nvmrc' - cache: npm - - - name: Get Composer Cache Directory - id: composer-cache - run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - - name: Configure Composer cache - uses: actions/cache@v3.2.3 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: | - ${{ runner.os }}-composer- - - - name: Install Node dependencies - run: npm ci - env: - CI: true - - - name: Install Composer dependencies - run: | - # phpdocumentor/reflection has to be removed as it makes use of an outdated dependency. - composer remove --dev phpdocumentor/reflection - composer install --prefer-dist --ignore-platform-reqs --no-progress --no-interaction - - # See https://github.com/wp-cli/wp-cli/issues/5484 - - name: Remove conflicting Requests library - run: composer remove --dev --ignore-platform-reqs --no-interaction --no-scripts roave/security-advisories wp-cli/export-command wp-cli/extension-command wp-cli/wp-cli wp-cli/wp-cli-tests - - - name: Update PHPUnit - if: needs.pre-run.outputs.changed-php-count > 0 - run: | - # We are using PHP 7.4 and WP Latest. - echo "Installing latest version of PHPUnit" - composer update --ignore-platform-reqs --no-interaction --no-scripts yoast/phpunit-polyfills --with-dependencies - - - name: Build plugin - run: npm run build:js - - - name: Move amp-wp to amp - run: cp -r "$PWD" "/tmp/amp" - - - name: Start wp-env - working-directory: /tmp/amp - run: npm run wp-env start - - - name: Run multisite unit tests - working-directory: /tmp/amp - run: npm run test:php:multisite ${{ matrix.testsuite == 'external-http' && '-- --testsuite external-http' || '' }} - -#----------------------------------------------------------------------------------------------------------------------- - - feature-test-php: - name: "Feature test${{ matrix.coverage && ' (with coverage)' || '' }}: PHP ${{ matrix.php }}, WP ${{ matrix.wp }}" - needs: pre-run - if: needs.pre-run.outputs.changed-php-count > 0 - runs-on: ubuntu-latest - env: - WP_VERSION: ${{ matrix.wp }} - services: - mysql: - image: mariadb:latest - env: - MYSQL_ALLOW_EMPTY_PASSWORD: true - MYSQL_ROOT_PASSWORD: - MYSQL_DATABASE: wordpress_test - ports: - - 3306 - options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 - continue-on-error: ${{ matrix.experimental == true }} - strategy: - fail-fast: false - matrix: - coverage: [false] - php: ['7.4', '7.3', '7.2', '7.1'] - wp: ['latest'] - include: - - php: '8.1' - wp: 'trunk' - experimental: true - coverage: false - - - php: '8.0' - wp: 'latest' - coverage: false - - # TODO: Enable this once codecov upload merging works as expected. - # - php: '7.4' - # wp: 'latest' - # coverage: true - - - php: '7.0' - wp: '5.1' - coverage: false - - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: ${{ matrix.php }} - extensions: curl, date, dom, gd, iconv, json, libxml, mysql, spl - coverage: ${{ matrix.coverage && 'pcov' || 'none' }} - ini-values: pcov.directory=. - - - name: Shutdown default MySQL service - run: sudo service mysql stop - - - name: Verify MariaDB connection - run: | - while ! mysqladmin ping -h"127.0.0.1" -P"${{ job.services.mysql.ports[3306] }}" --silent; do - sleep 1 - done - - - name: Setup Node - uses: actions/setup-node@v3.6.0 - with: - node-version-file: '.nvmrc' - cache: npm - - - name: Get Composer Cache Directory - id: composer-cache - run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - - name: Configure Composer cache - uses: actions/cache@v3.2.3 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: | - ${{ runner.os }}-composer- - - - name: Install Composer dependencies - run: composer install --prefer-dist --ignore-platform-reqs --no-progress --no-interaction - - - name: Install Node dependencies - run: npm ci - env: - CI: true - - - name: Build plugin - run: npm run build:js - - - name: Update PHPUnit to get latest php-code-coverage library - if: ${{ matrix.coverage == true }} - # phpdocumentor/reflection has to be removed as it makes use of an outdated dependency. - # phpunit/phpunit has to be updated as the one in use provides an older version of phpunit/php-code-coverage, - # but we need the v9.x branch. - # It cannot be removed, as it is a requirement of wp-cli/wp-cli-tests as well. - run: | - composer remove --dev phpdocumentor/reflection - composer require --dev --ignore-platform-reqs --update-with-all-dependencies phpunit/phpunit - - - name: Configure DB environment - run: | - export MYSQL_HOST=127.0.0.1 - export MYSQL_TCP_PORT=${{ job.services.mysql.ports['3306'] }} - echo "WP_CLI_TEST_DBROOTUSER=root" >> $GITHUB_ENV - echo "WP_CLI_TEST_DBROOTPASS=" >> $GITHUB_ENV - echo "WP_CLI_TEST_DBUSER=wp_cli_test" >> $GITHUB_ENV - echo "WP_CLI_TEST_DBPASS=password1" >> $GITHUB_ENV - echo "WP_CLI_TEST_DBHOST=$MYSQL_HOST:$MYSQL_TCP_PORT" >> $GITHUB_ENV - - - name: Prepare test database - run: composer prepare-tests - - - name: Run tests - env: - BEHAT_CODE_COVERAGE: ${{ matrix.coverage }} - run: vendor/bin/behat - - - name: Retrieve list of coverage files - if: ${{ matrix.coverage == true }} - run: | - FILES=$(ls -d -1 "$GITHUB_WORKSPACE/build/logs/clover-behat/"*.* | xargs echo | sed 's/ /,/g') - echo $FILES - echo "COVERAGE_FILES=$FILES" >> $GITHUB_ENV - - - name: Upload code coverage report - if: ${{ matrix.coverage == true }} - uses: codecov/codecov-action@v3 - with: - files: ${{ env.COVERAGE_FILES }} - flags: php,feature - fail_ci_if_error: true - -#----------------------------------------------------------------------------------------------------------------------- - - build-zip: - name: 'Build: ${{ matrix.build }} build ZIP' - # Only run if the PR was not authored by Dependabot and it is not a draft or not from a fork. - if: > - needs.pre-run.outputs.changed-file-count > 0 && - github.event.pull_request.draft == false && - github.event.pull_request.head.repo.fork == false && - github.event.pull_request.user.login != 'dependabot[bot]' - needs: pre-run - runs-on: ubuntu-latest - outputs: - branch-name: ${{ steps.retrieve-branch-name.outputs.branch_name }} - git-sha-8: ${{ steps.retrieve-git-sha-8.outputs.sha8 }} - strategy: - matrix: - build: ['dev', 'prod'] - - steps: - - name: Check out source files - uses: actions/checkout@v3 - - - name: Setup PHP - uses: shivammathur/setup-php@v2 - with: - php-version: '7.0' - - - name: Setup Node - uses: actions/setup-node@v3.6.0 - with: - node-version-file: '.nvmrc' - cache: npm - - - name: Get Composer Cache Directory - id: composer-cache - run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT - - - name: Configure Composer cache - uses: actions/cache@v3.2.3 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} - restore-keys: | - ${{ runner.os }}-composer- - - - name: Install Composer dependencies - # Scripts are not ignored as they are needed to apply patches for the - # `sabberworm/php-css-parser` dependency. - run: composer install --prefer-dist --optimize-autoloader - - - name: Install Node dependencies - run: npm ci - env: - CI: true - - - name: Create destination directories - run: mkdir -p builds/${{ matrix.build }} - - - name: Build plugin - run: | - npm run package:${{ matrix.build }} - mv amp.zip builds/${{ matrix.build }}/amp.zip - env: - LAST_PR_COMMIT_HASH: ${{ github.event.pull_request.head.sha }} - - - name: Retrieve branch name - id: retrieve-branch-name - run: echo "branch_name=$(REF=${GITHUB_HEAD_REF:-$GITHUB_REF} && echo ${REF#refs/heads/} | sed 's/\//-/g')" >> $GITHUB_OUTPUT - - - name: Retrieve git SHA-8 string - id: retrieve-git-sha-8 - run: echo "sha8=$(echo ${GITHUB_SHA} | cut -c1-8)" >> $GITHUB_OUTPUT - - - name: Upload build as artifact - uses: actions/upload-artifact@v3 - with: - name: amp-${{ steps.retrieve-branch-name.outputs.branch_name }}-${{ steps.retrieve-git-sha-8.outputs.sha8 }}-${{ matrix.build }} - path: builds/${{ matrix.build }} - -#----------------------------------------------------------------------------------------------------------------------- - - upload-to-gcs: - name: Upload plugin ZIPs to Google Cloud Storage - runs-on: ubuntu-latest - needs: - - build-zip - steps: - - name: Download dev build - uses: actions/download-artifact@v3 - with: - name: amp-${{ needs.build-zip.outputs.branch-name }}-${{ needs.build-zip.outputs.git-sha-8 }}-dev - path: builds/dev - - - name: Download prod build - uses: actions/download-artifact@v3 - with: - name: amp-${{ needs.build-zip.outputs.branch-name }}-${{ needs.build-zip.outputs.git-sha-8 }}-prod - path: builds/prod - - - name: Setup Google Cloud SDK - uses: google-github-actions/setup-gcloud@v0 - with: - project_id: ${{ secrets.GCS_PROJECT_ID }} - service_account_key: ${{ secrets.GCS_APPLICATION_CREDENTIALS }} - - - name: Upload dev build to bucket - run: gsutil cp -r builds/dev/amp.zip gs://ampwp_github_artifacts/${{ github.ref }}/dev/amp.zip - - - name: Upload prod build to bucket - run: gsutil cp -r builds/prod/amp.zip gs://ampwp_github_artifacts/${{ github.ref }}/prod/amp.zip - -#----------------------------------------------------------------------------------------------------------------------- - - comment-on-pr: - name: Comment on PR with links to plugin ZIPs - # Only run this job if it's a PR. One way to check for that is if `github.head_ref` is not empty. - if: ${{ github.head_ref && github.head_ref != null }} - runs-on: ubuntu-latest - needs: upload-to-gcs - - outputs: - comment_body: ${{ steps.get-comment-body.outputs.body }} - - steps: - - name: Check if a comment was already made - id: find-comment - uses: peter-evans/find-comment@v2 - with: - issue-number: ${{ github.event.pull_request.number }} - comment-author: github-actions[bot] - body-includes: Plugin builds for - - - name: Get comment body - id: get-comment-body - # Setting a multi-line output requires escaping line-feeds. See . - run: | - body="Plugin builds for ${{ github.event.pull_request.head.sha }} are ready :bellhop_bell:! - - Download [development build](https://storage.googleapis.com/ampwp_github_artifacts/${{ github.ref }}/dev/amp.zip?${{ github.sha }}) - - Download [production build](https://storage.googleapis.com/ampwp_github_artifacts/${{ github.ref }}/prod/amp.zip?${{ github.sha }})" - delimiter="${body//$'\n'/'%0A'}" - echo "body<<${delimiter}" >> $GITHUB_OUTPUT - echo "$body" >> $GITHUB_OUTPUT - echo "${delimiter}" >> $GITHUB_OUTPUT - - - name: Create comment on PR with links to plugin builds - if: ${{ steps.find-comment.outputs.comment-id == '' }} - uses: peter-evans/create-or-update-comment@v2 - with: - issue-number: ${{ github.event.pull_request.number }} - body: ${{ steps.get-comment-body.outputs.body }} - - - name: Update comment on PR with links to plugin builds - if: ${{ steps.find-comment.outputs.comment-id != '' }} - uses: peter-evans/create-or-update-comment@v2 - with: - comment-id: ${{ steps.find-comment.outputs.comment-id }} - edit-mode: replace - body: ${{ steps.get-comment-body.outputs.body }} + WP_VERSION: ${{ matrix.wp }} + services: + mysql: + image: mariadb:latest + env: + MYSQL_ALLOW_EMPTY_PASSWORD: true + MYSQL_ROOT_PASSWORD: + MYSQL_DATABASE: wordpress_test + ports: + - 3306 + options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 + continue-on-error: ${{ matrix.experimental == true }} + strategy: + fail-fast: false + matrix: + coverage: [false] + php: ['7.4', '7.3', '7.2', '7.1'] + wp: ['latest'] + include: + - php: '8.1' + wp: 'trunk' + experimental: true + coverage: false + + - php: '8.0' + wp: 'latest' + coverage: false + + # TODO: Enable this once codecov upload merging works as expected. + # - php: '7.4' + # wp: 'latest' + # coverage: true + + - php: '7.0' + wp: '5.1' + coverage: false + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: curl, date, dom, gd, iconv, json, libxml, mysql, spl + coverage: ${{ matrix.coverage && 'pcov' || 'none' }} + ini-values: pcov.directory=. + + - name: Shutdown default MySQL service + run: sudo service mysql stop + + - name: Verify MariaDB connection + run: | + while ! mysqladmin ping -h"127.0.0.1" -P"${{ job.services.mysql.ports[3306] }}" --silent; do + sleep 1 + done + + - name: Setup Node + uses: actions/setup-node@v3.6.0 + with: + node-version-file: '.nvmrc' + cache: npm + + - name: Get Composer Cache Directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Configure Composer cache + uses: actions/cache@v3.2.3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-composer- + + - name: Install Composer dependencies + run: composer install --prefer-dist --ignore-platform-reqs --no-progress --no-interaction + + - name: Install Node dependencies + run: npm ci + env: + CI: true + + - name: Build plugin + run: npm run build:js + + - name: Update PHPUnit to get latest php-code-coverage library + if: ${{ matrix.coverage == true }} + # phpdocumentor/reflection has to be removed as it makes use of an outdated dependency. + # phpunit/phpunit has to be updated as the one in use provides an older version of phpunit/php-code-coverage, + # but we need the v9.x branch. + # It cannot be removed, as it is a requirement of wp-cli/wp-cli-tests as well. + run: | + composer remove --dev phpdocumentor/reflection + composer require --dev --ignore-platform-reqs --update-with-all-dependencies phpunit/phpunit + + - name: Configure DB environment + run: | + export MYSQL_HOST=127.0.0.1 + export MYSQL_TCP_PORT=${{ job.services.mysql.ports['3306'] }} + echo "WP_CLI_TEST_DBROOTUSER=root" >> $GITHUB_ENV + echo "WP_CLI_TEST_DBROOTPASS=" >> $GITHUB_ENV + echo "WP_CLI_TEST_DBUSER=wp_cli_test" >> $GITHUB_ENV + echo "WP_CLI_TEST_DBPASS=password1" >> $GITHUB_ENV + echo "WP_CLI_TEST_DBHOST=$MYSQL_HOST:$MYSQL_TCP_PORT" >> $GITHUB_ENV + + - name: Prepare test database + run: composer prepare-tests + + - name: Run tests + env: + BEHAT_CODE_COVERAGE: ${{ matrix.coverage }} + run: vendor/bin/behat + + - name: Retrieve list of coverage files + if: ${{ matrix.coverage == true }} + run: | + FILES=$(ls -d -1 "$GITHUB_WORKSPACE/build/logs/clover-behat/"*.* | xargs echo | sed 's/ /,/g') + echo $FILES + echo "COVERAGE_FILES=$FILES" >> $GITHUB_ENV + + - name: Upload code coverage report + if: ${{ matrix.coverage == true }} + uses: codecov/codecov-action@v3 + with: + files: ${{ env.COVERAGE_FILES }} + flags: php,feature + fail_ci_if_error: true + + #----------------------------------------------------------------------------------------------------------------------- + + build-zip: + name: 'Build: ${{ matrix.build }} build ZIP' + # Only run if the PR was not authored by Dependabot and it is not a draft or not from a fork. + if: > + needs.pre-run.outputs.changed-file-count > 0 && + github.event.pull_request.draft == false && + github.event.pull_request.head.repo.fork == false && + github.event.pull_request.user.login != 'dependabot[bot]' + needs: pre-run + runs-on: ubuntu-latest + outputs: + branch-name: ${{ steps.retrieve-branch-name.outputs.branch_name }} + git-sha-8: ${{ steps.retrieve-git-sha-8.outputs.sha8 }} + strategy: + matrix: + build: ['dev', 'prod'] + + steps: + - name: Check out source files + uses: actions/checkout@v3 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '7.0' + + - name: Setup Node + uses: actions/setup-node@v3.6.0 + with: + node-version-file: '.nvmrc' + cache: npm + + - name: Get Composer Cache Directory + id: composer-cache + run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT + + - name: Configure Composer cache + uses: actions/cache@v3.2.3 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} + restore-keys: | + ${{ runner.os }}-composer- + + - name: Install Composer dependencies + # Scripts are not ignored as they are needed to apply patches for the + # `sabberworm/php-css-parser` dependency. + run: composer install --prefer-dist --optimize-autoloader + + - name: Install Node dependencies + run: npm ci + env: + CI: true + + - name: Create destination directories + run: mkdir -p builds/${{ matrix.build }} + + - name: Build plugin + run: | + npm run package:${{ matrix.build }} + mv amp.zip builds/${{ matrix.build }}/amp.zip + env: + LAST_PR_COMMIT_HASH: ${{ github.event.pull_request.head.sha }} + + - name: Retrieve branch name + id: retrieve-branch-name + run: echo "branch_name=$(REF=${GITHUB_HEAD_REF:-$GITHUB_REF} && echo ${REF#refs/heads/} | sed 's/\//-/g')" >> $GITHUB_OUTPUT + + - name: Retrieve git SHA-8 string + id: retrieve-git-sha-8 + run: echo "sha8=$(echo ${GITHUB_SHA} | cut -c1-8)" >> $GITHUB_OUTPUT + + - name: Upload build as artifact + uses: actions/upload-artifact@v3 + with: + name: amp-${{ steps.retrieve-branch-name.outputs.branch_name }}-${{ steps.retrieve-git-sha-8.outputs.sha8 }}-${{ matrix.build }} + path: builds/${{ matrix.build }} + + #----------------------------------------------------------------------------------------------------------------------- + + upload-to-gcs: + name: Upload plugin ZIPs to Google Cloud Storage + runs-on: ubuntu-latest + needs: + - build-zip + steps: + - name: Download dev build + uses: actions/download-artifact@v3 + with: + name: amp-${{ needs.build-zip.outputs.branch-name }}-${{ needs.build-zip.outputs.git-sha-8 }}-dev + path: builds/dev + + - name: Download prod build + uses: actions/download-artifact@v3 + with: + name: amp-${{ needs.build-zip.outputs.branch-name }}-${{ needs.build-zip.outputs.git-sha-8 }}-prod + path: builds/prod + + - name: Setup Google Cloud SDK + uses: google-github-actions/setup-gcloud@v0 + with: + project_id: ${{ secrets.GCS_PROJECT_ID }} + service_account_key: ${{ secrets.GCS_APPLICATION_CREDENTIALS }} + + - name: Upload dev build to bucket + run: gsutil cp -r builds/dev/amp.zip gs://ampwp_github_artifacts/${{ github.ref }}/dev/amp.zip + + - name: Upload prod build to bucket + run: gsutil cp -r builds/prod/amp.zip gs://ampwp_github_artifacts/${{ github.ref }}/prod/amp.zip + + #----------------------------------------------------------------------------------------------------------------------- + + comment-on-pr: + name: Comment on PR with links to plugin ZIPs + # Only run this job if it's a PR. One way to check for that is if `github.head_ref` is not empty. + if: ${{ github.head_ref && github.head_ref != null }} + runs-on: ubuntu-latest + needs: upload-to-gcs + + outputs: + comment_body: ${{ steps.get-comment-body.outputs.body }} + + steps: + - name: Check if a comment was already made + id: find-comment + uses: peter-evans/find-comment@v2 + with: + issue-number: ${{ github.event.pull_request.number }} + comment-author: github-actions[bot] + body-includes: Plugin builds for + + - name: Get comment body + id: get-comment-body + # Setting a multi-line output requires escaping line-feeds. See . + run: | + body="Plugin builds for ${{ github.event.pull_request.head.sha }} are ready :bellhop_bell:! + - Download [development build](https://storage.googleapis.com/ampwp_github_artifacts/${{ github.ref }}/dev/amp.zip?${{ github.sha }}) + - Download [production build](https://storage.googleapis.com/ampwp_github_artifacts/${{ github.ref }}/prod/amp.zip?${{ github.sha }})" + delimiter="${body//$'\n'/'%0A'}" + echo "body<<${delimiter}" >> $GITHUB_OUTPUT + echo "$body" >> $GITHUB_OUTPUT + echo "${delimiter}" >> $GITHUB_OUTPUT + + - name: Create comment on PR with links to plugin builds + if: ${{ steps.find-comment.outputs.comment-id == '' }} + uses: peter-evans/create-or-update-comment@v2 + with: + issue-number: ${{ github.event.pull_request.number }} + body: ${{ steps.get-comment-body.outputs.body }} + + - name: Update comment on PR with links to plugin builds + if: ${{ steps.find-comment.outputs.comment-id != '' }} + uses: peter-evans/create-or-update-comment@v2 + with: + comment-id: ${{ steps.find-comment.outputs.comment-id }} + edit-mode: replace + body: ${{ steps.get-comment-body.outputs.body }} diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 7524cfcd086..f81667a1b67 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -2,43 +2,43 @@ 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 on: - push: - # Only run if JS or Python files changed. - paths: - - '**.js' - - '**.py' - branches: - - develop - # Include all release branches. - - '[0-9]+.[0-9]+' - pull_request: - # Only run if JS or Python files changed. - paths: - - '**.js' - - '**.py' - branches: - - develop - # Include all release branches. - - '[0-9]+.[0-9]+' + push: + # Only run if JS or Python files changed. + paths: + - '**.js' + - '**.py' + branches: + - develop + # Include all release branches. + - '[0-9]+.[0-9]+' + pull_request: + # Only run if JS or Python files changed. + paths: + - '**.js' + - '**.py' + branches: + - develop + # Include all release branches. + - '[0-9]+.[0-9]+' jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 + analyze: + name: Analyze + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: javascript, python + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: javascript, python - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/gutenberg-packages-update.yml b/.github/workflows/gutenberg-packages-update.yml index 03d8880c11c..dbe4b7baf4f 100644 --- a/.github/workflows/gutenberg-packages-update.yml +++ b/.github/workflows/gutenberg-packages-update.yml @@ -1,188 +1,188 @@ name: Gutenberg packages update on: - # Allow for the workflow to be manually run if needed. - workflow_dispatch: - schedule: - # Once a day (https://crontab.guru/once-a-day) - - cron: '0 0 * * *' + # Allow for the workflow to be manually run if needed. + workflow_dispatch: + schedule: + # Once a day (https://crontab.guru/once-a-day) + - cron: '0 0 * * *' permissions: - pull-requests: write - contents: write + pull-requests: write + contents: write # 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 jobs: - check-gutenberg-release: - name: Check for a new Gutenberg release - runs-on: ubuntu-latest - outputs: - latest-version: ${{ steps.latest-release.outputs.version }} - should-update: ${{ steps.release-status.outputs.outdated }} - steps: - - name: Get latest release version - id: latest-release - run: echo "version=$(gh api -X GET repos/wordpress/gutenberg/releases/latest --jq '.name')" >> $GITHUB_OUTPUT - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Get release version from last PR - id: last-release - run: | - PR_TITLE=$(gh api -X GET search/issues -f q='${{ env.QUERY }}' -f sort='created' -f order='desc' --jq '.items.[0].title') - LAST_VERSION=$(sed -r 's/.+ v(.+) .+/\1/' <<< "$PR_TITLE") - if ! egrep -q '^[0-9][0-9]*(\.[0-9][0-9]*)*$' <<< "$LAST_VERSION"; then - LAST_VERSION='0.0.0' - fi - echo "version=$(echo "$LAST_VERSION")" >> $GITHUB_OUTPUT - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - QUERY: 'repo:ampproject/amp-wp is:pr author:app/github-actions is:merged in:title Update Gutenberg packages after' - - - name: Determine if package updates are needed - id: release-status - run: | - echo "Last version: $LAST_VER" - echo "Latest version: $LATEST_VER" - echo "outdated=$(php -r 'echo json_encode(version_compare($argv[1], $argv[2], ">"));' "$LATEST_VER" "$LAST_VER")" >> $GITHUB_OUTPUT - env: - LAST_VER: ${{ steps.last-release.outputs.version }} - LATEST_VER: ${{ steps.latest-release.outputs.version }} - - close-latest-pr: - name: Close latest open PR if one exists - # Run job if there is a new Gutenberg release. - if: needs.check-gutenberg-release.outputs.should-update == 'true' - runs-on: ubuntu-latest - needs: check-gutenberg-release - steps: - - name: Get latest open PR - id: latest-pr - run: | - PR_NUM=$(gh api -X GET search/issues -f q='${{ env.QUERY }}' -f sort='created' -f order='desc' --jq '.items.[0].number') - echo "num=$(echo $PR_NUM)" >> $GITHUB_OUTPUT - echo "Latest PR number: ${PR_NUM}" - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - QUERY: 'repo:ampproject/amp-wp is:pr author:app/github-actions is:open in:title Update Gutenberg packages after' - - # Needed to later close PR. - - name: Checkout repo - if: steps.latest-pr.num != '' - uses: actions/checkout@v3 - - - name: Close latest open PR - if: steps.latest-pr.num != '' - run: gh pr close ${{ env.PR_NUM }} --delete-branch - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - PR_NUM: ${{ steps.latest-pr.num }} - - update-packages: - name: Update Gutenberg npm dependencies - # Run job if there is a new Gutenberg release. - if: needs.check-gutenberg-release.outputs.should-update == 'true' - runs-on: ubuntu-latest - needs: check-gutenberg-release - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - # Fetch history for all branches and tags to allow for successful merge of base branch if needed. - fetch-depth: 0 - - - name: Determine branch name - id: branches - run: | - echo "base=$(echo ${GITHUB_REF#refs/heads/})" >> $GITHUB_OUTPUT - echo "head=$(echo "update/gutenberg-v$VERSION-packages")" >> $GITHUB_OUTPUT - env: - VERSION: ${{ needs.check-gutenberg-release.outputs.latest-version }} - - - name: Setup Node - uses: actions/setup-node@v3.6.0 - with: - node-version-file: '.nvmrc' - cache: npm - - - name: Configure git user - run: | - git config user.name ${{ secrets.GIT_USER }} - git config user.email ${{ secrets.GIT_USER_EMAIL }} - - - name: Check if remote branch exists - id: remote-branch - run: echo "exists=$([[ -z $(git ls-remote --heads origin "$HEAD_BRANCH" ) ]] && echo "0" || echo "1")" >> $GITHUB_OUTPUT - env: - HEAD_BRANCH: ${{ steps.branches.outputs.head }} - - - name: Create branch to base pull request on - if: steps.remote-branch.outputs.exists == 0 - run: git checkout -b "$HEAD_BRANCH" - env: - HEAD_BRANCH: ${{ steps.branches.outputs.head }} - - - name: Fetch existing branch to add commits to - if: steps.remote-branch.outputs.exists == 1 - run: | - git checkout "$HEAD_BRANCH" - git merge --no-edit "$BASE_BRANCH" - env: - BASE_BRANCH: ${{ steps.branches.outputs.base }} - HEAD_BRANCH: ${{ steps.branches.outputs.head }} - - - name: Install Node dependencies - run: npm ci - env: - CI: true - - - name: Check package updates - id: packages - run: | - # Get list of latest package versions. - PACKAGES=$(npm outdated --parseable | cut -d':' -f 4 | grep @wordpress | paste -s -d' ' || echo 0) - echo "list=$(echo "$PACKAGES")" >> $GITHUB_OUTPUT - - - name: Update packages - if: steps.packages.outputs.list != 0 - run: npm i $(echo "$PACKAGES") - env: - PACKAGES: ${{ steps.packages.outputs.list }} - - - name: Commit and push changes - if: steps.packages.outputs.list != 0 - run: | - git add --all . - git commit -m "Update Gutenberg package dependencies" - git push origin "$HEAD_BRANCH" - env: - HEAD_BRANCH: ${{ steps.branches.outputs.head }} - - - name: Create pull request - if: steps.packages.outputs.list != 0 && steps.remote-branch.outputs.exists == 0 - run: | - NPM_URL="https://www.npmjs.com/package" - BODY="**Following packages were updated:**" - for PACKAGE in $PACKAGES; do - PACKAGE_SLUG=$(echo $PACKAGE | sed 's/@/\/v\//2') - BODY="$BODY - - - [$PACKAGE]($NPM_URL/$PACKAGE_SLUG)" - done - - echo ${BODY//$'\n'/'%0A'} - - PR_URL=$(gh pr create --base "$BASE_BRANCH" --title "Update Gutenberg packages after v$VERSION release" --body "$BODY" --label dependencies | grep https://) - gh pr merge --auto --merge "$PR_URL" - env: - VERSION: ${{ needs.check-gutenberg-release.outputs.latest-version }} - GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} - BASE_BRANCH: ${{ steps.branches.outputs.base }} - HEAD_BRANCH: ${{ steps.branches.outputs.head }} - PACKAGES: ${{ steps.packages.outputs.list }} + check-gutenberg-release: + name: Check for a new Gutenberg release + runs-on: ubuntu-latest + outputs: + latest-version: ${{ steps.latest-release.outputs.version }} + should-update: ${{ steps.release-status.outputs.outdated }} + steps: + - name: Get latest release version + id: latest-release + run: echo "version=$(gh api -X GET repos/wordpress/gutenberg/releases/latest --jq '.name')" >> $GITHUB_OUTPUT + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Get release version from last PR + id: last-release + run: | + PR_TITLE=$(gh api -X GET search/issues -f q='${{ env.QUERY }}' -f sort='created' -f order='desc' --jq '.items.[0].title') + LAST_VERSION=$(sed -r 's/.+ v(.+) .+/\1/' <<< "$PR_TITLE") + if ! egrep -q '^[0-9][0-9]*(\.[0-9][0-9]*)*$' <<< "$LAST_VERSION"; then + LAST_VERSION='0.0.0' + fi + echo "version=$(echo "$LAST_VERSION")" >> $GITHUB_OUTPUT + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + QUERY: 'repo:ampproject/amp-wp is:pr author:app/github-actions is:merged in:title Update Gutenberg packages after' + + - name: Determine if package updates are needed + id: release-status + run: | + echo "Last version: $LAST_VER" + echo "Latest version: $LATEST_VER" + echo "outdated=$(php -r 'echo json_encode(version_compare($argv[1], $argv[2], ">"));' "$LATEST_VER" "$LAST_VER")" >> $GITHUB_OUTPUT + env: + LAST_VER: ${{ steps.last-release.outputs.version }} + LATEST_VER: ${{ steps.latest-release.outputs.version }} + + close-latest-pr: + name: Close latest open PR if one exists + # Run job if there is a new Gutenberg release. + if: needs.check-gutenberg-release.outputs.should-update == 'true' + runs-on: ubuntu-latest + needs: check-gutenberg-release + steps: + - name: Get latest open PR + id: latest-pr + run: | + PR_NUM=$(gh api -X GET search/issues -f q='${{ env.QUERY }}' -f sort='created' -f order='desc' --jq '.items.[0].number') + echo "num=$(echo $PR_NUM)" >> $GITHUB_OUTPUT + echo "Latest PR number: ${PR_NUM}" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + QUERY: 'repo:ampproject/amp-wp is:pr author:app/github-actions is:open in:title Update Gutenberg packages after' + + # Needed to later close PR. + - name: Checkout repo + if: steps.latest-pr.num != '' + uses: actions/checkout@v3 + + - name: Close latest open PR + if: steps.latest-pr.num != '' + run: gh pr close ${{ env.PR_NUM }} --delete-branch + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_NUM: ${{ steps.latest-pr.num }} + + update-packages: + name: Update Gutenberg npm dependencies + # Run job if there is a new Gutenberg release. + if: needs.check-gutenberg-release.outputs.should-update == 'true' + runs-on: ubuntu-latest + needs: check-gutenberg-release + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + # Fetch history for all branches and tags to allow for successful merge of base branch if needed. + fetch-depth: 0 + + - name: Determine branch name + id: branches + run: | + echo "base=$(echo ${GITHUB_REF#refs/heads/})" >> $GITHUB_OUTPUT + echo "head=$(echo "update/gutenberg-v$VERSION-packages")" >> $GITHUB_OUTPUT + env: + VERSION: ${{ needs.check-gutenberg-release.outputs.latest-version }} + + - name: Setup Node + uses: actions/setup-node@v3.6.0 + with: + node-version-file: '.nvmrc' + cache: npm + + - name: Configure git user + run: | + git config user.name ${{ secrets.GIT_USER }} + git config user.email ${{ secrets.GIT_USER_EMAIL }} + + - name: Check if remote branch exists + id: remote-branch + run: echo "exists=$([[ -z $(git ls-remote --heads origin "$HEAD_BRANCH" ) ]] && echo "0" || echo "1")" >> $GITHUB_OUTPUT + env: + HEAD_BRANCH: ${{ steps.branches.outputs.head }} + + - name: Create branch to base pull request on + if: steps.remote-branch.outputs.exists == 0 + run: git checkout -b "$HEAD_BRANCH" + env: + HEAD_BRANCH: ${{ steps.branches.outputs.head }} + + - name: Fetch existing branch to add commits to + if: steps.remote-branch.outputs.exists == 1 + run: | + git checkout "$HEAD_BRANCH" + git merge --no-edit "$BASE_BRANCH" + env: + BASE_BRANCH: ${{ steps.branches.outputs.base }} + HEAD_BRANCH: ${{ steps.branches.outputs.head }} + + - name: Install Node dependencies + run: npm ci + env: + CI: true + + - name: Check package updates + id: packages + run: | + # Get list of latest package versions. + PACKAGES=$(npm outdated --parseable | cut -d':' -f 4 | grep @wordpress | paste -s -d' ' || echo 0) + echo "list=$(echo "$PACKAGES")" >> $GITHUB_OUTPUT + + - name: Update packages + if: steps.packages.outputs.list != 0 + run: npm i $(echo "$PACKAGES") + env: + PACKAGES: ${{ steps.packages.outputs.list }} + + - name: Commit and push changes + if: steps.packages.outputs.list != 0 + run: | + git add --all . + git commit -m "Update Gutenberg package dependencies" + git push origin "$HEAD_BRANCH" + env: + HEAD_BRANCH: ${{ steps.branches.outputs.head }} + + - name: Create pull request + if: steps.packages.outputs.list != 0 && steps.remote-branch.outputs.exists == 0 + run: | + NPM_URL="https://www.npmjs.com/package" + BODY="**Following packages were updated:**" + for PACKAGE in $PACKAGES; do + PACKAGE_SLUG=$(echo $PACKAGE | sed 's/@/\/v\//2') + BODY="$BODY + + - [$PACKAGE]($NPM_URL/$PACKAGE_SLUG)" + done + + echo ${BODY//$'\n'/'%0A'} + + PR_URL=$(gh pr create --base "$BASE_BRANCH" --title "Update Gutenberg packages after v$VERSION release" --body "$BODY" --label dependencies | grep https://) + gh pr merge --auto --merge "$PR_URL" + env: + VERSION: ${{ needs.check-gutenberg-release.outputs.latest-version }} + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} + BASE_BRANCH: ${{ steps.branches.outputs.base }} + HEAD_BRANCH: ${{ steps.branches.outputs.head }} + PACKAGES: ${{ steps.packages.outputs.list }} diff --git a/.github/workflows/release-draft.yml b/.github/workflows/release-draft.yml index bb2998ccf57..1ec052ae98b 100644 --- a/.github/workflows/release-draft.yml +++ b/.github/workflows/release-draft.yml @@ -1,23 +1,23 @@ name: Release Draft on: - workflow_dispatch: - inputs: - milestone: - description: 'Milestone name (eg. v3.2.1)' - required: true + workflow_dispatch: + inputs: + milestone: + description: 'Milestone name (eg. v3.2.1)' + required: true jobs: - draft_release: - name: Draft release - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 + draft_release: + name: Draft release + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 - - name: Draft release - uses: ./.github/actions/draft-release - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - milestone: ${{ github.event.inputs.milestone }} + - name: Draft release + uses: ./.github/actions/draft-release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + milestone: ${{ github.event.inputs.milestone }} diff --git a/README.md b/README.md index 5f8f64683f0..85a35a2cda0 100644 --- a/README.md +++ b/README.md @@ -38,8 +38,8 @@ The official AMP plugin for WordPress is a powerful tool that helps you build us This plugin can be used by both developers and non-developer users: -- If you are a developer or tech savvy user, you can take advantage of advanced developer tools provided by the AMP plugin to fix validation issues your site may have and reach full AMP compatibility. -- If you are not a developer or tech savvy user, or you just simply don't want to deal with validation issues and tackling development tasks, the AMP plugin allows you to assemble fully AMP-compatible sites with different configurations taking advantage of AMP-compatible components. The plugin helps you to deal with validation issues by removing invalid AMP markup in cases where it is possible, or altogether suppressing AMP-incompatible plugins on AMP pages. +- If you are a developer or tech savvy user, you can take advantage of advanced developer tools provided by the AMP plugin to fix validation issues your site may have and reach full AMP compatibility. +- If you are not a developer or tech savvy user, or you just simply don't want to deal with validation issues and tackling development tasks, the AMP plugin allows you to assemble fully AMP-compatible sites with different configurations taking advantage of AMP-compatible components. The plugin helps you to deal with validation issues by removing invalid AMP markup in cases where it is possible, or altogether suppressing AMP-incompatible plugins on AMP pages. The bottom line is that regardless of your technical expertise, the AMP plugin can be useful to you. diff --git a/assets/src/admin/site-scan-notice/index.js b/assets/src/admin/site-scan-notice/index.js index 18f2b104776..428d42f882c 100644 --- a/assets/src/admin/site-scan-notice/index.js +++ b/assets/src/admin/site-scan-notice/index.js @@ -14,7 +14,7 @@ import { * WordPress dependencies */ import domReady from '@wordpress/dom-ready'; -import { render } from '@wordpress/element'; +import { createRoot } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; /** @@ -94,16 +94,15 @@ domReady(() => { event.filename && /amp-site-scan-notice(\.min)?\.js/.test(event.filename) ) { - render(, root); + createRoot(root).render(); } }; global.addEventListener('error', errorHandler); - render( + createRoot(root).render( - , - root + ); }); diff --git a/assets/src/block-validation/components/amp-document-status/test/amp-document-status-notification.js b/assets/src/block-validation/components/amp-document-status/test/amp-document-status-notification.js index 40269fe62f9..bdaa6d94383 100644 --- a/assets/src/block-validation/components/amp-document-status/test/amp-document-status-notification.js +++ b/assets/src/block-validation/components/amp-document-status/test/amp-document-status-notification.js @@ -1,12 +1,11 @@ /** * External dependencies */ -import { act } from 'react-dom/test-utils'; +import { render, fireEvent } from '@testing-library/react'; /** * WordPress dependencies */ -import { render, unmountComponentAtNode } from '@wordpress/element'; import { useDispatch, useSelect } from '@wordpress/data'; /** @@ -28,8 +27,6 @@ jest.mock('../../../hooks/use-errors-fetching-state-changes', () => ({ })); describe('AMPDocumentStatusNotification', () => { - let container; - const openGeneralSidebar = jest.fn(); const closePublishSidebar = jest.fn(); @@ -65,18 +62,6 @@ describe('AMPDocumentStatusNotification', () => { })); }); - beforeEach(() => { - // jest.clearAllMocks(); - container = document.createElement('div'); - document.body.appendChild(container); - }); - - afterEach(() => { - unmountComponentAtNode(container); - container.remove(); - container = null; - }); - it('renders only a toggle if AMP is disabled', () => { setupHooks( {}, @@ -86,9 +71,7 @@ describe('AMPDocumentStatusNotification', () => { } ); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.children).toHaveLength(1); expect(container.innerHTML).toContain('Enable AMP'); @@ -103,9 +86,7 @@ describe('AMPDocumentStatusNotification', () => { } ); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.innerHTML).toContain('Enable AMP'); expect( @@ -119,9 +100,7 @@ describe('AMPDocumentStatusNotification', () => { isPostDirty: true, }); - act(() => { - render(, container); - }); + let { container } = render(); expect(container.innerHTML).toContain('Enable AMP'); expect(container.innerHTML).toContain('Content has changed.'); @@ -133,14 +112,13 @@ describe('AMPDocumentStatusNotification', () => { maybeIsPostDirty: true, }); - act(() => { - render(, container); - }); + ({ container } = render()); expect(container.innerHTML).toContain('Content may have changed.'); // Simulate button click. - container.querySelector('button').click(); + fireEvent.click(container.querySelector('button')); + expect(openGeneralSidebar).toHaveBeenCalledTimes(1); expect(closePublishSidebar).toHaveBeenCalledTimes(1); }); @@ -150,9 +128,7 @@ describe('AMPDocumentStatusNotification', () => { keptMarkupValidationErrorCount: 3, }); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.innerHTML).toContain('Enable AMP'); expect(container.innerHTML).toContain( @@ -169,9 +145,7 @@ describe('AMPDocumentStatusNotification', () => { unreviewedValidationErrorCount: 1, }); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.innerHTML).toContain('Enable AMP'); expect(container.innerHTML).toContain( @@ -186,9 +160,7 @@ describe('AMPDocumentStatusNotification', () => { it('renders a correct message if there are no errors', () => { setupHooks(); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.innerHTML).toContain('Enable AMP'); expect(container.innerHTML).toContain( diff --git a/assets/src/block-validation/components/amp-toggle/test/amp-toggle.js b/assets/src/block-validation/components/amp-toggle/test/amp-toggle.js index 1bb7f837a7b..248e3c1a961 100644 --- a/assets/src/block-validation/components/amp-toggle/test/amp-toggle.js +++ b/assets/src/block-validation/components/amp-toggle/test/amp-toggle.js @@ -1,12 +1,7 @@ /** * External dependencies */ -import { act } from 'react-dom/test-utils'; - -/** - * WordPress dependencies - */ -import { render, unmountComponentAtNode } from '@wordpress/element'; +import { render, fireEvent } from '@testing-library/react'; /** * Internal dependencies @@ -19,8 +14,6 @@ jest.mock('../../../hooks/use-amp-document-toggle', () => ({ })); describe('AMPToggle', () => { - let container; - const toggleAMP = jest.fn(); function setupHooks(overrides) { @@ -33,15 +26,6 @@ describe('AMPToggle', () => { beforeEach(() => { jest.clearAllMocks(); - - container = document.createElement('div'); - document.body.appendChild(container); - }); - - afterEach(() => { - unmountComponentAtNode(container); - container.remove(); - container = null; }); it('renders a toggle that reacts to changes', () => { @@ -49,9 +33,7 @@ describe('AMPToggle', () => { isAMPEnabled: true, }); - act(() => { - render(, container); - }); + const { container } = render(); expect( container.querySelector('input[type="checkbox"]') @@ -60,7 +42,8 @@ describe('AMPToggle', () => { true ); - container.querySelector('input[type="checkbox"]').click(); + fireEvent.click(container.querySelector('input[type="checkbox"]')); + expect(toggleAMP).toHaveBeenCalledTimes(1); }); }); diff --git a/assets/src/block-validation/components/amp-validation-status/test/revalidate-notification.js b/assets/src/block-validation/components/amp-validation-status/test/revalidate-notification.js index f7a08f8ed7e..e5e993f4d15 100644 --- a/assets/src/block-validation/components/amp-validation-status/test/revalidate-notification.js +++ b/assets/src/block-validation/components/amp-validation-status/test/revalidate-notification.js @@ -1,12 +1,11 @@ /** * External dependencies */ -import { act } from 'react-dom/test-utils'; +import { render, fireEvent } from '@testing-library/react'; /** * WordPress dependencies */ -import { render, unmountComponentAtNode } from '@wordpress/element'; import { useDispatch, useSelect } from '@wordpress/data'; /** @@ -24,8 +23,6 @@ jest.mock('../../../hooks/use-errors-fetching-state-changes', () => ({ })); describe('AMPRevalidateNotification', () => { - let container; - const autosave = jest.fn(); const savePost = jest.fn(); @@ -45,27 +42,16 @@ describe('AMPRevalidateNotification', () => { }); beforeEach(() => { - container = document.createElement('div'); - document.body.appendChild(container); - useErrorsFetchingStateChanges.mockImplementation(() => ({ isFetchingErrors: false, fetchingErrorsMessage: '', })); }); - afterEach(() => { - unmountComponentAtNode(container); - container.remove(); - container = null; - }); - it('does not render revalidate message if post is not dirty', () => { setupUseSelect(); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.children).toHaveLength(0); }); @@ -76,9 +62,7 @@ describe('AMPRevalidateNotification', () => { fetchingErrorsMessage: 'Loading', })); - act(() => { - render(, container); - }); + const { container } = render(); expect( container.querySelector('.amp-spinner-container') @@ -91,9 +75,7 @@ describe('AMPRevalidateNotification', () => { isPostDirty: true, }); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.innerHTML).toMatchSnapshot(); expect(container.children).toHaveLength(1); @@ -103,7 +85,8 @@ describe('AMPRevalidateNotification', () => { 'Re-validate' ); - container.querySelector('button').click(); + fireEvent.click(container.querySelector('button')); + expect(autosave).toHaveBeenCalledWith({ isPreview: true }); }); @@ -113,9 +96,7 @@ describe('AMPRevalidateNotification', () => { isPostDirty: true, }); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.innerHTML).toMatchSnapshot(); expect(container.innerHTML).toContain('has changed'); @@ -123,7 +104,8 @@ describe('AMPRevalidateNotification', () => { 'Save draft' ); - container.querySelector('button').click(); + fireEvent.click(container.querySelector('button')); + expect(savePost).toHaveBeenCalledWith({ isPreview: true }); }); @@ -134,9 +116,7 @@ describe('AMPRevalidateNotification', () => { maybeIsPostDirty: true, }); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.innerHTML).toMatchSnapshot(); expect(container.children).toHaveLength(1); diff --git a/assets/src/block-validation/components/amp-validation-status/test/status-notification.js b/assets/src/block-validation/components/amp-validation-status/test/status-notification.js index 4b115a43327..22c207543a8 100644 --- a/assets/src/block-validation/components/amp-validation-status/test/status-notification.js +++ b/assets/src/block-validation/components/amp-validation-status/test/status-notification.js @@ -1,12 +1,11 @@ /** * External dependencies */ -import { act } from 'react-dom/test-utils'; +import { render, fireEvent } from '@testing-library/react'; /** * WordPress dependencies */ -import { render, unmountComponentAtNode } from '@wordpress/element'; import { useDispatch, useSelect } from '@wordpress/data'; /** @@ -20,8 +19,6 @@ jest.mock('@wordpress/data/build/components/use-dispatch/use-dispatch', () => ); describe('AMPValidationStatusNotification', () => { - let container; - const autosave = jest.fn(); const savePost = jest.fn(); @@ -44,25 +41,12 @@ describe('AMPValidationStatusNotification', () => { useDispatch.mockImplementation(() => ({ autosave, savePost })); }); - beforeEach(() => { - container = document.createElement('div'); - document.body.appendChild(container); - }); - - afterEach(() => { - unmountComponentAtNode(container); - container.remove(); - container = null; - }); - it('does not render when errors are being fetched', () => { setupUseSelect({ isFetchingErrors: true, }); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.children).toHaveLength(0); }); @@ -72,9 +56,7 @@ describe('AMPValidationStatusNotification', () => { isEditedPostNew: true, }); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.innerHTML).toMatchSnapshot(); expect(container.innerHTML).toContain( @@ -90,9 +72,7 @@ describe('AMPValidationStatusNotification', () => { fetchingErrorsRequestErrorMessage: 'request error message', }); - act(() => { - render(, container); - }); + let { container } = render(); expect(container.innerHTML).toMatchSnapshot(); expect(container.innerHTML).toContain('request error message'); @@ -100,7 +80,8 @@ describe('AMPValidationStatusNotification', () => { container.querySelector('a[href="http://example.com"]') ).toBeNull(); - container.querySelector('button').click(); + fireEvent.click(container.querySelector('button')); + expect(autosave).toHaveBeenCalledWith({ isPreview: true }); setupUseSelect({ @@ -108,10 +89,10 @@ describe('AMPValidationStatusNotification', () => { fetchingErrorsRequestErrorMessage: 'request error message', }); - act(() => { - render(, container); - }); - container.querySelector('button').click(); + ({ container } = render()); + + fireEvent.click(container.querySelector('button')); + expect(savePost).toHaveBeenCalledWith({ isPreview: true }); }); @@ -120,9 +101,7 @@ describe('AMPValidationStatusNotification', () => { keptMarkupValidationErrorCount: 2, }); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.innerHTML).toMatchSnapshot(); expect(container.innerHTML).toContain( @@ -138,9 +117,7 @@ describe('AMPValidationStatusNotification', () => { unreviewedValidationErrorCount: 3, }); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.innerHTML).toMatchSnapshot(); expect(container.innerHTML).toContain( @@ -156,9 +133,7 @@ describe('AMPValidationStatusNotification', () => { validationErrorCount: 1, }); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.innerHTML).toMatchSnapshot(); expect(container.innerHTML).toContain( @@ -172,9 +147,7 @@ describe('AMPValidationStatusNotification', () => { it('renders message when there are no AMP validation errors', () => { setupUseSelect(); - act(() => { - render(, container); - }); + const { container } = render(); expect(container.innerHTML).toMatchSnapshot(); expect(container.innerHTML).toContain( diff --git a/assets/src/block-validation/components/error/test/error.js b/assets/src/block-validation/components/error/test/error.js index 8e41b84fb0e..25532d5e102 100644 --- a/assets/src/block-validation/components/error/test/error.js +++ b/assets/src/block-validation/components/error/test/error.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { act } from 'react-dom/test-utils'; +import { render, act, fireEvent } from '@testing-library/react'; import { noop } from 'lodash'; import { VALIDATION_ERROR_ACK_ACCEPTED_STATUS, @@ -13,7 +13,6 @@ import { /** * WordPress dependencies */ -import { render } from '@wordpress/element'; import { dispatch, select } from '@wordpress/data'; import { registerBlockType, createBlock } from '@wordpress/blocks'; @@ -23,7 +22,7 @@ import { registerBlockType, createBlock } from '@wordpress/blocks'; import { Error } from '../index'; import { createStore } from '../../../store'; -let container, pluginBlock, muPluginBlock, themeBlock, coreBlock, unknownBlock; +let pluginBlock, muPluginBlock, themeBlock, coreBlock, unknownBlock; const TEST_PLUGIN_BLOCK = 'my-plugin/test-block'; const TEST_MU_PLUGIN_BLOCK = 'my-mu-plugin/test-block'; @@ -194,16 +193,6 @@ describe('Error', () => { createTestStoreAndBlocks(); }); - beforeEach(() => { - container = document.createElement('div'); - document.body.appendChild(container); - }); - - afterEach(() => { - document.body.removeChild(container); - container = null; - }); - it.each( [ VALIDATION_ERROR_ACK_ACCEPTED_STATUS, @@ -224,9 +213,7 @@ describe('Error', () => { )( 'errors with no associated blocks work correctly', (status, ErrorComponent) => { - act(() => { - render(, container); - }); + const { container } = render(); expect(container.firstChild.classList).toContain('amp-error'); expect( @@ -243,11 +230,18 @@ describe('Error', () => { ) ).not.toBeNull(); - container - .querySelector( + // container + // .querySelector( + // `.amp-error--${getErrorTypeClassName(status)} button` + // ) + // .click(); + + fireEvent.click( + container.querySelector( `.amp-error--${getErrorTypeClassName(status)} button` ) - .click(); + ); + expect( container.querySelector('.amp-error__block-type-icon') ).toBeNull(); @@ -281,9 +275,7 @@ describe('Error', () => { )( 'errors with associated blocks work correctly', (status, ErrorComponent) => { - act(() => { - render(, container); - }); + const { container } = render(); expect(container.firstChild.classList).toContain('amp-error'); expect( @@ -300,11 +292,12 @@ describe('Error', () => { ) ).not.toBeNull(); - container - .querySelector( + fireEvent.click( + container.querySelector( `.amp-error--${getErrorTypeClassName(status)} button` ) - .click(); + ); + expect( container.querySelector('.amp-error__block-type-icon') ).not.toBeNull(); @@ -341,9 +334,10 @@ describe('Error', () => { pluginBlock.clientId, false ); - render(, container); }); + const { container } = render(); + expect(container.firstChild.classList).toContain('amp-error'); expect( container.querySelectorAll( @@ -356,7 +350,8 @@ describe('Error', () => { container.querySelector('.amp-error--removed button') ).not.toBeNull(); - container.querySelector('.amp-error--removed button').click(); + fireEvent.click(container.querySelector('.amp-error--removed button')); + expect( container.querySelector('.amp-error__block-type-icon') ).toBeNull(); @@ -368,33 +363,20 @@ describe('Error', () => { }); describe('ErrorTypeIcon', () => { - beforeEach(() => { - container = document.createElement('div'); - document.body.appendChild(container); - }); - - afterEach(() => { - document.body.removeChild(container); - container = null; - }); - it.each([ 'js_error', 'html_attribute_error', 'html_element_error', 'css_error', ])('shows the correct error icon', (errorType) => { - act(() => { - render( - , - container - ); - }); + const { container } = render( + + ); expect( container.querySelector( @@ -404,17 +386,14 @@ describe('ErrorTypeIcon', () => { }); it('shows no error icon for unknown error type', () => { - act(() => { - render( - , - container - ); - }); + const { container } = render( + + ); expect( container.querySelector('svg[class^=amp-error__error-type-icon]') @@ -427,16 +406,6 @@ describe('ErrorContent', () => { createTestStoreAndBlocks(); }); - beforeEach(() => { - container = document.createElement('div'); - document.body.appendChild(container); - }); - - afterEach(() => { - document.body.removeChild(container); - container = null; - }); - /* eslint-disable jest/no-conditional-in-test */ it.each( [null, 'plugin', 'mu-plugin', 'theme', 'core', 'removed'].reduce( @@ -456,18 +425,17 @@ describe('ErrorContent', () => { (testBlockSource, status) => { const clientId = getTestBlock(testBlockSource); - render( + const { container } = render( , - container + /> ); - container.querySelector(`.components-button`).click(); + fireEvent.click(container.querySelector(`.components-button`)); expect(container.innerHTML).toContain('Markup status'); @@ -540,7 +508,10 @@ describe('ErrorContent', () => { : 'Kept' ); - container.querySelector('.amp-error__select-block').click(); + fireEvent.click( + container.querySelector('.amp-error__select-block') + ); + expect( select('core/block-editor').getSelectedBlock().clientId ).toBe(clientId); diff --git a/assets/src/block-validation/components/icon/test/icon.js b/assets/src/block-validation/components/icon/test/icon.js index f0d5153bc2a..6dd0f33e614 100644 --- a/assets/src/block-validation/components/icon/test/icon.js +++ b/assets/src/block-validation/components/icon/test/icon.js @@ -1,35 +1,16 @@ /** * External dependencies */ -import { act } from 'react-dom/test-utils'; - -/** - * WordPress dependencies - */ -import { render } from '@wordpress/element'; +import { render } from '@testing-library/react'; /** * Internal dependencies */ import { MoreMenuIcon, ToolbarIcon, StatusIcon } from '../index'; -let container; - describe('Icons', () => { - beforeEach(() => { - container = document.createElement('ul'); - document.body.appendChild(container); - }); - - afterEach(() => { - document.body.removeChild(container); - container = null; - }); - it('renders a toolbar icon without AMP broken and no badge', () => { - act(() => { - render(, container); - }); + const { container } = render(); expect(container.querySelector('.amp-toolbar-icon')).not.toBeNull(); expect( @@ -42,9 +23,7 @@ describe('Icons', () => { }); it('renders a toolbar icon without AMP broken and with a badge', () => { - act(() => { - render(, container); - }); + const { container } = render(); expect(container.querySelector('.amp-toolbar-icon')).not.toBeNull(); expect( @@ -57,9 +36,7 @@ describe('Icons', () => { }); it('renders a toolbar icon with AMP broken and with no badge', () => { - act(() => { - render(, container); - }); + const { container } = render(); expect(container.querySelector('.amp-toolbar-icon')).toBeNull(); expect( @@ -74,9 +51,7 @@ describe('Icons', () => { }); it('renders a toolbar icon with AMP broken and with a badge', () => { - act(() => { - render(, container); - }); + const { container } = render(); expect(container.querySelector('.amp-toolbar-icon')).toBeNull(); expect( @@ -91,9 +66,7 @@ describe('Icons', () => { }); it('renders the MoreMenuIcon', () => { - act(() => { - render(, container); - }); + const { container } = render(); expect(container.querySelector('.amp-toolbar-icon')).not.toBeNull(); expect( @@ -102,18 +75,14 @@ describe('Icons', () => { }); it('renders the StatusIcon', () => { - act(() => { - render(, container); - }); + const { container } = render(); expect(container.querySelector('.amp-status-icon')).not.toBeNull(); expect(container.querySelector('.amp-status-icon--broken')).toBeNull(); }); it('renders the broken StatusIcon', () => { - act(() => { - render(, container); - }); + const { container } = render(); expect( container.querySelector('.amp-status-icon--broken') diff --git a/assets/src/block-validation/components/sidebar-notification/test/sidebar-notification.js b/assets/src/block-validation/components/sidebar-notification/test/sidebar-notification.js index b0a839e0558..3afe9f02c19 100644 --- a/assets/src/block-validation/components/sidebar-notification/test/sidebar-notification.js +++ b/assets/src/block-validation/components/sidebar-notification/test/sidebar-notification.js @@ -1,12 +1,7 @@ /** * External dependencies */ -import { act } from 'react-dom/test-utils'; - -/** - * WordPress dependencies - */ -import { render, unmountComponentAtNode } from '@wordpress/element'; +import { render } from '@testing-library/react'; /** * Internal dependencies @@ -14,23 +9,8 @@ import { render, unmountComponentAtNode } from '@wordpress/element'; import { SidebarNotification } from '../index'; describe('SidebarNotification', () => { - let container; - - beforeEach(() => { - container = document.createElement('div'); - document.body.appendChild(container); - }); - - afterEach(() => { - unmountComponentAtNode(container); - container.remove(); - container = null; - }); - it('renders notification without icon and call to action', () => { - act(() => { - render(, container); - }); + const { container } = render(); expect(container.innerHTML).toMatchSnapshot(); expect(container.children).toHaveLength(1); @@ -45,16 +25,13 @@ describe('SidebarNotification', () => { }); it('renders status message with icon and call to action', () => { - act(() => { - render( - } - action={