Skip to content

Upgrade Node.js from 22.17.0 to 24.14.0#232

Open
cteyton wants to merge 11 commits intomainfrom
migration-node-24-14
Open

Upgrade Node.js from 22.17.0 to 24.14.0#232
cteyton wants to merge 11 commits intomainfrom
migration-node-24-14

Conversation

@cteyton
Copy link
Copy Markdown
Contributor

@cteyton cteyton commented Mar 25, 2026

Explanation

Upgrade Node.js runtime from 22.17.0 to 24.14.0 across the entire monorepo: version pins, Docker images, CI workflows, and Dockerfiles.

Type of Change

  • Bug fix
  • New feature
  • Improvement/Enhancement
  • Refactoring
  • Documentation
  • Breaking change

Affected Components

  • Domain packages affected: none (runtime-only change)
  • Frontend / Backend / Both: Both + CI + Docker
  • Breaking changes (if any): Node 24 native TS stripping conflicts with Jest config loading — requires NODE_OPTIONS="--no-experimental-strip-types" for test runs

Testing

  • Unit tests added/updated
  • Integration tests added/updated
  • Manual testing completed
  • Test coverage maintained or improved

Test Details:

Step Result
npm install (npm 11.11.0) Pass
nx build api Pass ([DEP0180] fs.Stats deprecated warning)
nx build frontend Pass ([MODULE_TYPELESS_PACKAGE_JSON] warning)
nx build packmind-cli Pass
nx build mcp-server Pass
Tests (24/25 projects) Pass with --no-experimental-strip-types
Lint (29 projects) Pass

Known issue: Node 24 enables --experimental-strip-types by default, which conflicts with Jest's TypeScript config loading. Workaround: NODE_OPTIONS="--no-experimental-strip-types". This needs to be added to CI test jobs.

TODO List

  • CHANGELOG Updated
  • Documentation Updated
  • Add --no-experimental-strip-types to CI test workflows
  • Update OpenSSL pin in Dockerfiles for Alpine 3.23

Reviewer Notes

  • migrate-24_11.md contains the backport guide for the proprietary repo
  • The package-lock.json diff is minimal (engine field + some optional peer dep cleanup by npm 11)
  • cli-e2e-tests were skipped (require external API connectivity)

🤖 Generated with Claude Code

Upgrade Node.js runtime across the monorepo: .nvmrc, package.json engines,
Docker Compose images (node:24.14.0-alpine3.23), Dockerfiles, and CI workflows.

Impact study results:
- npm install: clean (npm 11.11.0)
- All 4 app builds pass (api, frontend, cli, mcp-server)
- All tests pass with --no-experimental-strip-types
- All 29 lint targets pass
- Known issue: Node 24 native TS stripping conflicts with Jest config loading

Includes migrate-24_11.md with backport guide for proprietary repo.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 25, 2026

Greptile Summary

This PR upgrades the Node.js runtime from 22.17.0 to 24.14.0 across the entire monorepo — touching .nvmrc, all engines fields, every CI workflow, Docker Compose files, and Dockerfiles. It also adds the required NODE_OPTIONS="--no-experimental-strip-types" workaround to every build and test step to prevent Node 24's experimental TypeScript stripping from conflicting with Jest's config loading. A handful of TypeScript type-safety fixes in UI components (PMButton, PMIconButton, PMHeading, PMLink) and an icon rename (SiNuxtdotjsSiNuxt) are bundled in as well.

Key observations:

  • --no-experimental-strip-types coverage: The flag has been correctly added to all build and test steps in build.yml as well as the local npm test / npm run test:staged scripts in package.json. This is the necessary Node 24 workaround.
  • Docker workflow now runs on all branches: The job-level if guard was intentionally removed from both main.yml and docker.yml so that Docker builds and CVE scans run on every PR. Push steps retain their own refs/heads/main / refs/tags/release/* guards, so no images are pushed on feature branches.
  • npm version inconsistency: package.json pins "npm": "11.9.0" while apps/api/docker-package.json pins "npm": "11.11.0". The PR description confirms testing was done with npm 11.11.0, so package.json appears to have the wrong value.
  • OpenSSL unpinned in both Dockerfiles: Acknowledged in the PR's own TODO list. The previous pin (openssl=3.5.5-r0) was Alpine 3.21-specific, and a new pin for Alpine 3.23 has not yet been determined. Until it is, Docker builds are non-deterministic and there is a risk that the CVE scan passes today but fails after an Alpine mirror refresh.
  • packmind-lock.json deleted: This Packmind agent lockfile tracked pinned versions of installed standards and commands. Its deletion means those artifacts will be re-resolved at next install rather than using locked versions — confirm this is intentional.

Confidence Score: 4/5

  • PR is on the happy path to merge; one small npm version inconsistency and the known OpenSSL unpin are the only remaining items, neither of which blocks functionality.
  • All Node version references are consistently updated to 24.14.0, the --no-experimental-strip-types workaround is applied everywhere it is needed, and manual testing passed. The two outstanding items (npm version mismatch between package.json and docker-package.json, and unpinned OpenSSL) are minor and the latter is explicitly flagged as a TODO by the author. No functional regressions introduced.
  • package.json (npm engine version mismatch) and dockerfile/Dockerfile.api / dockerfile/Dockerfile.mcp (unpinned OpenSSL).

Important Files Changed

Filename Overview
.github/workflows/build.yml Added --no-experimental-strip-types to NODE_OPTIONS for all build and test steps to fix the Node 24 TypeScript-stripping conflict with Jest config loading.
.github/workflows/main.yml Node version bumped from 22.17.0 to 24.14.0; the if guard on the docker job call was removed, meaning docker builds now run on all branches (guarded only at the push steps inside docker.yml).
.github/workflows/docker.yml Job-level branch guard removed; Docker build and CVE scan now run on all branches, with push guarded only inside individual steps. Intentional change to allow vulnerability scanning on PRs.
dockerfile/Dockerfile.api Base image updated to node:24.14.0-alpine3.23; OpenSSL version pin removed (was openssl=3.5.5-r0), now installs latest available OpenSSL for Alpine 3.23 — a known TODO in the PR.
dockerfile/Dockerfile.mcp Base image updated to node:24.14.0-alpine3.23; same OpenSSL unpin as Dockerfile.api — acknowledged as a TODO.
package.json Node engine updated to 24.14.0, npm to 11.9.0; --no-experimental-strip-types added to local test scripts. npm version (11.9.0) is inconsistent with the 11.11.0 specified in apps/api/docker-package.json.
apps/api/docker-package.json Node engine bumped to 24.14.0, npm bumped to 11.11.0. Inconsistent with root package.json which pins npm at 11.9.0.
packmind-lock.json File deleted — appears to be the Packmind AI agent lockfile that tracked installed standards/commands. Deletion may cause loss of pinned versions for Packmind standards artifacts.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    PR[Pull Request / Push] --> Build[Stage 1: Build & Test\nbuild.yml\nNode 24.14.0\n--no-experimental-strip-types]
    Build --> Quality[Stage 2: Quality & Security\nquality.yml\nNode 24.14.0]
    Build --> Docker
    Quality --> Docker[Stage 3: Docker Build+Scan\ndocker.yml\nALL branches now]
    Docker --> PushMain{github.ref\n== main?}
    Docker --> PushRelease{release/*\ntag?}
    PushMain -->|Yes| SHAPush[Push SHA-tagged images\nto Docker Hub]
    PushRelease -->|Yes| MultiPlatform[Multi-platform build\n+ push version+latest tags]
    PushRelease -->|Yes| PublicImages[Build & push\npublic OSS images]
    Docker --> ScanOnly[Build + CVE Scan only\nno push on feature branches]

    subgraph DockerImages [Docker Base Images]
        API[Dockerfile.api\nnode:24.14.0-alpine3.23\nopenssl unpinned ⚠️]
        MCP[Dockerfile.mcp\nnode:24.14.0-alpine3.23\nopenssl unpinned ⚠️]
    end
Loading

Comments Outside Diff (1)

  1. dockerfile/Dockerfile.api, line 11 (link)

    OpenSSL version unpinned

    The previous Dockerfile explicitly pinned openssl=3.5.5-r0 for reproducibility and to pass the Docker Scout CVE scan. The new image switches to openssl (latest available in Alpine 3.23 at build time), which makes the build non-deterministic and could unexpectedly pull in a version with unfixed CVEs or break future builds if a newer package introduces a regression.

    This is already tracked as a TODO in the PR description ("Update OpenSSL pin in Dockerfiles for Alpine 3.23"). The same issue exists in dockerfile/Dockerfile.mcp. It's worth pinning before this lands on main to keep the Docker build reproducible and avoid a scout scan race condition.

Reviews (7): Last reviewed commit: "Fix prettier issue" | Re-trigger Greptile

profiles:
- dev
image: node:22.17.0-alpine3.21
image: node:24.14.0-alpine3.23
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Node version inconsistency: 24.14.1 vs 24.14.0 in Docker images

.nvmrc, package.json, apps/api/docker-package.json, and all CI workflow inputs specify 24.14.1, but every Docker image reference in docker-compose.yml, docker-compose.production.yml, Dockerfile.api, and Dockerfile.mcp uses node:24.14.0-alpine3.23.

If node:24.14.1-alpine3.23 exists on Docker Hub, the Docker images should be updated to match the pinned runtime version exactly. A mixed 24.14.0/24.14.1 environment could hide subtle ABI or behavior differences.

This same mismatch is present in docker-compose.production.yml and both Dockerfiles.

cteyton and others added 4 commits March 25, 2026 15:58
… workflow

Node 24 enables native TypeScript stripping by default, which conflicts
with Jest's own TS config loading (require() in .ts files, extensionless
imports). Append --no-experimental-strip-types to all NODE_OPTIONS in
build.yml to restore previous behavior.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Docker image node:24.14.1-alpine3.23 does not exist
- Align all config files with the available 24.14.0 image

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The pinned version openssl=3.5.5-r0 does not exist in Alpine 3.23,
causing Docker builds to fail at the apk add step.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove branch gate on docker job in main.yml
- Remove job-level if condition in docker.yml
- Push steps retain their own ref guards (main/release only)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@cteyton cteyton changed the title Upgrade Node.js from 22.17.0 to 24.14.1 Upgrade Node.js from 22.17.0 to 24.14.0 Mar 25, 2026
cteyton and others added 5 commits March 25, 2026 16:29
Remove phantom workspace references to non-existent
packages/linter-ast/parsers/* and regenerate lockfile with npm 11.9.0
(Node 24.14.0) to fix "invalid or damaged lockfile" CI errors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Rename SiNuxtdotjs to SiNuxt (react-icons API change)
- Fix Chakra UI variant type mismatches in PMLink, PMButton,
  PMIconButton, and PMHeading using Omit + cast pattern for
  custom variants not in Chakra's base types

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@sonarqubecloud
Copy link
Copy Markdown

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