commit 2456195fbc269217822ef1c30aab29541bac59cd Author: Madison Grubb Date: Thu Mar 12 22:41:33 2026 -0400 initial commit diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..3070d81 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +.github +.git diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9db8d11 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,9 @@ +* text=auto eol=lf + +# scripts +*.sh text eol=lf +*.bat text eol=crlf + +## DOCKER +*.dockerignore text +Dockerfile text diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml new file mode 100644 index 0000000..582c3c3 --- /dev/null +++ b/.gitea/workflows/build.yml @@ -0,0 +1,129 @@ +name: Build act images + +on: + schedule: + - cron: 0 12 */7 * * + push: + paths: + - '.github/workflows/build-ubuntu.yml' + - 'Dockerfile' + - 'scripts/**' + - 'build.sh' + branches: + - 'master' + workflow_dispatch: + +env: + REGISTRY: git.keligrubb.com + SLUG: ${{ github.repository_owner }}/ubuntu + IMAGE_LABEL_OWNER: ${{ github.repository_owner }} + IMAGE_LABEL_REPO: ${{ github.repository }} + NODE: '20 24' + BUILD_REF: ${{ github.sha }} + SKIP_TEST: false + LATEST_TAG: 24.04 + +jobs: + build-act: + name: Build act ${{ matrix.TAG }} + runs-on: ubuntu-latest + strategy: + fail-fast: true + max-parallel: 4 + matrix: + TAG: + - 24.04 + - 22.04 + + steps: + - uses: https://git.keligrubb.com/actions/checkout@v6 + + - name: Log in to container registry + uses: https://git.keligrubb.com/actions/docker-login-action@v4 + with: + registry: ${{ env.REGISTRY }} + username: jasper-agent + password: ${{ secrets.JASPER_REPO_TOKEN }} + + - name: Set up Docker Buildx + uses: https://git.keligrubb.com/actions/docker-setup-buildx-action@v4 + + - name: Compute tags and metadata + run: | + if [[ "${{ github.event_name }}" == "schedule" || "${{ github.event_name }}" == "workflow_dispatch" ]]; then + PART_TAG=$(date +%Y%m%d) + else + PART_TAG=dev + fi + echo "PART_TAG=$PART_TAG" >> "$GITHUB_ENV" + + if [ "${LATEST_TAG}" = "${{ matrix.TAG }}" ]; then + RELEASE_TAG=$(lsb_release -rs) + else + RELEASE_TAG="${{ matrix.TAG }}" + fi + echo "RELEASE_TAG=$RELEASE_TAG" >> "$GITHUB_ENV" + + BUILD_DATE=$(date -u +"%Y-%m-%d %H:%M:%SZ") + echo "BUILD_DATE=$BUILD_DATE" >> "$GITHUB_ENV" + + TAG_NAME="act-${{ matrix.TAG }}" + { + echo "${TAG_NAME}-${PART_TAG}" + if [ "${LATEST_TAG}" = "${{ matrix.TAG }}" ]; then + echo "act-latest-${PART_TAG}" + fi + echo "${TAG_NAME}" + if [ "${LATEST_TAG}" = "${{ matrix.TAG }}" ]; then + echo "act-latest" + fi + } > .tags + + echo "ACT_TEST_IMAGE=${{ env.REGISTRY }}/${{ env.SLUG }}:${TAG_NAME}-${PART_TAG}" >> "$GITHUB_ENV" + + - name: Build Docker image + uses: https://git.keligrubb.com/actions/docker-build-push-action@v7 + with: + context: . + file: ./Dockerfile + load: true + tags: act:built + build-args: | + NODE_VERSION=${{ env.NODE }} + DISTRO=ubuntu + TYPE=act + RUNNER=root + BUILD_DATE=${{ env.BUILD_DATE }} + BUILD_OWNER=${{ env.IMAGE_LABEL_OWNER }} + BUILD_REPO=${{ env.IMAGE_LABEL_REPO }} + BUILD_TAG=act-${{ matrix.TAG }} + BUILD_TAG_VERSION=${{ env.PART_TAG }} + BUILD_REF=${{ env.BUILD_REF }} + FROM_IMAGE=buildpack-deps + FROM_TAG=${{ env.RELEASE_TAG }} + + - name: Push Docker image (all tags from .tags) + run: | + IMAGE="${{ env.REGISTRY }}/${{ env.SLUG }}" + while read -r tag; do + docker tag act:built "$IMAGE:$tag" + docker push "$IMAGE:$tag" + done < .tags + + - if: ${{ !env.SKIP_TEST }} + uses: https://git.keligrubb.com/actions/setup-go@v6 + with: + go-version: '>=1.21.0' + + - if: ${{ !env.SKIP_TEST }} + uses: https://git.keligrubb.com/actions/checkout@v6 + with: + repository: nektos/act + path: act + + - if: ${{ !env.SKIP_TEST }} + env: + ACT_TEST_IMAGE: ${{ env.ACT_TEST_IMAGE }} + run: | + cd act/ + go test ./... diff --git a/.gitea/workflows/pr.yml b/.gitea/workflows/pr.yml new file mode 100644 index 0000000..153ddb0 --- /dev/null +++ b/.gitea/workflows/pr.yml @@ -0,0 +1,34 @@ +name: Lint Docker files and shell scripts + +on: + pull_request: + paths: + - '.gitea/workflows/**' + - 'Dockerfile' + - 'scripts/**' + - 'build.sh' + +jobs: + lint-dockerfile: + name: Lint Dockerfile with hadolint + runs-on: ubuntu-latest + steps: + - uses: https://git.keligrubb.com/actions/checkout@v6 + - name: Run hadolint + uses: hadolint/hadolint-action@v3 + with: + dockerfile: Dockerfile + + lint-shell-scripts: + name: Lint shell scripts with shellcheck + runs-on: ubuntu-latest + steps: + - uses: https://git.keligrubb.com/actions/checkout@v6 + - name: Install shellcheck + run: | + sudo apt-get update + sudo apt-get install -y shellcheck + - name: Run shellcheck + run: | + find . -name '*.sh' -print0 | xargs -0 -n1 shellcheck + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c82384b --- /dev/null +++ b/.gitignore @@ -0,0 +1,12 @@ +# custom stuff +.secrets +.env + +# wip +*.hcl + +# mega-linter +report + +# quick local actions for act +.github/workflows/act.yml diff --git a/.hadolint.yml b/.hadolint.yml new file mode 100644 index 0000000..d0dd9b5 --- /dev/null +++ b/.hadolint.yml @@ -0,0 +1,14 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/hadolint/hadolint/master/contrib/hadolint.json +--- +ignored: + - SC2086 + - DL3004 + - DL3002 + - DL3008 + - DL3016 + - DL3018 + - DL3003 +trustedRegistries: + - docker.io + - ghcr.io + - quay.io diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..ec809d8 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,47 @@ +ARG FROM_IMAGE +ARG FROM_TAG +FROM ${FROM_IMAGE}:${FROM_TAG} + +# > automatic buildx ARGs +ARG TARGETARCH + +# > ARGs before FROM are not accessible +ARG FROM_IMAGE +ARG FROM_TAG + +# > Our custom ARGs +# latest Node.js LTS versions +ARG NODE_VERSION="20 24" +ARG DISTRO=ubuntu +ARG TYPE=act +ARG RUNNER + +# > Force apt to not be interactive/not ask +ENV DEBIAN_FRONTEND=noninteractive + +SHELL [ "/bin/bash", "--login", "-e", "-o", "pipefail", "-c" ] +WORKDIR /tmp + +COPY ./scripts /imagegeneration/installers +RUN bash /imagegeneration/installers/${TYPE}.sh + +ARG BUILD_DATE +ARG BUILD_TAG=${TYPE} +ARG BUILD_REF +ARG BUILD_TAG_VERSION +ARG BUILD_OWNER +ARG BUILD_REPO + +LABEL org.opencontainers.image.created="${BUILD_DATE}" +LABEL org.opencontainers.image.vendor="${BUILD_OWNER}" +LABEL org.opencontainers.image.authors="https://github.com/${BUILD_OWNER}" +LABEL org.opencontainers.image.url="https://github.com/${BUILD_OWNER}/${BUILD_REPO}/tree/${BUILD_REF}/" +LABEL org.opencontainers.image.source="https://github.com/${BUILD_OWNER}/${BUILD_REPO}" +LABEL org.opencontainers.image.documentation="https://github.com/${BUILD_OWNER}/${BUILD_REPO}" +LABEL org.opencontainers.image.version="${BUILD_TAG_VERSION}" +LABEL org.opencontainers.image.title="${BUILD_TAG}-${TARGETARCH}" +LABEL org.opencontainers.image.description="Special image built for using with https://github.com/nektos/act" +LABEL org.opencontainers.image.revision="${BUILD_REF}" + +USER ${RUNNER} + diff --git a/README.md b/README.md new file mode 100644 index 0000000..71e9f02 --- /dev/null +++ b/README.md @@ -0,0 +1,88 @@ +# Docker images for act + +Ubuntu-based images for [nektos/act][nektos/act], kept small while staying compatible with most GitHub Actions. + +## Images + +Built from [`scripts/act.sh`](./scripts/act.sh). Published to this repo’s Gitea registry: + +- **Registry:** `git.keligrubb.com` +- **Image:** `git.keligrubb.com/actions/ubuntu` +- **Tags:** `act-22.04`, `act-24.04`, `act-latest` (and dated tags e.g. `act-24.04-YYYYMMDD`) + +## When images are updated + +- Dependencies required for actions change +- Changes to GitHub Actions, Act, or the container registry +- Size or performance improvements + +## Build locally + +You can build and push from this repo without using CI. + +**Prereqs:** Docker with `buildx`, and push access to your registry (e.g. `git.keligrubb.com`). + +**1. Set env (repo root):** + +```sh +export IMAGE_LABEL_OWNER="actions" +export IMAGE_LABEL_REPO="ubuntu" +export SLUG="actions/ubuntu" + +export DISTRO="ubuntu" +export TYPE="act" +export RUNNER="root" +export NODE="20 24" +export PLATFORMS="linux/amd64,linux/arm64" + +export FROM_IMAGE="buildpack-deps" +export FROM_TAG="24.04" + +export TAG="act-24.04" +export LATEST_TAG="act-latest" +export PART_TAG="$(date +%Y%m%d)" +export BUILD_TAG="${TAG}" +export BUILD_TAG_VERSION="${PART_TAG}" +export BUILD_REF="$(git rev-parse HEAD 2>/dev/null || echo unknown)" +``` + +**2. Log in to your registry:** + +```sh +docker login git.keligrubb.com +``` + +**3. Build and push:** + +```sh +tags="" +tags="${tags} git.keligrubb.com/${SLUG}:${TAG}-${PART_TAG}" +tags="${tags} git.keligrubb.com/${SLUG}:${LATEST_TAG}-${PART_TAG}" +tags="${tags} git.keligrubb.com/${SLUG}:${TAG}" +tags="${tags} git.keligrubb.com/${SLUG}:${LATEST_TAG}" + +./build.sh --push --tags ${tags} +``` + +This builds the root `Dockerfile` (which runs `scripts/act.sh`), then pushes to each tag. For a local build only (no push), run `./build.sh`. + +**4. Use with act** + +Point act at your image, e.g.: + +```sh +act -P ubuntu-latest=git.keligrubb.com/actions/ubuntu:act-24.04 +``` + +Or put the image in `.actrc` or your workflow’s `runs-on` image. + +## Customising + +Edit [`scripts/act.sh`](./scripts/act.sh) to add or remove packages. Keep `DISTRO=ubuntu`, `TYPE=act`, and a valid `RUNNER` user, then re-run the build steps above. + +## Licence + +Parts of this repository are from [actions/virtual-environments][actions/virtual-environments], used under the [MIT License](https://github.com/actions/virtual-environments/blob/main/LICENSE). + +[nektos/act]: https://github.com/nektos/act +[actions/virtual-environments]: https://github.com/actions/virtual-environments diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..9ac252d --- /dev/null +++ b/build.sh @@ -0,0 +1,212 @@ +#!/usr/bin/env sh + +set -u + +usage() { + cat <&2 + usage + exit 1 + ;; + esac +done + +# Helper to run a command and fail with a useful message (equivalent to exec in build.ps1) +exec_cmd() { + if ! "$@"; then + status=$? + printf '%s failed with exit code %s\n' "$*" "$status" >&2 + exit "$status" + fi +} + +if [ -z "$platforms" ]; then + printf 'Error: PLATFORMS is empty. Set PLATFORMS or pass --platforms.\n' >&2 + exit 1 +fi + +if [ -z "$from_image" ] || [ -z "$from_tag" ]; then + printf 'Error: FROM_IMAGE/FROM_TAG are empty. Set env vars or pass --from-image/--from-tag.\n' >&2 + exit 1 +fi + +if [ "$push" = true ]; then + # Combine tags and tag (if provided) + all_tags=$tags + if [ -n "$tag" ]; then + if [ -z "$all_tags" ]; then + all_tags=$tag + else + all_tags="$all_tags $tag" + fi + fi +else + # Even when not pushing, honor --tag so the local image is named. + all_tags=$tags + if [ -n "$tag" ]; then + if [ -z "$all_tags" ]; then + all_tags=$tag + else + all_tags="$all_tags $tag" + fi + fi +fi + +# Buildx expects comma-separated --platform list; reuse platforms as-is. + +tag_args="" +for t in $all_tags; do + tag_args="$tag_args -t $t" +done + +build_date=$(date -u +"%Y-%m-%d %H:%M:%SZ") + +# Build argument vector to preserve spacing/quoting (e.g. NODE_VERSION="20 24") +set -- docker buildx build \ + --ulimit "nofile=4096:4096" \ + --platform "$platforms" \ + --build-arg "TARGETARCH=\$TARGETARCH" \ + --build-arg "NODE_VERSION=$node" \ + --build-arg "DISTRO=$distro" \ + --build-arg "TYPE=$type" \ + --build-arg "RUNNER=$runner" \ + --build-arg "BUILD_DATE=$build_date" \ + --build-arg "BUILD_OWNER=$owner" \ + --build-arg "BUILD_OWNER_MAIL=$owner" \ + --build-arg "BUILD_REPO=$repository" \ + --build-arg "BUILD_TAG=$build_tag" \ + --build-arg "BUILD_TAG_VERSION=$build_tag_version" \ + --build-arg "BUILD_REF=$build_ref" \ + --build-arg "FROM_IMAGE=$from_image" \ + --build-arg "FROM_TAG=$from_tag" \ + --file "./Dockerfile" + +# Append tag flags +# shellcheck disable=SC2086 +set -- "$@" $tag_args + +# Append push/load and final PATH argument +if [ "$push" = true ]; then + set -- "$@" --push . +else + set -- "$@" --load . +fi + +exec_cmd "$@" + diff --git a/scripts/act.sh b/scripts/act.sh new file mode 100644 index 0000000..0a89cd7 --- /dev/null +++ b/scripts/act.sh @@ -0,0 +1,176 @@ +#!/bin/bash +# shellcheck disable=SC2174,SC1091 + +set -Eeuxo pipefail + +printf "\n\tπŸ‹ Build started πŸ‹\t\n" + +# Remove '"' so it can be sourced by sh/bash +sed 's|"||g' -i "/etc/environment" + +. /etc/os-release + +node_arch() { + case "$(uname -m)" in + 'aarch64') echo 'arm64' ;; + 'x86_64') echo 'x64' ;; + 'armv7l') echo 'armv7l' ;; + *) exit 1 ;; + esac +} + +ImageOS=ubuntu$(echo "${VERSION_ID}" | cut -d'.' -f 1) +AGENT_TOOLSDIRECTORY=/opt/hostedtoolcache +ACT_TOOLSDIRECTORY=/opt/acttoolcache +{ + echo "IMAGE_OS=$ImageOS" + echo "ImageOS=$ImageOS" + echo "LSB_RELEASE=${VERSION_ID}" + echo "AGENT_TOOLSDIRECTORY=${AGENT_TOOLSDIRECTORY}" + echo "RUN_TOOL_CACHE=${AGENT_TOOLSDIRECTORY}" + echo "DEPLOYMENT_BASEPATH=/opt/runner" + echo "USER=$(whoami)" + echo "RUNNER_USER=$(whoami)" + echo "ACT_TOOLSDIRECTORY=${ACT_TOOLSDIRECTORY}" +} | tee -a "/etc/environment" + +mkdir -m 0777 -p "${AGENT_TOOLSDIRECTORY}" +chown -R 1001:1000 "${AGENT_TOOLSDIRECTORY}" +mkdir -m 0777 -p "${ACT_TOOLSDIRECTORY}" +chown -R 1001:1000 "${ACT_TOOLSDIRECTORY}" + +mkdir -m 0777 -p /github +chown -R 1001:1000 /github + +printf "\n\tπŸ‹ Installing packages πŸ‹\t\n" +packages=( + ssh + gawk + curl + jq + shellcheck + wget + sudo + gnupg-agent + ca-certificates + software-properties-common + apt-transport-https + libyaml-0-2 + zstd + zip + unzip + xz-utils + python3-pip + python3-venv + pipx +) + +apt-get -yq update +apt-get -yq install --no-install-recommends --no-install-suggests "${packages[@]}" + +ln -s "$(which python3)" "/usr/local/bin/python" + +add-apt-repository ppa:git-core/ppa -y +apt-get update +apt-get install -y git + +git --version + +git config --system --add safe.directory '*' + +wget https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh -qO- | bash +apt-get update +apt-get install -y git-lfs + +LSB_OS_VERSION="${VERSION_ID//\./}" +echo "LSB_OS_VERSION=${LSB_OS_VERSION}" | tee -a "/etc/environment" + +wget -qO "/imagegeneration/toolset.json" "https://raw.githubusercontent.com/actions/virtual-environments/main/images/ubuntu/toolsets/toolset-${LSB_OS_VERSION}.json" || echo "File not available" +wget -qO "/imagegeneration/LICENSE" "https://raw.githubusercontent.com/actions/virtual-environments/main/LICENSE" + +if [ "$(uname -m)" = x86_64 ]; then + wget -qO "/usr/bin/jq" "https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64" + chmod +x "/usr/bin/jq" +fi + +printf "\n\tπŸ‹ Updated apt lists and upgraded packages πŸ‹\t\n" + +printf "\n\tπŸ‹ Creating ~/.ssh and adding 'github.com' πŸ‹\t\n" +mkdir -m 0700 -p ~/.ssh +ssh-keyscan github.com >>/etc/ssh/ssh_known_hosts + +printf "\n\tπŸ‹ Installed base utils πŸ‹\t\n" + +printf "\n\tπŸ‹ Installing docker cli πŸ‹\t\n" +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc +chmod a+r /etc/apt/keyrings/docker.asc +cat </etc/apt/sources.list.d/docker.sources +Types: deb +URIs: https://download.docker.com/linux/ubuntu +Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") +Components: stable +Signed-By: /etc/apt/keyrings/docker.asc +EOF +apt-get -yq update +apt-get -yq install --no-install-recommends --no-install-suggests docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin +printf "\n\tπŸ‹ Installed docker cli πŸ‹\t\n" +docker -v +printf "\n\tπŸ‹ Installed docker buildx πŸ‹\t\n" +docker buildx version +IFS=' ' read -r -a NODE <<<"$NODE_VERSION" +for ver in "${NODE[@]}"; do + if [[ "${ver}" == "24" && "$(node_arch)" == "armv7l" ]]; then + ver="22" # rip arm32/v7 + fi + printf "\n\tπŸ‹ Installing Node.JS=%s πŸ‹\t\n" "${ver}" + VER=$(curl https://nodejs.org/download/release/index.json | jq "[.[] | select(.version|test(\"^v${ver}\"))][0].version" -r) + NODEPATH="${ACT_TOOLSDIRECTORY}/node/${VER:1}/$(node_arch)" + mkdir -v -m 0777 -p "$NODEPATH" + wget "https://nodejs.org/download/release/latest-v${ver}.x/node-$VER-linux-$(node_arch).tar.xz" -O "node-$VER-linux-$(node_arch).tar.xz" + tar -Jxf "node-$VER-linux-$(node_arch).tar.xz" --strip-components=1 -C "$NODEPATH" + rm "node-$VER-linux-$(node_arch).tar.xz" + if [[ "${ver}" == "24" ]]; then # make this version the default (latest LTS) + sed "s|^PATH=|PATH=$NODEPATH/bin:|mg" -i /etc/environment + ln -sfn "$NODEPATH/bin/node" /usr/local/bin/node + ln -sfn "$NODEPATH/bin/npm" /usr/local/bin/npm + fi + export PATH="$NODEPATH/bin:$PATH" + + printf "\n\tπŸ‹ Installed Node.JS πŸ‹\t\n" + "${NODEPATH}"/bin/node -v + + printf "\n\tπŸ‹ Installed NPM πŸ‹\t\n" + "${NODEPATH}"/bin/npm -v +done + +case "$(uname -m)" in + 'aarch64') + scripts=( + yq + ) + ;; + 'x86_64') + scripts=( + yq + ) + ;; + 'armv7l') + scripts=( + yq + ) + ;; + *) exit 1 ;; +esac + +for SCRIPT in "${scripts[@]}"; do + printf "\n\t🧨 Executing %s.sh 🧨\t\n" "${SCRIPT}" + bash "/imagegeneration/installers/${SCRIPT}.sh" +done + +printf "\n\tπŸ‹ Cleaning image πŸ‹\t\n" +apt-get clean +rm -rf /var/cache/* /var/log/* /var/lib/apt/lists/* /tmp/* || echo 'Failed to delete directories' + +printf "\n\tπŸ‹ Cleaned up image πŸ‹\t\n" + diff --git a/scripts/yq.sh b/scripts/yq.sh new file mode 100644 index 0000000..5066782 --- /dev/null +++ b/scripts/yq.sh @@ -0,0 +1,78 @@ +#!/bin/bash -e +################################################################################ +## File: yq.sh +## Desc: Installs YQ with checksum validation +################################################################################ +# source: https://github.com/actions/runner-images/blob/5d6938f680075d63fa71f8aa70990866cd12884b/images/linux/scripts/installers/yq.sh + +download_with_retries() { + local URL="$1" + local DEST="${2:-.}" + local NAME="${3:-${URL##*/}}" + echo "Downloading '$URL' to '${DEST}/${NAME}'..." + local retries=20 + local interval=30 + while [ "$retries" -gt 0 ]; do + ((retries--)) || true + if curl -fsSL -o "${DEST}/${NAME}" "$URL"; then + echo "Download completed" + return 0 + fi + echo "Error downloading. Waiting ${interval}s before retry, ${retries} attempts left" + sleep "$interval" + done + echo "Could not download $URL" + return 1 +} + +get_hash_from_remote_file() { + local url=$1 + local keywords=("$2" "$3") + local delimiter=${4:-' '} + local word_number=${5:-1} + local matching_line + matching_line=$(curl -fsSL "$url" | sed 's/ */ /g' | tr -d '`') + for keyword in "${keywords[@]}"; do + matching_line=$(echo "$matching_line" | grep "$keyword" || true) + done + matching_line=$(echo "$matching_line" | head -n1) + if [ -z "$matching_line" ]; then + echo "Keywords (${keywords[*]}) not found in the file with hashes." >&2 + exit 1 + fi + echo "$matching_line" | cut -d "$delimiter" -f "$word_number" | tr -d -c '[:alnum:]' +} + +use_checksum_comparison() { + local file_path=$1 + local checksum=$2 + local sha_type=${3:-256} + local local_file_hash + echo "Performing checksum verification" + if [ ! -f "$file_path" ]; then + echo "File not found: $file_path" >&2 + exit 1 + fi + local_file_hash=$(shasum -a "$sha_type" "$file_path" | awk '{print $1}') + if [ "$local_file_hash" != "$checksum" ]; then + echo "Checksum verification failed. Expected: $checksum; Actual: $local_file_hash." >&2 + exit 1 + fi + echo "Checksum verification passed" +} + +yq_arch() { + case "$(uname -m)" in + 'aarch64') echo 'arm64' ;; + 'x86_64') echo 'amd64' ;; + 'armv7l') echo 'arm' ;; + *) exit 1 ;; + esac +} + +base_url="https://github.com/mikefarah/yq/releases/latest/download" +filename="yq_linux_$(yq_arch)" +download_with_retries "${base_url}/${filename}" "/tmp" "yq" +external_hash=$(get_hash_from_remote_file "${base_url}/checksums" "${filename} " "" " " "19") +use_checksum_comparison "/tmp/yq" "${external_hash}" +sudo install /tmp/yq /usr/bin/yq