Skip to main content

installers/_install-github-bin

1#!/usr/bin/env bash
2# Install one of my Rust binaries from GitHub.
3#
4# This was originally written to pull just my Rust binaries, but it
5# turns out it can work reasonably well for other projects. This allows
6# me to bypass Homebrew, which is generally nicer.
7#
8# For my CLI tools written in Rust, I use a GitHub Action [1]
9# to compile binaries and add them to a release on GitHub.
11# These are the "canonical" versions, rather than recompiling on
12# each machine and having slightly different versions because I
13# was using different checkouts of the code.
15# This script gets the latest version of a binary from GitHub and
16# adds it to my $PATH.
18# This script isn't meant to be run directly (hence the underscore) --
19# I have other scripts that invoke it (e.g. install-vfd), so I can find
20# those scripts with autocomplete in my shell, even on a new machine.
22# TODO: I publish macOS/Windows/Linux binaries, but this script only
23# fetches the macOS binary. In theory, it could detect which OS it's
24# running on and pick the right binary.
26# [1]: https://github.com/taiki-e/upload-rust-binary-action
28set -o errexit
29set -o nounset
31if (( "$#" != 1 ))
32then
33 echo "Usage: _install-rust-bin <REPO_NAME>"
34fi
36REPO_NAME="$1"
38RELEASES_API_URL="https://api.github.com/repos/$REPO_NAME/releases/latest"
40# Fetch the asset URL using the GitHub Releases API [2].
42# For the purposes of this script, these are the interesting bits of the
43# API response that we want to pay attention to:
45# {
46# "assets": [
47# {
48# "name": "vfd-x86_64-apple-darwin.tar.gz",
49# "url": "https://api.github.com/repos/alexwlchan/books.alexwlchan.net/releases/assets/64229966",
50# ...
51# },
52# {
53# "name": "vfd-x86_64-pc-windows-msvc.zip",
54# "url": "https://api.github.com/repos/alexwlchan/books.alexwlchan.net/releases/assets/64229889",
55# ...
56# },
57# {
58# "name": "vfd-x86_64-unknown-linux-gnu.tar.gz",
59# "url": "https://api.github.com/repos/alexwlchan/books.alexwlchan.net/releases/assets/64229611",
60# ...
61# }
62# ],
63# }
65# [2]: https://docs.github.com/en/rest/releases/releases#get-the-latest-release
67# Note: this will filter out ARM binaries because I'm not running on
68# Apple Silicon yet; this will need updating eventually.
70ASSET_URL=$(curl --silent "$RELEASES_API_URL" \
71 | jq -r '.assets | .[] | select(.name | contains("darwin")) | select(.name | contains("arm") | not) | select(.name | contains("aarch64") | not) | .url' \
72 | grep -v arm64
75if [[ "$ASSET_URL" == "" ]]
76then
77 echo "No macOS download available for the latest version! Is it still building?" >&2
78 exit 1
79fi
81# Download and unpack the asset using the GitHub Release Assets API [3].
83# We supply the headers required by the GitHub API, and the `--location`
84# flag caused curl to follow redirects.
86# Note: this assumes the binary is packaged as a tar.gz. The Windows
87# binaries are zipped instead of tar.gz-ed, so if you want to support
88# Windows, inspect the "content_type" field in the Releases API response.
90# [3]: https://docs.github.com/en/rest/releases/assets#get-a-release-asset
92cd $(mktemp -d)
94curl \
95 --header "Accept: application/octet-stream" \
96 --location \
97 --silent \
98 "$ASSET_URL" > "asset.tar.gz"
100# Identify the name of the binary, which may be different from the repo name.
102# We list all the files in the asset package, which should contain a single
103# file, and assume that's the name of the binary.
104ASSET_FILES=$(tar --list --file "asset.tar.gz")
106if [[ "$REPO_NAME" == "BurntSushi/ripgrep" ]]
107then
108 BINARY_PATH=$(echo "$ASSET_FILES" | grep "/rg$")
109 BINARY_NAME="rg"
110else
111 if (( $(echo "$ASSET_FILES" | wc -l) != 1 ))
112 then
113 echo "Release asset doesn't contain exactly 1 file; not sure what to do:" >&2
114 echo "$ASSET_FILES" >&2
115 exit 1
116 fi
118 BINARY_PATH="$(echo "$ASSET_FILES" | head -n 1)"
119 BINARY_NAME="$BINARY_PATH"
120fi
122# Now actually extract the binary, make it executable, and add it to the PATH.
123tar --extract --gunzip --file "asset.tar.gz"
125chmod +x "$BINARY_PATH"
126sudo mv "$BINARY_PATH" /usr/local/bin
128which "$BINARY_NAME"
129"$BINARY_NAME" --version