Skip to content

feat(cli): download Node.js for the expo APNs key setup when it is missing - #1997

Merged
ArnabChatterjee20k merged 2 commits into
messaging-provider-cli-apnsfrom
messaging-provider-cli-apns-expo-node
Oct 9, 2026
Merged

ArnabChatterjee20k merged 2 commits into
messaging-provider-cli-apnsfrom
messaging-provider-cli-apns-expo-node

Conversation

@ArnabChatterjee20k

Copy link
Copy Markdown
Member

Stacked on #1963. With this, --provider expo no longer requires Node.js to be installed.

What

Before, the expo APNs key setup stopped with "needs Node.js 18 or later" when node or npm was missing, or node was too old. Now it downloads Node.js itself and carries on:

$ appwrite init apns --create-key --provider expo
Node.js 18 or later was not found. Downloading Node.js v24.21.0 (about 50 MB, 200 MB unpacked) into ~/.appwrite/apns/expo/runtime ...

The download only happens for --provider expo (or APPWRITE_APNS_SETUP=expo) on a machine without a usable Node.js. The default appwrite setup needs no runtime.

How

  • Which node:
    1. A node set on the adapter is checked and never replaced.
    2. Otherwise node and npm from PATH, if node is 18 or later.
    3. Otherwise the downloaded runtime.
  • Download:
    • The pinned Node.js release is v24.21.0, the Active LTS, released 7 September 2026.
    • The build for this OS and CPU (darwin/linux x64/arm64 .tar.gz, win x64/arm64 .zip) comes from https://nodejs.org/dist/v24.21.0/.
    • The SHA-256 of each build is pinned in runtime.go, taken from the release's SHASUMS256.txt. A download that doesn't match is deleted and nothing is unpacked.
  • Unpack:
    • The build is unpacked into a staging folder beside its final location, then moved into place, so an interrupted run never leaves a half-unpacked runtime.
    • Entries that would land outside the folder (absolute paths or ..) are refused.
    • Symbolic links are skipped: they're only npm's and npx's shell wrappers.
  • Run: npm runs as node .../npm/bin/npm-cli.js ci …, so its wrappers aren't needed. The downloaded bin folder goes first on PATH for npm and the helper.
  • Where: <session folder>/runtime/node-v24.21.0-<os>-<arch>/, which is ~/.appwrite/apns/expo/runtime/ from the CLI. Nothing is installed system-wide, and later runs reuse it. Without a session folder it goes into a temporary folder that's removed afterwards.
  • Failure: if the download fails, the error is apns.ErrUnavailable with the reason, before anything is sent to Apple.

Tests

  • TestNodeBuild: build name and archive type for each OS/arch, a pinned checksum for each, and no build for unsupported platforms.
  • TestCreateKeyDownloadsNodeWhenMissing: with nothing but mkdir on PATH, it downloads a fake build (a shell-script node) from a local server, unpacks it, runs npm ci and the helper through it, and creates the key. A second run reuses it with no second download. node stays executable and npm's symbolic link isn't unpacked.
  • TestDownloadNodeRejectsABadChecksum: a mismatched checksum fails, and nothing is unpacked.
  • TestUntarRefusesPathsOutsideTheFolder: ../evil is refused and not written.
  • Manual check against the real nodejs.org (not committed): the pinned darwin-arm64 build downloaded, matched its checksum and unpacked, and then node --version printed v24.21.0 and npm-cli.js --version printed 11.19.0.
  • Full CLI suite (-race), gofmt, the WebAssembly browser build, GOOS=windows go vet for the apns packages, Rector and the Generation suite all pass.

Notes

  • The checksums come from nodejs.org over HTTPS. Node's signature on SHASUMS256.txt wasn't verified, because gpg wasn't available when they were pinned. A maintainer with gpg can check them against https://nodejs.org/dist/v24.21.0/SHASUMS256.txt.sig.
  • Moving to a newer Node.js means updating nodeRelease and the six checksums.

The expo setup stopped when node or npm was missing, or node was older
than 18. It now downloads the Node.js LTS (v24.21.0) for this OS and CPU
from nodejs.org into the setup's session folder, checks the archive
against the SHA-256 pinned for each official build, unpacks it beside
its final folder and moves it into place, and runs npm through node.
Nothing is installed system-wide, and later runs reuse it. Entries that
would unpack outside the folder are refused and symbolic links (npm's
shell wrappers) are skipped. A node set on the adapter is checked but
never replaced.
@hansi-codes

hansi-codes Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

🟢 Tier S · Ready to merge

Adds a pinned, checksum-verified Node.js runtime download for Expo APNs key setup when no usable Node.js is available. The runtime is unpacked in a staging directory, reused across runs, and covered by build-selection, download, extraction, and concurrency tests. The CLI generator includes the new runtime implementation and tests in generated CLI output.

Latest changes: The new commits avoid removing an already-published runtime during concurrent setup and add a test exercising concurrent first-time downloads.

Verdict New comments Fixed Still open
✅ Approved 0 1 0
📂 Walkthrough · 4
File Change
src/SDK/Language/CLI.php Registers the Expo runtime implementation and tests in generated CLI output.
templates/cli/internal/apns/expo/adapter.go Selects a usable Node.js toolchain and downloads the pinned runtime when needed for Expo APNs key setup.
templates/cli/internal/apns/expo/runtime.go Adds platform-specific Node.js builds, checksum-verified downloads, safe extraction, runtime reuse, and non-destructive concurrent publication.
templates/cli/internal/apns/expo/runtime_test.go Tests build selection, runtime download and reuse, checksum and archive-path rejection, and concurrent first-time setup.
✅ Fixed since the last review · 1
  • Concurrent first runs can remove an active runtime · templates/cli/internal/apns/expo/runtime.go:112

Reviewed the commits since fa93a7b · Details · Comment @hansi-codes review to re-run, or mention @hansi-codes with a question.

@hansi-codes hansi-codes 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.

🔵 Tier A · See the inline comments. Summary

Comment thread templates/cli/internal/apns/expo/runtime.go Outdated
Two expo setups starting together in the same session folder could both
download Node.js, and the later one removed the runtime the earlier one
had just published, maybe while it was running npm or the helper.
Publishing is now only a rename: an existing runtime is never removed,
and when another run published first, its complete runtime is used.

@hansi-codes hansi-codes 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.

🟢 Tier S · Looks good to merge. Summary

@ArnabChatterjee20k
ArnabChatterjee20k merged commit 89ea7ee into messaging-provider-cli-apns Oct 9, 2026
54 of 61 checks passed
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