feat(installer): the curl|bash no-warning path, auditable line by line (#479) - #511
Merged
Conversation
#479) A terminal installer that bootstraps the release wheels into a per-user venv at ~/.keel/.venv -- nothing is downloaded as an application, so no OS trust dialog is ever involved (that path stays the .dmg/.zip with docs/desktop-install.md; signing stays #438). Auditable by construction: set -euo pipefail, every step prints what it is about to do before running, every download URL is echoed, no sudo, no credentials, no nested pipe-to-shell. Python >= 3.11 is checked via the interpreter's own version_info and the failure names the floor. The five production wheels are selected by exact allowlisted name (equal to PRODUCTION_WHEEL_PREFIXES in keel/commands/update.py) and installed BY PATH -- never by name from an index (the PyPI 'keel' is an unrelated project). Wheel checksums are not published by the release; the script says so honestly and records each wheel's sha256 locally instead. config.yaml and keel*.db under ~/.keel are never overwritten. The venv is named .venv deliberately so 'keel update' serves what this script built (verified: it reports 'already at the latest release' on a fresh install), and the printed next steps compose with #439 option A. tests/test_install_script.py pins these properties over the script text, the house pattern from tests/test_desktop_packaging.py.
The acceptance evidence for #479's 'works on macOS and Linux': run scripts/install.sh FOR REAL on both runners (public repo, network, the actual release wheels) into an isolated HOME, then assert the installed venv's own 'keel versions' exits 0. shellcheck runs on the Linux leg only (ubuntu images ship it, macOS images do not; the bytes are the same on both). pull_request is filtered to the script's path so an unchanged installer costs no runners; the text-pinning suite in tests/test_install_script.py runs in CI on every PR regardless.
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 #479
What
curl | bashinstaller that bootstraps the release wheels — the no-warning path.scripts/install.sh(~215 lines, every step says what and why before it runs), 16 property-pinning tests over its text, a two-OS CI smoke that runs it for real, and pointers fromdocs/desktop-install.md(which now leads its no-warning section with the installer) and the README quickstart.Explicitly not downloading an app binary: the OS-warning path stays the
.dmg/.zipwalkthrough; signing stays #438.curl -fsSL https://raw.githubusercontent.com/CodeGateSoftware/keel/main/scripts/install.sh | bashDesign decisions
~/.keel/.venv, config beside it. One per-user folder you can look inside — keel's deployment model (keel_core/paths.py). The venv is named.venvdeliberately: that is the exact layoutkeel update'sdeployment_layout_refusalrecognises, so the updater serves what the installer built. Verified locally: on a fresh install,keel updatefrom~/.keelanswersalready at the latest release (0.11.0). No sudo, nothing written outside$HOME.uv --version, not justcommand -v— a broken shim (asdf + changed HOME failed exactly this way on my machine) is honestly treated as absent and the pip path (python -m venv+ensurepipbootstrap +pip install --no-input) takes over. Both branches install by exact wheel path with--find-links, mirroringkeel update's_uv_installform — never by name from an index (PyPI'skeelis an unrelated project).SHA256SUMSfor the desktop artifacts only; there are no published wheel checksums, and the script says so in its output rather than pretending to verify — it records each wheel's sha256 as computed locally instead, leaving an auditable record of what was installed.keel_core,keel_broker_api,keel_broker_coinbase,keel_broker_alpaca,keel_trader), selected by exact<prefix>-<version>-name — the test pins the script's allowlist equal toPRODUCTION_WHEEL_PREFIXESfromkeel/commands/update.py, so the two selectors cannot drift. The names of the excluded venue wheels never appear in the script at all.keel versionsbefore success. The verify runs from~/.keel(so state resolves against the deployment) and its failure fails the script; the success banner is unreachable otherwise. The next-steps output composes with D6 — Decide the update path for a packaged install #439 option A: re-run the installer, orkeel updatefor this venv layout; desktop bundles update by re-downloading.config.yamlis kept and said so;keel*.dbis acknowledged and untouched; re-running upgrades the venv in place.Real local run (this Mac, isolated
HOME)Fresh install via the pip path (this machine's
uvis an asdf shim that breaks under a changedHOME, so the fallback earned its keep), then re-run for idempotency:Also exercised: the uv path with a working
uvonPATH(exit 0; uv's output shows each keel wheelfrom file:///...whl— by path, proven), and a re-run over the existing install:CI
install-smoke.yml:workflow_dispatch+pull_requestfiltered toscripts/install.shonly; matrixubuntu-latest×macos-latest; shellcheck on the Linux leg (ubuntu ships it, macOS doesn't); runs the script for real into$RUNNER_TEMPHOME and asserts~/.keel/.venv/bin/keel versionsexits 0.Gates
uv run pytest -q— 4472 passed, 3 skipped (16 new)uv run ruff check keel tests— cleanuv run mypy— clean (351 files)shellcheck scripts/install.sh— clean locallyNotes / deviations
keel/commands/update.py's docstring) still says "four production wheels" in places; the code, the release assets and this installer all carry five (alpaca joined in keel update cannot update an Alpaca deployment — the equities profile is outside PRODUCTION_WHEEL_PREFIXES #425). The installer followsPRODUCTION_WHEEL_PREFIXESas built, and the test pins them equal.