1 Commits

Author SHA1 Message Date
Jason Swank
a5784e24e1 toolhive: v0.8.0 2026-01-22 10:04:05 -05:00
14 changed files with 160 additions and 3046 deletions

209
README.md
View File

@@ -1,177 +1,104 @@
# binst # binst
A curated collection of portable installation scripts for binary tools, powered by [binstaller](https://github.com/binary-install/binstaller). A collection of installation scripts for binary tools, generated using [binstaller](https://github.com/binary-install/binstaller). These scripts are portable POSIX shell scripts that work across Linux, macOS, and Windows (Git Bash/WSL) and are designed to be a simple, secure way to install self-contained binaries from GitHub releases.
## Overview * [Quick Start](#quick-start)
* [Workflows](#workflows)
This repository provides POSIX-compliant shell scripts that simplify the installation of popular binary tools from GitHub releases. Each script is: * [Creating New Installation Scripts](#creating-new-installation-scripts)
* [Notes](#notes)
- **Portable**: Works across Linux, macOS, and Windows (Git Bash/WSL) * [Binary Names](#binary-names)
- **Secure**: Includes checksum verification for downloaded binaries
- **Simple**: Single command installation with no dependencies
- **Self-contained**: No package manager or runtime required
## Table of Contents
- [Quick Start](#quick-start)
- [Available Tools](#available-tools)
- [Usage](#usage)
- [Installing Binaries](#installing-binaries)
- [Using Task Commands](#using-task-commands)
- [Creating New Scripts](#creating-new-scripts)
- [Prerequisites](#prerequisites)
- [Automatic Generation](#automatic-generation)
- [Manual Configuration](#manual-configuration)
- [Configuration](#configuration)
- [Binary Names](#binary-names)
- [Contributing](#contributing)
- [License](#license)
## Quick Start ## Quick Start
Install any binary directly using its installation script: Install any binary using its generated script:
```bash ```bash
# Install trufflehog # install trufflehog
./scripts/trufflehog-install.sh $ scripts/trufflehog-install.sh
# Install task # install task
./scripts/task-install.sh $ scripts/task-install.sh
# Install checkov
./scripts/checkov-install.sh
``` ```
Binaries are installed to `~/.local/bin` by default (customizable via environment variables). ## Workflows
## Available Tools Common workflows for the creation, maintenance, usage of the installation scripts are encapsulated in [Task](https://taskfile.dev) tasks.
Installation scripts are located in the `scripts/` directory. Run `ls scripts/` to see all available tools, or browse the directory on GitHub.
## Usage
### Installing Binaries
Run any installation script directly:
```bash ```bash
./scripts/<tool-name>-install.sh # list available tasks
$ task --list
task: Available tasks for this project:
* default: Create a new installation script for a binary
* embed-checksums: Embed checksums into a binst configuration file.
* gen: Generate installation script from binst configuration.
* init: Initialize binst configuration for a GitHub project.
* install-*: Install a binary using its installation script.
* latest-release: Determine the latest release available for a given repo.
# install a binary
$ task install-trufflehog
``` ```
The script will: ### Creating New Installation Scripts
1. Detect your OS and architecture
2. Download the latest release from GitHub
3. Verify checksums
4. Install the binary to your PATH
### Using Task Commands The default task uses binstaller to creates a new installation script for a binary from
its GitHub repository. This is often the only step needed to add a new installation
This repository includes [Taskfile](https://taskfile.dev) automation for common workflows: script to the collection.
To install binstaller, run:
```bash ```bash
# List all available tasks $ scripts/binstaller-install.sh
task --list
# Install a specific binary via Task
task install-trufflehog
task install-aichat
task install-checkov
``` ```
Available tasks: To create a new installation script:
- `task` - Create a new installation script (requires `REPO` variable)
- `task install-*` - Install a binary using its script
- `task init` - Initialize binstaller configuration for a GitHub project
- `task embed-checksums` - Embed checksums into a configuration file
- `task gen` - Generate installation script from configuration
- `task latest-release` - Check the latest release version
## Creating New Scripts
### Prerequisites
First, install binstaller:
```bash ```bash
./scripts/binstaller-install.sh # create a new installation script by providing the GitHub repository as an argument:
$ task REPO=owner/repo-name
# detailes summary
$ task --summary
task: default
Create a new installation script for a binary by initializing a binst config,
embedding checksums, and generating the installation script. The latest release, as
determined by the latest-release task, will be used unless a specific version is
provided.
Invoke this task like:
task default REPO=trufflesecurity/trufflehog
vars:
CONFIG_DIR: "./config"
SCRIPT_DIR: "./scripts"
BINARY: "{{.REPO | base}}"
VERSION: "latest"
requires:
vars:
- REPO
commands:
- Task: init
- Task: embed-checksums
- Task: gen
``` ```
### Automatic Generation ## Notes
The easiest way to add a new installation script is using the default Task workflow:
```bash
# Create script for a GitHub repository
task REPO=owner/repo-name
# Example: Add installation script for trufflehog
task REPO=trufflesecurity/trufflehog
```
This command will:
1. Initialize a binstaller configuration file
2. Fetch and embed checksums from the latest release
3. Generate the installation script
For more details on the default task:
```bash
task --summary
```
### Manual Configuration
For advanced use cases, you can manually create or edit configuration files:
1. **Initialize configuration**:
```bash
task init REPO=owner/repo-name
```
2. **Edit the configuration** in `config/repo-name.binstaller.yml` as needed
3. **Embed checksums**:
```bash
task embed-checksums BINARY=repo-name
```
4. **Generate the script**:
```bash
task gen BINARY=repo-name
```
## Configuration
### Binary Names ### Binary Names
In some cases, the binary executable name differs from the GitHub repository name. When this occurs, specify the actual binary name in the `asset.binaries` section of the configuration file. Sometimes the binary executable name differs from the GitHub repository name. When this occurs, the `asset.binaries` section in the configuration file defines the actual binary name. If this is the case, the generated installation script will need to be manually edited.
**Example**: The [stacklok/toolhive](https://github.com/stacklok/toolhive) repository releases a binary named `thv`. The [configuration file](config/toolhive.binstaller.yml) handles this: As an example, the released artifact for [stacklok/toolhive](https://github.com/stacklok/toolhive) is named `thv` rather than `toolhive`. The [configuration file](config/toolhive.binstaller.yml) specifies the correct name for the binary in the `asset.binaries` section.
```yaml ```yaml
repo: stacklok/toolhive repo: stacklok/toolhive
asset: asset:
binaries: binaries:
- name: thv - name: thv
path: thv path: thv
``` ```
After generation, you may wish to rename the installation script from `thv-install.sh` to `toolhive-install.sh` for consistency.
## Contributing
Contributions are welcome! To add a new binary installation script:
1. Fork this repository
2. Create a new script using `task REPO=owner/repo-name`
3. Test the installation script
4. Submit a pull request
Please ensure:
- The binary is a popular, well-maintained tool
- The installation script works across all supported platforms
- Checksums are embedded for security
## License ## License
MIT. See [LICENSE](LICENSE) for details. MIT. See [LICENSE](LICENSE) for details.

View File

@@ -54,6 +54,18 @@ tasks:
requires: requires:
vars: ["REPO"] vars: ["REPO"]
latest-release:
desc: Determine the latest release available for a given repo.
summary: |
Determine the latest release available for a given GitHub repository.
Invoke this task like:
task latest-release REPO=trufflesecurity/trufflehog
cmd: |
gh release view -R {{.REPO}} --json tagName --jq .tagName
requires:
vars: ["REPO"]
embed-checksums: embed-checksums:
desc: Embed checksums into a binst configuration file. desc: Embed checksums into a binst configuration file.
summary: | summary: |
@@ -69,15 +81,7 @@ tasks:
set +o errexit set +o errexit
binst embed-checksums --config {{.CONFIG_DIR}}/{{.BINARY}}.binstaller.yml --version {{.VERSION}} --mode download binst embed-checksums --config {{.CONFIG_DIR}}/{{.BINARY}}.binstaller.yml --version {{.VERSION}} --mode download
if [ $? -ne 0 ]; then if [ $? -ne 0 ]; then
# this is tougher than it should be... binst embed-checksums --config {{.CONFIG_DIR}}/{{.BINARY}}.binstaller.yml --version {{.VERSION}} --mode calculate
# without this, checksums aren't written to the file at all
printf 'checksums:\n' >> {{.CONFIG_DIR}}/{{.BINARY}}.binstaller.yml
binst embed-checksums \
--config {{.CONFIG_DIR}}/{{.BINARY}}.binstaller.yml \
--version latest \
--mode calculate
# then the formatting is weird, so in-place edit using yq
yq -i {{.CONFIG_DIR}}/{{.BINARY}}.binstaller.yml
fi fi
vars: vars:
@@ -99,19 +103,6 @@ tasks:
requires: requires:
vars: ["BINARY"] vars: ["BINARY"]
latest-release:
desc: Determine the latest release available for a given repo.
summary: |
Determine the latest release available for a given GitHub repository.
Invoke this task like:
task latest-release REPO=trufflesecurity/trufflehog
cmd: |
gh release view -R {{.REPO}} --json tagName --jq .tagName
requires:
vars: ["REPO"]
install-*: install-*:
desc: Install a binary using its installation script. desc: Install a binary using its installation script.
summary: | summary: |

View File

@@ -5,37 +5,21 @@ asset:
template: aichat-${TAG}-${ARCH}-${OS}${EXT} template: aichat-${TAG}-${ARCH}-${OS}${EXT}
default_extension: .tar.gz default_extension: .tar.gz
rules: rules:
- when: - when:
arch: amd64 arch: amd64
arch: x86_64 arch: x86_64
- when: - when:
arch: arm64 arch: arm64
arch: aarch64 arch: aarch64
- when: - when:
os: darwin os: darwin
os: apple-darwin os: apple-darwin
- when: - when:
os: linux os: linux
os: unknown-linux-musl os: unknown-linux-musl
- when: - when:
os: windows os: windows
os: pc-windows-msvc os: pc-windows-msvc
- when: - when:
os: windows os: windows
ext: .zip ext: .zip
checksums:
algorithm: sha256
embedded_checksums:
v0.30.0:
- filename: aichat-v0.30.0-aarch64-apple-darwin.tar.gz
hash: 680d36ed7f7ba8a2c2490a099df26c9da54495903c27956109a89c87eeb9edb3
- filename: aichat-v0.30.0-aarch64-pc-windows-msvc.zip
hash: 2f381e70ddaf0831df7e0181a1d25d700bb0d7e53287393a47fd435c253d6091
- filename: aichat-v0.30.0-aarch64-unknown-linux-musl.tar.gz
hash: eb1cd0948569404c5d9d01c10b32b902e11f8231073315456454dec246bdf26e
- filename: aichat-v0.30.0-x86_64-apple-darwin.tar.gz
hash: 94aa09315773929e027bcb399f78661c2ddffd887b65348bae446601989d9ddd
- filename: aichat-v0.30.0-x86_64-pc-windows-msvc.zip
hash: 89df8c4ccd6dad310ac713eb5d550494ae7fa14722cde346588fab38ff4afd8f
- filename: aichat-v0.30.0-x86_64-unknown-linux-musl.tar.gz
hash: 6b0cc08c5ceb551dc52bfac2221752f82215be5908c70605d655e9b91ab1557c

View File

@@ -20,3 +20,20 @@ asset:
- when: - when:
os: windows os: windows
ext: .zip ext: .zip
checksums:
algorithm: sha256
template: checksums.txt
embedded_checksums:
v0.12.0:
- filename: binst_Darwin_arm64.tar.gz
hash: 2c3a8cf9b8f95edb5d97b905ccb0204800b25f1a9bc2b4ad704596e756e41eb9
- filename: binst_Darwin_x86_64.tar.gz
hash: bd9eae149f5735671bf1f32204f5ba9f10de269a290755f21f93bf1bb5d09b03
- filename: binst_Linux_arm64.tar.gz
hash: 76bca4884ee3fa229d915473ddd53ab4d04c34c9e4b5a1eda36d9751763af916
- filename: binst_Linux_x86_64.tar.gz
hash: af36ebb92c01ad4b9867a79eb45d1a130efbce20930896ec7578b3746416ee41
- filename: binst_Windows_arm64.zip
hash: 133784089efd57f5a0164b84ac74c4924c299342c88eb40be65155193ca37761
- filename: binst_Windows_x86_64.zip
hash: afcc9eab78de6bfa1ce360aebbf1a48738c519cdbe6a9560e6979ec3a4fcb4ef

View File

@@ -8,32 +8,32 @@ checksums:
algorithm: sha256 algorithm: sha256
template: tofu_${VERSION}_SHA256SUMS template: tofu_${VERSION}_SHA256SUMS
embedded_checksums: embedded_checksums:
v1.11.4: v1.11.3:
- filename: tofu_1.11.4_darwin_amd64.tar.gz - filename: tofu_1.11.3_darwin_amd64.tar.gz
hash: 46abdd10b826e864f6daf2013a6f0dbc079d8c6e0f79b529138b7da50bea502f hash: c895c837af131f91ec6a493e5ab29e702bf38500ebccb5c3bf31e2ae823ab5c4
- filename: tofu_1.11.4_darwin_arm64.tar.gz - filename: tofu_1.11.3_darwin_arm64.tar.gz
hash: 2e52b9baccf925a1516ae850112b6eddce35d96e9b59fa954d191d6e8ef3af5f hash: ed13cc2c919a0e3532eeb71fd5cd275d44d9552d8e57f18e5867917149146490
- filename: tofu_1.11.4_freebsd_386.tar.gz - filename: tofu_1.11.3_freebsd_386.tar.gz
hash: ebeda7898c60c75869f60a57d1ff5e3f87bc8093cab117ff86b096943afb2922 hash: 9e94e9d4c1c0c6371069e55e7d85b9b80e31fb7651bdf6d86d6f6fd3c33d078e
- filename: tofu_1.11.4_freebsd_amd64.tar.gz - filename: tofu_1.11.3_freebsd_amd64.tar.gz
hash: 9759b92fe9b6daa8f95ce85ef6c766da2208fdea709a3e0409d13feb0f26b5dc hash: 8ce117bd91d28608369e7f057b7ea10c638bef1625d55eb8bbc6d0ab1a57382d
- filename: tofu_1.11.4_freebsd_arm.tar.gz - filename: tofu_1.11.3_freebsd_arm.tar.gz
hash: 2710a3cb6ec913dcfa734312aade5a9f617cb9c1c0f1362f3c68b4c50ebb3a3c hash: 6d60c289445d11f51bff7a828a8eaa3eeed6db1209e88eadd436c49852932775
- filename: tofu_1.11.4_linux_386.tar.gz - filename: tofu_1.11.3_linux_386.tar.gz
hash: 6e81bfbfc8cab3aff03da8bf74b42861682686c224a97d50a47ac3caa3a086bf hash: 15f5721d928af1c53a11a2cbcca700a16c3d81ddd0b1b6d205d662d3d8f6b320
- filename: tofu_1.11.4_linux_amd64.tar.gz - filename: tofu_1.11.3_linux_amd64.tar.gz
hash: 0d744081951095c3e54fd4f0af5c48491ec03116ab02f1ad5ca4ed60d3b60efd hash: 46b567512d4cfa631551b936f3616c02277954fece29d91a52d264537399ad03
- filename: tofu_1.11.4_linux_arm.tar.gz - filename: tofu_1.11.3_linux_arm.tar.gz
hash: 50a59e671c2d9a7119376547c02c6b94478b5bb57fb74555867a6757216eea36 hash: f670ddb67a1c187735bfe4d9e4642a1f35903e3f3548a5604fe15c0c4f3b0fb8
- filename: tofu_1.11.4_linux_arm64.tar.gz - filename: tofu_1.11.3_linux_arm64.tar.gz
hash: 6b81ff00501737fd3459fef6cee9c06ce2b08683f6b7af110b2616468d024228 hash: abb19fdbb4516a30f303f0686cd156f2ff768b34c8d1e433ce5e6f1d81399425
- filename: tofu_1.11.4_openbsd_386.tar.gz - filename: tofu_1.11.3_openbsd_386.tar.gz
hash: 8fc71eab3a1bf6765fbe5987e0e74115e3303d15819b0b87e8e81849076f0187 hash: e2b74b05a5e3faf5f957361382b47129a411840b68be07cce216b6ce723af7aa
- filename: tofu_1.11.4_openbsd_amd64.tar.gz - filename: tofu_1.11.3_openbsd_amd64.tar.gz
hash: ae52722b8b8bd8bf3198e7f70adea1a21a4bfffe9c4093001e7c891e718f22af hash: e4e21e05db28441c41d94267495d65ae098f791df365c6fcd2924e65d0f946d2
- filename: tofu_1.11.4_solaris_amd64.tar.gz - filename: tofu_1.11.3_solaris_amd64.tar.gz
hash: 6e8405c4e2854b06b3c55cf6147f6947925db5ca2f1950b92b1f0d59e9cbf3dd hash: a4a88ee5bdbd0afa47488d8dabc463733a3efd5a28be57199ead6b04fdd5bd9b
- filename: tofu_1.11.4_windows_386.tar.gz - filename: tofu_1.11.3_windows_386.tar.gz
hash: 2b84afcae1060913697000546f65df794dd9f066ec614449559114e624803d8c hash: dad3090337bebc23bbb0d645c86a36316827d743ae26b5ecc925c33d2d454868
- filename: tofu_1.11.4_windows_amd64.tar.gz - filename: tofu_1.11.3_windows_amd64.tar.gz
hash: 2cf504355d9c0d4bdf9fbb209b81c5fc4b441cc32af23b26f0220fe08c56529f hash: 5e97b41ee5d9387f1e4532b6e2de6ae244e93f70c9d48fb46ec606c7cacb7a07

View File

@@ -1,58 +0,0 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/binary-install/binstaller/main/schema/InstallSpec.json
schema: v1
repo: tofuutils/tenv
asset:
template: tenv_${TAG}_${OS}_${ARCH}${EXT}
default_extension: .tar.gz
binaries:
- name: atmos
path: atmos
- name: tenv
path: tenv
- name: terraform
path: terraform
- name: terragrunt
path: terragrunt
- name: terramate
path: terramate
- name: tf
path: tf
- name: tofu
path: tofu
rules:
- when:
arch: amd64
arch: x86_64
- when:
os: darwin
os: Darwin
- when:
os: linux
os: Linux
- when:
os: windows
os: Windows
- when:
os: windows
ext: .zip
checksums:
algorithm: sha256
template: tenv_${TAG}_checksums.txt
embedded_checksums:
v4.9.0:
- filename: tenv_v4.9.0_Darwin_arm64.tar.gz
hash: 9fe1bea568d89c877198caa3af8cdf78c44263aedd6117feb783be4f242bf09b
- filename: tenv_v4.9.0_Darwin_x86_64.tar.gz
hash: d2b807d5885222745e64421911ffc35dcc15a3e9e77820fe73d0508a26cda726
- filename: tenv_v4.9.0_Linux_arm64.tar.gz
hash: 7b1e3e46e946f6ae60fb5b8a307b6481771708b6a571d0ca42e106bb490cb062
- filename: tenv_v4.9.0_Linux_armv6.tar.gz
hash: 86ca60fb1020d17d73217a0f94233a4931205e7225c11ebbfcbfb62f05d3ee85
- filename: tenv_v4.9.0_Linux_x86_64.tar.gz
hash: 3aa5bbd0147405518d29eca0468c7ea9a93326a5fbef758799caece8428442a6
- filename: tenv_v4.9.0_Windows_arm64.zip
hash: 360cba142fdd2a731ac895b87b32e62724e41bf5afc6aed0459bf1f9d4de6c63
- filename: tenv_v4.9.0_Windows_armv6.zip
hash: 1d751bc4e0abdfb30bffed4bd2c8615ab149632ce595af471e971204b769391c
- filename: tenv_v4.9.0_Windows_x86_64.zip
hash: 2b798e4155478425be2c07a8ec857dd31c66fe418f20f8fc9cac4b4a5cf91fe2

View File

@@ -1,27 +0,0 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/binary-install/binstaller/main/schema/InstallSpec.json
schema: v1
repo: terraform-linters/tflint
asset:
template: tflint_${OS}_${ARCH}${EXT}
default_extension: .zip
checksums:
algorithm: sha256
template: checksums.txt
embedded_checksums:
v0.60.0:
- filename: tflint_darwin_amd64.zip
hash: 256f70ad2c9963690bccc31ffda6be0159f1c5f857b46773b70d01d56b711280
- filename: tflint_darwin_arm64.zip
hash: 753a392b70e37b2970732bdaf0c9ad98b0f8ecb96026b21e91261e4e967c7f5e
- filename: tflint_linux_386.zip
hash: b25d41922b6dd4e30be74876d4691695b0d8de6f5b4cd93ddfd3706c3d285262
- filename: tflint_linux_amd64.zip
hash: 3476ceedcf0c4f9f2bed35e92988e1411bec2caa543c9387bffaa720df9efaf7
- filename: tflint_linux_arm.zip
hash: 59b6c1acf15f4faee2e28074a27214c78970b5427dff7ab16b9478f9d57fc2a8
- filename: tflint_linux_arm64.zip
hash: 8f01d273e58f44f6ed10e198fa1f5d0a8080b01869de64658528275e943ef47a
- filename: tflint_windows_386.zip
hash: 561a7c633009f4dcba82769742d7b1d14b64a5795a0868db5d3311ef19514998
- filename: tflint_windows_amd64.zip
hash: a6e08412ec6bf9041325d75a0b88846f8e3b8fb24e5dda105574fa7565235f4c

View File

@@ -1,39 +0,0 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/binary-install/binstaller/main/schema/InstallSpec.json
schema: v1
repo: aquasecurity/trivy
asset:
template: trivy_${VERSION}_${OS}-${ARCH}${EXT}
default_extension: .tar.gz
rules:
- when:
arch: amd64
arch: 64bit
- when:
arch: arm64
arch: ARM64
- when:
os: darwin
os: macOS
- when:
os: linux
os: Linux
- when:
os: windows
ext: .zip
checksums:
algorithm: sha256
template: trivy_${VERSION}_checksums.txt
embedded_checksums:
v0.68.2:
- filename: trivy_0.68.2_Linux-64bit.tar.gz
hash: 3d933bbc3685f95ec15280f620583d05d97ee3affb66944d14481d5d6d567064
- filename: trivy_0.68.2_Linux-ARM64.tar.gz
hash: 33c87995fd0c3d1559086c3e18fd3148051296dfd0ca2a67583eb64f89998c91
- filename: trivy_0.68.2_Linux-s390x.tar.gz
hash: fd45fc808622ecb11393f4c27d1fbd20e1d78838148a282b1129624964dd0628
- filename: trivy_0.68.2_macOS-64bit.tar.gz
hash: c0790530cd717b6bdd02ed437be0710f5c7043078fafaf6841be7c865bf251ce
- filename: trivy_0.68.2_macOS-ARM64.tar.gz
hash: dfbe15ffe47426dad9fd3e0d52aeacf3dbbb25ca5dbc66049f5920834435988d
- filename: trivy_0.68.2_windows-64bit.zip
hash: 2aaa0ce06f9f2221a6bb21e1fc0e0ecc6aeb56362bc5c9463e9fd7b06983c3c3

View File

@@ -409,13 +409,7 @@ github_release() {
} }
# --- Embedded Checksums (Format: VERSION:FILENAME:HASH) --- # --- Embedded Checksums (Format: VERSION:FILENAME:HASH) ---
EMBEDDED_CHECKSUMS=" EMBEDDED_CHECKSUMS=""
0.30.0:aichat-v0.30.0-aarch64-apple-darwin.tar.gz:680d36ed7f7ba8a2c2490a099df26c9da54495903c27956109a89c87eeb9edb3
0.30.0:aichat-v0.30.0-aarch64-pc-windows-msvc.zip:2f381e70ddaf0831df7e0181a1d25d700bb0d7e53287393a47fd435c253d6091
0.30.0:aichat-v0.30.0-aarch64-unknown-linux-musl.tar.gz:eb1cd0948569404c5d9d01c10b32b902e11f8231073315456454dec246bdf26e
0.30.0:aichat-v0.30.0-x86_64-apple-darwin.tar.gz:94aa09315773929e027bcb399f78661c2ddffd887b65348bae446601989d9ddd
0.30.0:aichat-v0.30.0-x86_64-pc-windows-msvc.zip:89df8c4ccd6dad310ac713eb5d550494ae7fa14722cde346588fab38ff4afd8f
0.30.0:aichat-v0.30.0-x86_64-unknown-linux-musl.tar.gz:6b0cc08c5ceb551dc52bfac2221752f82215be5908c70605d655e9b91ab1557c"
# Find embedded checksum for a given version and filename # Find embedded checksum for a given version and filename
find_embedded_checksum() { find_embedded_checksum() {

View File

@@ -1,615 +0,0 @@
#!/bin/sh
# Code generated by binstaller. DO NOT EDIT.
#
set -e
usage() {
this=$1
cat <<EOF
$this: download ${NAME} from ${REPO}
Usage: $this [-b bindir] [-d] [-q] [-n] [tag]
-b sets bindir or installation directory, Defaults to ${BINSTALLER_BIN:-${HOME}/.local/bin}
-d turns on debug logging
-q turns on quiet mode (errors only)
-n turns on dry run mode
[tag] is a tag from
https://github.com/bridgecrewio/checkov/releases
If tag is missing, then latest will be used.
Environment variables:
BINSTALLER_NO_PROGRESS=1 Disable progress indicators
BINSTALLER_OS=... Override OS detection
BINSTALLER_ARCH=... Override architecture detection
Generated by binstaller
https://github.com/binary-install/binstaller
EOF
exit 2
}
cat /dev/null <<EOF
------------------------------------------------------------------------
https://github.com/client9/shlib - portable posix shell functions
Public domain - http://unlicense.org
https://github.com/client9/shlib/blob/master/LICENSE.md
but credit (and pull requests) appreciated.
------------------------------------------------------------------------
EOF
is_command() {
command -v "$1" >/dev/null
}
echoerr() {
echo "$@" 1>&2
}
_logp=6
log_set_priority() {
_logp="$1"
}
log_priority() {
if test -z "$1"; then
echo "$_logp"
return
fi
[ "$1" -le "$_logp" ]
}
log_tag() {
case $1 in
0) echo "emerg" ;;
1) echo "alert" ;;
2) echo "crit" ;;
3) echo "err" ;;
4) echo "warning" ;;
5) echo "notice" ;;
6) echo "info" ;;
7) echo "debug" ;;
*) echo "$1" ;;
esac
}
log_debug() {
log_priority 7 || return 0
echoerr "$(log_prefix)" "$(log_tag 7)" "$@"
}
log_info() {
log_priority 6 || return 0
echoerr "$(log_prefix)" "$(log_tag 6)" "$@"
}
log_err() {
log_priority 3 || return 0
echoerr "$(log_prefix)" "$(log_tag 3)" "$@"
}
log_crit() {
log_priority 2 || return 0
echoerr "$(log_prefix)" "$(log_tag 2)" "$@"
}
uname_os() {
os=$(uname -s | tr '[:upper:]' '[:lower:]')
case "$os" in
msys*) os="windows" ;;
mingw*) os="windows" ;;
cygwin*) os="windows" ;;
esac
if [ "$os" = "sunos" ]; then
if [ "$(uname -o)" = "illumos" ]; then
os="illumos"
else
os="solaris"
fi
fi
echo "$os"
}
uname_arch() {
arch=$(uname -m)
case $arch in
x86_64) arch="amd64" ;;
i86pc) arch="amd64" ;;
x86) arch="386" ;;
i686) arch="386" ;;
i386) arch="386" ;;
aarch64) arch="arm64" ;;
armv5*) arch="armv5" ;;
armv6*) arch="armv6" ;;
armv7*) arch="armv7" ;;
esac
echo "${arch}"
}
uname_os_check() {
os=$(uname_os)
case "$os" in
darwin) return 0 ;;
dragonfly) return 0 ;;
freebsd) return 0 ;;
linux) return 0 ;;
android) return 0 ;;
midnightbsd) return 0 ;;
nacl) return 0 ;;
netbsd) return 0 ;;
openbsd) return 0 ;;
plan9) return 0 ;;
solaris) return 0 ;;
illumos) return 0 ;;
windows) return 0 ;;
esac
log_crit "uname_os_check '$(uname -s)' got converted to '$os' which is not a GOOS value. Please file bug at https://github.com/client9/shlib"
return 1
}
uname_arch_check() {
arch=$(uname_arch)
case "$arch" in
386) return 0 ;;
amd64) return 0 ;;
arm64) return 0 ;;
armv5) return 0 ;;
armv6) return 0 ;;
armv7) return 0 ;;
ppc64) return 0 ;;
ppc64le) return 0 ;;
mips) return 0 ;;
mipsle) return 0 ;;
mips64) return 0 ;;
mips64le) return 0 ;;
s390x) return 0 ;;
amd64p32) return 0 ;;
esac
log_crit "uname_arch_check '$(uname -m)' got converted to '$arch' which is not a GOARCH value. Please file bug report at https://github.com/client9/shlib"
return 1
}
cat /dev/null <<EOF
------------------------------------------------------------------------
End of functions from https://github.com/client9/shlib
------------------------------------------------------------------------
EOF
hash_sha256() {
TARGET=${1:-/dev/stdin}
if is_command gsha256sum; then
hash=$(gsha256sum "$TARGET") || return 1
echo "$hash" | cut -d ' ' -f 1
elif is_command sha256sum; then
hash=$(sha256sum "$TARGET") || return 1
echo "$hash" | cut -d ' ' -f 1
elif is_command shasum; then
hash=$(shasum -a 256 "$TARGET" 2>/dev/null) || return 1
echo "$hash" | cut -d ' ' -f 1
elif is_command openssl; then
hash=$(openssl dgst -sha256 "$TARGET") || return 1
echo "$hash" | cut -d ' ' -f 2
else
log_crit "hash_sha256 unable to find command to compute sha-256 hash"
return 1
fi
}
hash_compute() {
hash_sha256 "$1"
}
# shellcheck shell=sh
# Terminal progress reporting functions
progress_init() {
# Only show progress on interactive terminals and when not disabled
if [ ! -t 2 ] || [ "${BINSTALLER_NO_PROGRESS}" = "1" ]; then
return 0
fi
# OSC 9;4 sequences are safely ignored by unsupporting terminals
# Only need special handling for tmux passthrough
if [ -n "$TMUX" ]; then
# Tmux passthrough: DCS tmux; <doubled ESC sequence> ST
# ESC characters in the wrapped sequence must be doubled
# Format: ESC P tmux; ESC ESC ] 9;4; ... ESC ESC \ ESC \
PROGRESS_START=$(printf '\033Ptmux;\033\033]9;4;')
# shellcheck disable=SC1003
PROGRESS_END=$(printf '\033\033\\\033\\')
else
# Direct OSC 9;4 - terminals that don't support it will safely ignore
PROGRESS_START=$(printf '\033]9;4;')
PROGRESS_END=$(printf '\007')
fi
}
# Start pulsing progress animation
progress_pulse_start() {
# Only show progress on interactive terminals and when not disabled
if [ ! -t 2 ] || [ "${BINSTALLER_NO_PROGRESS}" = "1" ]; then
return 0
fi
# Send OSC 9;4 with state 3 (indeterminate/pulsing) once
# The terminal will handle the continuous animation
printf "%s3%s" "$PROGRESS_START" "$PROGRESS_END" >&2
}
# Clear progress indicator
progress_clear() {
# Only show progress on interactive terminals and when not disabled
if [ ! -t 2 ] || [ "${BINSTALLER_NO_PROGRESS}" = "1" ]; then
return 0
fi
printf "%s0;%s" "$PROGRESS_START" "$PROGRESS_END" >&2
}
untar() {
tarball=$1
strip_components=${2:-0} # default 0
case "${tarball}" in
*.tar.gz | *.tgz) tar --no-same-owner -xzf "${tarball}" --strip-components "${strip_components}" ;;
*.tar.xz) tar --no-same-owner -xJf "${tarball}" --strip-components "${strip_components}" ;;
*.tar.bz2) tar --no-same-owner -xjf "${tarball}" --strip-components "${strip_components}" ;;
*.tar) tar --no-same-owner -xf "${tarball}" --strip-components "${strip_components}" ;;
*.gz) gunzip "${tarball}" ;;
*.zip)
# unzip doesn't have a standard --strip-components
# Workaround: extract to a subdir and move contents up if stripping
if [ "$strip_components" -gt 0 ]; then
extract_dir=$(basename "${tarball%.zip}")_extracted
unzip -q "${tarball}" -d "${extract_dir}"
# Move contents of the *first* directory found inside extract_dir up
# This assumes wrap_in_directory=true convention
first_subdir=$(find "${extract_dir}" -mindepth 1 -maxdepth 1 -type d -print -quit)
if [ -n "$first_subdir" ]; then
# Move all contents (* includes hidden files)
mv "${first_subdir}"/* .
# Optionally remove the now-empty subdir and the extract_dir
rmdir "${first_subdir}"
rmdir "${extract_dir}"
else
log_warn "Could not find subdirectory in zip to strip components from ${extract_dir}"
# Files are extracted in current dir anyway, proceed
fi
else
unzip -q "${tarball}"
fi
;;
*)
log_err "untar unknown archive format for ${tarball}"
return 1
;;
esac
}
hash_verify() {
TARGET_PATH=$1
SUMFILE=$2
if [ -z "${SUMFILE}" ]; then
log_err "hash_verify checksum file not specified in arg2"
return 1
fi
got=$(hash_compute "$TARGET_PATH")
if [ -z "${got}" ]; then
log_err "failed to calculate hash: ${TARGET_PATH}"
return 1
fi
BASENAME=${TARGET_PATH##*/}
# Check for line matches in checksum file
# Format: "<hash> <filename>" or "<hash> *<filename>"
# Filename may include path prefix (e.g., "deployment/m2/file.tar.gz")
while IFS= read -r line || [ -n "$line" ]; do
# Normalize tabs to spaces
line=$(echo "$line" | tr '\t' ' ')
# Remove trailing spaces for hash-only line check
line_trimmed=$(echo "$line" | sed 's/[[:space:]]*$//')
# Check for hash-only line (no filename) - early return
if [ "$line_trimmed" = "$got" ]; then
return 0
fi
# Extract hash and filename parts
# First field is the hash, rest is filename (which may contain spaces)
line_hash=$(echo "$line" | cut -d' ' -f1)
# Skip if hash doesn't match
if [ "$line_hash" != "$got" ]; then
continue
fi
# Hash matches, now check filename
# Remove the hash part from the beginning of the line
line_rest="${line#"$got"}"
# Remove leading spaces
while [ "${line_rest#[ ]}" != "$line_rest" ]; do
line_rest="${line_rest#[ ]}"
done
# Remove leading asterisk if present (binary mode indicator)
if [ "${line_rest#\*}" != "$line_rest" ]; then
line_rest="${line_rest#\*}"
fi
# Extract just the filename without any path
line_filename="${line_rest##*/}"
# Check if the filename matches
if [ "$line_filename" = "$BASENAME" ]; then
return 0
fi
done < "$SUMFILE"
log_err "hash_verify checksum for '$TARGET_PATH' did not verify"
log_err " Expected hash: ${got}"
log_err " Checksum file content:"
cat "$SUMFILE" >&2
return 1
}
# GitHub HTTP download functions with GITHUB_TOKEN support
github_http_download_curl() {
local_file=$1
source_url=$2
header=$3
if [ -n "$GITHUB_TOKEN" ]; then
log_debug "Using GITHUB_TOKEN for authentication"
if [ -z "$header" ]; then
curl -fsSL -H "Authorization: Bearer $GITHUB_TOKEN" -o "$local_file" "$source_url"
else
curl -fsSL -H "Authorization: Bearer $GITHUB_TOKEN" -H "$header" -o "$local_file" "$source_url"
fi
else
if [ -z "$header" ]; then
curl -fsSL -o "$local_file" "$source_url"
else
curl -fsSL -H "$header" -o "$local_file" "$source_url"
fi
fi
}
github_http_download_wget() {
local_file=$1
source_url=$2
header=$3
if [ -n "$GITHUB_TOKEN" ]; then
log_debug "Using GITHUB_TOKEN for authentication"
if [ -z "$header" ]; then
wget -q --header "Authorization: Bearer $GITHUB_TOKEN" -O "$local_file" "$source_url"
else
wget -q --header "Authorization: Bearer $GITHUB_TOKEN" --header "$header" -O "$local_file" "$source_url"
fi
else
if [ -z "$header" ]; then
wget -q -O "$local_file" "$source_url"
else
wget -q --header "$header" -O "$local_file" "$source_url"
fi
fi
}
github_http_download() {
log_debug "github_http_download $2"
if is_command curl; then
github_http_download_curl "$@"
return
elif is_command wget; then
github_http_download_wget "$@"
return
fi
log_crit "github_http_download unable to find wget or curl"
return 1
}
github_http_copy() {
tmp=$(mktemp)
github_http_download "${tmp}" "$@" || return 1
body=$(cat "$tmp")
rm -f "${tmp}"
echo "$body"
}
github_release() {
owner_repo=$1
version=$2
test -z "$version" && version="latest"
giturl="https://github.com/${owner_repo}/releases/${version}"
json=$(github_http_copy "$giturl" "Accept:application/json")
test -z "$json" && return 1
version=$(echo "$json" | tr -s '\n' ' ' | sed 's/.*"tag_name":"//' | sed 's/".*//')
test -z "$version" && return 1
echo "$version"
}
# --- Embedded Checksums (Format: VERSION:FILENAME:HASH) ---
EMBEDDED_CHECKSUMS="
3.2.497:checkov_darwin_X86_64.zip:35129a227f25dc37c2347e8b7b6f61984243201807beeb27eb4f33fda0cbe32a
3.2.497:checkov_linux_X86_64.zip:f713e29c9b0d477df4d2e4b57428dfe3b8333ce425093d626cc02d87e532e627
3.2.497:checkov_linux_arm64.zip:05060050d59207e6c99fd1d4aae8b2711d0f192c33bbfca7a1de139468bdaeea
3.2.497:checkov_windows_X86_64.zip:3b2e958c4b6d8a50c573e693ba3a3e6270145a26fad403635179b51e51152f1f"
# Find embedded checksum for a given version and filename
find_embedded_checksum() {
version="$1"
filename="$2"
echo "$EMBEDDED_CHECKSUMS" | grep -E "^${version}:${filename}:" | cut -d':' -f3
}
parse_args() {
BINDIR="${BINSTALLER_BIN:-${HOME}/.local/bin}"
DRY_RUN=0
while getopts "b:dqh?xn" arg; do
case "$arg" in
b) BINDIR="$OPTARG" ;;
d) log_set_priority 10 ;;
q) log_set_priority 3 ;;
h | \?) usage "$0" ;;
x) set -x ;;
n) DRY_RUN=1 ;;
esac
done
shift $((OPTIND - 1))
TAG="${1:-latest}"
}
tag_to_version() {
if [ "$TAG" = "latest" ]; then
log_info "checking GitHub for latest tag"
REALTAG=$(github_release "${REPO}" "${TAG}") && true
test -n "$REALTAG" || {
log_crit "Could not determine latest tag for ${REPO}"
exit 1
}
else
# Assume TAG is a valid tag/version string
REALTAG="$TAG"
fi
if test -z "$REALTAG"; then
log_crit "unable to find '${TAG}' - use 'latest' or see https://github.com/${REPO}/releases for details"
exit 1
fi
VERSION=${REALTAG#v} # Strip leading 'v'
TAG="$REALTAG" # Use the resolved tag
log_info "Resolved version: ${VERSION} (tag: ${TAG})"
}
is_rosetta2_available() {
[ "$(uname -s)" = Darwin ] || return 1
[ "$(uname -m)" = arm64 ] || return 1
arch -arch x86_64 true 2>/dev/null
}
resolve_asset_filename() {
# --- Apply Rules ---
ASSET_FILENAME=""
if [ "${UNAME_ARCH}" = 'amd64' ] && true
then
ARCH='X86_64'
fi
if [ -z "${ASSET_FILENAME}" ]; then
ASSET_FILENAME="checkov_${OS}_${ARCH}${EXT}"
fi
}
# Cleanup function to remove temporary files and stop progress
cleanup() {
# Stop progress animation
progress_clear
if [ -n "$TMPDIR" ] && [ -d "$TMPDIR" ]; then
log_debug "Cleaning up temporary directory: $TMPDIR"
rm -rf -- "$TMPDIR"
fi
}
execute() {
STRIP_COMPONENTS=0
CHECKSUM_FILENAME=""
# --- Construct URLs ---
GITHUB_DOWNLOAD="https://github.com/${REPO}/releases/download"
ASSET_URL="${GITHUB_DOWNLOAD}/${TAG}/${ASSET_FILENAME}"
CHECKSUM_URL=""
if [ -n "$CHECKSUM_FILENAME" ]; then
CHECKSUM_URL="${GITHUB_DOWNLOAD}/${TAG}/${CHECKSUM_FILENAME}"
fi
# --- Download and Verify ---
TMPDIR=$(mktemp -d)
# Set up cleanup trap that includes progress clearing
trap cleanup EXIT HUP INT TERM
log_debug "Downloading files into ${TMPDIR}"
log_info "Downloading ${ASSET_URL}"
github_http_download "${TMPDIR}/${ASSET_FILENAME}" "${ASSET_URL}"
# Try to find embedded checksum first
EMBEDDED_HASH=$(find_embedded_checksum "$VERSION" "$ASSET_FILENAME")
if [ -n "$EMBEDDED_HASH" ]; then
log_info "Using embedded checksum for verification"
# Verify using embedded hash
got=$(hash_compute "${TMPDIR}/${ASSET_FILENAME}")
if [ "$got" != "$EMBEDDED_HASH" ]; then
log_crit "Checksum verification failed for ${ASSET_FILENAME}"
log_crit "Expected: ${EMBEDDED_HASH}"
log_crit "Got: ${got}"
return 1
fi
log_info "Checksum verification successful"
elif [ -n "$CHECKSUM_URL" ]; then
# Fall back to downloading checksum file
log_info "Downloading checksums from ${CHECKSUM_URL}"
github_http_download "${TMPDIR}/${CHECKSUM_FILENAME}" "${CHECKSUM_URL}"
log_info "Verifying checksum ..."
hash_verify "${TMPDIR}/${ASSET_FILENAME}" "${TMPDIR}/${CHECKSUM_FILENAME}"
else
log_info "No checksum found, skipping verification."
fi
if [ -z "${EXT}" ] || [ "${EXT}" = ".exe" ]; then
log_debug "Target is raw binary"
else
log_info "Extracting ${ASSET_FILENAME}..."
(cd "${TMPDIR}" && untar "${ASSET_FILENAME}" "${STRIP_COMPONENTS}")
fi
BINARY_NAME='checkov'
if [ -z "${EXT}" ] || [ "${EXT}" = ".exe" ]; then
BINARY_PATH="${TMPDIR}/${ASSET_FILENAME}"
else
BINARY_PATH="${TMPDIR}/dist/checkov"
fi
if [ "${UNAME_OS}" = "windows" ]; then
case "${BINARY_NAME}" in *.exe) ;; *) BINARY_NAME="${BINARY_NAME}.exe" ;; esac
case "${BINARY_PATH}" in *.exe) ;; *) BINARY_PATH="${BINARY_PATH}.exe" ;; esac
fi
if [ ! -f "${BINARY_PATH}" ]; then
log_crit "Binary not found: ${BINARY_PATH}"
log_crit "Listing contents of ${TMPDIR} ..."
if command -v find >/dev/null 2>&1; then
cd "${TMPDIR}" && find .
else
cd "${TMPDIR}" && ls -R .
fi
return 1
fi
progress_clear
# Install the binary
INSTALL_PATH="${BINDIR}/${BINARY_NAME}"
if [ "$DRY_RUN" = "1" ]; then
log_info "[DRY RUN] ${BINARY_NAME} dry-run installation succeeded! (Would install to: ${INSTALL_PATH})"
else
log_info "Installing binary to ${INSTALL_PATH}"
test ! -d "${BINDIR}" && install -d "${BINDIR}"
install "${BINARY_PATH}" "${INSTALL_PATH}"
log_info "${BINARY_NAME} installation complete!"
fi
}
# --- Configuration ---
NAME='checkov'
REPO='bridgecrewio/checkov'
EXT='.zip'
# use in logging routines
log_prefix() {
echo "${REPO}"
}
parse_args "$@"
progress_init
progress_pulse_start
# --- Determine target platform ---
OS="${BINSTALLER_OS:-$(uname_os)}"
UNAME_OS="${OS}"
if is_rosetta2_available; then
log_info 'Apple Silicon with Rosetta 2 found: using amd64 as ARCH'
ARCH="${BINSTALLER_ARCH:-amd64}"
else
ARCH="${BINSTALLER_ARCH:-$(uname_arch)}"
fi
UNAME_ARCH="${ARCH}"
log_info "Detected Platform: ${OS}/${ARCH}"
# --- Validate platform ---
uname_os_check "$OS"
uname_arch_check "$ARCH"
tag_to_version
resolve_asset_filename
execute

View File

@@ -410,20 +410,20 @@ github_release() {
# --- Embedded Checksums (Format: VERSION:FILENAME:HASH) --- # --- Embedded Checksums (Format: VERSION:FILENAME:HASH) ---
EMBEDDED_CHECKSUMS=" EMBEDDED_CHECKSUMS="
1.11.4:tofu_1.11.4_darwin_amd64.tar.gz:46abdd10b826e864f6daf2013a6f0dbc079d8c6e0f79b529138b7da50bea502f 1.11.3:tofu_1.11.3_darwin_amd64.tar.gz:c895c837af131f91ec6a493e5ab29e702bf38500ebccb5c3bf31e2ae823ab5c4
1.11.4:tofu_1.11.4_darwin_arm64.tar.gz:2e52b9baccf925a1516ae850112b6eddce35d96e9b59fa954d191d6e8ef3af5f 1.11.3:tofu_1.11.3_darwin_arm64.tar.gz:ed13cc2c919a0e3532eeb71fd5cd275d44d9552d8e57f18e5867917149146490
1.11.4:tofu_1.11.4_freebsd_386.tar.gz:ebeda7898c60c75869f60a57d1ff5e3f87bc8093cab117ff86b096943afb2922 1.11.3:tofu_1.11.3_freebsd_386.tar.gz:9e94e9d4c1c0c6371069e55e7d85b9b80e31fb7651bdf6d86d6f6fd3c33d078e
1.11.4:tofu_1.11.4_freebsd_amd64.tar.gz:9759b92fe9b6daa8f95ce85ef6c766da2208fdea709a3e0409d13feb0f26b5dc 1.11.3:tofu_1.11.3_freebsd_amd64.tar.gz:8ce117bd91d28608369e7f057b7ea10c638bef1625d55eb8bbc6d0ab1a57382d
1.11.4:tofu_1.11.4_freebsd_arm.tar.gz:2710a3cb6ec913dcfa734312aade5a9f617cb9c1c0f1362f3c68b4c50ebb3a3c 1.11.3:tofu_1.11.3_freebsd_arm.tar.gz:6d60c289445d11f51bff7a828a8eaa3eeed6db1209e88eadd436c49852932775
1.11.4:tofu_1.11.4_linux_386.tar.gz:6e81bfbfc8cab3aff03da8bf74b42861682686c224a97d50a47ac3caa3a086bf 1.11.3:tofu_1.11.3_linux_386.tar.gz:15f5721d928af1c53a11a2cbcca700a16c3d81ddd0b1b6d205d662d3d8f6b320
1.11.4:tofu_1.11.4_linux_amd64.tar.gz:0d744081951095c3e54fd4f0af5c48491ec03116ab02f1ad5ca4ed60d3b60efd 1.11.3:tofu_1.11.3_linux_amd64.tar.gz:46b567512d4cfa631551b936f3616c02277954fece29d91a52d264537399ad03
1.11.4:tofu_1.11.4_linux_arm.tar.gz:50a59e671c2d9a7119376547c02c6b94478b5bb57fb74555867a6757216eea36 1.11.3:tofu_1.11.3_linux_arm.tar.gz:f670ddb67a1c187735bfe4d9e4642a1f35903e3f3548a5604fe15c0c4f3b0fb8
1.11.4:tofu_1.11.4_linux_arm64.tar.gz:6b81ff00501737fd3459fef6cee9c06ce2b08683f6b7af110b2616468d024228 1.11.3:tofu_1.11.3_linux_arm64.tar.gz:abb19fdbb4516a30f303f0686cd156f2ff768b34c8d1e433ce5e6f1d81399425
1.11.4:tofu_1.11.4_openbsd_386.tar.gz:8fc71eab3a1bf6765fbe5987e0e74115e3303d15819b0b87e8e81849076f0187 1.11.3:tofu_1.11.3_openbsd_386.tar.gz:e2b74b05a5e3faf5f957361382b47129a411840b68be07cce216b6ce723af7aa
1.11.4:tofu_1.11.4_openbsd_amd64.tar.gz:ae52722b8b8bd8bf3198e7f70adea1a21a4bfffe9c4093001e7c891e718f22af 1.11.3:tofu_1.11.3_openbsd_amd64.tar.gz:e4e21e05db28441c41d94267495d65ae098f791df365c6fcd2924e65d0f946d2
1.11.4:tofu_1.11.4_solaris_amd64.tar.gz:6e8405c4e2854b06b3c55cf6147f6947925db5ca2f1950b92b1f0d59e9cbf3dd 1.11.3:tofu_1.11.3_solaris_amd64.tar.gz:a4a88ee5bdbd0afa47488d8dabc463733a3efd5a28be57199ead6b04fdd5bd9b
1.11.4:tofu_1.11.4_windows_386.tar.gz:2b84afcae1060913697000546f65df794dd9f066ec614449559114e624803d8c 1.11.3:tofu_1.11.3_windows_386.tar.gz:dad3090337bebc23bbb0d645c86a36316827d743ae26b5ecc925c33d2d454868
1.11.4:tofu_1.11.4_windows_amd64.tar.gz:2cf504355d9c0d4bdf9fbb209b81c5fc4b441cc32af23b26f0220fe08c56529f" 1.11.3:tofu_1.11.3_windows_amd64.tar.gz:5e97b41ee5d9387f1e4532b6e2de6ae244e93f70c9d48fb46ec606c7cacb7a07"
# Find embedded checksum for a given version and filename # Find embedded checksum for a given version and filename
find_embedded_checksum() { find_embedded_checksum() {

View File

@@ -1,834 +0,0 @@
#!/bin/sh
# Code generated by binstaller. DO NOT EDIT.
#
set -e
usage() {
this=$1
cat <<EOF
$this: download ${NAME} from ${REPO}
Usage: $this [-b bindir] [-d] [-q] [-n] [tag]
-b sets bindir or installation directory, Defaults to ${BINSTALLER_BIN:-${HOME}/.local/bin}
-d turns on debug logging
-q turns on quiet mode (errors only)
-n turns on dry run mode
[tag] is a tag from
https://github.com/tofuutils/tenv/releases
If tag is missing, then latest will be used.
Environment variables:
BINSTALLER_NO_PROGRESS=1 Disable progress indicators
BINSTALLER_OS=... Override OS detection
BINSTALLER_ARCH=... Override architecture detection
Generated by binstaller
https://github.com/binary-install/binstaller
EOF
exit 2
}
cat /dev/null <<EOF
------------------------------------------------------------------------
https://github.com/client9/shlib - portable posix shell functions
Public domain - http://unlicense.org
https://github.com/client9/shlib/blob/master/LICENSE.md
but credit (and pull requests) appreciated.
------------------------------------------------------------------------
EOF
is_command() {
command -v "$1" >/dev/null
}
echoerr() {
echo "$@" 1>&2
}
_logp=6
log_set_priority() {
_logp="$1"
}
log_priority() {
if test -z "$1"; then
echo "$_logp"
return
fi
[ "$1" -le "$_logp" ]
}
log_tag() {
case $1 in
0) echo "emerg" ;;
1) echo "alert" ;;
2) echo "crit" ;;
3) echo "err" ;;
4) echo "warning" ;;
5) echo "notice" ;;
6) echo "info" ;;
7) echo "debug" ;;
*) echo "$1" ;;
esac
}
log_debug() {
log_priority 7 || return 0
echoerr "$(log_prefix)" "$(log_tag 7)" "$@"
}
log_info() {
log_priority 6 || return 0
echoerr "$(log_prefix)" "$(log_tag 6)" "$@"
}
log_err() {
log_priority 3 || return 0
echoerr "$(log_prefix)" "$(log_tag 3)" "$@"
}
log_crit() {
log_priority 2 || return 0
echoerr "$(log_prefix)" "$(log_tag 2)" "$@"
}
uname_os() {
os=$(uname -s | tr '[:upper:]' '[:lower:]')
case "$os" in
msys*) os="windows" ;;
mingw*) os="windows" ;;
cygwin*) os="windows" ;;
esac
if [ "$os" = "sunos" ]; then
if [ "$(uname -o)" = "illumos" ]; then
os="illumos"
else
os="solaris"
fi
fi
echo "$os"
}
uname_arch() {
arch=$(uname -m)
case $arch in
x86_64) arch="amd64" ;;
i86pc) arch="amd64" ;;
x86) arch="386" ;;
i686) arch="386" ;;
i386) arch="386" ;;
aarch64) arch="arm64" ;;
armv5*) arch="armv5" ;;
armv6*) arch="armv6" ;;
armv7*) arch="armv7" ;;
esac
echo "${arch}"
}
uname_os_check() {
os=$(uname_os)
case "$os" in
darwin) return 0 ;;
dragonfly) return 0 ;;
freebsd) return 0 ;;
linux) return 0 ;;
android) return 0 ;;
midnightbsd) return 0 ;;
nacl) return 0 ;;
netbsd) return 0 ;;
openbsd) return 0 ;;
plan9) return 0 ;;
solaris) return 0 ;;
illumos) return 0 ;;
windows) return 0 ;;
esac
log_crit "uname_os_check '$(uname -s)' got converted to '$os' which is not a GOOS value. Please file bug at https://github.com/client9/shlib"
return 1
}
uname_arch_check() {
arch=$(uname_arch)
case "$arch" in
386) return 0 ;;
amd64) return 0 ;;
arm64) return 0 ;;
armv5) return 0 ;;
armv6) return 0 ;;
armv7) return 0 ;;
ppc64) return 0 ;;
ppc64le) return 0 ;;
mips) return 0 ;;
mipsle) return 0 ;;
mips64) return 0 ;;
mips64le) return 0 ;;
s390x) return 0 ;;
amd64p32) return 0 ;;
esac
log_crit "uname_arch_check '$(uname -m)' got converted to '$arch' which is not a GOARCH value. Please file bug report at https://github.com/client9/shlib"
return 1
}
cat /dev/null <<EOF
------------------------------------------------------------------------
End of functions from https://github.com/client9/shlib
------------------------------------------------------------------------
EOF
hash_sha256() {
TARGET=${1:-/dev/stdin}
if is_command gsha256sum; then
hash=$(gsha256sum "$TARGET") || return 1
echo "$hash" | cut -d ' ' -f 1
elif is_command sha256sum; then
hash=$(sha256sum "$TARGET") || return 1
echo "$hash" | cut -d ' ' -f 1
elif is_command shasum; then
hash=$(shasum -a 256 "$TARGET" 2>/dev/null) || return 1
echo "$hash" | cut -d ' ' -f 1
elif is_command openssl; then
hash=$(openssl dgst -sha256 "$TARGET") || return 1
echo "$hash" | cut -d ' ' -f 2
else
log_crit "hash_sha256 unable to find command to compute sha-256 hash"
return 1
fi
}
hash_compute() {
hash_sha256 "$1"
}
# shellcheck shell=sh
# Terminal progress reporting functions
progress_init() {
# Only show progress on interactive terminals and when not disabled
if [ ! -t 2 ] || [ "${BINSTALLER_NO_PROGRESS}" = "1" ]; then
return 0
fi
# OSC 9;4 sequences are safely ignored by unsupporting terminals
# Only need special handling for tmux passthrough
if [ -n "$TMUX" ]; then
# Tmux passthrough: DCS tmux; <doubled ESC sequence> ST
# ESC characters in the wrapped sequence must be doubled
# Format: ESC P tmux; ESC ESC ] 9;4; ... ESC ESC \ ESC \
PROGRESS_START=$(printf '\033Ptmux;\033\033]9;4;')
# shellcheck disable=SC1003
PROGRESS_END=$(printf '\033\033\\\033\\')
else
# Direct OSC 9;4 - terminals that don't support it will safely ignore
PROGRESS_START=$(printf '\033]9;4;')
PROGRESS_END=$(printf '\007')
fi
}
# Start pulsing progress animation
progress_pulse_start() {
# Only show progress on interactive terminals and when not disabled
if [ ! -t 2 ] || [ "${BINSTALLER_NO_PROGRESS}" = "1" ]; then
return 0
fi
# Send OSC 9;4 with state 3 (indeterminate/pulsing) once
# The terminal will handle the continuous animation
printf "%s3%s" "$PROGRESS_START" "$PROGRESS_END" >&2
}
# Clear progress indicator
progress_clear() {
# Only show progress on interactive terminals and when not disabled
if [ ! -t 2 ] || [ "${BINSTALLER_NO_PROGRESS}" = "1" ]; then
return 0
fi
printf "%s0;%s" "$PROGRESS_START" "$PROGRESS_END" >&2
}
untar() {
tarball=$1
strip_components=${2:-0} # default 0
case "${tarball}" in
*.tar.gz | *.tgz) tar --no-same-owner -xzf "${tarball}" --strip-components "${strip_components}" ;;
*.tar.xz) tar --no-same-owner -xJf "${tarball}" --strip-components "${strip_components}" ;;
*.tar.bz2) tar --no-same-owner -xjf "${tarball}" --strip-components "${strip_components}" ;;
*.tar) tar --no-same-owner -xf "${tarball}" --strip-components "${strip_components}" ;;
*.gz) gunzip "${tarball}" ;;
*.zip)
# unzip doesn't have a standard --strip-components
# Workaround: extract to a subdir and move contents up if stripping
if [ "$strip_components" -gt 0 ]; then
extract_dir=$(basename "${tarball%.zip}")_extracted
unzip -q "${tarball}" -d "${extract_dir}"
# Move contents of the *first* directory found inside extract_dir up
# This assumes wrap_in_directory=true convention
first_subdir=$(find "${extract_dir}" -mindepth 1 -maxdepth 1 -type d -print -quit)
if [ -n "$first_subdir" ]; then
# Move all contents (* includes hidden files)
mv "${first_subdir}"/* .
# Optionally remove the now-empty subdir and the extract_dir
rmdir "${first_subdir}"
rmdir "${extract_dir}"
else
log_warn "Could not find subdirectory in zip to strip components from ${extract_dir}"
# Files are extracted in current dir anyway, proceed
fi
else
unzip -q "${tarball}"
fi
;;
*)
log_err "untar unknown archive format for ${tarball}"
return 1
;;
esac
}
hash_verify() {
TARGET_PATH=$1
SUMFILE=$2
if [ -z "${SUMFILE}" ]; then
log_err "hash_verify checksum file not specified in arg2"
return 1
fi
got=$(hash_compute "$TARGET_PATH")
if [ -z "${got}" ]; then
log_err "failed to calculate hash: ${TARGET_PATH}"
return 1
fi
BASENAME=${TARGET_PATH##*/}
# Check for line matches in checksum file
# Format: "<hash> <filename>" or "<hash> *<filename>"
# Filename may include path prefix (e.g., "deployment/m2/file.tar.gz")
while IFS= read -r line || [ -n "$line" ]; do
# Normalize tabs to spaces
line=$(echo "$line" | tr '\t' ' ')
# Remove trailing spaces for hash-only line check
line_trimmed=$(echo "$line" | sed 's/[[:space:]]*$//')
# Check for hash-only line (no filename) - early return
if [ "$line_trimmed" = "$got" ]; then
return 0
fi
# Extract hash and filename parts
# First field is the hash, rest is filename (which may contain spaces)
line_hash=$(echo "$line" | cut -d' ' -f1)
# Skip if hash doesn't match
if [ "$line_hash" != "$got" ]; then
continue
fi
# Hash matches, now check filename
# Remove the hash part from the beginning of the line
line_rest="${line#"$got"}"
# Remove leading spaces
while [ "${line_rest#[ ]}" != "$line_rest" ]; do
line_rest="${line_rest#[ ]}"
done
# Remove leading asterisk if present (binary mode indicator)
if [ "${line_rest#\*}" != "$line_rest" ]; then
line_rest="${line_rest#\*}"
fi
# Extract just the filename without any path
line_filename="${line_rest##*/}"
# Check if the filename matches
if [ "$line_filename" = "$BASENAME" ]; then
return 0
fi
done < "$SUMFILE"
log_err "hash_verify checksum for '$TARGET_PATH' did not verify"
log_err " Expected hash: ${got}"
log_err " Checksum file content:"
cat "$SUMFILE" >&2
return 1
}
# GitHub HTTP download functions with GITHUB_TOKEN support
github_http_download_curl() {
local_file=$1
source_url=$2
header=$3
if [ -n "$GITHUB_TOKEN" ]; then
log_debug "Using GITHUB_TOKEN for authentication"
if [ -z "$header" ]; then
curl -fsSL -H "Authorization: Bearer $GITHUB_TOKEN" -o "$local_file" "$source_url"
else
curl -fsSL -H "Authorization: Bearer $GITHUB_TOKEN" -H "$header" -o "$local_file" "$source_url"
fi
else
if [ -z "$header" ]; then
curl -fsSL -o "$local_file" "$source_url"
else
curl -fsSL -H "$header" -o "$local_file" "$source_url"
fi
fi
}
github_http_download_wget() {
local_file=$1
source_url=$2
header=$3
if [ -n "$GITHUB_TOKEN" ]; then
log_debug "Using GITHUB_TOKEN for authentication"
if [ -z "$header" ]; then
wget -q --header "Authorization: Bearer $GITHUB_TOKEN" -O "$local_file" "$source_url"
else
wget -q --header "Authorization: Bearer $GITHUB_TOKEN" --header "$header" -O "$local_file" "$source_url"
fi
else
if [ -z "$header" ]; then
wget -q -O "$local_file" "$source_url"
else
wget -q --header "$header" -O "$local_file" "$source_url"
fi
fi
}
github_http_download() {
log_debug "github_http_download $2"
if is_command curl; then
github_http_download_curl "$@"
return
elif is_command wget; then
github_http_download_wget "$@"
return
fi
log_crit "github_http_download unable to find wget or curl"
return 1
}
github_http_copy() {
tmp=$(mktemp)
github_http_download "${tmp}" "$@" || return 1
body=$(cat "$tmp")
rm -f "${tmp}"
echo "$body"
}
github_release() {
owner_repo=$1
version=$2
test -z "$version" && version="latest"
giturl="https://github.com/${owner_repo}/releases/${version}"
json=$(github_http_copy "$giturl" "Accept:application/json")
test -z "$json" && return 1
version=$(echo "$json" | tr -s '\n' ' ' | sed 's/.*"tag_name":"//' | sed 's/".*//')
test -z "$version" && return 1
echo "$version"
}
# --- Embedded Checksums (Format: VERSION:FILENAME:HASH) ---
EMBEDDED_CHECKSUMS="
4.9.0:tenv_v4.9.0_Darwin_arm64.tar.gz:9fe1bea568d89c877198caa3af8cdf78c44263aedd6117feb783be4f242bf09b
4.9.0:tenv_v4.9.0_Darwin_x86_64.tar.gz:d2b807d5885222745e64421911ffc35dcc15a3e9e77820fe73d0508a26cda726
4.9.0:tenv_v4.9.0_Linux_arm64.tar.gz:7b1e3e46e946f6ae60fb5b8a307b6481771708b6a571d0ca42e106bb490cb062
4.9.0:tenv_v4.9.0_Linux_armv6.tar.gz:86ca60fb1020d17d73217a0f94233a4931205e7225c11ebbfcbfb62f05d3ee85
4.9.0:tenv_v4.9.0_Linux_x86_64.tar.gz:3aa5bbd0147405518d29eca0468c7ea9a93326a5fbef758799caece8428442a6
4.9.0:tenv_v4.9.0_Windows_arm64.zip:360cba142fdd2a731ac895b87b32e62724e41bf5afc6aed0459bf1f9d4de6c63
4.9.0:tenv_v4.9.0_Windows_armv6.zip:1d751bc4e0abdfb30bffed4bd2c8615ab149632ce595af471e971204b769391c
4.9.0:tenv_v4.9.0_Windows_x86_64.zip:2b798e4155478425be2c07a8ec857dd31c66fe418f20f8fc9cac4b4a5cf91fe2"
# Find embedded checksum for a given version and filename
find_embedded_checksum() {
version="$1"
filename="$2"
echo "$EMBEDDED_CHECKSUMS" | grep -E "^${version}:${filename}:" | cut -d':' -f3
}
parse_args() {
BINDIR="${BINSTALLER_BIN:-${HOME}/.local/bin}"
DRY_RUN=0
while getopts "b:dqh?xn" arg; do
case "$arg" in
b) BINDIR="$OPTARG" ;;
d) log_set_priority 10 ;;
q) log_set_priority 3 ;;
h | \?) usage "$0" ;;
x) set -x ;;
n) DRY_RUN=1 ;;
esac
done
shift $((OPTIND - 1))
TAG="${1:-latest}"
}
tag_to_version() {
if [ "$TAG" = "latest" ]; then
log_info "checking GitHub for latest tag"
REALTAG=$(github_release "${REPO}" "${TAG}") && true
test -n "$REALTAG" || {
log_crit "Could not determine latest tag for ${REPO}"
exit 1
}
else
# Assume TAG is a valid tag/version string
REALTAG="$TAG"
fi
if test -z "$REALTAG"; then
log_crit "unable to find '${TAG}' - use 'latest' or see https://github.com/${REPO}/releases for details"
exit 1
fi
VERSION=${REALTAG#v} # Strip leading 'v'
TAG="$REALTAG" # Use the resolved tag
log_info "Resolved version: ${VERSION} (tag: ${TAG})"
}
resolve_asset_filename() {
# --- Apply Rules ---
ASSET_FILENAME=""
if [ "${UNAME_ARCH}" = 'amd64' ] && true
then
ARCH='x86_64'
fi
if [ "${UNAME_OS}" = 'darwin' ] && true
then
OS='Darwin'
fi
if [ "${UNAME_OS}" = 'linux' ] && true
then
OS='Linux'
fi
if [ "${UNAME_OS}" = 'windows' ] && true
then
OS='Windows'
fi
if [ "${UNAME_OS}" = 'windows' ] && true
then
EXT='.zip'
fi
if [ -z "${ASSET_FILENAME}" ]; then
ASSET_FILENAME="tenv_${TAG}_${OS}_${ARCH}${EXT}"
fi
}
# Cleanup function to remove temporary files and stop progress
cleanup() {
# Stop progress animation
progress_clear
if [ -n "$TMPDIR" ] && [ -d "$TMPDIR" ]; then
log_debug "Cleaning up temporary directory: $TMPDIR"
rm -rf -- "$TMPDIR"
fi
}
execute() {
STRIP_COMPONENTS=0
CHECKSUM_FILENAME="tenv_${TAG}_checksums.txt"
# --- Construct URLs ---
GITHUB_DOWNLOAD="https://github.com/${REPO}/releases/download"
ASSET_URL="${GITHUB_DOWNLOAD}/${TAG}/${ASSET_FILENAME}"
CHECKSUM_URL=""
if [ -n "$CHECKSUM_FILENAME" ]; then
CHECKSUM_URL="${GITHUB_DOWNLOAD}/${TAG}/${CHECKSUM_FILENAME}"
fi
# --- Download and Verify ---
TMPDIR=$(mktemp -d)
# Set up cleanup trap that includes progress clearing
trap cleanup EXIT HUP INT TERM
log_debug "Downloading files into ${TMPDIR}"
log_info "Downloading ${ASSET_URL}"
github_http_download "${TMPDIR}/${ASSET_FILENAME}" "${ASSET_URL}"
# Try to find embedded checksum first
EMBEDDED_HASH=$(find_embedded_checksum "$VERSION" "$ASSET_FILENAME")
if [ -n "$EMBEDDED_HASH" ]; then
log_info "Using embedded checksum for verification"
# Verify using embedded hash
got=$(hash_compute "${TMPDIR}/${ASSET_FILENAME}")
if [ "$got" != "$EMBEDDED_HASH" ]; then
log_crit "Checksum verification failed for ${ASSET_FILENAME}"
log_crit "Expected: ${EMBEDDED_HASH}"
log_crit "Got: ${got}"
return 1
fi
log_info "Checksum verification successful"
elif [ -n "$CHECKSUM_URL" ]; then
# Fall back to downloading checksum file
log_info "Downloading checksums from ${CHECKSUM_URL}"
github_http_download "${TMPDIR}/${CHECKSUM_FILENAME}" "${CHECKSUM_URL}"
log_info "Verifying checksum ..."
hash_verify "${TMPDIR}/${ASSET_FILENAME}" "${TMPDIR}/${CHECKSUM_FILENAME}"
else
log_info "No checksum found, skipping verification."
fi
if [ -z "${EXT}" ] || [ "${EXT}" = ".exe" ]; then
log_debug "Target is raw binary"
else
log_info "Extracting ${ASSET_FILENAME}..."
(cd "${TMPDIR}" && untar "${ASSET_FILENAME}" "${STRIP_COMPONENTS}")
fi
BINARY_NAME='atmos'
if [ -z "${EXT}" ] || [ "${EXT}" = ".exe" ]; then
BINARY_PATH="${TMPDIR}/${ASSET_FILENAME}"
else
BINARY_PATH="${TMPDIR}/atmos"
fi
if [ "${UNAME_OS}" = "windows" ]; then
case "${BINARY_NAME}" in *.exe) ;; *) BINARY_NAME="${BINARY_NAME}.exe" ;; esac
case "${BINARY_PATH}" in *.exe) ;; *) BINARY_PATH="${BINARY_PATH}.exe" ;; esac
fi
if [ ! -f "${BINARY_PATH}" ]; then
log_crit "Binary not found: ${BINARY_PATH}"
log_crit "Listing contents of ${TMPDIR} ..."
if command -v find >/dev/null 2>&1; then
cd "${TMPDIR}" && find .
else
cd "${TMPDIR}" && ls -R .
fi
return 1
fi
progress_clear
# Install the binary
INSTALL_PATH="${BINDIR}/${BINARY_NAME}"
if [ "$DRY_RUN" = "1" ]; then
log_info "[DRY RUN] ${BINARY_NAME} dry-run installation succeeded! (Would install to: ${INSTALL_PATH})"
else
log_info "Installing binary to ${INSTALL_PATH}"
test ! -d "${BINDIR}" && install -d "${BINDIR}"
install "${BINARY_PATH}" "${INSTALL_PATH}"
log_info "${BINARY_NAME} installation complete!"
fi
BINARY_NAME='tenv'
if [ -z "${EXT}" ] || [ "${EXT}" = ".exe" ]; then
BINARY_PATH="${TMPDIR}/${ASSET_FILENAME}"
else
BINARY_PATH="${TMPDIR}/tenv"
fi
if [ "${UNAME_OS}" = "windows" ]; then
case "${BINARY_NAME}" in *.exe) ;; *) BINARY_NAME="${BINARY_NAME}.exe" ;; esac
case "${BINARY_PATH}" in *.exe) ;; *) BINARY_PATH="${BINARY_PATH}.exe" ;; esac
fi
if [ ! -f "${BINARY_PATH}" ]; then
log_crit "Binary not found: ${BINARY_PATH}"
log_crit "Listing contents of ${TMPDIR} ..."
if command -v find >/dev/null 2>&1; then
cd "${TMPDIR}" && find .
else
cd "${TMPDIR}" && ls -R .
fi
return 1
fi
progress_clear
# Install the binary
INSTALL_PATH="${BINDIR}/${BINARY_NAME}"
if [ "$DRY_RUN" = "1" ]; then
log_info "[DRY RUN] ${BINARY_NAME} dry-run installation succeeded! (Would install to: ${INSTALL_PATH})"
else
log_info "Installing binary to ${INSTALL_PATH}"
test ! -d "${BINDIR}" && install -d "${BINDIR}"
install "${BINARY_PATH}" "${INSTALL_PATH}"
log_info "${BINARY_NAME} installation complete!"
fi
BINARY_NAME='terraform'
if [ -z "${EXT}" ] || [ "${EXT}" = ".exe" ]; then
BINARY_PATH="${TMPDIR}/${ASSET_FILENAME}"
else
BINARY_PATH="${TMPDIR}/terraform"
fi
if [ "${UNAME_OS}" = "windows" ]; then
case "${BINARY_NAME}" in *.exe) ;; *) BINARY_NAME="${BINARY_NAME}.exe" ;; esac
case "${BINARY_PATH}" in *.exe) ;; *) BINARY_PATH="${BINARY_PATH}.exe" ;; esac
fi
if [ ! -f "${BINARY_PATH}" ]; then
log_crit "Binary not found: ${BINARY_PATH}"
log_crit "Listing contents of ${TMPDIR} ..."
if command -v find >/dev/null 2>&1; then
cd "${TMPDIR}" && find .
else
cd "${TMPDIR}" && ls -R .
fi
return 1
fi
progress_clear
# Install the binary
INSTALL_PATH="${BINDIR}/${BINARY_NAME}"
if [ "$DRY_RUN" = "1" ]; then
log_info "[DRY RUN] ${BINARY_NAME} dry-run installation succeeded! (Would install to: ${INSTALL_PATH})"
else
log_info "Installing binary to ${INSTALL_PATH}"
test ! -d "${BINDIR}" && install -d "${BINDIR}"
install "${BINARY_PATH}" "${INSTALL_PATH}"
log_info "${BINARY_NAME} installation complete!"
fi
BINARY_NAME='terragrunt'
if [ -z "${EXT}" ] || [ "${EXT}" = ".exe" ]; then
BINARY_PATH="${TMPDIR}/${ASSET_FILENAME}"
else
BINARY_PATH="${TMPDIR}/terragrunt"
fi
if [ "${UNAME_OS}" = "windows" ]; then
case "${BINARY_NAME}" in *.exe) ;; *) BINARY_NAME="${BINARY_NAME}.exe" ;; esac
case "${BINARY_PATH}" in *.exe) ;; *) BINARY_PATH="${BINARY_PATH}.exe" ;; esac
fi
if [ ! -f "${BINARY_PATH}" ]; then
log_crit "Binary not found: ${BINARY_PATH}"
log_crit "Listing contents of ${TMPDIR} ..."
if command -v find >/dev/null 2>&1; then
cd "${TMPDIR}" && find .
else
cd "${TMPDIR}" && ls -R .
fi
return 1
fi
progress_clear
# Install the binary
INSTALL_PATH="${BINDIR}/${BINARY_NAME}"
if [ "$DRY_RUN" = "1" ]; then
log_info "[DRY RUN] ${BINARY_NAME} dry-run installation succeeded! (Would install to: ${INSTALL_PATH})"
else
log_info "Installing binary to ${INSTALL_PATH}"
test ! -d "${BINDIR}" && install -d "${BINDIR}"
install "${BINARY_PATH}" "${INSTALL_PATH}"
log_info "${BINARY_NAME} installation complete!"
fi
BINARY_NAME='terramate'
if [ -z "${EXT}" ] || [ "${EXT}" = ".exe" ]; then
BINARY_PATH="${TMPDIR}/${ASSET_FILENAME}"
else
BINARY_PATH="${TMPDIR}/terramate"
fi
if [ "${UNAME_OS}" = "windows" ]; then
case "${BINARY_NAME}" in *.exe) ;; *) BINARY_NAME="${BINARY_NAME}.exe" ;; esac
case "${BINARY_PATH}" in *.exe) ;; *) BINARY_PATH="${BINARY_PATH}.exe" ;; esac
fi
if [ ! -f "${BINARY_PATH}" ]; then
log_crit "Binary not found: ${BINARY_PATH}"
log_crit "Listing contents of ${TMPDIR} ..."
if command -v find >/dev/null 2>&1; then
cd "${TMPDIR}" && find .
else
cd "${TMPDIR}" && ls -R .
fi
return 1
fi
progress_clear
# Install the binary
INSTALL_PATH="${BINDIR}/${BINARY_NAME}"
if [ "$DRY_RUN" = "1" ]; then
log_info "[DRY RUN] ${BINARY_NAME} dry-run installation succeeded! (Would install to: ${INSTALL_PATH})"
else
log_info "Installing binary to ${INSTALL_PATH}"
test ! -d "${BINDIR}" && install -d "${BINDIR}"
install "${BINARY_PATH}" "${INSTALL_PATH}"
log_info "${BINARY_NAME} installation complete!"
fi
BINARY_NAME='tf'
if [ -z "${EXT}" ] || [ "${EXT}" = ".exe" ]; then
BINARY_PATH="${TMPDIR}/${ASSET_FILENAME}"
else
BINARY_PATH="${TMPDIR}/tf"
fi
if [ "${UNAME_OS}" = "windows" ]; then
case "${BINARY_NAME}" in *.exe) ;; *) BINARY_NAME="${BINARY_NAME}.exe" ;; esac
case "${BINARY_PATH}" in *.exe) ;; *) BINARY_PATH="${BINARY_PATH}.exe" ;; esac
fi
if [ ! -f "${BINARY_PATH}" ]; then
log_crit "Binary not found: ${BINARY_PATH}"
log_crit "Listing contents of ${TMPDIR} ..."
if command -v find >/dev/null 2>&1; then
cd "${TMPDIR}" && find .
else
cd "${TMPDIR}" && ls -R .
fi
return 1
fi
progress_clear
# Install the binary
INSTALL_PATH="${BINDIR}/${BINARY_NAME}"
if [ "$DRY_RUN" = "1" ]; then
log_info "[DRY RUN] ${BINARY_NAME} dry-run installation succeeded! (Would install to: ${INSTALL_PATH})"
else
log_info "Installing binary to ${INSTALL_PATH}"
test ! -d "${BINDIR}" && install -d "${BINDIR}"
install "${BINARY_PATH}" "${INSTALL_PATH}"
log_info "${BINARY_NAME} installation complete!"
fi
BINARY_NAME='tofu'
if [ -z "${EXT}" ] || [ "${EXT}" = ".exe" ]; then
BINARY_PATH="${TMPDIR}/${ASSET_FILENAME}"
else
BINARY_PATH="${TMPDIR}/tofu"
fi
if [ "${UNAME_OS}" = "windows" ]; then
case "${BINARY_NAME}" in *.exe) ;; *) BINARY_NAME="${BINARY_NAME}.exe" ;; esac
case "${BINARY_PATH}" in *.exe) ;; *) BINARY_PATH="${BINARY_PATH}.exe" ;; esac
fi
if [ ! -f "${BINARY_PATH}" ]; then
log_crit "Binary not found: ${BINARY_PATH}"
log_crit "Listing contents of ${TMPDIR} ..."
if command -v find >/dev/null 2>&1; then
cd "${TMPDIR}" && find .
else
cd "${TMPDIR}" && ls -R .
fi
return 1
fi
progress_clear
# Install the binary
INSTALL_PATH="${BINDIR}/${BINARY_NAME}"
if [ "$DRY_RUN" = "1" ]; then
log_info "[DRY RUN] ${BINARY_NAME} dry-run installation succeeded! (Would install to: ${INSTALL_PATH})"
else
log_info "Installing binary to ${INSTALL_PATH}"
test ! -d "${BINDIR}" && install -d "${BINDIR}"
install "${BINARY_PATH}" "${INSTALL_PATH}"
log_info "${BINARY_NAME} installation complete!"
fi
}
# --- Configuration ---
NAME='tenv'
REPO='tofuutils/tenv'
EXT='.tar.gz'
# use in logging routines
log_prefix() {
echo "${REPO}"
}
parse_args "$@"
progress_init
progress_pulse_start
# --- Determine target platform ---
OS="${BINSTALLER_OS:-$(uname_os)}"
UNAME_OS="${OS}"
ARCH="${BINSTALLER_ARCH:-$(uname_arch)}"
UNAME_ARCH="${ARCH}"
log_info "Detected Platform: ${OS}/${ARCH}"
# --- Validate platform ---
uname_os_check "$OS"
uname_arch_check "$ARCH"
tag_to_version
resolve_asset_filename
execute

View File

@@ -1,604 +0,0 @@
#!/bin/sh
# Code generated by binstaller. DO NOT EDIT.
#
set -e
usage() {
this=$1
cat <<EOF
$this: download ${NAME} from ${REPO}
Usage: $this [-b bindir] [-d] [-q] [-n] [tag]
-b sets bindir or installation directory, Defaults to ${BINSTALLER_BIN:-${HOME}/.local/bin}
-d turns on debug logging
-q turns on quiet mode (errors only)
-n turns on dry run mode
[tag] is a tag from
https://github.com/terraform-linters/tflint/releases
If tag is missing, then latest will be used.
Environment variables:
BINSTALLER_NO_PROGRESS=1 Disable progress indicators
BINSTALLER_OS=... Override OS detection
BINSTALLER_ARCH=... Override architecture detection
Generated by binstaller
https://github.com/binary-install/binstaller
EOF
exit 2
}
cat /dev/null <<EOF
------------------------------------------------------------------------
https://github.com/client9/shlib - portable posix shell functions
Public domain - http://unlicense.org
https://github.com/client9/shlib/blob/master/LICENSE.md
but credit (and pull requests) appreciated.
------------------------------------------------------------------------
EOF
is_command() {
command -v "$1" >/dev/null
}
echoerr() {
echo "$@" 1>&2
}
_logp=6
log_set_priority() {
_logp="$1"
}
log_priority() {
if test -z "$1"; then
echo "$_logp"
return
fi
[ "$1" -le "$_logp" ]
}
log_tag() {
case $1 in
0) echo "emerg" ;;
1) echo "alert" ;;
2) echo "crit" ;;
3) echo "err" ;;
4) echo "warning" ;;
5) echo "notice" ;;
6) echo "info" ;;
7) echo "debug" ;;
*) echo "$1" ;;
esac
}
log_debug() {
log_priority 7 || return 0
echoerr "$(log_prefix)" "$(log_tag 7)" "$@"
}
log_info() {
log_priority 6 || return 0
echoerr "$(log_prefix)" "$(log_tag 6)" "$@"
}
log_err() {
log_priority 3 || return 0
echoerr "$(log_prefix)" "$(log_tag 3)" "$@"
}
log_crit() {
log_priority 2 || return 0
echoerr "$(log_prefix)" "$(log_tag 2)" "$@"
}
uname_os() {
os=$(uname -s | tr '[:upper:]' '[:lower:]')
case "$os" in
msys*) os="windows" ;;
mingw*) os="windows" ;;
cygwin*) os="windows" ;;
esac
if [ "$os" = "sunos" ]; then
if [ "$(uname -o)" = "illumos" ]; then
os="illumos"
else
os="solaris"
fi
fi
echo "$os"
}
uname_arch() {
arch=$(uname -m)
case $arch in
x86_64) arch="amd64" ;;
i86pc) arch="amd64" ;;
x86) arch="386" ;;
i686) arch="386" ;;
i386) arch="386" ;;
aarch64) arch="arm64" ;;
armv5*) arch="armv5" ;;
armv6*) arch="armv6" ;;
armv7*) arch="armv7" ;;
esac
echo "${arch}"
}
uname_os_check() {
os=$(uname_os)
case "$os" in
darwin) return 0 ;;
dragonfly) return 0 ;;
freebsd) return 0 ;;
linux) return 0 ;;
android) return 0 ;;
midnightbsd) return 0 ;;
nacl) return 0 ;;
netbsd) return 0 ;;
openbsd) return 0 ;;
plan9) return 0 ;;
solaris) return 0 ;;
illumos) return 0 ;;
windows) return 0 ;;
esac
log_crit "uname_os_check '$(uname -s)' got converted to '$os' which is not a GOOS value. Please file bug at https://github.com/client9/shlib"
return 1
}
uname_arch_check() {
arch=$(uname_arch)
case "$arch" in
386) return 0 ;;
amd64) return 0 ;;
arm64) return 0 ;;
armv5) return 0 ;;
armv6) return 0 ;;
armv7) return 0 ;;
ppc64) return 0 ;;
ppc64le) return 0 ;;
mips) return 0 ;;
mipsle) return 0 ;;
mips64) return 0 ;;
mips64le) return 0 ;;
s390x) return 0 ;;
amd64p32) return 0 ;;
esac
log_crit "uname_arch_check '$(uname -m)' got converted to '$arch' which is not a GOARCH value. Please file bug report at https://github.com/client9/shlib"
return 1
}
cat /dev/null <<EOF
------------------------------------------------------------------------
End of functions from https://github.com/client9/shlib
------------------------------------------------------------------------
EOF
hash_sha256() {
TARGET=${1:-/dev/stdin}
if is_command gsha256sum; then
hash=$(gsha256sum "$TARGET") || return 1
echo "$hash" | cut -d ' ' -f 1
elif is_command sha256sum; then
hash=$(sha256sum "$TARGET") || return 1
echo "$hash" | cut -d ' ' -f 1
elif is_command shasum; then
hash=$(shasum -a 256 "$TARGET" 2>/dev/null) || return 1
echo "$hash" | cut -d ' ' -f 1
elif is_command openssl; then
hash=$(openssl dgst -sha256 "$TARGET") || return 1
echo "$hash" | cut -d ' ' -f 2
else
log_crit "hash_sha256 unable to find command to compute sha-256 hash"
return 1
fi
}
hash_compute() {
hash_sha256 "$1"
}
# shellcheck shell=sh
# Terminal progress reporting functions
progress_init() {
# Only show progress on interactive terminals and when not disabled
if [ ! -t 2 ] || [ "${BINSTALLER_NO_PROGRESS}" = "1" ]; then
return 0
fi
# OSC 9;4 sequences are safely ignored by unsupporting terminals
# Only need special handling for tmux passthrough
if [ -n "$TMUX" ]; then
# Tmux passthrough: DCS tmux; <doubled ESC sequence> ST
# ESC characters in the wrapped sequence must be doubled
# Format: ESC P tmux; ESC ESC ] 9;4; ... ESC ESC \ ESC \
PROGRESS_START=$(printf '\033Ptmux;\033\033]9;4;')
# shellcheck disable=SC1003
PROGRESS_END=$(printf '\033\033\\\033\\')
else
# Direct OSC 9;4 - terminals that don't support it will safely ignore
PROGRESS_START=$(printf '\033]9;4;')
PROGRESS_END=$(printf '\007')
fi
}
# Start pulsing progress animation
progress_pulse_start() {
# Only show progress on interactive terminals and when not disabled
if [ ! -t 2 ] || [ "${BINSTALLER_NO_PROGRESS}" = "1" ]; then
return 0
fi
# Send OSC 9;4 with state 3 (indeterminate/pulsing) once
# The terminal will handle the continuous animation
printf "%s3%s" "$PROGRESS_START" "$PROGRESS_END" >&2
}
# Clear progress indicator
progress_clear() {
# Only show progress on interactive terminals and when not disabled
if [ ! -t 2 ] || [ "${BINSTALLER_NO_PROGRESS}" = "1" ]; then
return 0
fi
printf "%s0;%s" "$PROGRESS_START" "$PROGRESS_END" >&2
}
untar() {
tarball=$1
strip_components=${2:-0} # default 0
case "${tarball}" in
*.tar.gz | *.tgz) tar --no-same-owner -xzf "${tarball}" --strip-components "${strip_components}" ;;
*.tar.xz) tar --no-same-owner -xJf "${tarball}" --strip-components "${strip_components}" ;;
*.tar.bz2) tar --no-same-owner -xjf "${tarball}" --strip-components "${strip_components}" ;;
*.tar) tar --no-same-owner -xf "${tarball}" --strip-components "${strip_components}" ;;
*.gz) gunzip "${tarball}" ;;
*.zip)
# unzip doesn't have a standard --strip-components
# Workaround: extract to a subdir and move contents up if stripping
if [ "$strip_components" -gt 0 ]; then
extract_dir=$(basename "${tarball%.zip}")_extracted
unzip -q "${tarball}" -d "${extract_dir}"
# Move contents of the *first* directory found inside extract_dir up
# This assumes wrap_in_directory=true convention
first_subdir=$(find "${extract_dir}" -mindepth 1 -maxdepth 1 -type d -print -quit)
if [ -n "$first_subdir" ]; then
# Move all contents (* includes hidden files)
mv "${first_subdir}"/* .
# Optionally remove the now-empty subdir and the extract_dir
rmdir "${first_subdir}"
rmdir "${extract_dir}"
else
log_warn "Could not find subdirectory in zip to strip components from ${extract_dir}"
# Files are extracted in current dir anyway, proceed
fi
else
unzip -q "${tarball}"
fi
;;
*)
log_err "untar unknown archive format for ${tarball}"
return 1
;;
esac
}
hash_verify() {
TARGET_PATH=$1
SUMFILE=$2
if [ -z "${SUMFILE}" ]; then
log_err "hash_verify checksum file not specified in arg2"
return 1
fi
got=$(hash_compute "$TARGET_PATH")
if [ -z "${got}" ]; then
log_err "failed to calculate hash: ${TARGET_PATH}"
return 1
fi
BASENAME=${TARGET_PATH##*/}
# Check for line matches in checksum file
# Format: "<hash> <filename>" or "<hash> *<filename>"
# Filename may include path prefix (e.g., "deployment/m2/file.tar.gz")
while IFS= read -r line || [ -n "$line" ]; do
# Normalize tabs to spaces
line=$(echo "$line" | tr '\t' ' ')
# Remove trailing spaces for hash-only line check
line_trimmed=$(echo "$line" | sed 's/[[:space:]]*$//')
# Check for hash-only line (no filename) - early return
if [ "$line_trimmed" = "$got" ]; then
return 0
fi
# Extract hash and filename parts
# First field is the hash, rest is filename (which may contain spaces)
line_hash=$(echo "$line" | cut -d' ' -f1)
# Skip if hash doesn't match
if [ "$line_hash" != "$got" ]; then
continue
fi
# Hash matches, now check filename
# Remove the hash part from the beginning of the line
line_rest="${line#"$got"}"
# Remove leading spaces
while [ "${line_rest#[ ]}" != "$line_rest" ]; do
line_rest="${line_rest#[ ]}"
done
# Remove leading asterisk if present (binary mode indicator)
if [ "${line_rest#\*}" != "$line_rest" ]; then
line_rest="${line_rest#\*}"
fi
# Extract just the filename without any path
line_filename="${line_rest##*/}"
# Check if the filename matches
if [ "$line_filename" = "$BASENAME" ]; then
return 0
fi
done < "$SUMFILE"
log_err "hash_verify checksum for '$TARGET_PATH' did not verify"
log_err " Expected hash: ${got}"
log_err " Checksum file content:"
cat "$SUMFILE" >&2
return 1
}
# GitHub HTTP download functions with GITHUB_TOKEN support
github_http_download_curl() {
local_file=$1
source_url=$2
header=$3
if [ -n "$GITHUB_TOKEN" ]; then
log_debug "Using GITHUB_TOKEN for authentication"
if [ -z "$header" ]; then
curl -fsSL -H "Authorization: Bearer $GITHUB_TOKEN" -o "$local_file" "$source_url"
else
curl -fsSL -H "Authorization: Bearer $GITHUB_TOKEN" -H "$header" -o "$local_file" "$source_url"
fi
else
if [ -z "$header" ]; then
curl -fsSL -o "$local_file" "$source_url"
else
curl -fsSL -H "$header" -o "$local_file" "$source_url"
fi
fi
}
github_http_download_wget() {
local_file=$1
source_url=$2
header=$3
if [ -n "$GITHUB_TOKEN" ]; then
log_debug "Using GITHUB_TOKEN for authentication"
if [ -z "$header" ]; then
wget -q --header "Authorization: Bearer $GITHUB_TOKEN" -O "$local_file" "$source_url"
else
wget -q --header "Authorization: Bearer $GITHUB_TOKEN" --header "$header" -O "$local_file" "$source_url"
fi
else
if [ -z "$header" ]; then
wget -q -O "$local_file" "$source_url"
else
wget -q --header "$header" -O "$local_file" "$source_url"
fi
fi
}
github_http_download() {
log_debug "github_http_download $2"
if is_command curl; then
github_http_download_curl "$@"
return
elif is_command wget; then
github_http_download_wget "$@"
return
fi
log_crit "github_http_download unable to find wget or curl"
return 1
}
github_http_copy() {
tmp=$(mktemp)
github_http_download "${tmp}" "$@" || return 1
body=$(cat "$tmp")
rm -f "${tmp}"
echo "$body"
}
github_release() {
owner_repo=$1
version=$2
test -z "$version" && version="latest"
giturl="https://github.com/${owner_repo}/releases/${version}"
json=$(github_http_copy "$giturl" "Accept:application/json")
test -z "$json" && return 1
version=$(echo "$json" | tr -s '\n' ' ' | sed 's/.*"tag_name":"//' | sed 's/".*//')
test -z "$version" && return 1
echo "$version"
}
# --- Embedded Checksums (Format: VERSION:FILENAME:HASH) ---
EMBEDDED_CHECKSUMS="
0.60.0:tflint_darwin_amd64.zip:256f70ad2c9963690bccc31ffda6be0159f1c5f857b46773b70d01d56b711280
0.60.0:tflint_darwin_arm64.zip:753a392b70e37b2970732bdaf0c9ad98b0f8ecb96026b21e91261e4e967c7f5e
0.60.0:tflint_linux_386.zip:b25d41922b6dd4e30be74876d4691695b0d8de6f5b4cd93ddfd3706c3d285262
0.60.0:tflint_linux_amd64.zip:3476ceedcf0c4f9f2bed35e92988e1411bec2caa543c9387bffaa720df9efaf7
0.60.0:tflint_linux_arm.zip:59b6c1acf15f4faee2e28074a27214c78970b5427dff7ab16b9478f9d57fc2a8
0.60.0:tflint_linux_arm64.zip:8f01d273e58f44f6ed10e198fa1f5d0a8080b01869de64658528275e943ef47a
0.60.0:tflint_windows_386.zip:561a7c633009f4dcba82769742d7b1d14b64a5795a0868db5d3311ef19514998
0.60.0:tflint_windows_amd64.zip:a6e08412ec6bf9041325d75a0b88846f8e3b8fb24e5dda105574fa7565235f4c"
# Find embedded checksum for a given version and filename
find_embedded_checksum() {
version="$1"
filename="$2"
echo "$EMBEDDED_CHECKSUMS" | grep -E "^${version}:${filename}:" | cut -d':' -f3
}
parse_args() {
BINDIR="${BINSTALLER_BIN:-${HOME}/.local/bin}"
DRY_RUN=0
while getopts "b:dqh?xn" arg; do
case "$arg" in
b) BINDIR="$OPTARG" ;;
d) log_set_priority 10 ;;
q) log_set_priority 3 ;;
h | \?) usage "$0" ;;
x) set -x ;;
n) DRY_RUN=1 ;;
esac
done
shift $((OPTIND - 1))
TAG="${1:-latest}"
}
tag_to_version() {
if [ "$TAG" = "latest" ]; then
log_info "checking GitHub for latest tag"
REALTAG=$(github_release "${REPO}" "${TAG}") && true
test -n "$REALTAG" || {
log_crit "Could not determine latest tag for ${REPO}"
exit 1
}
else
# Assume TAG is a valid tag/version string
REALTAG="$TAG"
fi
if test -z "$REALTAG"; then
log_crit "unable to find '${TAG}' - use 'latest' or see https://github.com/${REPO}/releases for details"
exit 1
fi
VERSION=${REALTAG#v} # Strip leading 'v'
TAG="$REALTAG" # Use the resolved tag
log_info "Resolved version: ${VERSION} (tag: ${TAG})"
}
resolve_asset_filename() {
# --- Apply Rules ---
ASSET_FILENAME=""
if [ -z "${ASSET_FILENAME}" ]; then
ASSET_FILENAME="tflint_${OS}_${ARCH}${EXT}"
fi
}
# Cleanup function to remove temporary files and stop progress
cleanup() {
# Stop progress animation
progress_clear
if [ -n "$TMPDIR" ] && [ -d "$TMPDIR" ]; then
log_debug "Cleaning up temporary directory: $TMPDIR"
rm -rf -- "$TMPDIR"
fi
}
execute() {
STRIP_COMPONENTS=0
CHECKSUM_FILENAME="checksums.txt"
# --- Construct URLs ---
GITHUB_DOWNLOAD="https://github.com/${REPO}/releases/download"
ASSET_URL="${GITHUB_DOWNLOAD}/${TAG}/${ASSET_FILENAME}"
CHECKSUM_URL=""
if [ -n "$CHECKSUM_FILENAME" ]; then
CHECKSUM_URL="${GITHUB_DOWNLOAD}/${TAG}/${CHECKSUM_FILENAME}"
fi
# --- Download and Verify ---
TMPDIR=$(mktemp -d)
# Set up cleanup trap that includes progress clearing
trap cleanup EXIT HUP INT TERM
log_debug "Downloading files into ${TMPDIR}"
log_info "Downloading ${ASSET_URL}"
github_http_download "${TMPDIR}/${ASSET_FILENAME}" "${ASSET_URL}"
# Try to find embedded checksum first
EMBEDDED_HASH=$(find_embedded_checksum "$VERSION" "$ASSET_FILENAME")
if [ -n "$EMBEDDED_HASH" ]; then
log_info "Using embedded checksum for verification"
# Verify using embedded hash
got=$(hash_compute "${TMPDIR}/${ASSET_FILENAME}")
if [ "$got" != "$EMBEDDED_HASH" ]; then
log_crit "Checksum verification failed for ${ASSET_FILENAME}"
log_crit "Expected: ${EMBEDDED_HASH}"
log_crit "Got: ${got}"
return 1
fi
log_info "Checksum verification successful"
elif [ -n "$CHECKSUM_URL" ]; then
# Fall back to downloading checksum file
log_info "Downloading checksums from ${CHECKSUM_URL}"
github_http_download "${TMPDIR}/${CHECKSUM_FILENAME}" "${CHECKSUM_URL}"
log_info "Verifying checksum ..."
hash_verify "${TMPDIR}/${ASSET_FILENAME}" "${TMPDIR}/${CHECKSUM_FILENAME}"
else
log_info "No checksum found, skipping verification."
fi
if [ -z "${EXT}" ] || [ "${EXT}" = ".exe" ]; then
log_debug "Target is raw binary"
else
log_info "Extracting ${ASSET_FILENAME}..."
(cd "${TMPDIR}" && untar "${ASSET_FILENAME}" "${STRIP_COMPONENTS}")
fi
BINARY_NAME='tflint'
if [ -z "${EXT}" ] || [ "${EXT}" = ".exe" ]; then
BINARY_PATH="${TMPDIR}/${ASSET_FILENAME}"
else
BINARY_PATH="${TMPDIR}/tflint"
fi
if [ "${UNAME_OS}" = "windows" ]; then
case "${BINARY_NAME}" in *.exe) ;; *) BINARY_NAME="${BINARY_NAME}.exe" ;; esac
case "${BINARY_PATH}" in *.exe) ;; *) BINARY_PATH="${BINARY_PATH}.exe" ;; esac
fi
if [ ! -f "${BINARY_PATH}" ]; then
log_crit "Binary not found: ${BINARY_PATH}"
log_crit "Listing contents of ${TMPDIR} ..."
if command -v find >/dev/null 2>&1; then
cd "${TMPDIR}" && find .
else
cd "${TMPDIR}" && ls -R .
fi
return 1
fi
progress_clear
# Install the binary
INSTALL_PATH="${BINDIR}/${BINARY_NAME}"
if [ "$DRY_RUN" = "1" ]; then
log_info "[DRY RUN] ${BINARY_NAME} dry-run installation succeeded! (Would install to: ${INSTALL_PATH})"
else
log_info "Installing binary to ${INSTALL_PATH}"
test ! -d "${BINDIR}" && install -d "${BINDIR}"
install "${BINARY_PATH}" "${INSTALL_PATH}"
log_info "${BINARY_NAME} installation complete!"
fi
}
# --- Configuration ---
NAME='tflint'
REPO='terraform-linters/tflint'
EXT='.zip'
# use in logging routines
log_prefix() {
echo "${REPO}"
}
parse_args "$@"
progress_init
progress_pulse_start
# --- Determine target platform ---
OS="${BINSTALLER_OS:-$(uname_os)}"
UNAME_OS="${OS}"
ARCH="${BINSTALLER_ARCH:-$(uname_arch)}"
log_info "Detected Platform: ${OS}/${ARCH}"
# --- Validate platform ---
uname_os_check "$OS"
uname_arch_check "$ARCH"
tag_to_version
resolve_asset_filename
execute

View File

@@ -1,622 +0,0 @@
#!/bin/sh
# Code generated by binstaller. DO NOT EDIT.
#
set -e
usage() {
this=$1
cat <<EOF
$this: download ${NAME} from ${REPO}
Usage: $this [-b bindir] [-d] [-q] [-n] [tag]
-b sets bindir or installation directory, Defaults to ${BINSTALLER_BIN:-${HOME}/.local/bin}
-d turns on debug logging
-q turns on quiet mode (errors only)
-n turns on dry run mode
[tag] is a tag from
https://github.com/aquasecurity/trivy/releases
If tag is missing, then latest will be used.
Environment variables:
BINSTALLER_NO_PROGRESS=1 Disable progress indicators
BINSTALLER_OS=... Override OS detection
BINSTALLER_ARCH=... Override architecture detection
Generated by binstaller
https://github.com/binary-install/binstaller
EOF
exit 2
}
cat /dev/null <<EOF
------------------------------------------------------------------------
https://github.com/client9/shlib - portable posix shell functions
Public domain - http://unlicense.org
https://github.com/client9/shlib/blob/master/LICENSE.md
but credit (and pull requests) appreciated.
------------------------------------------------------------------------
EOF
is_command() {
command -v "$1" >/dev/null
}
echoerr() {
echo "$@" 1>&2
}
_logp=6
log_set_priority() {
_logp="$1"
}
log_priority() {
if test -z "$1"; then
echo "$_logp"
return
fi
[ "$1" -le "$_logp" ]
}
log_tag() {
case $1 in
0) echo "emerg" ;;
1) echo "alert" ;;
2) echo "crit" ;;
3) echo "err" ;;
4) echo "warning" ;;
5) echo "notice" ;;
6) echo "info" ;;
7) echo "debug" ;;
*) echo "$1" ;;
esac
}
log_debug() {
log_priority 7 || return 0
echoerr "$(log_prefix)" "$(log_tag 7)" "$@"
}
log_info() {
log_priority 6 || return 0
echoerr "$(log_prefix)" "$(log_tag 6)" "$@"
}
log_err() {
log_priority 3 || return 0
echoerr "$(log_prefix)" "$(log_tag 3)" "$@"
}
log_crit() {
log_priority 2 || return 0
echoerr "$(log_prefix)" "$(log_tag 2)" "$@"
}
uname_os() {
os=$(uname -s | tr '[:upper:]' '[:lower:]')
case "$os" in
msys*) os="windows" ;;
mingw*) os="windows" ;;
cygwin*) os="windows" ;;
esac
if [ "$os" = "sunos" ]; then
if [ "$(uname -o)" = "illumos" ]; then
os="illumos"
else
os="solaris"
fi
fi
echo "$os"
}
uname_arch() {
arch=$(uname -m)
case $arch in
x86_64) arch="amd64" ;;
i86pc) arch="amd64" ;;
x86) arch="386" ;;
i686) arch="386" ;;
i386) arch="386" ;;
aarch64) arch="arm64" ;;
armv5*) arch="armv5" ;;
armv6*) arch="armv6" ;;
armv7*) arch="armv7" ;;
esac
echo "${arch}"
}
uname_os_check() {
os=$(uname_os)
case "$os" in
darwin) return 0 ;;
dragonfly) return 0 ;;
freebsd) return 0 ;;
linux) return 0 ;;
android) return 0 ;;
midnightbsd) return 0 ;;
nacl) return 0 ;;
netbsd) return 0 ;;
openbsd) return 0 ;;
plan9) return 0 ;;
solaris) return 0 ;;
illumos) return 0 ;;
windows) return 0 ;;
esac
log_crit "uname_os_check '$(uname -s)' got converted to '$os' which is not a GOOS value. Please file bug at https://github.com/client9/shlib"
return 1
}
uname_arch_check() {
arch=$(uname_arch)
case "$arch" in
386) return 0 ;;
amd64) return 0 ;;
arm64) return 0 ;;
armv5) return 0 ;;
armv6) return 0 ;;
armv7) return 0 ;;
ppc64) return 0 ;;
ppc64le) return 0 ;;
mips) return 0 ;;
mipsle) return 0 ;;
mips64) return 0 ;;
mips64le) return 0 ;;
s390x) return 0 ;;
amd64p32) return 0 ;;
esac
log_crit "uname_arch_check '$(uname -m)' got converted to '$arch' which is not a GOARCH value. Please file bug report at https://github.com/client9/shlib"
return 1
}
cat /dev/null <<EOF
------------------------------------------------------------------------
End of functions from https://github.com/client9/shlib
------------------------------------------------------------------------
EOF
hash_sha256() {
TARGET=${1:-/dev/stdin}
if is_command gsha256sum; then
hash=$(gsha256sum "$TARGET") || return 1
echo "$hash" | cut -d ' ' -f 1
elif is_command sha256sum; then
hash=$(sha256sum "$TARGET") || return 1
echo "$hash" | cut -d ' ' -f 1
elif is_command shasum; then
hash=$(shasum -a 256 "$TARGET" 2>/dev/null) || return 1
echo "$hash" | cut -d ' ' -f 1
elif is_command openssl; then
hash=$(openssl dgst -sha256 "$TARGET") || return 1
echo "$hash" | cut -d ' ' -f 2
else
log_crit "hash_sha256 unable to find command to compute sha-256 hash"
return 1
fi
}
hash_compute() {
hash_sha256 "$1"
}
# shellcheck shell=sh
# Terminal progress reporting functions
progress_init() {
# Only show progress on interactive terminals and when not disabled
if [ ! -t 2 ] || [ "${BINSTALLER_NO_PROGRESS}" = "1" ]; then
return 0
fi
# OSC 9;4 sequences are safely ignored by unsupporting terminals
# Only need special handling for tmux passthrough
if [ -n "$TMUX" ]; then
# Tmux passthrough: DCS tmux; <doubled ESC sequence> ST
# ESC characters in the wrapped sequence must be doubled
# Format: ESC P tmux; ESC ESC ] 9;4; ... ESC ESC \ ESC \
PROGRESS_START=$(printf '\033Ptmux;\033\033]9;4;')
# shellcheck disable=SC1003
PROGRESS_END=$(printf '\033\033\\\033\\')
else
# Direct OSC 9;4 - terminals that don't support it will safely ignore
PROGRESS_START=$(printf '\033]9;4;')
PROGRESS_END=$(printf '\007')
fi
}
# Start pulsing progress animation
progress_pulse_start() {
# Only show progress on interactive terminals and when not disabled
if [ ! -t 2 ] || [ "${BINSTALLER_NO_PROGRESS}" = "1" ]; then
return 0
fi
# Send OSC 9;4 with state 3 (indeterminate/pulsing) once
# The terminal will handle the continuous animation
printf "%s3%s" "$PROGRESS_START" "$PROGRESS_END" >&2
}
# Clear progress indicator
progress_clear() {
# Only show progress on interactive terminals and when not disabled
if [ ! -t 2 ] || [ "${BINSTALLER_NO_PROGRESS}" = "1" ]; then
return 0
fi
printf "%s0;%s" "$PROGRESS_START" "$PROGRESS_END" >&2
}
untar() {
tarball=$1
strip_components=${2:-0} # default 0
case "${tarball}" in
*.tar.gz | *.tgz) tar --no-same-owner -xzf "${tarball}" --strip-components "${strip_components}" ;;
*.tar.xz) tar --no-same-owner -xJf "${tarball}" --strip-components "${strip_components}" ;;
*.tar.bz2) tar --no-same-owner -xjf "${tarball}" --strip-components "${strip_components}" ;;
*.tar) tar --no-same-owner -xf "${tarball}" --strip-components "${strip_components}" ;;
*.gz) gunzip "${tarball}" ;;
*.zip)
# unzip doesn't have a standard --strip-components
# Workaround: extract to a subdir and move contents up if stripping
if [ "$strip_components" -gt 0 ]; then
extract_dir=$(basename "${tarball%.zip}")_extracted
unzip -q "${tarball}" -d "${extract_dir}"
# Move contents of the *first* directory found inside extract_dir up
# This assumes wrap_in_directory=true convention
first_subdir=$(find "${extract_dir}" -mindepth 1 -maxdepth 1 -type d -print -quit)
if [ -n "$first_subdir" ]; then
# Move all contents (* includes hidden files)
mv "${first_subdir}"/* .
# Optionally remove the now-empty subdir and the extract_dir
rmdir "${first_subdir}"
rmdir "${extract_dir}"
else
log_warn "Could not find subdirectory in zip to strip components from ${extract_dir}"
# Files are extracted in current dir anyway, proceed
fi
else
unzip -q "${tarball}"
fi
;;
*)
log_err "untar unknown archive format for ${tarball}"
return 1
;;
esac
}
hash_verify() {
TARGET_PATH=$1
SUMFILE=$2
if [ -z "${SUMFILE}" ]; then
log_err "hash_verify checksum file not specified in arg2"
return 1
fi
got=$(hash_compute "$TARGET_PATH")
if [ -z "${got}" ]; then
log_err "failed to calculate hash: ${TARGET_PATH}"
return 1
fi
BASENAME=${TARGET_PATH##*/}
# Check for line matches in checksum file
# Format: "<hash> <filename>" or "<hash> *<filename>"
# Filename may include path prefix (e.g., "deployment/m2/file.tar.gz")
while IFS= read -r line || [ -n "$line" ]; do
# Normalize tabs to spaces
line=$(echo "$line" | tr '\t' ' ')
# Remove trailing spaces for hash-only line check
line_trimmed=$(echo "$line" | sed 's/[[:space:]]*$//')
# Check for hash-only line (no filename) - early return
if [ "$line_trimmed" = "$got" ]; then
return 0
fi
# Extract hash and filename parts
# First field is the hash, rest is filename (which may contain spaces)
line_hash=$(echo "$line" | cut -d' ' -f1)
# Skip if hash doesn't match
if [ "$line_hash" != "$got" ]; then
continue
fi
# Hash matches, now check filename
# Remove the hash part from the beginning of the line
line_rest="${line#"$got"}"
# Remove leading spaces
while [ "${line_rest#[ ]}" != "$line_rest" ]; do
line_rest="${line_rest#[ ]}"
done
# Remove leading asterisk if present (binary mode indicator)
if [ "${line_rest#\*}" != "$line_rest" ]; then
line_rest="${line_rest#\*}"
fi
# Extract just the filename without any path
line_filename="${line_rest##*/}"
# Check if the filename matches
if [ "$line_filename" = "$BASENAME" ]; then
return 0
fi
done < "$SUMFILE"
log_err "hash_verify checksum for '$TARGET_PATH' did not verify"
log_err " Expected hash: ${got}"
log_err " Checksum file content:"
cat "$SUMFILE" >&2
return 1
}
# GitHub HTTP download functions with GITHUB_TOKEN support
github_http_download_curl() {
local_file=$1
source_url=$2
header=$3
if [ -n "$GITHUB_TOKEN" ]; then
log_debug "Using GITHUB_TOKEN for authentication"
if [ -z "$header" ]; then
curl -fsSL -H "Authorization: Bearer $GITHUB_TOKEN" -o "$local_file" "$source_url"
else
curl -fsSL -H "Authorization: Bearer $GITHUB_TOKEN" -H "$header" -o "$local_file" "$source_url"
fi
else
if [ -z "$header" ]; then
curl -fsSL -o "$local_file" "$source_url"
else
curl -fsSL -H "$header" -o "$local_file" "$source_url"
fi
fi
}
github_http_download_wget() {
local_file=$1
source_url=$2
header=$3
if [ -n "$GITHUB_TOKEN" ]; then
log_debug "Using GITHUB_TOKEN for authentication"
if [ -z "$header" ]; then
wget -q --header "Authorization: Bearer $GITHUB_TOKEN" -O "$local_file" "$source_url"
else
wget -q --header "Authorization: Bearer $GITHUB_TOKEN" --header "$header" -O "$local_file" "$source_url"
fi
else
if [ -z "$header" ]; then
wget -q -O "$local_file" "$source_url"
else
wget -q --header "$header" -O "$local_file" "$source_url"
fi
fi
}
github_http_download() {
log_debug "github_http_download $2"
if is_command curl; then
github_http_download_curl "$@"
return
elif is_command wget; then
github_http_download_wget "$@"
return
fi
log_crit "github_http_download unable to find wget or curl"
return 1
}
github_http_copy() {
tmp=$(mktemp)
github_http_download "${tmp}" "$@" || return 1
body=$(cat "$tmp")
rm -f "${tmp}"
echo "$body"
}
github_release() {
owner_repo=$1
version=$2
test -z "$version" && version="latest"
giturl="https://github.com/${owner_repo}/releases/${version}"
json=$(github_http_copy "$giturl" "Accept:application/json")
test -z "$json" && return 1
version=$(echo "$json" | tr -s '\n' ' ' | sed 's/.*"tag_name":"//' | sed 's/".*//')
test -z "$version" && return 1
echo "$version"
}
# --- Embedded Checksums (Format: VERSION:FILENAME:HASH) ---
EMBEDDED_CHECKSUMS="
0.68.2:trivy_0.68.2_Linux-64bit.tar.gz:3d933bbc3685f95ec15280f620583d05d97ee3affb66944d14481d5d6d567064
0.68.2:trivy_0.68.2_Linux-ARM64.tar.gz:33c87995fd0c3d1559086c3e18fd3148051296dfd0ca2a67583eb64f89998c91
0.68.2:trivy_0.68.2_Linux-s390x.tar.gz:fd45fc808622ecb11393f4c27d1fbd20e1d78838148a282b1129624964dd0628
0.68.2:trivy_0.68.2_macOS-64bit.tar.gz:c0790530cd717b6bdd02ed437be0710f5c7043078fafaf6841be7c865bf251ce
0.68.2:trivy_0.68.2_macOS-ARM64.tar.gz:dfbe15ffe47426dad9fd3e0d52aeacf3dbbb25ca5dbc66049f5920834435988d
0.68.2:trivy_0.68.2_windows-64bit.zip:2aaa0ce06f9f2221a6bb21e1fc0e0ecc6aeb56362bc5c9463e9fd7b06983c3c3"
# Find embedded checksum for a given version and filename
find_embedded_checksum() {
version="$1"
filename="$2"
echo "$EMBEDDED_CHECKSUMS" | grep -E "^${version}:${filename}:" | cut -d':' -f3
}
parse_args() {
BINDIR="${BINSTALLER_BIN:-${HOME}/.local/bin}"
DRY_RUN=0
while getopts "b:dqh?xn" arg; do
case "$arg" in
b) BINDIR="$OPTARG" ;;
d) log_set_priority 10 ;;
q) log_set_priority 3 ;;
h | \?) usage "$0" ;;
x) set -x ;;
n) DRY_RUN=1 ;;
esac
done
shift $((OPTIND - 1))
TAG="${1:-latest}"
}
tag_to_version() {
if [ "$TAG" = "latest" ]; then
log_info "checking GitHub for latest tag"
REALTAG=$(github_release "${REPO}" "${TAG}") && true
test -n "$REALTAG" || {
log_crit "Could not determine latest tag for ${REPO}"
exit 1
}
else
# Assume TAG is a valid tag/version string
REALTAG="$TAG"
fi
if test -z "$REALTAG"; then
log_crit "unable to find '${TAG}' - use 'latest' or see https://github.com/${REPO}/releases for details"
exit 1
fi
VERSION=${REALTAG#v} # Strip leading 'v'
TAG="$REALTAG" # Use the resolved tag
log_info "Resolved version: ${VERSION} (tag: ${TAG})"
}
resolve_asset_filename() {
# --- Apply Rules ---
ASSET_FILENAME=""
if [ "${UNAME_ARCH}" = 'amd64' ] && true
then
ARCH='64bit'
fi
if [ "${UNAME_ARCH}" = 'arm64' ] && true
then
ARCH='ARM64'
fi
if [ "${UNAME_OS}" = 'darwin' ] && true
then
OS='macOS'
fi
if [ "${UNAME_OS}" = 'linux' ] && true
then
OS='Linux'
fi
if [ "${UNAME_OS}" = 'windows' ] && true
then
EXT='.zip'
fi
if [ -z "${ASSET_FILENAME}" ]; then
ASSET_FILENAME="trivy_${VERSION}_${OS}-${ARCH}${EXT}"
fi
}
# Cleanup function to remove temporary files and stop progress
cleanup() {
# Stop progress animation
progress_clear
if [ -n "$TMPDIR" ] && [ -d "$TMPDIR" ]; then
log_debug "Cleaning up temporary directory: $TMPDIR"
rm -rf -- "$TMPDIR"
fi
}
execute() {
STRIP_COMPONENTS=0
CHECKSUM_FILENAME="trivy_${VERSION}_checksums.txt"
# --- Construct URLs ---
GITHUB_DOWNLOAD="https://github.com/${REPO}/releases/download"
ASSET_URL="${GITHUB_DOWNLOAD}/${TAG}/${ASSET_FILENAME}"
CHECKSUM_URL=""
if [ -n "$CHECKSUM_FILENAME" ]; then
CHECKSUM_URL="${GITHUB_DOWNLOAD}/${TAG}/${CHECKSUM_FILENAME}"
fi
# --- Download and Verify ---
TMPDIR=$(mktemp -d)
# Set up cleanup trap that includes progress clearing
trap cleanup EXIT HUP INT TERM
log_debug "Downloading files into ${TMPDIR}"
log_info "Downloading ${ASSET_URL}"
github_http_download "${TMPDIR}/${ASSET_FILENAME}" "${ASSET_URL}"
# Try to find embedded checksum first
EMBEDDED_HASH=$(find_embedded_checksum "$VERSION" "$ASSET_FILENAME")
if [ -n "$EMBEDDED_HASH" ]; then
log_info "Using embedded checksum for verification"
# Verify using embedded hash
got=$(hash_compute "${TMPDIR}/${ASSET_FILENAME}")
if [ "$got" != "$EMBEDDED_HASH" ]; then
log_crit "Checksum verification failed for ${ASSET_FILENAME}"
log_crit "Expected: ${EMBEDDED_HASH}"
log_crit "Got: ${got}"
return 1
fi
log_info "Checksum verification successful"
elif [ -n "$CHECKSUM_URL" ]; then
# Fall back to downloading checksum file
log_info "Downloading checksums from ${CHECKSUM_URL}"
github_http_download "${TMPDIR}/${CHECKSUM_FILENAME}" "${CHECKSUM_URL}"
log_info "Verifying checksum ..."
hash_verify "${TMPDIR}/${ASSET_FILENAME}" "${TMPDIR}/${CHECKSUM_FILENAME}"
else
log_info "No checksum found, skipping verification."
fi
if [ -z "${EXT}" ] || [ "${EXT}" = ".exe" ]; then
log_debug "Target is raw binary"
else
log_info "Extracting ${ASSET_FILENAME}..."
(cd "${TMPDIR}" && untar "${ASSET_FILENAME}" "${STRIP_COMPONENTS}")
fi
BINARY_NAME='trivy'
if [ -z "${EXT}" ] || [ "${EXT}" = ".exe" ]; then
BINARY_PATH="${TMPDIR}/${ASSET_FILENAME}"
else
BINARY_PATH="${TMPDIR}/trivy"
fi
if [ "${UNAME_OS}" = "windows" ]; then
case "${BINARY_NAME}" in *.exe) ;; *) BINARY_NAME="${BINARY_NAME}.exe" ;; esac
case "${BINARY_PATH}" in *.exe) ;; *) BINARY_PATH="${BINARY_PATH}.exe" ;; esac
fi
if [ ! -f "${BINARY_PATH}" ]; then
log_crit "Binary not found: ${BINARY_PATH}"
log_crit "Listing contents of ${TMPDIR} ..."
if command -v find >/dev/null 2>&1; then
cd "${TMPDIR}" && find .
else
cd "${TMPDIR}" && ls -R .
fi
return 1
fi
progress_clear
# Install the binary
INSTALL_PATH="${BINDIR}/${BINARY_NAME}"
if [ "$DRY_RUN" = "1" ]; then
log_info "[DRY RUN] ${BINARY_NAME} dry-run installation succeeded! (Would install to: ${INSTALL_PATH})"
else
log_info "Installing binary to ${INSTALL_PATH}"
test ! -d "${BINDIR}" && install -d "${BINDIR}"
install "${BINARY_PATH}" "${INSTALL_PATH}"
log_info "${BINARY_NAME} installation complete!"
fi
}
# --- Configuration ---
NAME='trivy'
REPO='aquasecurity/trivy'
EXT='.tar.gz'
# use in logging routines
log_prefix() {
echo "${REPO}"
}
parse_args "$@"
progress_init
progress_pulse_start
# --- Determine target platform ---
OS="${BINSTALLER_OS:-$(uname_os)}"
UNAME_OS="${OS}"
ARCH="${BINSTALLER_ARCH:-$(uname_arch)}"
UNAME_ARCH="${ARCH}"
log_info "Detected Platform: ${OS}/${ARCH}"
# --- Validate platform ---
uname_os_check "$OS"
uname_arch_check "$ARCH"
tag_to_version
resolve_asset_filename
execute