Skip to content

JakeTRogers/getRelease

Repository files navigation

getRelease

Description

getRelease is a Go CLI for downloading GitHub release assets, extracting archives, installing binaries, and tracking what was installed so later upgrades can be automated. It can target a repository by owner and repo name or by full GitHub URL, prefers assets that match the current platform, and falls back to interactive selection when more than one candidate fits.

Features

  • Install the latest release or a specific tag from any GitHub repository.
  • Target repositories with --owner and --repo or a single --url.
  • Match assets by operating system, architecture, and preferred archive formats.
  • Auto-select the best asset when there is a clear winner, otherwise prompt interactively.
  • Extract common archive formats including .tar.gz, .tar.xz, .tar.bz2, .tar, and .zip.
  • Install one binary or multiple binaries from the selected asset.
  • Rename a single installed binary with --install-as.
  • Skip installation and keep the downloaded payload with --download-only.
  • Track install history for upgrades, version pinning, shell completion, and cleanup workflows.
  • Upgrade one installed package or every installed package still present on disk.
  • Manage config and history from built-in config and history subcommands.
  • Emit machine-readable JSON from the main install flow and list/history/config commands.
  • Enforce a release cooldown by default to harden against supply-chain attacks, with per-run and per-owner overrides.

Installation

  1. Download the binary for your preferred platform from the releases page
  2. Extract the archive. It contains this readme, a copy of the Apache 2.0 license, and the getRelease binary.
  3. Copy the binary to a directory in your $PATH. i.e. /usr/local/bin

Usage

Install the latest release for a repository:

getRelease --owner sharkdp --repo bat

Install a specific tagged release:

getRelease --owner junegunn --repo fzf --tag 0.66.0

Resolve the repository from a GitHub URL instead of separate flags:

getRelease --url https://github.com/junegunn/fzf

Download an asset without installing it:

getRelease --owner sharkdp --repo fd --download-only

Install a single binary under a different name:

getRelease --owner sharkdp --repo bat --install-as bat-preview

List recent releases for a repository:

getRelease list --owner JakeTRogers --repo timeBuddy

List the assets for a specific release tag:

getRelease list --owner JakeTRogers --repo timeBuddy --tag v2.0.0

Preview an upgrade without changing anything:

getRelease upgrade timeBuddy --dry-run

Upgrade every installed package that still exists on disk:

getRelease upgrade --all

Pin an installed package to its current minor line:

getRelease pin timeBuddy --level minor

Remove version pinning from an installed package:

getRelease unpin timeBuddy

pin works on tracked installs from local history. Pin levels mean:

  • patch: stay on the current exact release
  • minor: allow patch updates within the current minor line
  • major: allow minor and patch updates within the current major line

When a pinned package has no eligible newer release inside its allowed range, upgrade and upgrade --all report it as unchanged instead of failed.

Inspect tracked installs:

getRelease history list

history list shows the current pin policy in the PIN column using -, patch, minor, or major.

Prune history records for binaries that are no longer installed:

getRelease history prune

Show the effective configuration:

getRelease config show

Set preferred archive formats:

getRelease config set assetPreferences.formats '["tar.gz","zip"]'

The CLI stores configuration with Viper precedence rules:

  • CLI flags
  • Environment variables prefixed with GETRELEASE_
  • config.yaml
  • Built-in defaults

Common environment variable examples:

export GETRELEASE_INSTALLDIR="$HOME/.local/bin"
export GETRELEASE_ASSETPREFERENCES_FORMATS='["tar.gz","zip"]'

Release Cooldown

A freshly published release is the riskiest thing you can install: if a repository is compromised, the malicious release is usually detected and yanked within days. To give the ecosystem that window, getRelease refuses to install releases younger than the cooldown — 10 days by default.

When the latest release is still inside the cooldown, getRelease automatically falls back to the newest release that is old enough:

release v1.4.0 is 2 day(s) old, cooldown is 10 days — falling back to v1.3.2

An explicit --tag request has no fallback and fails instead, and the check also covers the selected asset's upload time — a binary re-uploaded onto an old release (a common tampering pattern) is refused even though the release itself is old enough.

Change the cooldown or opt out:

# one-off: disable (or change) the cooldown for a single run
getRelease --owner sharkdp --repo bat --cooldown 0

# permanently change the window (0 disables it entirely)
getRelease config set cooldown 5

# or via environment variable
export GETRELEASE_COOLDOWN=5

# skip the cooldown for owners you trust (e.g. your own repos); case-insensitive
getRelease config set trustedOwners 'JakeTRogers'

Authentication

API requests are anonymous by default, which is subject to GitHub's 60 requests/hour per-IP rate limit. To authenticate (5,000 requests/hour, plus access to private-repo releases), getRelease uses the first token it finds:

  1. The token config key, or the GETRELEASE_TOKEN environment variable
  2. The GH_TOKEN environment variable
  3. The GITHUB_TOKEN environment variable (set automatically in GitHub Codespaces and Actions)
  4. The gh CLI's stored credentials, via gh auth token

If none are found, requests silently fall back to anonymous. Prefer environment variables or gh over storing a token in config.yaml; config show redacts the token either way.

GitHub Enterprise Cloud with data residency (*.ghe.com)

getRelease targets github.com by default. Targeting a GitHub Enterprise Cloud tenant with data residency (a *.ghe.com host) is always explicit — environment variables like GH_HOST are deliberately ignored so an ambient setting can never silently retarget a command:

# the URL's host is used directly
getRelease --url https://acme.ghe.com/acme/tool

# or name the host explicitly with --owner/--repo
getRelease --owner acme --repo tool --host acme.ghe.com

The host a package was installed from is recorded in install history, so getRelease upgrade, and later --owner/--repo invocations for that same package, target the right host automatically without repeating --host.

getRelease derives the REST API endpoint (https://api.acme.ghe.com) and web URLs from the host, and passes --hostname to gh auth token so the right stored credentials are used. Self-hosted GitHub Enterprise Server (with a customer-owned domain and /api/v3 path) is not supported.

The main commands are:

  • getRelease: download, extract, and install a release asset
  • getRelease list: list recent releases or release assets
  • getRelease upgrade: upgrade an installed package from recorded history
  • getRelease pin: pin an installed package to the current patch, minor, or major line
  • getRelease unpin: remove version pinning from an installed package
  • getRelease history: inspect and maintain install history
  • getRelease config: inspect and change configuration
  • getRelease version: print version and platform information

Shell Completion

getRelease uses Cobra's built-in completion command, so you can install shell completion with the standard Cobra flow:

# Bash
source <(getRelease completion bash)

# Zsh
source <(getRelease completion zsh)

# Fish
getRelease completion fish | source

# PowerShell
getRelease completion powershell | Out-String | Invoke-Expression

The completion callbacks are extended to read local install history. That gives you history-backed suggestions for commands such as:

getRelease -o <TAB>
getRelease -o JakeTRogers -r <TAB>
getRelease upgrade <TAB>
getRelease pin <TAB>
getRelease upgrade -o <TAB>

upgrade, pin, and unpin target suggestions are limited to binaries that are still installed on disk. The pin --level flag completes patch, minor, and major.

Generate completion scripts explicitly if you prefer to install them into your shell startup files:

getRelease completion bash
getRelease completion zsh
getRelease completion fish
getRelease completion powershell

Notes

  • Asset selection is automatic when there is exactly one match or one clearly preferred match for the current platform.
  • When an archive contains multiple binaries, the CLI can install all of them or prompt you to choose one.
  • Install history is what powers upgrade, pin, unpin, owner and repo completion, and installed-target suggestions.

Development

Running Tests

go test ./... -v

Coverage Report

go test ./... -coverprofile=coverage.out
go tool cover -html=coverage.out

Pre-commit Hooks

This project uses pre-commit hooks to ensure code quality. The hooks run:

  • go test: Runs all tests with race detection
  • go test coverage: Ensures cmd package maintains ≥85% coverage
  • golangci-lint: Comprehensive Go linting
  • commitizen: Enforces conventional commit messages

To install pre-commit hooks:

# Install pre-commit (if not already installed)
pip install pre-commit

# Install the git hooks
pre-commit install --hook-type pre-commit --hook-type commit-msg

# Run hooks manually on all files
pre-commit run --all-files

The hooks will automatically run before each commit. To skip hooks temporarily:

git commit --no-verify

About

Go CLI for downloading & installing GitHub release binaries

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Contributors