Skip to content

feat: install.sh - #59

Open
khvn26 wants to merge 2 commits into
docker-ghcrfrom
install-sh
Open

feat: install.sh#59
khvn26 wants to merge 2 commits into
docker-ghcrfrom
install-sh

Conversation

@khvn26

@khvn26 khvn26 commented Jul 29, 2026

Copy link
Copy Markdown
Member

Closes #44.

curl -fsSL https://raw.githubusercontent.com/Flagsmith/flagsmith-cli/main/install.sh | sh

The script installs to $HOME/.local/bin, verifies the sha256 from checksums.txt, and adds the install directory to PATH if it's not there.

The script pins the version it shipped with. The pin is bumped by release-please.

Verified locally

Against a goreleaser snapshot served over http, into a sandboxed HOME:

  • dry run
  • real install
  • binary runs
  • env script written
  • .profile sources it, and sourcing it puts flagsmith on PATH
  • re-install doesn't duplicate the rc line
  • --no-modify-path writes neither the rc line nor the env script
  • tampered checksum results in exit 1 with checksum mismatch
  • missing checksum entry results in exit 1 with expected exactly one checksum
  • unknown version, unknown flag and a version without the leading v all behave

Important

  • DEFAULT_VERSION is v2.0.0-beta.1, which is what ci: configure release-please for the 2.0.0 beta line #54's Release-As: footer forces.
  • The checksum comes from the same origin as the archive, so it proves the download wasn't corrupted, nothing more. Provenance attestation is in ci: build release binaries with goreleaser #55/ci: publish multi-arch images to ghcr.io #56gh attestation verify --owner Flagsmith <file> — but the script doesn't check it, since users won't have gh installed.
  • macOS notarization and Windows Authenticode are still absent. curl | sh is unaffected (curl sets no quarantine xattr); a browser download on macOS will be Gatekeeper-blocked.
  • install.ps1 for Windows is deliberately out of scope — the script tells Windows users to take the .zip.

add_ci_path appends the install dir to $GITHUB_PATH, so curl … | sh in one Actions step leaves the CLI on PATH for later steps — an Actions shell is neither login nor interactive, so it never reads the startup files the installer edits. Taken from uv. The release smoke job relies on it rather than sourcing the env script.

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 419487dd-11ae-41b5-a36d-551aac73e5af

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@khvn26 khvn26 changed the title feat: add install.sh feat: install.sh Jul 29, 2026
@khvn26
khvn26 marked this pull request as ready for review July 29, 2026 21:02
@khvn26 khvn26 mentioned this pull request Jul 29, 2026

@Zaimwa9 Zaimwa9 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.

I'd like to check the go.mod path and fix the error surfacing that could have a wrong install leaving the shell half configured

Comment thread install.sh
case "$ARCH" in
x86_64 | amd64) ARCH=amd64 ;;
aarch64 | arm64) ARCH=arm64 ;;
*) err "unsupported architecture '${ARCH}' — 'go install github.com/${REPO}@${VERSION}' builds from source" ;;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Ok claude is flagging an issue with the go.mod from here:

Both go install fallbacks are broken for v2: @latest never selects prereleases (silently installs v1.1.0), and once 2.0.0 is stable it still resolves v1.1.0 because go.mod lacks the /v2 module-path suffix.

Can we check it please ?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Confirmed. go.mod declares module github.com/Flagsmith/flagsmith-cli (no /v2), so:

  • go install github.com/Flagsmith/flagsmith-cli@latest resolves the v0/v1 module path → v1.1.0 (and @latest never selects prereleases regardless).
  • go install github.com/Flagsmith/flagsmith-cli@v2.0.0-beta.1 would be rejected: major version v2 requires a /v2 module-path suffix.

The same issue affects README.md, which now says go install github.com/Flagsmith/flagsmith-cli@latest as an alternative. Fixing go.mod is separate work; for this PR, either remove the go install suggestion or caveat it as v1-only.

Comment thread install.sh
fi
}

main "$@" || exit 1

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggested change
main "$@" || exit 1
main "$@"

Otherwise the || will turn off the set -eu inside main. Leading to swallowing errors it's supposed to raise and succeeding because last command is an echo.

Reproduced with the following

set -eu
main() { false; echo "STILL RUNNING after failure"; }
main "$@" || exit 1

-- 

set -eu
main() { false; echo "STILL RUNNING"; }
main "$@"

khvn26 added 2 commits July 30, 2026 11:36
The script pins the version it was released alongside, so the common path makes
no API call and cannot be rate limited: release-please rewrites DEFAULT_VERSION
through the `extra-files` entry, whose Generic updater replaces the first semver
token on any line carrying `x-release-please-version`. Only the token changes,
so the leading v survives.

Everything lives in functions with `main "$@"` last, so a truncated download
cannot execute half a script. The strict curl flags apply to https URLs only —
FLAGSMITH_CLI_BASE_URL exists to point the script at a local server for testing,
and that server is plain http.

PATH handling follows uv: an env script the startup files source, edited once
each, skipped when the install dir is already on PATH. The env script lives
under our own directory because $HOME/.local/bin/env belongs to cargo-dist and
uv writes it.

beep boop
Each `run:` step gets a fresh shell, and an Actions shell is neither a login
nor an interactive one, so nothing it starts reads the startup files the
installer edited. Appending the directory to the file $GITHUB_PATH points at is
the mechanism the runner does honour: it prepends those entries for every later
step. So `curl ... | sh` in one step and `flagsmith` in the next now works on
any runner, rather than only on images that already ship ~/.local/bin on PATH.

Taken from uv's Add-Ci-Path. The release smoke job drops its explicit sourcing
of the env script and relies on this instead.

beep boop
@Zaimwa9

Zaimwa9 commented Jul 30, 2026

Copy link
Copy Markdown

@themis-blindfold review

@themis-blindfold

Copy link
Copy Markdown

⚖️ Themis review: 🟠 Fix before merge

Well-structured install script modelled on established installers (uv, rustup). Two issues from the existing review threads need addressing before merge: main "$@" || exit 1 silently suppresses set -eu error handling inside main, and the README's go install suggestion won't work for v2 because go.mod lacks the /v2 module-path suffix.

All checks from the latest CI run passed; the cancelled checks are from a superseded run.

Area Score
🎯 Correctness 3/5
🧪 Test coverage 3/5
📐 Code quality 4/5
🚀 Product impact 4/5

🟠 Majors

  • install.sh:270main "$@" || exit 1 suppresses set -eu inside main. The || puts main in a condition context where POSIX set -e is disabled. Commands without explicit error handling (tar, mkdir -p, chmod, mv) fail silently. Fix: main "$@" — with set -eu, a failing command already produces a non-zero exit. (Raised by @Zaimwa9.)

  • README.md:22 / install.sh:119go install github.com/Flagsmith/flagsmith-cli@latest silently installs v1. go.mod declares module github.com/Flagsmith/flagsmith-cli (no /v2), so Go resolves the v0/v1 module path and ignores v2 tags. @latest also never selects prereleases. An explicit @v2.0.0-beta.1 would be rejected outright because the major version doesn't match the module path. Fix for this PR: either remove the go install suggestion or caveat it as v1-only; fixing go.mod is separate work. (Raised by @Zaimwa9.)

📝 Walkthrough
  • install.sh — new POSIX shell installer: downloads the platform-appropriate release archive, verifies its sha256 against checksums.txt, installs the binary to $HOME/.local/bin (configurable), and wires PATH via env scripts sourced from shell rc files. Rosetta detection, GITHUB_PATH integration for Actions, and --dry-run are included.
  • .github/workflows/release.yml — adds an install-script smoke job that runs after goreleaser on Linux and macOS, exercising the installer against the just-published release.
  • README.md — adds an Install section with the curl-pipe-sh one-liner, option examples, and a go install fallback.
  • .pre-commit-config.yaml — adds shellcheck and shfmt hooks.
  • release-please-config.json — registers install.sh as an extra file so the x-release-please-version annotation keeps DEFAULT_VERSION in sync with releases.
🧪 How to verify
  1. Apply the main "$@" fix, then run sh -c 'set -eu; main() { false; echo "BUG: still running"; }; main "$@"' to confirm set -e is no longer suppressed.
  2. Run sh install.sh --dry-run and verify the archive URL and checksum URL are well-formed for the default version.
  3. In a disposable HOME, run sh install.sh --version v2.0.0-beta.1 --bin-dir /tmp/test-bin against a real or snapshot release and confirm the binary executes.
  4. Run sh install.sh --no-modify-path and confirm no rc files are touched.
  5. Verify go install github.com/Flagsmith/flagsmith-cli@latest installs v1.1.0 (not v2), confirming the README claim is inaccurate.

Automate: a CI job that runs the installer against a goreleaser snapshot (already added in the release workflow; consider also running it on PR CI with a mock server).

Product take: This is the primary binary distribution channel for the Go CLI rewrite — essential for adoption. The script itself is solid and follows established conventions. Once the two Majors are addressed, it's ready to ship.

🧭 Assumptions & unverified claims
  • The x-release-please-version annotation on DEFAULT_VERSION is assumed to correctly update the version string on release; if release-please strips the v prefix, the script's case "$VERSION" in v*) ... esac re-adds it, so it works either way.
  • go install github.com/Flagsmith/flagsmith-cli@v2.0.0-beta.1 is predicted to fail based on Go module version rules (module path lacks /v2); this was not executed in-sandbox.

A script that diligently verifies checksums but then || exit 1s its own error handling — trust issues all around. · reviewed at 9ebe5d0

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.

Add install.sh

2 participants