From d2207330d81e71959810c3dc16eeaf6639d51dde Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Tue, 3 Mar 2026 12:46:16 -0800 Subject: [PATCH 1/7] Add GitHub Action for JavaScript type checking. This introduces a new GitHub Action workflow for JavaScript type checking, mirroring the implementation for PHPStan. It also adds a `typecheck:js` Grunt task and includes it in the `precommit:js` task list. Co-authored-by: gemini-cli <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .../workflows/javascript-type-checking.yml | 98 +++++++++++++++ .../reusable-javascript-type-checking.yml | 112 ++++++++++++++++++ Gruntfile.js | 13 ++ 3 files changed, 223 insertions(+) create mode 100644 .github/workflows/javascript-type-checking.yml create mode 100644 .github/workflows/reusable-javascript-type-checking.yml diff --git a/.github/workflows/javascript-type-checking.yml b/.github/workflows/javascript-type-checking.yml new file mode 100644 index 0000000000000..a3e2d70bc28aa --- /dev/null +++ b/.github/workflows/javascript-type-checking.yml @@ -0,0 +1,98 @@ +name: JavaScript Type Checking + +on: + # JavaScript type checking was introduced in 7.0.0. + push: + branches: + - trunk + - '[7-9].[0-9]' + tags: + - '[7-9].[0-9]' + - '[7-9]+.[0-9].[0-9]+' + pull_request: + branches: + - trunk + - '[7-9].[0-9]' + paths: + # This workflow only scans JavaScript files. + - '**.js' + # These files configure npm. Changes could affect the outcome. + - 'package*.json' + - '.nvmrc' + # This file configures TypeScript. Changes could affect the outcome. + - 'tsconfig.json' + # This directory contains TypeScript definitions. Changes could affect the outcome. + - 'typings/**' + # Confirm any changes to relevant workflow files. + - '.github/workflows/javascript-type-checking.yml' + - '.github/workflows/reusable-javascript-type-checking.yml' + 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 + +# Disable permissions for all available scopes by default. +# Any needed permissions should be configured at the job level. +permissions: {} + +jobs: + # Runs JavaScript type checking. + typecheck: + name: JavaScript type checking + uses: ./.github/workflows/reusable-javascript-type-checking.yml + permissions: + contents: read + if: ${{ github.repository == 'WordPress/wordpress-develop' || ( github.event_name == 'pull_request' && github.actor != 'dependabot[bot]' ) }} + + slack-notifications: + name: Slack Notifications + uses: ./.github/workflows/slack-notifications.yml + permissions: + actions: read + contents: read + needs: [ typecheck ] + if: ${{ github.repository == 'WordPress/wordpress-develop' && github.event_name != 'pull_request' && always() }} + with: + calling_status: ${{ contains( needs.*.result, 'cancelled' ) && 'cancelled' || contains( needs.*.result, 'failure' ) && 'failure' || 'success' }} + 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 }} + + failed-workflow: + name: Failed workflow tasks + runs-on: ubuntu-24.04 + permissions: + actions: write + needs: [ slack-notifications ] + if: | + always() && + github.repository == 'WordPress/wordpress-develop' && + github.event_name != 'pull_request' && + github.run_attempt < 2 && + ( + contains( needs.*.result, 'cancelled' ) || + contains( needs.*.result, 'failure' ) + ) + + steps: + - name: Dispatch workflow run + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + with: + retries: 2 + retry-exempt-status-codes: 418 + script: | + github.rest.actions.createWorkflowDispatch({ + owner: context.repo.owner, + repo: context.repo.repo, + workflow_id: 'failed-workflow.yml', + ref: 'trunk', + inputs: { + run_id: `${context.runId}`, + } + }); diff --git a/.github/workflows/reusable-javascript-type-checking.yml b/.github/workflows/reusable-javascript-type-checking.yml new file mode 100644 index 0000000000000..4ee771fa03dd6 --- /dev/null +++ b/.github/workflows/reusable-javascript-type-checking.yml @@ -0,0 +1,112 @@ +## +# A reusable workflow that runs JavaScript Type Checking. +## +name: JavaScript Type Checking + +on: + workflow_call: + inputs: + php-version: + description: 'The PHP version to use.' + required: false + type: 'string' + default: 'latest' + +# Disable permissions for all available scopes by default. +# Any needed permissions should be configured at the job level. +permissions: {} + +jobs: + # Runs JavaScript type checking. + # + # Violations are reported inline with annotations. + # + # Performs the following steps: + # - Checks out the repository. + # - Sets up Node.js. + # - Sets up PHP. + # - Logs debug information. + # - Installs Composer dependencies. + # - Make Composer packages available globally. + # - Installs npm dependencies. + # - Build WordPress. + # - Configures caching for TypeScript build info. + # - Runs JavaScript type checking. + # - Saves the TypeScript build info. + # - Ensures version-controlled files are not modified or deleted. + typecheck: + name: Run JavaScript type checking + runs-on: ubuntu-24.04 + permissions: + contents: read + timeout-minutes: 20 + + steps: + - name: Checkout repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + show-progress: ${{ runner.debug == '1' && 'true' || 'false' }} + persist-credentials: false + + - name: Set up Node.js + uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 + with: + node-version-file: '.nvmrc' + cache: npm + + - name: Set up PHP + uses: shivammathur/setup-php@20529878ed81ef8e78ddf08b480401e6101a850f # v2.35.3 + with: + php-version: ${{ inputs.php-version }} + coverage: none + + # This date is used to ensure that the Composer cache is cleared at least once every week. + # http://man7.org/linux/man-pages/man1/date.1.html + - name: "Get last Monday's date" + id: get-date + run: echo "date=$(/bin/date -u --date='last Mon' "+%F")" >> "$GITHUB_OUTPUT" + + - name: Log debug information + run: | + npm --version + node --version + composer --version + + # Since Composer dependencies are installed using `composer update` and no lock file is in version control, + # passing a custom cache suffix ensures that the cache is flushed at least once per week. + - name: Install Composer dependencies + uses: ramsey/composer-install@3cf229dc2919194e9e36783941438d17239e8520 # v3.1.1 + with: + custom-cache-suffix: ${{ steps.get-date.outputs.date }} + + - name: Make Composer packages available globally + run: echo "${PWD}/vendor/bin" >> "$GITHUB_PATH" + + - name: Install npm dependencies + run: npm ci --ignore-scripts + + - name: Build WordPress + run: npm run build:dev + + - name: Cache TypeScript build info + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + with: + path: | + *.tsbuildinfo + key: "ts-build-info-${{ github.run_id }}" + restore-keys: | + ts-build-info- + + - name: Run JavaScript type checking + run: npm run typecheck:js + + - name: "Save result cache" + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + if: ${{ !cancelled() }} + with: + path: | + *.tsbuildinfo + key: "ts-build-info-${{ github.run_id }}" + + - name: Ensure version-controlled files are not modified or deleted + run: git diff --exit-code diff --git a/Gruntfile.js b/Gruntfile.js index 2fe7dac819c6c..b5c69553f3f0d 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1556,6 +1556,7 @@ module.exports = function(grunt) { grunt.registerTask( 'precommit:js', [ 'webpack:prod', 'jshint:corejs', + 'typecheck:js', 'uglify:imgareaselect', 'uglify:jqueryform', 'uglify:moment', @@ -2009,6 +2010,18 @@ module.exports = function(grunt) { grunt.registerTask( 'test', 'Runs all QUnit and PHPUnit tasks.', ['qunit:compiled', 'phpunit'] ); + grunt.registerTask( 'typecheck:js', 'Runs TypeScript type checking.', function() { + var done = this.async(); + + grunt.util.spawn( { + cmd: 'npm', + args: [ 'run', 'typecheck:js' ], + opts: { stdio: 'inherit' } + }, function( error ) { + done( ! error ); + } ); + } ); + grunt.registerTask( 'phpstan', 'Runs PHPStan on the entire codebase.', function() { var done = this.async(); From 31d017c44daee02102b1fb3f5ce87c45b307c92c Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Tue, 3 Mar 2026 12:51:39 -0800 Subject: [PATCH 2/7] Streamline JavaScript type checking workflow. Remove unnecessary PHP, Composer, and build steps since `tsc --build` only requires npm dependencies and the source JavaScript files. Co-authored-by: gemini-cli <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .../reusable-javascript-type-checking.yml | 36 ------------------- 1 file changed, 36 deletions(-) diff --git a/.github/workflows/reusable-javascript-type-checking.yml b/.github/workflows/reusable-javascript-type-checking.yml index 4ee771fa03dd6..3caf22ffdd3f4 100644 --- a/.github/workflows/reusable-javascript-type-checking.yml +++ b/.github/workflows/reusable-javascript-type-checking.yml @@ -5,12 +5,6 @@ name: JavaScript Type Checking on: workflow_call: - inputs: - php-version: - description: 'The PHP version to use.' - required: false - type: 'string' - default: 'latest' # Disable permissions for all available scopes by default. # Any needed permissions should be configured at the job level. @@ -24,12 +18,8 @@ jobs: # Performs the following steps: # - Checks out the repository. # - Sets up Node.js. - # - Sets up PHP. # - Logs debug information. - # - Installs Composer dependencies. - # - Make Composer packages available globally. # - Installs npm dependencies. - # - Build WordPress. # - Configures caching for TypeScript build info. # - Runs JavaScript type checking. # - Saves the TypeScript build info. @@ -54,40 +44,14 @@ jobs: node-version-file: '.nvmrc' cache: npm - - name: Set up PHP - uses: shivammathur/setup-php@20529878ed81ef8e78ddf08b480401e6101a850f # v2.35.3 - with: - php-version: ${{ inputs.php-version }} - coverage: none - - # This date is used to ensure that the Composer cache is cleared at least once every week. - # http://man7.org/linux/man-pages/man1/date.1.html - - name: "Get last Monday's date" - id: get-date - run: echo "date=$(/bin/date -u --date='last Mon' "+%F")" >> "$GITHUB_OUTPUT" - - name: Log debug information run: | npm --version node --version - composer --version - - # Since Composer dependencies are installed using `composer update` and no lock file is in version control, - # passing a custom cache suffix ensures that the cache is flushed at least once per week. - - name: Install Composer dependencies - uses: ramsey/composer-install@3cf229dc2919194e9e36783941438d17239e8520 # v3.1.1 - with: - custom-cache-suffix: ${{ steps.get-date.outputs.date }} - - - name: Make Composer packages available globally - run: echo "${PWD}/vendor/bin" >> "$GITHUB_PATH" - name: Install npm dependencies run: npm ci --ignore-scripts - - name: Build WordPress - run: npm run build:dev - - name: Cache TypeScript build info uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: From 3cfad506cda530499faab73228f6622936cc9128 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Tue, 3 Mar 2026 13:01:13 -0800 Subject: [PATCH 3/7] Update github-script version in PHPStan workflow. Use actions/github-script@v8.0.0 to match other workflows. Co-authored-by: gemini-cli <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .github/workflows/phpstan-static-analysis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/phpstan-static-analysis.yml b/.github/workflows/phpstan-static-analysis.yml index 9bb12e40927e2..85f492e5f13af 100644 --- a/.github/workflows/phpstan-static-analysis.yml +++ b/.github/workflows/phpstan-static-analysis.yml @@ -81,7 +81,7 @@ jobs: steps: - name: Dispatch workflow run - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: retries: 2 retry-exempt-status-codes: 418 From d2ad278f767da48ec06b667c4a4bfa2f1c628291 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Tue, 3 Mar 2026 13:09:15 -0800 Subject: [PATCH 4/7] Try intentional TypeScript error --- src/js/_enqueues/wp/code-editor.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/js/_enqueues/wp/code-editor.js b/src/js/_enqueues/wp/code-editor.js index 86d5e03254166..83eaf9c194365 100644 --- a/src/js/_enqueues/wp/code-editor.js +++ b/src/js/_enqueues/wp/code-editor.js @@ -419,6 +419,8 @@ if ( 'undefined' === typeof window.wp.codeEditor ) { $textarea = $( textarea ); } + window.console.log( settings.doesNotExist ); + /** @type {CodeEditorSettings} */ const instanceSettings = $.extend( true, {}, wp.codeEditor.defaultSettings, settings ); From 6dfc36bc3897f6abc27ebde6fa10288ef229d4d0 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Tue, 3 Mar 2026 13:16:27 -0800 Subject: [PATCH 5/7] Revert "Try intentional TypeScript error" This reverts commit d2ad278f767da48ec06b667c4a4bfa2f1c628291. --- src/js/_enqueues/wp/code-editor.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/js/_enqueues/wp/code-editor.js b/src/js/_enqueues/wp/code-editor.js index 83eaf9c194365..86d5e03254166 100644 --- a/src/js/_enqueues/wp/code-editor.js +++ b/src/js/_enqueues/wp/code-editor.js @@ -419,8 +419,6 @@ if ( 'undefined' === typeof window.wp.codeEditor ) { $textarea = $( textarea ); } - window.console.log( settings.doesNotExist ); - /** @type {CodeEditorSettings} */ const instanceSettings = $.extend( true, {}, wp.codeEditor.defaultSettings, settings ); From 760d949045f70785028e7a1e92bfe63140684bea Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Wed, 4 Mar 2026 01:29:31 -0800 Subject: [PATCH 6/7] Add TypeScript extensions Co-authored-by: Jon Surrell --- .github/workflows/javascript-type-checking.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/javascript-type-checking.yml b/.github/workflows/javascript-type-checking.yml index a3e2d70bc28aa..2cafb4c8d04fd 100644 --- a/.github/workflows/javascript-type-checking.yml +++ b/.github/workflows/javascript-type-checking.yml @@ -16,6 +16,8 @@ on: paths: # This workflow only scans JavaScript files. - '**.js' + - '**.ts' + - '**.tsx' # These files configure npm. Changes could affect the outcome. - 'package*.json' - '.nvmrc' From bbbf117cca8ff3ed98d126b0c1e5b3423e0e597f Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Wed, 4 Mar 2026 01:29:54 -0800 Subject: [PATCH 7/7] Reduce timeout Co-authored-by: Jon Surrell --- .github/workflows/reusable-javascript-type-checking.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/reusable-javascript-type-checking.yml b/.github/workflows/reusable-javascript-type-checking.yml index 3caf22ffdd3f4..3737bba6abb74 100644 --- a/.github/workflows/reusable-javascript-type-checking.yml +++ b/.github/workflows/reusable-javascript-type-checking.yml @@ -29,7 +29,7 @@ jobs: runs-on: ubuntu-24.04 permissions: contents: read - timeout-minutes: 20 + timeout-minutes: 10 steps: - name: Checkout repository