Repository navigation
feat: release standalone binaries for macOS and Linux, with an install script - #320
Merged
Merged
Conversation
…l script Each release now ships a single-file configfile binary per system (macOS and Linux, x64 and arm64), built as a Node.js single executable application, so configfile can be installed on a new machine without Node.js or a package manager: curl -fsSL https://docs.configfile.sh/install.sh | sh. Closes #301
On a re-run, the files a release already has are kept, and were attested with the new ones: a file uploaded by hand would then get a build provenance attestation it never earned.
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #301.
Context
configfile is a CLI that keeps dotfiles in a git repository and deploys them on each machine. Until now it was installed with npm or Homebrew, which both need Node.js 24.11 or later. That's awkward exactly where configfile is most useful: on a new machine, where nothing is set up yet and installing Node.js is one of the things your dotfiles would do.
This PR makes each release ship a standalone binary per system, with a one-line install:
curl -fsSL https://docs.configfile.sh/install.sh | shnpm and Homebrew keep working as before.
What changes
The binaries (
tools/build-binary.ts,pnpm build:binary)configfile-{macos,linux}-{arm64,x64}.tar.gz, holdingconfigfile,LICENSEandTHIRD-PARTY-LICENSES(configfile's bundled dependencies and Node.js itself).NODE_OPTIONSis ignored by the binary (execArgvExtension: "none"): it is meant for the user's Node.js, and a value such as--require ./.pnp.cjswould otherwise stop configfile before it starts.Source changes needed to run as a binary
src/cli.ts: no top-level await, since the binary runs CommonJS. A run whose promise never settles still exits with 13, as a pending top-level await does.src/program.ts: the version comes from a constant defined at build time (CONFIGFILE_VERSION), as there is nopackage.jsonnext to the binary.src/process.ts: a.jsscript without a shebang line used to run with configfile's own Node.js. In the binary, that Node.js runs configfile only, so such scripts run with thenodeinPATH. When there is none, or it can't be executed, the error says so. Nothing changes for npm and Homebrew installs.The install script (
docs/public/install.sh, served by the docs site)sh, checked by shellcheck in CI.SHA256SUMS.~/.local/bin, withCONFIGFILE_INSTALL_DIR,CONFIGFILE_VERSIONandCONFIGFILE_DOWNLOAD_URL(for tests and mirrors) as settings. It says when the folder isn't inPATH, when another configfile comes first, and when git is missing.Release workflow (
.github/workflows/publish.yml)binariesjob builds the binary on each of the four systems and runs the end-to-end tests with it.SHA256SUMS, and a build provenance attestation for each archive.CI (
.github/workflows/ci.yml)A new
binaryjob, on the same four systems, on every PR:configfile init's question on a real terminal (script), withNODE_OPTIONSset to a value that would crash a normal Node.js.Docs
The installation page, the new-machine guide, the scripts reference, the upgrading-from-0.3 guide, the README and the CHANGELOG. They state the binaries' minimums (macOS 13.5, GNU C library 2.28, inherited from Node.js 24), how to update and uninstall, and the macOS Gatekeeper note for browser downloads.
Compatibility
curl … | shcommand works once a release with binaries is out; 1.0.0 has none (the docs say so). The README ondevelopshows it already: this assumes the next release follows the merge.Tests
tests/install.test.ts(23 tests): the install script against fake releases and fakeuname/sysctl/ldd. They cover:*namelines;PATH, and a folder that can't be created;tests/process-sea.test.ts: the binary-only.jspath:nodefromPATH, missing, not executable.tests/e2e.test.ts:--versionand a.jsscript end to end. The suite runs with the npm build, and with the binary whenCONFIGFILE_BINARYis set (as CI does).pnpm checkpasses locally (516 tests); shellcheck, actionlint and zizmor are clean.Manual test
On macOS or Linux:
The binary is about 120 MB uncompressed (38 MB as an archive), mostly Node.js itself.