茶蜂 danger: high entropy

The Huberator

I have come across more and more utilities that are hosted directly on Github and are simple binaries. As I am not thrilled at how the homebrew setup works on Linux, and other tools seemed a little heavy for my use case, I thought I would see how simple I could make something to do the same job. Below is my zsh script, which requires jq, yq, and gh to be installed.

The config file is a yaml file stored at $HOME/.config/huberator.yaml, and it has the following structure (using hugo as an example):

repos:
  - name: hugo                                  # Name of the repo, for display only
    repo: gohugoio/hugo                         # Github repo owner/project
    version: v0.143.1                           # Current, installed version. The script will change this
    glob: hugo_extended_w*linux-amd64.tar.gz    # Glob pattern that matches the specific asset to download from the releases page
    file: hugo                                  # Specific binary to download from the tarball
    strip: 0                                    # Some tarballs have a leading path ./ or other path structures

The script will read each entry in the repos array, check the latest non-draft release, and compare the tag with the version in the config file. If they do not match, it will download the tarball that matches the glob pattern and extract the binary named file to the $HOME/bin directory. This makes it ideal to be added to a cron job to keep those binaries up to date.

Here is the huberator in its entirety:

#!/bin/zsh

FN="${HOME}/.config/huberator.yaml"

if [[ ! -f $FN ]]; then
    echo "repos: []" > $FN
fi

cnt=$(yq '.repos | length' $FN)

typeset -A REPO
for i in `seq $cnt`; do
    export index=$((i-1))
    rep=$(yq '.repos[env(index)] | "name \(.name) repo \(.repo) version \(.version) glob \"\(.glob)\" file \"\(.file)\" strip \"\(.strip // 0)\""' $FN)
    eval "REPO=( $rep )"
    echo -n "Checking repo ${REPO[name]}..."
    version=$(gh release ls --exclude-pre-releases --exclude-drafts -L 1 -R "${REPO[repo]}" --json tagName | jq -r '.[0].tagName')
    echo " published version: $version (installed is ${REPO[version]})"
    if [[ "$version" != "${REPO[version]}" ]]; then
        echo ".... Downloading binary ${REPO[file]}"
        gh release download $version -R "${REPO[repo]}" -p "${REPO[glob]}" -O - | tar -C $HOME/bin/ --strip-components="${REPO[strip]}" -zx "${REPO[file]}"
        export version
        yq -i '.repos[env(index)].version=env(version)' $FN
    fi
done