Skip to content

feat(cli): build the patch tools with a command instead of a script path - #186

Merged
floyd-soomgo merged 9 commits into
masterfrom
feat/build-patch-tools-command
Aug 28, 2026
Merged

feat(cli): build the patch tools with a command instead of a script path#186
floyd-soomgo merged 9 commits into
masterfrom
feat/build-patch-tools-command

Conversation

@floyd-soomgo

@floyd-soomgo floyd-soomgo commented Aug 28, 2026

Copy link
Copy Markdown
Member

Background

Building the binary patch generator meant reaching into the package's own layout: running
node_modules/@bravemobile/react-native-code-push/scripts/binary-patch/build-hdiffpatch.sh
by hand, and overriding where it installs, because the script's default is the package
root - which under node_modules sits below the project, where the CLI never looks. The
README explained the mismatch and how to point HDIFFPATCH_TOOLS_DIR around it. A CI cache
of the built tools was keyed by a checksum of the same path. And the error a release raises
when the tools are missing named scripts/binary-patch/build-hdiffpatch.sh, a path relative
to the package root that does not run from a project directory.

The path into node_modules is not part of the CLI's interface, and it is not even
reliable: in a workspace that hoists the package it does not exist at the project directory.

Changes

npx code-push build-patch-tools

Runs the shipped script itself and installs where release will look: HDIFFPATCH_TOOLS_DIR
when it is set, and otherwise .hdiffpatch-tools in the working directory - the first place
the lookup checks. --tools-dir overrides both, --force passes through. The script's
output streams to the terminal, since a first build clones and compiles for about a minute.

--print-hash prints the SHA-256 of the shipped script and exits without building. The
script pins the sources and the build flags, so the hash changes only with a version of this
package that changes them - what a CI cache of the install directory needs as a key, without
the path.

The command does not check the version of an already installed pair, which is the script's
existing behavior; the README says to --force after an upgrade that pins a different
HDiffPatch.

The missing-tools error

Names the command instead of the script path.

CI

unit-test.yml now builds the CLI and starts one command (build-patch-tools --print-hash)
on every push. jest runs babel in CJS mode and cannot load the modules that use
import.meta, so this is the one check that the compiled CLI resolves its own files.

Docs

The prerequisites paragraph under release is down to the one command, and
build-patch-tools has a section of its own, in both languages. The heading anchors
docs/diff-updates.md links to are unchanged.

What existing CLI users see

Scope Change
release --binary-bundle-path Unchanged. The lookup order for the tools is what it was; only the message for a missing tool changed.
scripts/binary-patch/build-hdiffpatch.sh Still shipped and unchanged. Running it directly keeps working.
New The build-patch-tools command.

For a project that today runs the script by its node_modules path with
HDIFFPATCH_TOOLS_DIR set to <project>/.hdiffpatch-tools:

npx code-push build-patch-tools

and for a CI cache keyed by the script's checksum:

npx code-push build-patch-tools --print-hash > .hdiffpatch-tools.hash
# then key the cache by the checksum of that file, alongside the architecture

Verification

  • CLI tests: 102 passing in 11 suites, 7 of them new. The wrapper is tested against a script
    that records what it was handed, so the install directory and --force are proven without
    cloning; the shipped script is run once against an install it already finds complete.
  • tsc --noEmit passes.
  • The script path is resolved from import.meta.url, which the jest setup (babel, CJS)
    cannot evaluate, so it has no unit test. It was verified by running the compiled CLI:
    --help, the default directory from the repository root, and --tools-dir from another
    working directory.
  • One real fresh build through the command into an empty directory: cloned, compiled,
    installed hdiffz (1.0 MB) and hpatchz (240 KB), exit 0.
  • --print-hash output equals shasum -a 256 scripts/binary-patch/build-hdiffpatch.sh,
    one line on stdout.
  • The new CI step, run locally: npm run build:cli && node bin/code-push.js build-patch-tools --print-hash > /dev/null exits 0.

Building hdiffz and hpatchz meant running
node_modules/@bravemobile/react-native-code-push/scripts/binary-patch/build-hdiffpatch.sh
by hand - a path into the package's own layout - and overriding where it
installs, because the script's default is the package root, which sits below
the project where the CLI never looks.

`npx code-push build-patch-tools` runs the shipped script itself and installs
where `release` will look: `HDIFFPATCH_TOOLS_DIR` when it is set, and otherwise
`.hdiffpatch-tools` in the working directory. `--tools-dir` overrides both and
`--force` passes through.
… builds them

The error named `scripts/binary-patch/build-hdiffpatch.sh`, a path relative to
the package root that does not run from a project directory.
The prerequisites paragraph no longer has to explain that the script installs
where the CLI does not look, or how to point HDIFFPATCH_TOOLS_DIR into
node_modules.
A CI cache of the installed tools is keyed by a checksum of the build script,
which is what the script pins the sources and build flags in. Computing it
meant naming the script's path inside node_modules - the path the command
exists to hide.

`--print-hash` prints the SHA-256 of the shipped script and exits without
building.
jest runs babel in CJS mode and cannot load the modules that use
`import.meta`, so nothing exercised the compiled CLI before publish - the
relative path `build-patch-tools` resolves its script by could break without
a test noticing. Building the CLI and starting one command proves it
resolves its own files, on every push.
…e shipped script runs

Without the install the shipped script clones and compiles for minutes, and
`spawnSync` holds the worker past any jest timeout. Also reads
`HDIFFPATCH_TOOLS_DIR` with `||`, as the CLI and `jest.globalSetup.ts` do.
@floyd-soomgo
floyd-soomgo marked this pull request as ready for review August 28, 2026 07:28
@floyd-soomgo
floyd-soomgo merged commit bbc773d into master Aug 28, 2026
1 check passed
@floyd-soomgo
floyd-soomgo deleted the feat/build-patch-tools-command branch August 28, 2026 07:29
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