Index: branches/3.9/.github/workflows/coding-standards.yml
===================================================================
--- branches/3.9/.github/workflows/coding-standards.yml	(revision 52882)
+++ branches/3.9/.github/workflows/coding-standards.yml	(revision 53622)
@@ -6,5 +6,4 @@
   push:
     branches:
-      - master
       - trunk
       - '3.[89]'
@@ -15,5 +14,4 @@
   pull_request:
     branches:
-      - master
       - trunk
       - '3.[89]'
@@ -35,4 +33,11 @@
   workflow_dispatch:
 
+# Cancels all previous workflow runs for pull requests that have not completed.
+concurrency:
+  # The concurrency group contains the workflow name and the branch name for pull requests
+  # or the commit hash for any other events.
+  group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }}
+  cancel-in-progress: true
+
 jobs:
   # Runs the JavaScript coding standards checks.
@@ -42,14 +47,13 @@
   # Performs the following steps:
   # - Checks out the repository.
-  # - Logs debug information about the runner container.
-  # - Installs NodeJS 14.
-  # - Sets up caching for NPM.
+  # - Logs debug information about the GitHub Action runner.
+  # - Installs NodeJS.
   # - Logs updated debug information.
-  # _ Installs NPM dependencies using install-changed to hash the `package.json` file.
+  # _ Installs NPM dependencies.
   # - Run the WordPress JSHint checks.
-  # - todo: Configure Slack notifications for failing tests.
   jshint:
     name: JavaScript coding standards
     runs-on: ubuntu-latest
+    timeout-minutes: 20
     if: ${{ github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' }}
     env:
@@ -58,5 +62,5 @@
     steps:
       - name: Checkout repository
-        uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
+        uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
 
       - name: Log debug information
@@ -68,16 +72,8 @@
 
       - name: Install NodeJS
-        uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea # v2.1.5
+        uses: actions/setup-node@eeb10cff27034e7acf239c5d29f62154018672fd # v3.3.0
         with:
-          node-version: 14
-
-      - name: Cache NodeJS modules
-        uses: actions/cache@26968a09c0ea4f3e233fdddbafd1166051a095f6 # v2.1.4
-        env:
-          cache-name: cache-node-modules
-        with:
-          # npm cache files are stored in `~/.npm` on Linux/macOS
-          path: ~/.npm
-          key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
+          node-version-file: '.nvmrc'
+          cache: npm
 
       - name: Log debug information
@@ -91,2 +87,15 @@
       - name: Run JSHint
         run: npm run grunt jshint
+
+  slack-notifications:
+    name: Slack Notifications
+    uses: WordPress/wordpress-develop/.github/workflows/slack-notifications.yml@trunk
+    needs: [ jshint ]
+    if: ${{ github.repository == 'WordPress/wordpress-develop' && github.event_name != 'pull_request' && always() }}
+    with:
+      calling_status: ${{ needs.jshint.result == 'success' && 'success' || needs.jshint.result == 'cancelled' && 'cancelled' || 'failure' }}
+    secrets:
+      SLACK_GHA_SUCCESS_WEBHOOK: ${{ secrets.SLACK_GHA_SUCCESS_WEBHOOK }}
+      SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }}
+      SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }}
+      SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }}
Index: branches/3.9/.github/workflows/end-to-end-tests.yml
===================================================================
--- branches/3.9/.github/workflows/end-to-end-tests.yml	(revision 52882)
+++ 	(revision )
@@ -1,122 +1,0 @@
-name: End-to-end Tests
-
-on:
-  # The end to end test suite was introduced in WordPress 5.3.
-  push:
-    branches:
-      - master
-      - trunk
-      - '5.[3-9]'
-      - '[6-9].[0-9]'
-    tags:
-      - '5.[3-9]*'
-      - '[6-9].[0-9]*'
-  pull_request:
-    branches:
-      - master
-      - trunk
-      - '5.[3-9]'
-      - '[6-9].[0-9]'
-  workflow_dispatch:
-
-env:
-  LOCAL_DIR: build
-
-jobs:
-  # Runs the end-to-end test suite.
-  #
-  # Performs the following steps:
-  # - Cancels all previous workflow runs for pull requests that have not completed.
-  # - Set environment variables.
-  # - Checks out the repository.
-  # - Logs debug information about the runner container.
-  # - Installs NodeJS 14.
-  # - Sets up caching for NPM.
-  # _ Installs NPM dependencies using install-changed to hash the `package.json` file.
-  # - Builds WordPress to run from the `build` directory.
-  # - Starts the WordPress Docker container.
-  # - Logs general debug information.
-  # - Logs the running Docker containers.
-  # - Logs Docker debug information (about both the Docker installation within the runner and the WordPress container).
-  # - Install WordPress within the Docker container.
-  # - Run the E2E tests.
-  # - todo: Configure Slack notifications for failing tests.
-  e2e-tests:
-    name: E2E Tests
-    runs-on: ubuntu-latest
-    if: ${{ github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' }}
-
-    steps:
-      - name: Cancel previous runs of this workflow (pull requests only)
-        if: ${{ github.event_name == 'pull_request' }}
-        uses: styfle/cancel-workflow-action@3d86a7cc43670094ac248017207be0295edbc31d # v0.8.0
-
-      - name: Configure environment variables
-        run: |
-          echo "PHP_FPM_UID=$(id -u)" >> $GITHUB_ENV
-          echo "PHP_FPM_GID=$(id -g)" >> $GITHUB_ENV
-
-      - name: Checkout repository
-        uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
-
-      - name: Log debug information
-        run: |
-          npm --version
-          node --version
-          curl --version
-          git --version
-          svn --version
-          php --version
-          php -i
-          locale -a
-
-      - name: Install NodeJS
-        uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea # v2.1.5
-        with:
-          node-version: 14
-
-      - name: Cache NodeJS modules
-        uses: actions/cache@26968a09c0ea4f3e233fdddbafd1166051a095f6 # v2.1.4
-        env:
-          cache-name: cache-node-modules
-        with:
-          # npm cache files are stored in `~/.npm` on Linux/macOS
-          path: ~/.npm
-          key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
-
-      - name: Install Dependencies
-        run: npm ci
-
-      - name: Build WordPress
-        run: npm run build
-
-      - name: Start Docker environment
-        run: |
-          npm run env:start
-
-      - name: General debug information
-        run: |
-          npm --version
-          node --version
-          curl --version
-          git --version
-          svn --version
-
-      - name: Log running Docker containers
-        run: docker ps -a
-
-      - name: Docker debug information
-        run: |
-          docker -v
-          docker-compose -v
-          docker-compose run --rm mysql mysql --version
-          docker-compose run --rm php php --version
-          docker-compose run --rm php php -m
-          docker-compose run --rm php php -i
-          docker-compose run --rm php locale -a
-
-      - name: Install WordPress
-        run: npm run env:install
-
-      - name: Run E2E tests
-        run: npm run test:e2e
Index: branches/3.9/.github/workflows/javascript-tests.yml
===================================================================
--- branches/3.9/.github/workflows/javascript-tests.yml	(revision 52882)
+++ branches/3.9/.github/workflows/javascript-tests.yml	(revision 53622)
@@ -5,5 +5,4 @@
   push:
     branches:
-      - master
       - trunk
       - '3.[89]'
@@ -14,5 +13,4 @@
   pull_request:
     branches:
-      - master
       - trunk
       - '3.[89]'
@@ -33,29 +31,30 @@
   workflow_dispatch:
 
+# Cancels all previous workflow runs for pull requests that have not completed.
+concurrency:
+  # The concurrency group contains the workflow name and the branch name for pull requests
+  # or the commit hash for any other events.
+  group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }}
+  cancel-in-progress: true
+
 jobs:
   # Runs the QUnit tests for WordPress.
   #
   # Performs the following steps:
-  # - Cancels all previous workflow runs for pull requests that have not completed.
   # - Checks out the repository.
-  # - Logs debug information about the runner container.
-  # - Installs NodeJS 14.
-  # - Sets up caching for NPM.
+  # - Logs debug information about the GitHub Action runner.
+  # - Installs NodeJS.
   # - Logs updated debug information.
-  # _ Installs NPM dependencies using install-changed to hash the `package.json` file.
+  # _ Installs NPM dependencies.
   # - Run the WordPress QUnit tests.
-  # - todo: Configure Slack notifications for failing tests.
   test-js:
     name: QUnit Tests
     runs-on: ubuntu-latest
+    timeout-minutes: 20
     if: ${{ github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' }}
 
     steps:
-      - name: Cancel previous runs of this workflow (pull requests only)
-        if: ${{ github.event_name == 'pull_request' }}
-        uses: styfle/cancel-workflow-action@3d86a7cc43670094ac248017207be0295edbc31d # v0.8.0
-
       - name: Checkout repository
-        uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
+        uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
 
       - name: Log debug information
@@ -67,16 +66,8 @@
 
       - name: Install NodeJS
-        uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea # v2.1.5
+        uses: actions/setup-node@eeb10cff27034e7acf239c5d29f62154018672fd # v3.3.0
         with:
-          node-version: 14
-
-      - name: Cache NodeJS modules
-        uses: actions/cache@26968a09c0ea4f3e233fdddbafd1166051a095f6 # v2.1.4
-        env:
-          cache-name: cache-node-modules
-        with:
-          # npm cache files are stored in `~/.npm` on Linux/macOS
-          path: ~/.npm
-          key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
+          node-version-file: '.nvmrc'
+          cache: npm
 
       - name: Log debug information
@@ -90,2 +81,15 @@
       - name: Run QUnit tests
         run: npm run grunt qunit:compiled
+
+  slack-notifications:
+    name: Slack Notifications
+    uses: WordPress/wordpress-develop/.github/workflows/slack-notifications.yml@trunk
+    needs: [ test-js ]
+    if: ${{ github.repository == 'WordPress/wordpress-develop' && github.event_name != 'pull_request' && always() }}
+    with:
+      calling_status: ${{ needs.test-js.result == 'success' && 'success' || needs.test-js.result == 'cancelled' && 'cancelled' || 'failure' }}
+    secrets:
+      SLACK_GHA_SUCCESS_WEBHOOK: ${{ secrets.SLACK_GHA_SUCCESS_WEBHOOK }}
+      SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }}
+      SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }}
+      SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }}
Index: branches/3.9/.github/workflows/php-compatibility.yml
===================================================================
--- branches/3.9/.github/workflows/php-compatibility.yml	(revision 52882)
+++ 	(revision )
@@ -1,79 +1,0 @@
-name: PHP Compatibility
-
-on:
-  # PHP compatibility testing was introduced in WordPress 5.5.
-  push:
-    branches:
-      - master
-      - trunk
-      - '5.[5-9]'
-      - '[6-9].[0-9]'
-    tags:
-      - '5.[5-9]*'
-      - '[6-9].[0-9]*'
-  pull_request:
-    branches:
-      - master
-      - trunk
-      - '5.[5-9]'
-      - '[6-9].[0-9]'
-    paths:
-      # This workflow only scans PHP files.
-      - '**.php'
-      # These files configure Composer. Changes could affect the outcome.
-      - 'composer.*'
-      # This file configures PHP Compatibility scanning. Changes could affect the outcome.
-      - 'phpcompat.xml.dist'
-      # Changes to workflow files should always verify all workflows are successful.
-      - '.github/workflows/*.yml'
-  workflow_dispatch:
-
-jobs:
-
-  # Runs PHP compatibility testing.
-  #
-  # Violations are reported inline with annotations.
-  #
-  # Performs the following steps:
-  # - Checks out the repository.
-  # - Sets up PHP.
-  # - Logs debug information about the runner container.
-  # - Installs Composer dependencies (use cache if possible).
-  # - Make Composer packages available globally.
-  # - Logs PHP_CodeSniffer debug information.
-  # - Runs the PHP compatibility tests.
-  # - todo: Configure Slack notifications for failing scans.
-  php-comatibility:
-    name: Check PHP compatibility
-    runs-on: ubuntu-latest
-    if: ${{ github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' }}
-
-    steps:
-      - name: Checkout repository
-        uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
-
-      - name: Set up PHP
-        uses: shivammathur/setup-php@afefcaf556d98dc7896cca380e181decb609ca44 # v2.10.0
-        with:
-          php-version: '7.4'
-          coverage: none
-          tools: composer, cs2pr
-
-      - name: Log debug information
-        run: |
-          php --version
-          composer --version
-
-      - name: Install Composer dependencies
-        uses: ramsey/composer-install@92a7904348d4ad30236f3611e33b7f0c6f9edd70 # v1.1.0
-        with:
-          composer-options: "--no-progress --no-ansi --no-interaction"
-
-      - name: Make Composer packages available globally
-        run: echo "${PWD}/vendor/bin" >> $GITHUB_PATH
-
-      - name: Log PHPCS debug information
-        run: phpcs -i
-
-      - name: Run PHP compatibility tests
-        run: phpcs --standard=phpcompat.xml.dist -q --report=checkstyle | cs2pr
Index: branches/3.9/.github/workflows/phpunit-tests.yml
===================================================================
--- branches/3.9/.github/workflows/phpunit-tests.yml	(revision 52882)
+++ branches/3.9/.github/workflows/phpunit-tests.yml	(revision 53622)
@@ -4,5 +4,4 @@
   push:
     branches:
-      - master
       - trunk
       - '3.[7-9]'
@@ -13,5 +12,4 @@
   pull_request:
     branches:
-      - master
       - trunk
       - '3.[7-9]'
@@ -22,4 +20,11 @@
     - cron: '0 0 * * 0'
 
+# Cancels all previous workflow runs for pull requests that have not completed.
+concurrency:
+    # The concurrency group contains the workflow name and the branch name for pull requests
+    # or the commit hash for any other events.
+  group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }}
+  cancel-in-progress: true
+
 env:
   LOCAL_DIR: build
@@ -36,8 +41,7 @@
   # - Cancels all previous workflow runs for pull requests that have not completed.
   # - Checks out the repository.
-  # - Logs debug information about the runner container.
-  # - Installs NodeJS 14.
-  # - Sets up caching for NPM.
-  # _ Installs NPM dependencies using install-changed to hash the `package.json` file.
+  # - Logs debug information about the GitHub Action runner.
+  # - Installs NodeJS.
+  # _ Installs NPM dependencies.
   # - Builds WordPress to run from the `build` directory.
   # - Creates a ZIP file of compiled WordPress.
@@ -49,10 +53,6 @@
 
     steps:
-      - name: Cancel previous runs of this workflow (pull requests only)
-        if: ${{ github.event_name == 'pull_request' }}
-        uses: styfle/cancel-workflow-action@3d86a7cc43670094ac248017207be0295edbc31d # v0.8.0
-
       - name: Checkout repository
-        uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
+        uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
 
       - name: Log debug information
@@ -70,16 +70,8 @@
 
       - name: Install NodeJS
-        uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea # v2.1.5
-        with:
-          node-version: 14
-
-      - name: Cache NodeJS modules
-        uses: actions/cache@26968a09c0ea4f3e233fdddbafd1166051a095f6 # v2.1.4
-        env:
-          cache-name: cache-node-modules
-        with:
-          # npm cache files are stored in `~/.npm` on Linux/macOS
-          path: ~/.npm
-          key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
+        uses: actions/setup-node@eeb10cff27034e7acf239c5d29f62154018672fd # v3.3.0
+        with:
+          node-version-file: '.nvmrc'
+          cache: npm
 
       - name: Install Dependencies
@@ -90,5 +82,5 @@
 
       - name: Create ZIP artifact
-        uses: thedoctor0/zip-release@a1afcab9c664c9976ac398fa831eac67bed1eb0e # v0.4.1
+        uses: thedoctor0/zip-release@09336613be18a8208dfa66bd57efafd9e2685657 # v0.6.2
         with:
           filename: built-wp-${{ github.sha }}.zip
@@ -96,5 +88,5 @@
 
       - name: Upload build artifact
-        uses: actions/upload-artifact@e448a9b857ee2131e752b06002bf0e093c65e571 # v2.2.2
+        uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
         with:
           name: built-wp-${{ github.sha }}
@@ -105,19 +97,18 @@
   #
   # Performs the following steps:
-  # - Set environment variables.
+  # - Sets environment variables.
   # - Sets up the environment variables needed for testing with memcached (if desired).
   # - Downloads the built WordPress artifact from the previous job.
   # - Unzips the artifact.
-  # - Installs NodeJS 14.
-  # - Sets up caching for NPM.
-  # _ Installs NPM dependencies using install-changed to hash the `package.json` file.
+  # - Installs NodeJS.
+  # _ Installs NPM dependencies.
   # - Configures caching for Composer.
   # _ Installs Composer dependencies (if desired).
-  # - Logs Docker debug information (about both the Docker installation within the runner).
+  # - Logs Docker debug information (about the Docker installation within the runner).
   # - Starts the WordPress Docker container.
-  # - Starts the memcached server after the Docker network has been created (if desired).
-  # - Logs WordPress Docker container debug information.
-  # - Logs debug general information.
+  # - Starts the Memcached server after the Docker network has been created (if desired).
+  # - Logs general debug information about the runner.
   # - Logs the running Docker containers.
+  # - Logs debug information from inside the WordPress Docker container.
   # - Logs debug information about what's installed within the WordPress Docker containers.
   # - Install WordPress within the Docker container.
@@ -126,9 +117,9 @@
   # - Reconnect the directory to the Git repository.
   # - Submit the test results to the WordPress.org host test results.
-  # - todo: Configure Slack notifications for failing tests.
   test-php:
-    name: ${{ matrix.php }}${{ matrix.multisite && ' multisite' || '' }}${{ matrix.split_slow && ' slow tests' || '' }} ${{ matrix.memcached && ' with memcached' || '' }} on ${{ matrix.os }}
+    name: ${{ matrix.php }}${{ matrix.multisite && ' multisite' || '' }}${{ matrix.split_slow && ' slow tests' || '' }}${{ matrix.memcached && ' with memcached' || '' }} on ${{ matrix.os }}
     needs: setup-wordpress
     runs-on: ${{ matrix.os }}
+    timeout-minutes: 20
     strategy:
       fail-fast: false
@@ -151,5 +142,5 @@
 
       - name: Download the built WordPress artifact
-        uses: actions/download-artifact@4a7a711286f30c025902c28b541c10e147a9b843 # v2.0.8
+        uses: actions/download-artifact@fb598a63ae348fa914e94cd0ff38f362e927b741 # v3.0.0
         with:
           name: built-wp-${{ github.sha }}
@@ -159,16 +150,8 @@
 
       - name: Install NodeJS
-        uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea # v2.1.5
-        with:
-          node-version: 14
-
-      - name: Use cached Node modules
-        uses: actions/cache@26968a09c0ea4f3e233fdddbafd1166051a095f6 # v2.1.4
-        env:
-          cache-name: cache-node-modules
-        with:
-          # npm cache files are stored in `~/.npm` on Linux/macOS
-          path: ~/.npm
-          key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
+        uses: actions/setup-node@eeb10cff27034e7acf239c5d29f62154018672fd # v3.3.0
+        with:
+          node-version-file: '.nvmrc'
+          cache: npm
 
       - name: Install Dependencies
@@ -177,5 +160,5 @@
       - name: Cache Composer dependencies
         if: ${{ env.COMPOSER_INSTALL == true }}
-        uses: actions/cache@26968a09c0ea4f3e233fdddbafd1166051a095f6 # v2.1.4
+        uses: actions/cache@c3f1317a9e7b1ef106c153ac8c0f00fed3ddbc0d # v3.0.4
         env:
           cache-name: cache-composer-dependencies
@@ -253,6 +236,6 @@
 
       - name: Checkout the WordPress Test Reporter
-        if: ${{ github.repository == 'WordPress/wordpress-develop' && github.ref == 'refs/heads/master' && matrix.report }}
-        uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
+        if: ${{ github.repository == 'WordPress/wordpress-develop' && github.ref == 'refs/heads/trunk' && matrix.report }}
+        uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
         with:
           repository: 'WordPress/phpunit-test-runner'
@@ -260,14 +243,27 @@
 
       - name: Set up the Git repository
-        if: ${{ github.repository == 'WordPress/wordpress-develop' && github.ref == 'refs/heads/master' && matrix.report }}
+        if: ${{ github.repository == 'WordPress/wordpress-develop' && github.ref == 'refs/heads/trunk' && matrix.report }}
         run: |
           git init
           git remote add origin https://github.com/WordPress/wordpress-develop.git
           git fetch
-          git reset origin/master
+          git reset origin/trunk
 
       - name: Submit test results to the WordPress.org host test results
-        if: ${{ github.repository == 'WordPress/wordpress-develop' && github.ref == 'refs/heads/master' && matrix.report }}
+        if: ${{ github.repository == 'WordPress/wordpress-develop' && github.ref == 'refs/heads/trunk' && matrix.report }}
         env:
           WPT_REPORT_API_KEY: "${{ secrets.WPT_REPORT_API_KEY }}"
         run: docker-compose run --rm -e WPT_REPORT_API_KEY -e WPT_PREPARE_DIR=/var/www -e WPT_TEST_DIR=/var/www php php test-runner/report.php
+
+  slack-notifications:
+    name: Slack Notifications
+    uses: WordPress/wordpress-develop/.github/workflows/slack-notifications.yml@trunk
+    needs: [ setup-wordpress, test-php ]
+    if: ${{ github.repository == 'WordPress/wordpress-develop' && github.event_name != 'pull_request' && always() }}
+    with:
+      calling_status: ${{ needs.test-php.result == 'success' && 'success' || needs.test-php.result == 'cancelled' && 'cancelled' || 'failure' }}
+    secrets:
+      SLACK_GHA_SUCCESS_WEBHOOK: ${{ secrets.SLACK_GHA_SUCCESS_WEBHOOK }}
+      SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }}
+      SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }}
+      SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }}
Index: branches/3.9/.github/workflows/test-npm.yml
===================================================================
--- branches/3.9/.github/workflows/test-npm.yml	(revision 52882)
+++ branches/3.9/.github/workflows/test-npm.yml	(revision 53622)
@@ -4,5 +4,4 @@
   push:
     branches:
-      - master
       - trunk
       - '3.[7-9]'
@@ -10,5 +9,4 @@
   pull_request:
     branches:
-      - master
       - trunk
       - '3.[7-9]'
@@ -26,30 +24,23 @@
   workflow_dispatch:
 
+# Cancels all previous workflow runs for pull requests that have not completed.
+concurrency:
+    # The concurrency group contains the workflow name and the branch name for pull requests
+    # or the commit hash for any other events.
+  group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }}
+  cancel-in-progress: true
+
 env:
   PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: ${{ true }}
 
 jobs:
-  # Prepares the workflow.
-  #
-  # Performs the following steps:
-  # - Cancels all previous workflow runs for pull requests that have not completed.
-  prepare-workflow:
-    name: Prepare the workflow
-    runs-on: ubuntu-latest
-    if: ${{ github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' }}
-
-    steps:
-      - name: Cancel previous runs of this workflow (pull requests only)
-        if: ${{ github.event_name == 'pull_request' }}
-        uses: styfle/cancel-workflow-action@3d86a7cc43670094ac248017207be0295edbc31d # v0.8.0
-
   # Verifies that installing NPM dependencies and building WordPress works as expected.
   #
   # Performs the following steps:
   # - Checks out the repository.
-  # - Logs debug information about the runner container.
-  # - Installs NodeJS 14.
+  # - Logs debug information about the GitHub Action runner.
+  # - Installs NodeJS.
   # - Sets up caching for NPM.
-  # _ Installs NPM dependencies using install-changed to hash the `package.json` file.
+  # _ Installs NPM dependencies.
   # - Builds WordPress to run from the `build` directory.
   # - Cleans up after building WordPress to the `build` directory.
@@ -57,6 +48,6 @@
     name: Test NPM on ${{ matrix.os }}
     runs-on: ${{ matrix.os }}
+    timeout-minutes: 20
     if: ${{ github.repository == 'WordPress/wordpress-develop' || github.event_name == 'pull_request' }}
-    needs: prepare-workflow
     strategy:
       matrix:
@@ -65,5 +56,5 @@
     steps:
       - name: Checkout repository
-        uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
+        uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
 
       - name: Log debug information
@@ -76,26 +67,8 @@
 
       - name: Install NodeJS
-        uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea # v2.1.5
+        uses: actions/setup-node@eeb10cff27034e7acf239c5d29f62154018672fd # v3.3.0
         with:
-          node-version: 14
-
-      - name: Cache NodeJS modules (Ubuntu & MacOS)
-        uses: actions/cache@26968a09c0ea4f3e233fdddbafd1166051a095f6 # v2.1.4
-        if: ${{ matrix.os != 'windows-latest' }}
-        with:
-          path: ~/.npm
-          key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
-
-      - name: Get NPM cache directory (Windows only)
-        if: ${{ matrix.os == 'windows-latest' }}
-        id: npm-cache
-        run: echo "::set-output name=dir::$(npm config get cache)"
-
-      - name: Cache NodeJS modules (Windows only)
-        uses: actions/cache@26968a09c0ea4f3e233fdddbafd1166051a095f6 # v2.1.4
-        if: ${{ matrix.os == 'windows-latest' }}
-        with:
-          path: ${{ steps.npm-cache.outputs.dir }}
-          key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
+          node-version-file: '.nvmrc'
+          cache: npm
 
       - name: Install Dependencies
@@ -110,12 +83,12 @@
   # Verifies that installing NPM dependencies and building WordPress works as expected on MacOS.
   #
-  # This is a separate job in order to that more strict conditions can be used.
+  # This is separate from the job above in order to use stricter conditions about when to run.
+  # This avoids unintentionally consuming excessive minutes, as MacOS jobs consume minutes at a 10x rate.
   #
   # Performs the following steps:
   # - Checks out the repository.
-  # - Logs debug information about the runner container.
-  # - Installs NodeJS 14.
-  # - Sets up caching for NPM.
-  # _ Installs NPM dependencies using install-changed to hash the `package.json` file.
+  # - Logs debug information about the GitHub Action runner.
+  # - Installs NodeJS.
+  # _ Installs NPM dependencies.
   # - Builds WordPress to run from the `build` directory.
   # - Cleans up after building WordPress to the `build` directory.
@@ -124,8 +97,7 @@
     runs-on: macos-latest
     if: ${{ github.repository == 'WordPress/wordpress-develop' }}
-    needs: prepare-workflow
     steps:
       - name: Checkout repository
-        uses: actions/checkout@5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f # v2.3.4
+        uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # v3.0.2
 
       - name: Log debug information
@@ -138,14 +110,8 @@
 
       - name: Install NodeJS
-        uses: actions/setup-node@46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea # v2.1.5
+        uses: actions/setup-node@eeb10cff27034e7acf239c5d29f62154018672fd # v3.3.0
         with:
-          node-version: 14
-
-      - name: Cache NodeJS modules
-        uses: actions/cache@26968a09c0ea4f3e233fdddbafd1166051a095f6 # v2.1.4
-        if: ${{ matrix.os != 'windows-latest' }}
-        with:
-          path: ~/.npm
-          key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
+          node-version-file: '.nvmrc'
+          cache: npm
 
       - name: Install Dependencies
@@ -157,2 +123,15 @@
       - name: Clean after building
         run: npm run grunt clean
+
+  slack-notifications:
+    name: Slack Notifications
+    uses: WordPress/wordpress-develop/.github/workflows/slack-notifications.yml@trunk
+    needs: [ test-npm, test-npm-macos ]
+    if: ${{ github.repository == 'WordPress/wordpress-develop' && github.event_name != 'pull_request' && always() }}
+    with:
+      calling_status: ${{ needs.test-npm.result == 'success' && needs.test-npm-macos.result == 'success' && 'success' || ( needs.test-npm.result == 'cancelled' || needs.test-npm-macos.result == 'cancelled' ) && 'cancelled' || 'failure' }}
+    secrets:
+      SLACK_GHA_SUCCESS_WEBHOOK: ${{ secrets.SLACK_GHA_SUCCESS_WEBHOOK }}
+      SLACK_GHA_CANCELLED_WEBHOOK: ${{ secrets.SLACK_GHA_CANCELLED_WEBHOOK }}
+      SLACK_GHA_FIXED_WEBHOOK: ${{ secrets.SLACK_GHA_FIXED_WEBHOOK }}
+      SLACK_GHA_FAILURE_WEBHOOK: ${{ secrets.SLACK_GHA_FAILURE_WEBHOOK }}
Index: branches/3.9/.github/workflows/welcome-new-contributors.yml
===================================================================
--- branches/3.9/.github/workflows/welcome-new-contributors.yml	(revision 52882)
+++ branches/3.9/.github/workflows/welcome-new-contributors.yml	(revision 53622)
@@ -9,4 +9,5 @@
   post-welcome-message:
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     if: ${{ github.repository == 'WordPress/wordpress-develop' }}
 
