From 86b3fec0ea94c77bd90efc4d57488f0c2b0de4d3 Mon Sep 17 00:00:00 2001 From: Mike Odnis Date: Sat, 18 Apr 2026 23:34:57 -0400 Subject: [PATCH 1/2] feat(installer): fetch resq-cli binary + per-shell completions (Stage 2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Until now, install.sh cloned the target repo and set up the nix shell but never actually installed the resq binary that the whole toolchain is named after. Users had to remember `cargo install resq-cli` or `gh release download` separately. Stage 2 closes that gap. After post_clone_setup, the installer now: - Detects platform (Linux x86_64/aarch64, macOS x86_64/arm64) and maps to the right Rust target triple. - Queries `gh release list` for the latest `resq-cli-v*` tag in resq-software/crates (Windows is skipped; install.ps1 will handle it separately later). - Downloads the matching tar.gz and SHA256SUMS via `gh release download`. - Verifies the checksum with `sha256sum -c` — a failed checksum aborts the install with a warning, not silently. - Drops the verified binary at $RESQ_BIN_DIR/resq (default ~/.local/bin/resq, mode 0755). - Detects the user's $SHELL (bash/zsh/fish) and writes the generated completion script to the conventional user-local path. Other shells get a hint to run `resq completions ` manually. - Warns if ~/.local/bin isn't already on $PATH. Idempotent: if `resq --version` already matches the latest release tag, we skip the download and just refresh completions. Opt out entirely with `SKIP_RESQ_CLI=1`. Also improved post_clone_setup's nix develop step: the previous "a few minutes" message was too vague to be useful. Now we state the expected download size (500 MB–2 GB) and time (2–5 min) up front, and report the actual elapsed seconds when it succeeds. Still no real-time progress — that would need tee-ing the nix log — but expectation-setting is free. --- install.sh | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 132 insertions(+), 2 deletions(-) diff --git a/install.sh b/install.sh index 04c6d18..9a18753 100755 --- a/install.sh +++ b/install.sh @@ -316,8 +316,14 @@ clone_repo() { post_clone_setup() { if [ -f "$TARGET_DIR/flake.nix" ] && has nix; then - info "Nix flake detected — building dev environment (first run may take a few minutes)..." - if ! nix develop "$TARGET_DIR" --command true; then + info "Building Nix dev environment at $TARGET_DIR" + info " (first run downloads ~500 MB – 2 GB; expect 2–5 minutes, no progress bar)" + _nix_start="$(date +%s 2>/dev/null || echo 0)" + if nix develop "$TARGET_DIR" --command true; then + _nix_end="$(date +%s 2>/dev/null || echo 0)" + _nix_elapsed=$((_nix_end - _nix_start)) + ok "Nix dev environment ready (${_nix_elapsed}s)" + else warn "nix develop failed — cd into $TARGET_DIR and run 'nix develop' to see errors" fi fi @@ -331,6 +337,129 @@ post_clone_setup() { fi } +# Install the `resq` binary from resq-software/crates GitHub Releases. Chooses +# the tar.gz for the current $OS/$ARCH, verifies SHA256 against the release's +# SHA256SUMS, and drops the binary into $RESQ_BIN_DIR (default ~/.local/bin). +# Idempotent: skips when the currently-installed `resq --version` matches the +# latest release. Skip entirely with SKIP_RESQ_CLI=1. +install_resq_cli() { + if [ "${SKIP_RESQ_CLI:-0}" = "1" ]; then + info "SKIP_RESQ_CLI=1 — skipping resq binary install" + return 0 + fi + + case "$OS-$ARCH" in + Linux-x86_64) _triple="x86_64-unknown-linux-gnu" ;; + Linux-aarch64|Linux-arm64) _triple="aarch64-unknown-linux-gnu" ;; + Darwin-x86_64) _triple="x86_64-apple-darwin" ;; + Darwin-arm64) _triple="aarch64-apple-darwin" ;; + *) + warn "No resq-cli binary published for $OS-$ARCH — skipping" + return 0 + ;; + esac + + _tag="$(gh release list --repo "$ORG/crates" --limit 40 \ + --json tagName --jq '.[] | .tagName' 2>/dev/null \ + | grep -m1 '^resq-cli-v' || true)" + if [ -z "$_tag" ]; then + warn "No resq-cli release found in $ORG/crates — skipping binary install" + return 0 + fi + _expected_ver="$(echo "$_tag" | sed 's/^resq-cli-v//')" + + _bin_dir="${RESQ_BIN_DIR:-$HOME/.local/bin}" + _bin_path="$_bin_dir/resq" + + if [ -x "$_bin_path" ]; then + _installed_ver="$("$_bin_path" --version 2>/dev/null | awk '{print $NF}')" + if [ "$_installed_ver" = "$_expected_ver" ]; then + ok "resq $_expected_ver already installed at $_bin_path" + install_resq_completions + return 0 + fi + fi + + info "Installing resq $_expected_ver for $_triple..." + _tmp="$(mktemp -d)" + # shellcheck disable=SC2064 + trap "rm -rf \"$_tmp\"" EXIT HUP INT QUIT TERM + + _asset="resq-cli-${_tag}-${_triple}.tar.gz" + if ! gh release download "$_tag" --repo "$ORG/crates" \ + --pattern "$_asset" --pattern 'SHA256SUMS' --dir "$_tmp" --clobber >/dev/null 2>&1; then + warn "Failed to download $_asset from $_tag — skipping" + return 0 + fi + + # Verify checksum. SHA256SUMS lists every asset; filter to just ours before + # feeding to `sha256sum -c` so other missing files don't trigger failures. + if ! (cd "$_tmp" && grep -F " $_asset" SHA256SUMS | sha256sum -c --quiet >/dev/null 2>&1); then + warn "SHA256 verification failed for $_asset — not installing" + return 0 + fi + + tar -xzf "$_tmp/$_asset" -C "$_tmp" + _staging_dir="$_tmp/resq-cli-${_tag}-${_triple}" + if [ ! -x "$_staging_dir/resq" ]; then + warn "Archive layout unexpected ($_staging_dir/resq missing) — skipping" + return 0 + fi + + mkdir -p "$_bin_dir" + install -m 0755 "$_staging_dir/resq" "$_bin_path" + ok "Installed $_bin_path" + + case ":$PATH:" in + *":$_bin_dir:"*) ;; + *) warn "$_bin_dir is not in PATH. Add to your shell rc: export PATH=\"$_bin_dir:\$PATH\"" ;; + esac + + install_resq_completions +} + +# Emit shell completion scripts for the user's current shell into the +# conventional user-local path. Bash / zsh / fish are handled; other shells +# get a hint to run `resq completions ` manually. Silent-ok if the +# `resq` binary couldn't be installed. +install_resq_completions() { + _bin_dir="${RESQ_BIN_DIR:-$HOME/.local/bin}" + _bin_path="$_bin_dir/resq" + if [ ! -x "$_bin_path" ]; then + return 0 + fi + + _shell_name="$(basename "${SHELL:-sh}")" + case "$_shell_name" in + bash) + _compl_dir="$HOME/.local/share/bash-completion/completions" + _compl_file="$_compl_dir/resq" + ;; + zsh) + _compl_dir="$HOME/.local/share/zsh/site-functions" + _compl_file="$_compl_dir/_resq" + ;; + fish) + _compl_dir="$HOME/.config/fish/completions" + _compl_file="$_compl_dir/resq.fish" + ;; + *) + info "Shell completions: run \`resq completions \` manually" + return 0 + ;; + esac + + mkdir -p "$_compl_dir" + if "$_bin_path" completions "$_shell_name" > "$_compl_file" 2>/dev/null; then + ok "Installed $_shell_name completions to $_compl_file" + if [ "$_shell_name" = "zsh" ]; then + info " zsh: add to ~/.zshrc if not already: fpath+=(\"$_compl_dir\"); autoload -Uz compinit && compinit" + fi + else + warn "Failed to generate $_shell_name completions — skip" + fi +} + print_repo_info() { case "$REPO" in programs) @@ -382,6 +511,7 @@ main() { choose_repo clone_repo post_clone_setup + install_resq_cli print_repo_info printf "${BOLD}${GREEN} Ready!${RESET}\n\n" >&2 From 6f6925084d5b6b2b145911d4e190d7302ae95fc4 Mon Sep 17 00:00:00 2001 From: Mike Odnis Date: Sun, 19 Apr 2026 00:25:50 -0400 Subject: [PATCH 2/2] fix(installer): macOS sha256sum fallback + find-based binary lookup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses gemini-code-assist review on PR #16. - sha256sum is GNU-only; macOS ships `shasum -a 256` instead. Use sha256sum when available, fall back to shasum. Also drop the `--quiet` flag (GNU-only) — stdout already redirects to /dev/null. - Stop relying on the hardcoded `resq-cli--/resq` staging-dir layout. `find` the extracted binary instead; matches the pattern already used in scripts/install-resq.sh and stays resilient if release.yml ever changes the archive's inner dir name. --- install.sh | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/install.sh b/install.sh index 9a18753..4da87b7 100755 --- a/install.sh +++ b/install.sh @@ -393,21 +393,30 @@ install_resq_cli() { fi # Verify checksum. SHA256SUMS lists every asset; filter to just ours before - # feeding to `sha256sum -c` so other missing files don't trigger failures. - if ! (cd "$_tmp" && grep -F " $_asset" SHA256SUMS | sha256sum -c --quiet >/dev/null 2>&1); then + # feeding to the checker so other missing files don't trigger failures. + # macOS ships `shasum -a 256` but not `sha256sum`; prefer sha256sum when + # available and fall back to shasum. `--quiet` is a GNU-only flag, so drop + # it and redirect stdout to /dev/null instead. + _check_cmd="sha256sum -c" + has sha256sum || _check_cmd="shasum -a 256 -c" + if ! (cd "$_tmp" && grep -F " $_asset" SHA256SUMS | $_check_cmd >/dev/null 2>&1); then warn "SHA256 verification failed for $_asset — not installing" return 0 fi tar -xzf "$_tmp/$_asset" -C "$_tmp" - _staging_dir="$_tmp/resq-cli-${_tag}-${_triple}" - if [ ! -x "$_staging_dir/resq" ]; then - warn "Archive layout unexpected ($_staging_dir/resq missing) — skipping" + # Locate the binary inside the extracted tree rather than assuming the + # staging-dir layout. Matches the pattern already used by + # scripts/install-resq.sh and stays resilient if release.yml ever renames + # the inner directory. + _staging_bin="$(find "$_tmp" -type f -name resq | head -n 1)" + if [ -z "$_staging_bin" ]; then + warn "Archive layout unexpected (resq binary missing) — skipping" return 0 fi mkdir -p "$_bin_dir" - install -m 0755 "$_staging_dir/resq" "$_bin_path" + install -m 0755 "$_staging_bin" "$_bin_path" ok "Installed $_bin_path" case ":$PATH:" in