Make WordPress Core

Opened 2 weeks ago

Last modified 5 hours ago

#64662 reopened task (blessed)

Add TypeScript static analysis for core JavaScript files

Reported by: westonruter's profile westonruter Owned by: westonruter's profile westonruter
Milestone: 7.0 Priority: normal
Severity: normal Version:
Component: Build/Test Tools Keywords: has-patch changes-requested
Focuses: javascript Cc:

Description (last modified by westonruter)

For #64661, a PR is proposed which adds TypeScript checking for the scripts related to the CodeMirror code editor integrations. With that in place, core should start expanding the scope of which JS files are checked to ensure code quality and fix subtle bugs. The same is being done for PHP with PHPStan in #61175.

Note that TypeScript is already being used in Gutenberg. See https://make.wordpress.org/core/2021/03/18/proposal-native-typescript-support-in-gutenberg/

To do:

  1. Commit https://github.com/WordPress/wordpress-develop/pull/10900
  2. Add typecheck:js to the precommit Grunt task.
  3. Add GHA workflow which runs typecheck:js

Change History (15)

#1 @westonruter
2 weeks ago

  • Description modified (diff)

#2 @westonruter
2 weeks ago

  • Milestone changed from Awaiting Review to 7.0

#3 @westonruter
2 weeks ago

  • Owner set to westonruter
  • Status changed from new to accepted

#4 @westonruter
13 days ago

PHPStan static analysis (exposed via npm run typecheck:php and composer phpstan) has landed in r61699.

#5 @westonruter
32 hours ago

In 61800:

Code Editor: Improve types and fix options handling to avoid double-linting at initialization.

  • Refactor how CodeMirror is initialized so that the full settings are provided up-front. This avoids the linting from being applied twice at initialization, the first time with an incorrect configuration.
  • Add initial TypeScript configuration for core with npm run typecheck:js.
  • Add comprehensive types for code editor files: code-editor.js, javascript-lint.js, and htmlhint-kses.js.
  • Move code editor scripts from src/js/_enqueues/vendor/codemirror/ to src/js/_enqueues/lib/codemirror/. The CodeMirror library is sourced from the npm package as of r61539.
  • Remove (deprecated) esprima.js from being committed to SVN since in r61539 it was switched to using the npm package as its source.
  • Move fakejshint.js to src/js/_enqueues/deprecated.

Developed in https://github.com/WordPress/wordpress-develop/pull/10900

Follow up to r61611, r61539.

Props westonruter, jonsurrell, justlevine.
See #64662, #48456.
Fixes #64661.

This ticket was mentioned in PR #11131 on WordPress/wordpress-develop by @westonruter.


31 hours ago
#6

  • Keywords has-patch added

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.

Trac ticket: https://core.trac.wordpress.org/ticket/64662

## Use of AI Tools

Initial commit authored by Gemini CLI with prompt:

Take a look at https://core.trac.wordpress.org/ticket/64662 and implement. You can see that typecheck:js npm script was added in b6c1bb776b360ef64a00468e6df72792511866d3. Similarly, you can see in 8a82e67cf65766fcb8a11e3fe5c6e2f48083fcdb how typecheck:php was introduced for PHPStan and a GitHub action was added to automatically run. What was done for PHPStan, implement similarly for TypeScript.

@westonruter commented on PR #11131:


31 hours ago
#7

Difference between reusable-phpstan-static-analysis.yml and reusable-javascript-type-checking.yml:

  • .github/workflows/

    old new  
    11##
    2 # A reusable workflow that runs PHP Static Analysis tests.
     2# A reusable workflow that runs .
    33##
    4 name: PHP Static Analysis
     4name:
    55
    66on:
    77  workflow_call:
    8     inputs:
    9       php-version:
    10         description: 'The PHP version to use.'
    11         required: false
    12         type: 'string'
    13         default: 'latest'
    148
    159# Disable permissions for all available scopes by default.
    1610# Any needed permissions should be configured at the job level.
    1711permissions: {}
    1812
    1913jobs:
    20   # Runs PHP static analysis tests.
     14  # Runs .
    2115  #
    2216  # Violations are reported inline with annotations.
    2317  #
    2418  # Performs the following steps:
    2519  # - Checks out the repository.
    26   # - Sets up PHP.
     20  # - Sets up .
    2721  # - Logs debug information.
    28   # - Installs Composer dependencies.
    29   # - Configures caching for PHP static analysis scans.
    30   # - Make Composer packages available globally.
    31   # - Runs PHPStan static analysis (with Pull Request annotations).
    32   # - Saves the PHPStan result cache.
     22  # - Installs npm dependencies.
     23  # - Configures caching for TypeScript build info.
     24  # - Runs JavaScript type checking.
     25  # - Saves the TypeScript build info.
    3326  # - Ensures version-controlled files are not modified or deleted.
    34   phpstan:
    35     name: Run PHP static analysis
     27  :
     28    name: Run
    3629    runs-on: ubuntu-24.04
    3730    permissions:
    3831      contents: read
     
    5144          node-version-file: '.nvmrc'
    5245          cache: npm
    5346
    54       - name: Set up PHP
    55         uses: shivammathur/setup-php@20529878ed81ef8e78ddf08b480401e6101a850f # v2.35.3
    56         with:
    57           php-version: ${{ inputs.php-version }}
    58           coverage: none
    59           tools: cs2pr
    60 
    61       # This date is used to ensure that the Composer cache is cleared at least once every week.
    62       # http://man7.org/linux/man-pages/man1/date.1.html
    63       - name: "Get last Monday's date"
    64         id: get-date
    65         run: echo "date=$(/bin/date -u --date='last Mon' "+%F")" >> "$GITHUB_OUTPUT"
    66 
    67       - name: General debug information
     47      - name: Log debug information
    6848        run: |
    6949          npm --version
    7050          node --version
    71           composer --version
    7251
    73       # Since Composer dependencies are installed using `composer update` and no lock file is in version control,
    74       # passing a custom cache suffix ensures that the cache is flushed at least once per week.
    75       - name: Install Composer dependencies
    76         uses: ramsey/composer-install@3cf229dc2919194e9e36783941438d17239e8520 # v3.1.1
    77         with:
    78           custom-cache-suffix: ${{ steps.get-date.outputs.date }}
    79 
    80       - name: Make Composer packages available globally
    81         run: echo "${PWD}/vendor/bin" >> "$GITHUB_PATH"
    82 
    8352      - name: Install npm dependencies
    8453        run: npm ci --ignore-scripts
    8554
    86       - name: Build WordPress
    87         run: npm run build:dev
    88 
    89       - name: Cache PHP Static Analysis scan cache
     55      - name: Cache TypeScript build info
    9056        uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
    9157        with:
    92           path: .cache # This is defined in the base.neon file.
    93           key: "phpstan-result-cache-${{ github.run_id }}"
     58          path: |
     59            *.tsbuildinfo
     60          key: "ts-build-info-${{ github.run_id }}"
    9461          restore-keys: |
    95             phpstan-result-cache-
     62            -
    9663
    97       - name: Run PHP static analysis tests
    98         id: phpstan
    99         run: composer run phpstan -- -vvv --error-format=checkstyle | cs2pr --errors-as-warnings --graceful-warnings
     64      - name: Run JavaScript type checking
     65        run: npm run typecheck:js
    10066
    10167      - name: "Save result cache"
    10268        uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
    10369        if: ${{ !cancelled() }}
    10470        with:
    105           path: .cache
    106           key: "phpstan-result-cache-${{ github.run_id }}"
     71          path: |
     72            *.tsbuildinfo
     73          key: "ts-build-info-${{ github.run_id }}"
    10774
    10875      - name: Ensure version-controlled files are not modified or deleted
    10976        run: git diff --exit-code

@westonruter commented on PR #11131:


31 hours ago
#8

Difference between .github/workflows/phpstan-static-analysis.yml and .github/workflows/javascript-type-checking.yml:

  • .github/workflows/

    old new  
    1 name: PHPStan Static Analysis
     1name:
    22
    33on:
    4   # PHPStan testing was introduced in 7.0.0.
     4  # ing was introduced in 7.0.0.
    55  push:
    66    branches:
    77      - trunk
     
    1414      - trunk
    1515      - '[7-9].[0-9]'
    1616    paths:
    17       # This workflow only scans PHP files.
    18       - '**.php'
    19       # These files configure Composer. Changes could affect the outcome.
    20       - 'composer.*'
    21       # These files configure PHPStan. Changes could affect the outcome.
    22       - 'phpstan.neon.dist'
    23       - 'tests/phpstan/base.neon'
    24       - 'tests/phpstan/baseline.php'
     17      # This workflow only scans JavaScript files.
     18      - '**.js'
     19      # These files configure npm. Changes could affect the outcome.
     20      - 'package*.json'
     21      - '.nvmrc'
     22      # This file configures TypeScript. Changes could affect the outcome.
     23      - 'tsconfig.json'
     24      # This directory contains TypeScript definitions. Changes could affect the outcome.
     25      - 'typings/**'
    2526      # Confirm any changes to relevant workflow files.
    26       - '.github/workflows/phpstan-static-analysis.yml'
    27       - '.github/workflows/reusable-phpstan-static-analysis.yml'
     27      - '.github/workflows/.yml'
     28      - '.github/workflows/reusable-.yml'
    2829  workflow_dispatch:
    2930
    3031# Cancels all previous workflow runs for pull requests that have not completed.
     
    3940permissions: {}
    4041
    4142jobs:
    42   # Runs PHPStan Static Analysis.
    43   phpstan:
    44     name: PHP static analysis
    45     uses: ./.github/workflows/reusable-phpstan-static-analysis.yml
     43  # Runs .
     44  :
     45    name:
     46    uses: ./.github/workflows/reusable-.yml
    4647    permissions:
    4748      contents: read
    4849    if: ${{ github.repository == 'WordPress/wordpress-develop' || ( github.event_name == 'pull_request' && github.actor != 'dependabot[bot]' ) }}
     
    5354    permissions:
    5455      actions: read
    5556      contents: read
    56     needs: [ phpstan ]
     57    needs: [ ]
    5758    if: ${{ github.repository == 'WordPress/wordpress-develop' && github.event_name != 'pull_request' && always() }}
    5859    with:
    5960      calling_status: ${{ contains( needs.*.result, 'cancelled' ) && 'cancelled' || contains( needs.*.result, 'failure' ) && 'failure' || 'success' }}
     
    8182
    8283    steps:
    8384      - name: Dispatch workflow run
    84         uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
     85        uses: actions/github-script@
    8586        with:
    8687          retries: 2
    8788          retry-exempt-status-codes: 418

@westonruter commented on PR #11131:


31 hours ago
#9

When a TypeScript error occurs (e.g. d2ad278), the job fails as expected:

https://github.com/user-attachments/assets/1952be8b-f2d5-43ae-9679-3addf7c5375c

https://github.com/user-attachments/assets/7c8aa3e1-450d-44b4-a2b2-133f0177cc41

And the errors are annotated in the PR:

https://github.com/user-attachments/assets/353fd1ef-73d1-4d8e-b719-ea7514aaa864

This is in contrast with PHPStan's analysis which does _not_ fail its job when there are errors, but instead the errors are annotated as warnings.

I think this is fine given that TypeScript checking is being incrementally added to files on an opt-in basis. (Personally I would have wanted PHPStan errors to also cause jobs to fail with error annotations.)

#10 @westonruter
31 hours ago

PR is ready for review.

@westonruter commented on PR #11131:


31 hours ago
#11

Also, running npx grunt precommit:js with d2ad278 staged:

...
https://github.com/user-attachments/assets/5c2ca068-128f-4193-9c71-90c34ce481bd

#12 @westonruter
8 hours ago

  • Resolution set to fixed
  • Status changed from accepted to closed

In 61830:

Build/Test Tools: Integrate TypeScript into the core development workflow.

This introduces a new GitHub Action workflow for JavaScript type checking, mirroring the implementation for PHPStan in #61175. It also adds a typecheck:js Grunt task and includes it in the precommit:js task list. Only files related to the code editor are initially checked with TypeScript, with the expectation that additional files will be added to the files list in tsconfig.json as a part of ongoing maintenance work, for example #64238 and #64226.

Developed in https://github.com/WordPress/wordpress-develop/pull/11131

Follow up to r61699, r61800, r61539.

Props westonruter, jonsurrell.
See #61175, #64661, #48456.
Fixes #64662.

#13 @desrosj
7 hours ago

  • Keywords changes-requested added
  • Resolution fixed deleted
  • Status changed from closed to reopened

Thanks for this, everyone!

I have a few small points of feedback for a follow up commit. Can the reusable workflow file be renamed to include a -v1 suffix? Initially only the PHPUnit reusable workflow contained the -v1 suffix, but all new ones introduced since then have included it.

I know it's inconsistent, but I would like to update all the others eventually. It's just a pain to backport to every single branch calling the file. I do plan to try and tackle that the next time a given workflow requires a new -v2 file.

It just makes it more apparent which one is the most recent. It's reasonable to assume that the file without any suffix is the current or active version and all with a suffix are old.

( github.event_name == 'pull_request' && github.actor != 'dependabot[bot]' )

Can we remove the dependabot check here? The bot was deactivated in [61049] because it stopped working when GitHub switched over to their new runner architecture, and all bot specific checks were removed in [61050].

If we ever decide to try and get that working again, we can re-add this check with the others.

#14 @westonruter
5 hours ago

@desrosj Would this also apply to the new PHPStan reusable workflow .github/workflows/reusable-phpstan-static-analysis.yml added in #61175?

This ticket was mentioned in PR #11163 on WordPress/wordpress-develop by @westonruter.


5 hours ago
#15

Trac ticket: https://core.trac.wordpress.org/ticket/64662

  • Add -v1 suffix to reusable workflows for JavaScript type checking and PHPStan analysis: This follows the established convention of including a version suffix for reusable workflow files, ensuring consistency with other workflows like PHPUnit.
  • Remove Dependabot exclusion from type checking workflows: Since Dependabot was deactivated in b60c06c67e4a5a2b1351cb8bb54ed4cdd2e8e49e and other bot-specific checks were removed in 26230c33261cf559907a90547b4827ea66ff9f30, this exclusion is no longer necessary.

## Use of AI Tools

Feedback from @desrosj fed into Gemini CLI to implement.

Note: See TracTickets for help on using tickets.