Skip to content

Conversation

@richardkmichael
Copy link
Collaborator

@richardkmichael richardkmichael commented Dec 6, 2025

I think this is at the point where it can be looked at. Likely low-priority, except perhaps the first bits.

Summary

The changes started from investigating two CI failures:

  1. Prettier problems caused by mismatch between development and CI environments

  2. Release build failures when --no-package-lock caused CI to resolve newer dependency versions
    than the locked versions used in development

As I investigated, it seemed worth reorganizing workflows for better PR "checks" and GitHub Actions
UI organization. I also added a matrix for cross-platform testing on Windows.

Regarding review --

I tried to keep commits small, with the intent of reviewing each by paging through the PR UI.
[Opt] commits are changes about which I was uncertain, and need closer attention. I'll reword to
drop [Opt] if they'll be kept.

I've ordered them to make it easy to slice up. So if preferrable, I can split this into multiple
smaller PRs (e.g., CI fixes, then workflow organization, etc.). Submitting it as one since it's
conceptually related.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Documentation update
  • Refactoring (no functional changes)
  • Test updates
  • Build/CI improvements

Core Fixes

  1. Replace --no-package-lock with npm clean-install
  • Ensure CI uses the specified versions, preventing unexpected failures in CI only
  • Adds a separate dependency range test job to explicitly validate compatibility with newer
    semver-compatible versions
  1. Fix Prettier on Windows
  • Configure git checkout to preserve LF line endings on Windows (prevents Prettier warnings)
  • Ensures consistent linting results across all platforms

Workflow Organization

  1. Consolidate jobs into semantic workflows
  • build.yml: All PR-relevant jobs (build, test, lint, dependency testing, e2e tests)
    • PR authors can review all checks in one workflow run, in one click from the PR
    • Eliminates confusion from "skipped" publish jobs that don't apply to PRs
  • release.yml: Contains publish jobs (only runs on releases)
    • Moved from main.yml for clarity
    • Includes dependency on build workflow to ensure tests pass before publishing
  • claude.yml: Remains separate (Claude-assisted development tasks)
  1. Use a matrix for cross-platform / node
  • Linux (ubuntu-latest) and Windows (windows-latest)
  • Node.js 20, 22, and 24 (all currently supported LTS/Current versions)

package-lock.json handling

  1. Add validation for cross-platform dependencies
  • scripts/validate-platform-dependencies.js detects missing platform-dependencies in the lockfile
  • Addresses npm bug #4828 (fixed in npm 11.3.0, but affects Node 22 which ships npm 10.x)
  • [Opt] Includes pre-commit hook validation
  • [Opt] Use engines for npm version 11.3.0 (warn EBADENGINE)

Consistency & Maintenance

  1. Use package.json scripts consistently
  • CI now uses npm run prettier-check and npm run lint instead of invoking tools directly
  • Ensures local and CI environments run identical commands (make CI less special)
  1. Update GitHub Actions
  • actions/setup-node@v6 for latest features
  • actions/checkout@v6 for improved performance
  • Enable workflow_dispatch for manual workflow triggering
  1. Minor cleanups
  • Consistent YAML formatting
  • Clear workflow naming for GitHub Actions UI
  • Documentation of GitHub release event types

Related Issues

Testing

  • All workflows tested in fork before submission
  • Manual testing performed

Example CI in fork:

Test Results and/or Instructions

I'm wondering about release testing. Could test with a pre-release to be sure release works. I could also change release to be no-op (but exit 0 so it works) in my fork and "release" there.

Checklist

  • Code follows the style guidelines (ran npm run prettier-fix)
  • Self-review completed
  • Documentation updated (README, comments, etc.)
  • Code is commented where necessary

I considered adding CI documentation; can do if helpful.

Breaking Changes

Shouldn't be.

Additional Context

Why these changes?

Ensure CI tests are unsurprising, and test what is expected to be released. When CI uses different
versions than local development (via --no-package-lock), it can cause surprising failures that
block releases and waste time debugging.

Separately, the GitHub Actions UI benefits from semantic workflow organization. Having all
PR-relevant checks in one workflow makes it easier for contributors to review results without
clicking through multiple workflows.

Questions / future

Feedback needed on a few uncertain areas:

0. Semver dependency test job

"Dependency range test" is a fairly awful name. Suggestions?

1. .gitattributes for EOL consistency

autocrlf: false is used in the checkout action to prevent LF→CRLF conversion on Windows.

Perhaps better to instead add: .gitattributes with text=auto eol=lf

  • .gitattributes
    • more contributor-friendly (works automatically, no git config needed)
    • eliminates special CI configuration (the less "special" CI, the better)

Should we add .gitattributes or use this CI-only approach (or even at least for now)?

2. Historical workflow cleanup

The GitHub Actions UI will continue to show old workflow files and run history, even though the
workflows have been reorganized; so UI clutter will remain. I have a script for this, since it bulk run delete is not available in the UI.

Options:

  • Delete all historical workflow runs to fully clean up the UI
  • Keep historical runs (although logs have expired for old runs, so limited value for debugging)

Question: Is there value in keeping historical workflow runs? If so: all, or which?

3. Optional changes [Opt]

Several commits are marked [Opt] because I'm uncertain if they'd be desired:

  • Lockfile validation script and pre-commit hook
  • npm version enforcement in engines field

Question: Are these useful, or drop?

Future

Further ideas, happy to discuss and add here or in future PRs:

  1. Move CLI tests into build workflow - IMO, these should go into build, since the CLI does depend
    on code which could break it, but I wanted a review of the revised workflows first.
  2. Scheduled workflow for workflow history cleanup - Automatically remove old/skipped workflow runs
    (especially Claude Code runs, the vast majority are just "skipped" noise)
  3. GitHub Actions linting - Use actionlint for consistency
  4. More release automation - Integrate npm run update-version into release workflow?
  5. Improved job naming - More human-friendly names in GitHub Actions UI

The `--no-package-lock` workaround was added due to npm bug #4828, where
npm < 11.3.0 generates incomplete lockfiles for packages with optional
platform dependencies (esbuild, rollup).

Optional cross-platform dependencies were restored to
`package-lock.json` in 358f276, so npm will be able to install from the
lock file in the GitHub Actions.

Also, fixed in npm 11.3.0 (Apr 2025), but Node v22 ships npm v10 and
will remain affected out-of-the-box.

Investigation notes follow.

What happened?
--------------

1. Switch from yarn to npm: `package-lock.json` added, `yarn.lock` removed
  - modelcontextprotocol@702f827

  Presumably:
    - run `npm install` to generate a `package-lock.json` from the yarn-managed `node_modules`, on macos
    - bug #4828: npm omitted optional cross-platform dependencies from the lock file

  npm can't easily fix this.  `npm install [email protected]` could write a
  resolved dependency, but at the exact version so `foo` would be pinned,
  and semver operator twiddling would be required to restore it as-was.

  The fix would be to "manually" re-add the missing metadata.

2. Pull 47, tries `npm ci`, and reverts, on 11 Nov 2024
modelcontextprotocol@3789ef9
  - "Try restoring npm ci" --> testing the new node release for the bug?
  - ran against `setup-node`, `node-version: 18`, likely: 18.20.5 (released nov 11, 2024; ~same day)
    - git show 3789ef9:.github/workflows/main.yml

  - Failed action, and logs have expired
    - https://github.com/modelcontextprotocol/inspector/actions/runs/11782443393/job/32817472448

  - https://nodejs.org/en/download/archive/v18.20.5
    - uses npm 10.8.2

  - Re-tried in inspector fork
    - workflow run at 3789ef9
    - change `node-version: 18` to `18.20.5` (exact node / npm on commit date)
    - Fails due to missing `linux-x64-gnu` platform dep (rollup, would similarly affect esbuild)

3. Cross-platform dependencies restored to lockfile on 1 May 2025
modelcontextprotocol#372
  - modelcontextprotocol@358f276
  - worked because `package-lock.json` and `node_modules` were both removed
    - i.e., not the bug conditions -> even npm < 11.3.0 generates correct lockfile

  - At that point, `--no-package-lock` could've been removed from CI, Dockerfile, etc.

NPM
---

npm (aborist) fixed #4828
npm/cli#8184
  - npm/cli#4828 --> frequent http 500, due to many comments
  - npm/cli@a96d8f6
  - will not be backported

Released in 11.3.0 on 8 Apr
npm/cli#8150
  - https://github.com/npm/cli/releases/tag/v11.3.0
    - arborist 9.0.2
    - https://github.com/npm/cli/releases/tag/arborist-v9.0.2

  - npm v11.3.0 ships with node v24.2.0, on 6 May 2025
    - https://nodejs.org/en/download/archive/v24

Node v22 ships npm v10
  - https://nodejs.org/en/download/archive/v22
  - will always be affected, no backport coming
Top-level `npm run lint` runs `prettier --check .` and lint in client/

Using the package script after install ensures the same procedure and
versions are used in CI and development, and also avoids yet-another
variant of a direct prettier invocation.
Separates publish jobs into `release.yml` to eliminate "skipped" status
noise on pull requests.

All PRs currently display "skipped" for publish jobs, which is correct
since they should only run on releases. However, this can confuse PR
submitters who may not realize the skipping is expected rather than a
failure related to their changes (accidental release trigger, etc.).

Separate workflows keep PR checks focused on build and test jobs
relevant to the submitter.
- Shows all jobs related to a PR in one workflow run for convenience
- Fewer "duplicate" runs, de-cluttering the Github Actions UI
- Conceptual grouping since it uses the same triggers as build job
- Shows all jobs related to a PR in one workflow run for convenience
- Fewer "duplicate" runs, de-cluttering the Github Actions UI
- Conceptual grouping since it uses the same triggers as build job
From npm/cli:

   $ git log -1 -p -G'"node":' -U0 --format=""  v11.3.0 -- package.json | grep node
    -    "node": "^18.17.0 || >=20.5.0"
    +    "node": "^20.17.0 || >=22.9.0"
Since prettier lacks CRLF configuration, presumably Windows contributors
are configuring EOL using git-config.

Using `gitattributes` would be more user-friendly for those not knowing
git configuration details, and eliminate this config hidden in CI.
GitHub Runner version >= 2.239.0 is required.

Workflow `Set up job` runs do indicate that runner version is used:

  > Current runner version: '2.329.0'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant