Skip to content

Conversation

@gmegidish
Copy link
Member

@gmegidish gmegidish commented Dec 9, 2025

Summary by CodeRabbit

  • New Features

    • Platform-specific binary packages now available for macOS (Apple Silicon & Intel), Linux (ARM64 & x86-64), and Windows (x86-64).
    • Improved error handling for unsupported platform-architecture combinations.
  • Chores

    • Restructured publishing workflow to enable per-platform binary distribution.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 9, 2025

Walkthrough

Implements per-platform npm package publishing for mobilecli across Darwin and Linux architectures (ARM64 and x64) plus Windows x64. Introduces platform-specific package.json files and updates the build workflow and main package to support optional dependencies and dynamic binary resolution.

Changes

Cohort / File(s) Change Summary
Build Workflow
\.github/workflows/build\.yml
Refactors publishing from a bulk binary relocation step to per-platform publishing workflow. Adds discrete publish steps for darwin-arm64, darwin-amd64, linux-arm64, linux-amd64, and windows-amd64, each copying platform-specific binaries to dedicated folders, versioning, and publishing with public access. Retains main package publishing.
Platform-Specific Package Manifests
publish/npm-darwin-amd64/package\.json, publish/npm-darwin-arm64/package\.json, publish/npm-linux-amd64/package\.json, publish/npm-linux-arm64/package\.json, publish/npm-windows-amd64/package\.json
Adds five new package.json manifests, each defining a platform-specific npm package with scoped names (e.g., @mobilenext/mobilecli-darwin-arm64), version 0.0.4, author Mobile Next, repository, MIT license, and OS/CPU constraints matching the platform target.
Main Package Configuration
publish/npm/index\.js, publish/npm/package\.json
Updates index.js to dynamically resolve platform-specific binary paths using require.resolve() based on detected OS and architecture, with error handling for unsupported combinations. Adds optionalDependencies block in package.json listing all five platform-specific packages at version 0.0.4.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately reflects the main change: splitting the mobilecli binary into platform-specific optional dependencies published as separate npm packages, which is the core objective of this changeset.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat-split-into-optional-depds

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.

Copy link

@coderabbitai coderabbitai bot left a comment

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)
publish/npm/package.json (1)

13-20: Consider how you want platform package versions to track the wrapper

optionalDependencies are pinned to "0.0.4" while the publish workflow runs npm version "${{ github.ref_name }}" in both the wrapper and each per-platform package. That means future wrapper releases will keep depending on the exact 0.0.4 binary packages unless this file is also updated.

If you intend the wrapper to consume newer binary package versions without manually editing this file every time, consider:

  • Using a semver range (e.g. ^0.0.4) instead of a fixed version, or
  • Adding a small pre-publish step that rewrites these versions to ${{ github.ref_name }} alongside npm version.
.github/workflows/build.yml (1)

399-447: Platform-specific npm publish logic is correct but quite repetitive

The copy/chmod/npm version/npm publish sequence for each platform looks consistent with the directory layout and package names, so behavior-wise this should work.

If you expect to add more platforms or tweak the flow often, consider:

  • Moving this into a small matrix job, or
  • Using a loop over a list of (platform, package-dir, binary-name) tuples inside the script,

to reduce duplication and lower the chance of one platform block drifting from the others.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 762dd2d and 2c647d3.

📒 Files selected for processing (8)
  • .github/workflows/build.yml (1 hunks)
  • publish/npm-darwin-amd64/package.json (1 hunks)
  • publish/npm-darwin-arm64/package.json (1 hunks)
  • publish/npm-linux-amd64/package.json (1 hunks)
  • publish/npm-linux-arm64/package.json (1 hunks)
  • publish/npm-windows-amd64/package.json (1 hunks)
  • publish/npm/index.js (2 hunks)
  • publish/npm/package.json (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: lint
  • GitHub Check: Analyze (go)
🔇 Additional comments (6)
publish/npm-windows-amd64/package.json (1)

1-13: Windows x64 binary manifest looks consistent

Name, version, and os/cpu constraints match the intended win32 x64 binary package. No issues spotted.

publish/npm-darwin-amd64/package.json (1)

1-13: macOS x64 binary manifest is aligned with the per-platform scheme

Package name, description, and os/cpu selectors correctly target macOS x64 and match the naming used in the wrapper.

publish/npm-darwin-arm64/package.json (1)

1-13: macOS ARM64 manifest matches naming and platform constraints

The @mobilenext/mobilecli-darwin-arm64 package is correctly scoped to os: ["darwin"] and cpu: ["arm64"], matching the build artifacts and index.js mappings.

publish/npm-linux-arm64/package.json (1)

1-13: Linux ARM64 manifest is consistent with the other platform packages

Name, description, and os/cpu values correctly target Linux ARM64 and line up with the binary naming used in the workflow and wrapper.

publish/npm-linux-amd64/package.json (1)

1-13: Linux x64 manifest looks correct

The @mobilenext/mobilecli-linux-amd64 package correctly targets os: ["linux"], cpu: ["x64"] and matches the naming used elsewhere.

publish/npm/index.js (1)

9-53: Platform/arch → package mapping is clear and well-bounded

The switch on process.platform/process.arch maps cleanly to the new per-platform package names and binary filenames, and the extra if (!packageName) guard gives a clear error for unsupported combinations (e.g., non-x64 Windows or non-arm64/x64 Linux).

This part looks solid.

Comment on lines +55 to +62
let binaryPath;
try {
const packagePath = require.resolve(packageName);
binaryPath = join(packagePath, "..", binaryName);
} catch (error) {
console.error(`Failed to find ${packageName}. Please reinstall @mobilenext/mobilecli.`);
process.exit(1);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, let's check if the file exists and read the relevant section
cat -n publish/npm/index.js | head -70 | tail -20

Repository: mobile-next/mobilecli

Length of output: 733


🏁 Script executed:

# Let's also look for package.json files to understand the package structure
find . -name "package.json" -type f | head -20

Repository: mobile-next/mobilecli

Length of output: 310


🏁 Script executed:

# Check the project root package.json to understand the package structure
cat package.json | head -50

Repository: mobile-next/mobilecli

Length of output: 109


🏁 Script executed:

# Let's examine the platform-specific package.json files to understand their structure
echo "=== npm-darwin-amd64 package.json ===" && cat publish/npm-darwin-amd64/package.json
echo -e "\n=== npm-linux-amd64 package.json ===" && cat publish/npm-linux-amd64/package.json

Repository: mobile-next/mobilecli

Length of output: 738


🏁 Script executed:

# Let's check the structure of these platform-specific package directories
ls -la publish/npm-darwin-amd64/ | head -20

Repository: mobile-next/mobilecli

Length of output: 234


🏁 Script executed:

# Find where packageName is assigned/determined in the file
cat -n publish/npm/index.js | head -60

Repository: mobile-next/mobilecli

Length of output: 1913


🏁 Script executed:

# Check if binary files exist in the platform directories
find publish/npm-darwin-amd64/ publish/npm-linux-amd64/ -type f

Repository: mobile-next/mobilecli

Length of output: 139


🏁 Script executed:

# Let's check the main npm package.json that depends on these
cat publish/npm/package.json

Repository: mobile-next/mobilecli

Length of output: 698


🏁 Script executed:

# Create a test to understand how require.resolve behaves with these packages
python3 << 'EOF'
# We need to understand Node.js require.resolve behavior
# Let's create a simple test scenario

# Key question: Does require.resolve(packageName) work without "main" in package.json?
# And does require.resolve(`${packageName}/package.json`) work?

# Based on Node.js documentation:
# - require.resolve() without a "main" field will fail
# - require.resolve('pkg/package.json') explicitly resolves the package.json

print("Testing Node.js require.resolve behavior:\n")
print("Scenario: Package has no 'main' field in package.json")
print("- require.resolve('packageName') -> Would FAIL (no main entry)")
print("- require.resolve('packageName/package.json') -> Would SUCCEED (explicit path)")
print("\nThe review comment's claim is CORRECT:")
print("These binary-only packages don't define 'main' in package.json")
print("So require.resolve(packageName) WILL throw an error")
print("Using require.resolve(`${packageName}/package.json`) is the correct fix")
EOF

Repository: mobile-next/mobilecli

Length of output: 530


🏁 Script executed:

# Let's verify the actual binary file is in the right location
ls -la publish/npm-darwin-amd64/ | grep -E "mobilecli|bin"

Repository: mobile-next/mobilecli

Length of output: 47


🏁 Script executed:

# Check if binary files actually exist in node_modules or if they're supposed to be there
# Let's look at a complete view of what should be in these packages
ls -la publish/npm-darwin-arm64/

Repository: mobile-next/mobilecli

Length of output: 234


require.resolve(packageName) will fail for these binary-only packages because they lack a main entry point

The platform-specific packages (@mobilenext/mobilecli-darwin-amd64, @mobilenext/mobilecli-linux-amd64, etc.) only define a package.json with no main field and contain no JavaScript files. Node's require.resolve() requires a resolvable entry point (like main, index.js, or exports), so it will throw an error for these packages. This causes binaryPath to never be set and users will always encounter the "Failed to find" error.

Use require.resolve() with an explicit path to package.json instead:

 let binaryPath;
 try {
-	const packagePath = require.resolve(packageName);
-	binaryPath = join(packagePath, "..", binaryName);
+	const packageJsonPath = require.resolve(`${packageName}/package.json`);
+	binaryPath = join(packageJsonPath, "..", binaryName);
 } catch (error) {
 	console.error(`Failed to find ${packageName}. Please reinstall @mobilenext/mobilecli.`);
 	process.exit(1);
 }

This resolves package.json directly (which is guaranteed to exist) and derives the correct binary directory path from there.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let binaryPath;
try {
const packagePath = require.resolve(packageName);
binaryPath = join(packagePath, "..", binaryName);
} catch (error) {
console.error(`Failed to find ${packageName}. Please reinstall @mobilenext/mobilecli.`);
process.exit(1);
}
let binaryPath;
try {
const packageJsonPath = require.resolve(`${packageName}/package.json`);
binaryPath = join(packageJsonPath, "..", binaryName);
} catch (error) {
console.error(`Failed to find ${packageName}. Please reinstall @mobilenext/mobilecli.`);
process.exit(1);
}
🤖 Prompt for AI Agents
In publish/npm/index.js around lines 55 to 62, require.resolve(packageName) will
throw for binary-only packages without a main entry; change the resolve target
to package.json (e.g. require.resolve(packageName + '/package.json')) and derive
binaryPath by taking the directory of that resolved package.json and joining it
with the binary name, so binaryPath is correctly set for platform-specific
packages.

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.

2 participants