Skip to content

fix: write .npmrc in preinstall to resolve bun install 401 on @packrat-ai/nativewindui#1901

Draft
Copilot wants to merge 3 commits intomainfrom
copilot/fix-github-token-install-error
Draft

fix: write .npmrc in preinstall to resolve bun install 401 on @packrat-ai/nativewindui#1901
Copilot wants to merge 3 commits intomainfrom
copilot/fix-github-token-install-error

Conversation

Copy link
Contributor

Copilot AI commented Mar 9, 2026

  • Update .github/scripts/configure-deps.ts to write a .npmrc file with the auth token instead of setting env var (which doesn't propagate to parent process)
  • Handle existing .npmrc gracefully by merging (update auth line if present, insert before trailing newline otherwise)
  • Add empty token validation before writing
  • Add .npmrc to .gitignore to prevent committing the auth token
  • Update script comments to explain why .npmrc is used instead of process.env
  • Trim token inside writeNpmrc uniformly for all callers (review feedback)
  • Fix append logic to insert before trailing empty string from split('\n'), not after (review feedback)
Original prompt

This section details on the original issue you should resolve

<issue_title>[QA] Install fails — expired/missing GitHub token for @packrat-ai/nativewindui</issue_title>
<issue_description>## Description
bun install fails with a 401 fetching @packrat-ai/nativewindui@1.0.10 from npm.pkg.github.com.

Root Cause

The preinstall script (.github/scripts/configure-deps.ts) sets PACKRAT_NATIVEWIND_UI_GITHUB_TOKEN via process.env in the child preinstall process, but that env var does not propagate back to the parent bun install process that reads bunfig.toml. The script prints a misleading "Using GitHub CLI token for authentication" success message while the install still fails.

Workaround

PACKRAT_NATIVEWIND_UI_GITHUB_TOKEN=$(gh auth token) bun install

Proper Fix

The preinstall script needs to either:

  1. Write the token directly into bunfig.toml temporarily
  2. Write an .npmrc file with the auth token
  3. Or document the manual export step in the README

Additional Setup Requirements

  • gh auth needs read:packages scope: gh auth refresh -h github.com -s read:packages
  • A .env file is needed for DB-dependent tests

Environment

  • Bun 1.3.9, macOS Darwin 24.6.0

🤖 Updated by QA agent via Claude Code</issue_description>

Comments on the Issue (you are @copilot in this section)

@andrew-bierman @copilot Assigned for POC development. Please investigate and create a proof of concept implementation.

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

…1 error

Co-authored-by: andrew-bierman <94939237+andrew-bierman@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix install failure due to expired GitHub token fix: write .npmrc in preinstall to resolve bun install 401 on @packrat-ai/nativewindui Mar 9, 2026
@andrew-bierman
Copy link
Collaborator

@coderabbitai Please review this PR for code quality, best practices, and potential issues.

@coderabbitai
Copy link

coderabbitai bot commented Mar 9, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Read the configure-deps.ts file
cat .github/scripts/configure-deps.ts

echo "---GITIGNORE---"
# Read the .gitignore to check the added .npmrc entry
grep -n "npmrc" .gitignore || echo ".npmrc not found in .gitignore"

# Also check the full .gitignore for context
cat .gitignore

Length of output: 4946


@andrew-bierman: Here's a thorough review of PR #1901. The overall approach is sound — writing .npmrc is the correct fix for the child-process env-mutation limitation. A few issues worth addressing:


🐛 Bug — Double blank line when merging into an existing .npmrc

In writeNpmrc, when the existing file ends with a newline (standard for text files), split('\n') produces a trailing "" element. Pushing the new auth line after it causes a spurious blank line in the output:

// e.g. existing = "registry=https://...\n"
// split('\n') → ["registry=https://...", ""]
// after push  → ["registry=https://...", "", newAuthLine]
// join('\n')  → "registry=https://...\n\nnewAuthLine"   ← double blank line

Fix — filter out the trailing empty string before pushing:

const lines = existing.trimEnd().split('\n'); // strips trailing newline(s) before splitting
const idx = lines.findIndex((l) => l.startsWith(GITHUB_REGISTRY_LINE_PREFIX));
if (idx !== -1) {
  lines[idx] = newAuthLine;
} else {
  lines.push(newAuthLine);
}
writeFileSync(NPMRC_PATH, lines.join('\n') + '\n', { mode: 0o600 }); // always end with one newline

⚠️ Inconsistency — Env-var tokens not trimmed, but gh auth token output is

gh auth token output is correctly trimmed:

const token = await $`gh auth token`.text();
writeNpmrc(token.trim()); // ✅

But the two process.env paths pass the value directly:

writeNpmrc(process.env.PACKRAT_NATIVEWIND_UI_GITHUB_TOKEN); // ⚠️ no .trim()

While environment variables rarely contain leading/trailing whitespace, it's defensive to apply .trim() consistently — especially if someone copies a token with trailing whitespace into their shell or CI secret.

writeNpmrc(process.env.PACKRAT_NATIVEWIND_UI_GITHUB_TOKEN.trim());

⚠️ Top-level async call missing .catch()

if (import.meta.main) {
  configureDeps(); // missing .catch()
}

configureDeps has an internal try/catch, so most failures are handled. However, if something throws before the try block is entered (e.g., a top-level import failure), the unhandled rejection would be silently swallowed in some runtimes. The safer pattern:

if (import.meta.main) {
  configureDeps().catch((err) => {
    console.error('❌ Unexpected error:', err);
    process.exit(1);
  });
}

✅ What's done well

  • mode: 0o600 — restricts .npmrc to owner-only read/write; great security practice for a file containing auth tokens.
  • Merge logic — avoids clobbering other registry config in an existing .npmrc.
  • import.meta.main guard — makes the script safely importable as a module without side effects.
  • Detailed inline documentation — the "Why .npmrc and not process.env?" comment is exactly the right explanation to leave for future maintainers.
  • .gitignore entry — the descriptive comment # GitHub Package Registry auth token (generated by preinstall script) clearly documents the intent.

🧠 Learnings used
Learnt from: CR
Repo: PackRat-AI/PackRat PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-03-01T10:08:42.658Z
Learning: Ensure GitHub authentication is completed before running bun install to access private package packrat-ai/nativewindui; without authentication bun install will fail with 401 errors

Learnt from: CR
Repo: PackRat-AI/PackRat PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-03-01T10:08:42.658Z
Learning: Configure required CI/CD environment variables: PACKRAT_NATIVEWIND_UI_GITHUB_TOKEN for GitHub package access, Cloudflare API tokens for API deployment, and Expo credentials for mobile builds

Learnt from: CR
Repo: PackRat-AI/PackRat PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-03-01T10:08:42.658Z
Learning: Applies to .env* : Configure environment variables using .env.example as a reference template, including PACKRAT_NATIVEWIND_UI_GITHUB_TOKEN for private package access, NEON_DATABASE_URL for database connection, OPENAI_API_KEY for AI features, and EXPO_PUBLIC_* for client-side Expo variables

Learnt from: CR
Repo: PackRat-AI/PackRat PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-03-01T10:08:42.658Z
Learning: Authenticate with GitHub using gh auth login and gh auth refresh -h github.com -s read:packages for private package access to packrat-ai/nativewindui

Learnt from: CR
Repo: PackRat-AI/PackRat PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-03-01T10:08:42.658Z
Learning: Applies to **/package.json : When adding dependencies, update relevant package.json files and ensure private packages require GitHub authentication

@andrew-bierman
Copy link
Collaborator

@copilot CodeRabbit has reviewed this PR and provided feedback. Please address the review comments and push updates. Once you've made the changes, the monitor will ask CodeRabbit to re-review.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a bun install 401 error when fetching @packrat-ai/nativewindui from npm.pkg.github.com. The root cause was that the preinstall script set PACKRAT_NATIVEWIND_UI_GITHUB_TOKEN via process.env, but env mutations in a child process don't propagate back to the parent bun install process that reads bunfig.toml. The fix writes the token directly to a repo-root .npmrc file, which bun reads for registry authentication across all processes.

Changes:

  • writeNpmrc() helper that creates or merges a .npmrc file with the GitHub registry auth token (mode 0o600), replacing the process.env mutation approach.
  • All three auth paths (CI env var, local env var, gh auth token) now call writeNpmrc() to persist the token.
  • .npmrc is added to .gitignore to prevent the generated file from being committed.

Reviewed changes

Copilot reviewed 1 out of 2 changed files in this pull request and generated 2 comments.

File Description
.github/scripts/configure-deps.ts Adds writeNpmrc() function and routes all auth paths through it instead of process.env mutation
.gitignore Adds .npmrc entry to prevent the generated auth file from being committed

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +74 to +81
writeNpmrc(process.env.PACKRAT_NATIVEWIND_UI_GITHUB_TOKEN);
console.log('✓ Using PACKRAT_NATIVEWIND_UI_GITHUB_TOKEN for CI authentication');
return;
}

// For local development, check if PACKRAT_NATIVEWIND_UI_GITHUB_TOKEN is already set
if (process.env.PACKRAT_NATIVEWIND_UI_GITHUB_TOKEN) {
writeNpmrc(process.env.PACKRAT_NATIVEWIND_UI_GITHUB_TOKEN);
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

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

The writeNpmrc function does not trim the token internally, yet the two env-var code paths (CI and local env var) pass the value directly from process.env without calling .trim(), while the GitHub CLI path explicitly calls token.trim() before passing. If a token in the environment variable has accidental leading/trailing whitespace (e.g. from a .env file), the auth line will be written with embedded whitespace, producing an invalid token. Either trim inside writeNpmrc so all callers benefit uniformly, or add .trim() at lines 74 and 81 to match the behavior at line 95.

Copilot uses AI. Check for mistakes.
Comment on lines +50 to +53
} else {
// Append before any trailing newline
lines.push(newAuthLine);
}
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

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

The comment on line 51 says "Append before any trailing newline", but the implementation doesn't do that. When an existing .npmrc ends with a newline (as is typical), existing.split('\n') produces a trailing empty string '' at the end of lines. Pushing newAuthLine after that empty string and then joining produces a blank line before the auth token and no trailing newline on the file (e.g., "line1\n\n//npm.pkg.github.com/…").

To correctly insert before the trailing newline, the code should check whether the last element is an empty string and, if so, insert before it using splice rather than push. While the resulting file is still functionally parseable, the blank line is an unintended formatting artifact that contradicts the stated intent.

Copilot uses AI. Check for mistakes.
@andrew-bierman
Copy link
Collaborator

@copilot Please address the CodeRabbit review feedback on this PR (2 inline comments).

…logic

Co-authored-by: andrew-bierman <94939237+andrew-bierman@users.noreply.github.com>
@andrew-bierman
Copy link
Collaborator

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Mar 9, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link

coderabbitai bot commented Mar 9, 2026

Warning

Rate limit exceeded

@andrew-bierman has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 5 minutes and 38 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 060a3786-511e-4147-b057-01eb2ccd1b64

📥 Commits

Reviewing files that changed from the base of the PR and between 3f94763 and 6928412.

📒 Files selected for processing (2)
  • .github/scripts/configure-deps.ts
  • .gitignore
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch copilot/fix-github-token-install-error

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

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.

[QA] Install fails — expired/missing GitHub token for @packrat-ai/nativewindui

3 participants