diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 16bae3cc..331e9146 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -63,22 +63,22 @@ stages: # Fast, lightweight gate: shellcheck + shfmt over the shell scripts. # Runs first so a lint failure stops the pipeline before the multi-hour builds. -# Uses a minimal Alpine image (both tools are in Alpine's community repo) and is -# NOT namespace-gated, so it also runs for forks / contributor pipelines. +# Uses a minimal image and is NOT namespace-gated, so it also runs for forks / contributor pipelines. lint-scripts: - image: alpine:3.21 + image: fedora:43 stage: lint rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" - if: $CI_COMMIT_BRANCH before_script: - - apk add --no-cache bash git shellcheck shfmt - # Print tool versions so any local-vs-CI skew (e.g. default-check changes - # between shellcheck releases) is visible in the logs. - - shellcheck --version - - shfmt --version + - set -euo pipefail + - /bin/sudo /bin/dnf update -y --refresh + - /bin/sudo /bin/dnf install -y bash curl + - /bin/bash scripts/get_sources.sh shellcheck + - /bin/bash scripts/get_sources.sh shfmt script: - - bash scripts/lint.sh + - set -euo pipefail + - /bin/bash scripts/lint.sh update-fdroid-repo: image: fedora:43 @@ -98,6 +98,7 @@ update-fdroid-repo: REPO_DIR_PATH: "./fdroid/repo" <<: *build_variables before_script: + - set -euo pipefail - sudo dnf update -y --refresh - sudo dnf install -y bash curl git git-lfs jq make - git config --global user.email "${IF_CI_EMAIL}" @@ -134,6 +135,7 @@ update-site-repo: TARGET_REPO_BRANCH: dev <<: *build_variables before_script: + - set -euo pipefail - sudo dnf update -y --refresh - sudo dnf install -y bash curl git make yq - git config --global user.email "${IF_CI_EMAIL}" @@ -298,6 +300,7 @@ prepare-release: variables: <<: *build_variables before_script: + - set -euo pipefail - sudo dnf update -y --refresh - sudo dnf install -y curl jq script: diff --git a/README.md b/README.md index c2f46f5d..cc062389 100644 --- a/README.md +++ b/README.md @@ -181,9 +181,15 @@ In addition to the `AAB`, the `bundle` target also produces APKs for each archit IronFox is largely driven by shell scripts, which are checked with [`shellcheck`](https://www.shellcheck.net/) *(static analysis)* and [`shfmt`](https://github.com/mvdan/sh) *(formatting)*. These run automatically in CI *(the `lint-scripts` job)* and are enforced there — a lint failure stops the pipeline before any build starts. -`./scripts/bootstrap.sh` installs both tools and enables a git pre-commit hook *(via `core.hooksPath`)* that lints your staged scripts before each commit. The hook is a convenience and can be bypassed with `git commit --no-verify`; CI remains the source of truth. +`./scripts/get_sources.sh` installs both tools and enables a git pre-commit hook *(via `core.hooksPath`)* that lints your staged scripts before each commit. The hook is a convenience and can be bypassed with `git commit --no-verify`; CI remains the source of truth. -To run the checks manually: +If you are providing your own copies of `shellcheck` and `shfmt` *(instead of getting them from `./scripts/get_sources.sh`)*, after setting `IRONFOX_SHELLCHECK_DIR` and `IRONFOX_SHFMT_DIR` to the appropriate directories, you can set-up the pre-commit hook directly by running: + +```sh +./scripts/lint-hook.sh +``` + +To run the linting checks manually: ```sh ./scripts/lint.sh diff --git a/scripts/bootstrap.sh b/scripts/bootstrap.sh index 770d995f..2997538d 100755 --- a/scripts/bootstrap.sh +++ b/scripts/bootstrap.sh @@ -86,8 +86,6 @@ if [[ "${IRONFOX_OS}" == 'osx' ]] || [[ "${IRONFOX_OS}" == 'secureblue' ]]; then ninja \ perl \ shasum \ - shellcheck \ - shfmt \ yq || error_fn echo @@ -134,8 +132,6 @@ elif [[ "${IRONFOX_OS}" == 'fedora' ]]; then patch \ perl \ shasum \ - ShellCheck \ - shfmt \ xz \ yq \ zlib-devel || error_fn @@ -161,26 +157,12 @@ elif [[ "${IRONFOX_OS}" == 'ubuntu' ]]; then ninja-build \ patch \ perl \ - shellcheck \ tar \ unzip \ xz-utils \ yq \ zlib1g-dev || error_fn echo - - # shfmt isn't reliably packaged on all Ubuntu releases; fetch the static - # binary if apt didn't provide it. - if ! command -v shfmt > /dev/null 2>&1; then - echo_green_text "Installing shfmt..." - readonly SHFMT_VERSION='v3.13.1' - SHFMT_ARCH="$(dpkg --print-architecture)" - readonly SHFMT_ARCH - sudo curl -fsSL -o /usr/local/bin/shfmt \ - "https://github.com/mvdan/sh/releases/download/${SHFMT_VERSION}/shfmt_${SHFMT_VERSION}_linux_${SHFMT_ARCH}" || error_fn - sudo chmod +x /usr/local/bin/shfmt || error_fn - echo - fi else echo_red_text "Apologies, your operating system is currently not supported." echo_red_text "If you think this is a mistake, please let us know!" @@ -188,11 +170,3 @@ else echo_red_text "Otherwise, please try again on a system running the latest version of Fedora, macOS, secureblue, or Ubuntu." exit 1 fi - -# Enable the pre-commit hook so shell scripts are linted (shellcheck + shfmt) -# before each commit. CI enforces the same checks, so this is just a fast local -# safeguard (and is bypassable with `git commit --no-verify`). -echo_green_text "Configuring git pre-commit hook..." -REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" -git -C "${REPO_ROOT}" config core.hooksPath scripts/git-hooks || error_fn -echo diff --git a/scripts/env.sh b/scripts/env.sh index 86389887..6959d822 100755 --- a/scripts/env.sh +++ b/scripts/env.sh @@ -100,6 +100,8 @@ if [[ -z "${IRONFOX_SET_ENVS+x}" ]]; then "${IRONFOX_LN}" -sf "${IRONFOX_SED}" "${IRONFOX_PATH}/gsed" "${IRONFOX_LN}" -sf "${IRONFOX_SED}" "${IRONFOX_PATH}/sed" "${IRONFOX_LN}" -sf "${IRONFOX_SH}" "${IRONFOX_PATH}/sh" + "${IRONFOX_LN}" -sf "${IRONFOX_SHELLCHECK}" "${IRONFOX_PATH}/shellcheck" + "${IRONFOX_LN}" -sf "${IRONFOX_SHFMT}" "${IRONFOX_PATH}/shfmt" "${IRONFOX_LN}" -sf "${IRONFOX_SHASUM}" "${IRONFOX_PATH}/shasum" "${IRONFOX_LN}" -sf "${IRONFOX_SHA1SUM}" "${IRONFOX_PATH}/sha1sum" "${IRONFOX_LN}" -sf "${IRONFOX_SHA256SUM}" "${IRONFOX_PATH}/sha256sum" diff --git a/scripts/env_common.sh b/scripts/env_common.sh index dcab197f..28fb8aa7 100644 --- a/scripts/env_common.sh +++ b/scripts/env_common.sh @@ -1187,6 +1187,26 @@ fi readonly IRONFOX_SHA512SUM export IRONFOX_SHA512SUM +# -shellcheck +readonly IRONFOX_SHELLCHECK_DIR_DEFAULT="${IRONFOX_EXTERNAL}/shellcheck" +if [[ -z "${IRONFOX_SHELLCHECK_DIR+x}" ]]; then + IRONFOX_SHELLCHECK_DIR="${IRONFOX_SHELLCHECK_DIR_DEFAULT}" +fi +readonly IRONFOX_SHELLCHECK_DIR +readonly IRONFOX_SHELLCHECK="${IRONFOX_SHELLCHECK_DIR}/shellcheck" +export IRONFOX_SHELLCHECK +export IRONFOX_SHELLCHECK_DIR + +# shfmt +readonly IRONFOX_SHFMT_DIR_DEFAULT="${IRONFOX_EXTERNAL}/shfmt" +if [[ -z "${IRONFOX_SHFMT_DIR+x}" ]]; then + IRONFOX_SHFMT_DIR="${IRONFOX_SHFMT_DIR_DEFAULT}" +fi +readonly IRONFOX_SHFMT_DIR +readonly IRONFOX_SHFMT="${IRONFOX_SHFMT_DIR}/shfmt" +export IRONFOX_SHFMT +export IRONFOX_SHFMT_DIR + # sleep readonly IRONFOX_SLEEP_DEFAULT='/bin/sleep' if [[ -z "${IRONFOX_SLEEP+x}" ]]; then diff --git a/scripts/get_sources-if.sh b/scripts/get_sources-if.sh index aa2dd69f..aee2d73b 100755 --- a/scripts/get_sources-if.sh +++ b/scripts/get_sources-if.sh @@ -54,6 +54,8 @@ IRONFOX_GET_SOURCE_PYTHON=0 IRONFOX_GET_SOURCE_PYYAML=0 IRONFOX_GET_SOURCE_RUST=0 IRONFOX_GET_SOURCE_S3CMD=0 +IRONFOX_GET_SOURCE_SHELLCHECK=0 +IRONFOX_GET_SOURCE_SHFMT=0 IRONFOX_GET_SOURCE_UNIFFI=0 IRONFOX_GET_SOURCE_UP_AC=0 IRONFOX_GET_SOURCE_UV=0 @@ -152,6 +154,12 @@ elif [[ "${target}" == 's3cmd' ]]; then # Get s3cmd ## NOTE: This isn't installed if "all" is used below, as it's only used in CI and targeted specifically when it's needed IRONFOX_GET_SOURCE_S3CMD=1 +elif [[ "${target}" == 'shellcheck' ]]; then + # Get shellcheck + IRONFOX_GET_SOURCE_SHELLCHECK=1 +elif [[ "${target}" == 'shfmt' ]]; then + # Get shfmt + IRONFOX_GET_SOURCE_SHFMT=1 elif [[ "${target}" == 'uniffi' ]]; then # Get uniffi IRONFOX_GET_SOURCE_UNIFFI=1 @@ -195,6 +203,14 @@ elif [[ "${target}" == 'all' ]]; then IRONFOX_GET_SOURCE_UP_AC=1 IRONFOX_GET_SOURCE_UV=1 + # CI only uses shellcheck and shfmt in the `lint` stage (where they're retrieved directly) + # If git is missing, we know the user isn't contributing (at least from this repo directly), so we don't need to download them in + # those cases either + if [[ -x "${IRONFOX_GIT}" ]] && [[ "${IRONFOX_CI}" != 1 ]]; then + IRONFOX_GET_SOURCE_SHELLCHECK=1 + IRONFOX_GET_SOURCE_SHFMT=1 + fi + if [[ "${IRONFOX_NO_PREBUILDS}" == 1 ]]; then # If IRONFOX_NO_PREBUILDS is true, we need to get the Prebuilds repo (so that they can be built from source) IRONFOX_GET_SOURCE_PREBUILDS=1 @@ -236,6 +252,8 @@ else echo 'PyYAML: pyyaml' echo 'Rust: rust' echo 's3cmd: s3cmd' + echo 'shellcheck: shellcheck' + echo 'shfmt: shfmt' echo 'UnifiedPush-AC: up-ac' echo 'uniffi-bindgen: uniffi' echo 'uv: uv' @@ -273,6 +291,8 @@ readonly IRONFOX_GET_SOURCE_PYTHON readonly IRONFOX_GET_SOURCE_PYYAML readonly IRONFOX_GET_SOURCE_RUST readonly IRONFOX_GET_SOURCE_S3CMD +readonly IRONFOX_GET_SOURCE_SHELLCHECK +readonly IRONFOX_GET_SOURCE_SHFMT readonly IRONFOX_GET_SOURCE_UNIFFI readonly IRONFOX_GET_SOURCE_UP_AC readonly IRONFOX_GET_SOURCE_UV @@ -1703,6 +1723,124 @@ function get_s3cmd() { fi } +# Get shellcheck +function get_shellcheck() { + if [[ "${IRONFOX_GET_SOURCE_CHECKSUM_UPDATE}" == 1 ]]; then + echo_red_text 'Downloading shellcheck (Linux - ARM64)...' + download "https://github.com/koalaman/shellcheck/releases/download/${IRONFOX_SHELLCHECK_VERSION}/shellcheck-${IRONFOX_SHELLCHECK_VERSION}.linux.aarch64.tar.xz" "${IRONFOX_SHELLCHECK_DIR}" "${IRONFOX_SHELLCHECK_SHA512SUM_LINUX_ARM64}" + + echo_red_text 'Downloading shellcheck (Linux - x86_64)...' + download "https://github.com/koalaman/shellcheck/releases/download/${IRONFOX_SHELLCHECK_VERSION}/shellcheck-${IRONFOX_SHELLCHECK_VERSION}.linux.x86_64.tar.xz" "${IRONFOX_SHELLCHECK_DIR}" "${IRONFOX_SHELLCHECK_SHA512SUM_LINUX_X86_64}" + + echo_red_text 'Downloading shellcheck (OS X - ARM64)...' + download "https://github.com/koalaman/shellcheck/releases/download/${IRONFOX_SHELLCHECK_VERSION}/shellcheck-${IRONFOX_SHELLCHECK_VERSION}.darwin.aarch64.tar.xz" "${IRONFOX_SHELLCHECK_DIR}" "${IRONFOX_SHELLCHECK_SHA512SUM_OSX_ARM64}" + + echo_red_text 'Downloading shellcheck (OS X - x86_64)...' + download "https://github.com/koalaman/shellcheck/releases/download/${IRONFOX_SHELLCHECK_VERSION}/shellcheck-${IRONFOX_SHELLCHECK_VERSION}.darwin.x86_64.tar.xz" "${IRONFOX_SHELLCHECK_DIR}" "${IRONFOX_SHELLCHECK_SHA512SUM_OSX_X86_64}" + else + # Set our platform + if [[ "${IRONFOX_PLATFORM}" == 'darwin' ]]; then + local -r IRONFOX_SHELLCHECK_PLATFORM='darwin' + else + local -r IRONFOX_SHELLCHECK_PLATFORM='linux' + fi + + # Set our platform architecture + if [[ "${IRONFOX_PLATFORM_ARCH}" == 'aarch64' ]]; then + local -r IRONFOX_SHELLCHECK_ARCH='aarch64' + else + local -r IRONFOX_SHELLCHECK_ARCH='x86_64' + fi + + # Set our checksum to verify + if [[ "${IRONFOX_PLATFORM_ARCH}" == 'aarch64' ]]; then + if [[ "${IRONFOX_PLATFORM}" == 'darwin' ]]; then + local -r IRONFOX_SHELLCHECK_SHA512SUM="${IRONFOX_SHELLCHECK_SHA512SUM_OSX_ARM64}" + else + local -r IRONFOX_SHELLCHECK_SHA512SUM="${IRONFOX_SHELLCHECK_SHA512SUM_LINUX_ARM64}" + fi + else + if [[ "${IRONFOX_PLATFORM}" == 'darwin' ]]; then + local -r IRONFOX_SHELLCHECK_SHA512SUM="${IRONFOX_SHELLCHECK_SHA512SUM_OSX_X86_64}" + else + local -r IRONFOX_SHELLCHECK_SHA512SUM="${IRONFOX_SHELLCHECK_SHA512SUM_LINUX_X86_64}" + fi + fi + + echo_red_text 'Downloading shellcheck...' + download_and_extract 'shellcheck' "https://github.com/koalaman/shellcheck/releases/download/${IRONFOX_SHELLCHECK_VERSION}/shellcheck-${IRONFOX_SHELLCHECK_VERSION}.${IRONFOX_SHELLCHECK_PLATFORM}.${IRONFOX_SHELLCHECK_ARCH}.tar.xz" "${IRONFOX_SHELLCHECK_DIR}" "${IRONFOX_SHELLCHECK_SHA512SUM}" + + if [[ "${IRONFOX_PERFORM_POST_DOWNLOAD}" == 1 ]]; then + # Set-up the linting pre-commit hook + if [[ "${IRONFOX_CI}" != 1 ]] && [[ -x "${IRONFOX_GIT}" ]] && [[ ! -f "${IRONFOX_BUILD}/set-hook" ]]; then + /bin/bash "${IRONFOX_SCRIPTS}/lint-hook.sh" + fi + + echo_green_text "SUCCESS: Set-up shellcheck at ${IRONFOX_SHELLCHECK}" + fi + fi +} + +# Get shfmt +function get_shfmt() { + if [[ "${IRONFOX_GET_SOURCE_CHECKSUM_UPDATE}" == 1 ]]; then + echo_red_text 'Downloading shfmt (Linux - ARM64)...' + download "https://github.com/mvdan/sh/releases/download/${IRONFOX_SHFMT_VERSION}/shfmt_${IRONFOX_SHFMT_VERSION}_linux_arm64" "${IRONFOX_SHFMT}" "${IRONFOX_SHFMT_SHA512SUM_LINUX_ARM64}" + + echo_red_text 'Downloading shfmt (Linux - x86_64)...' + download "https://github.com/mvdan/sh/releases/download/${IRONFOX_SHFMT_VERSION}/shfmt_${IRONFOX_SHFMT_VERSION}_linux_amd64" "${IRONFOX_SHFMT}" "${IRONFOX_SHFMT_SHA512SUM_LINUX_X86_64}" + + echo_red_text 'Downloading shfmt (OS X - ARM64)...' + download "https://github.com/mvdan/sh/releases/download/${IRONFOX_SHFMT_VERSION}/shfmt_${IRONFOX_SHFMT_VERSION}_darwin_arm64" "${IRONFOX_SHFMT}" "${IRONFOX_SHFMT_SHA512SUM_OSX_ARM64}" + + echo_red_text 'Downloading shfmt (OS X - x86_64)...' + download "https://github.com/mvdan/sh/releases/download/${IRONFOX_SHFMT_VERSION}/shfmt_${IRONFOX_SHFMT_VERSION}_darwin_amd64" "${IRONFOX_SHFMT}" "${IRONFOX_SHFMT_SHA512SUM_OSX_X86_64}" + else + # Set our platform + if [[ "${IRONFOX_PLATFORM}" == 'darwin' ]]; then + local -r IRONFOX_SHFMT_PLATFORM='darwin' + else + local -r IRONFOX_SHFMT_PLATFORM='linux' + fi + + # Set our platform architecture + if [[ "${IRONFOX_PLATFORM_ARCH}" == 'aarch64' ]]; then + local -r IRONFOX_SHFMT_ARCH='arm64' + else + local -r IRONFOX_SHFMT_ARCH='amd64' + fi + + # Set our checksum to verify + if [[ "${IRONFOX_PLATFORM_ARCH}" == 'aarch64' ]]; then + if [[ "${IRONFOX_PLATFORM}" == 'darwin' ]]; then + local -r IRONFOX_SHFMT_SHA512SUM="${IRONFOX_SHFMT_SHA512SUM_OSX_ARM64}" + else + local -r IRONFOX_SHFMT_SHA512SUM="${IRONFOX_SHFMT_SHA512SUM_LINUX_ARM64}" + fi + else + if [[ "${IRONFOX_PLATFORM}" == 'darwin' ]]; then + local -r IRONFOX_SHFMT_SHA512SUM="${IRONFOX_SHFMT_SHA512SUM_OSX_X86_64}" + else + local -r IRONFOX_SHFMT_SHA512SUM="${IRONFOX_SHFMT_SHA512SUM_LINUX_X86_64}" + fi + fi + + echo_red_text 'Downloading shfmt...' + download "https://github.com/mvdan/sh/releases/download/${IRONFOX_SHFMT_VERSION}/shfmt_${IRONFOX_SHFMT_VERSION}_${IRONFOX_SHFMT_PLATFORM}_${IRONFOX_SHFMT_ARCH}" "${IRONFOX_SHFMT}" "${IRONFOX_SHFMT_SHA512SUM}" + + if [[ "${IRONFOX_PERFORM_POST_DOWNLOAD}" == 1 ]]; then + "${IRONFOX_CHMOD}" +x "${IRONFOX_SHFMT}" + + # Set-up the linting pre-commit hook + if [[ "${IRONFOX_CI}" != 1 ]] && [[ -x "${IRONFOX_GIT}" ]] && [[ ! -f "${IRONFOX_BUILD}/set-hook" ]]; then + /bin/bash "${IRONFOX_SCRIPTS}/lint-hook.sh" + fi + + echo_green_text "SUCCESS: Set-up shfmt at ${IRONFOX_SHFMT}" + fi + fi +} + # Get Tor's no-op UniFFi binding generator function get_uniffi() { # Get uniffi-bindgen for Linux @@ -1963,6 +2101,14 @@ if [[ "${IRONFOX_GET_SOURCE_S3CMD}" == 1 ]]; then get_s3cmd fi +if [[ "${IRONFOX_GET_SOURCE_SHELLCHECK}" == 1 ]]; then + get_shellcheck +fi + +if [[ "${IRONFOX_GET_SOURCE_SHFMT}" == 1 ]]; then + get_shfmt +fi + if [[ "${IRONFOX_GET_SOURCE_UNIFFI}" == 1 ]]; then get_uniffi fi diff --git a/scripts/git-hooks/pre-commit b/scripts/git-hooks/pre-commit index 1bdc3014..5665a0b9 100755 --- a/scripts/git-hooks/pre-commit +++ b/scripts/git-hooks/pre-commit @@ -3,7 +3,7 @@ # IronFox pre-commit hook: lints staged shell scripts with shellcheck + shfmt. # # Enabled by pointing git at this directory (done automatically by -# scripts/bootstrap.sh): +# scripts/lint-hook.sh): # git config core.hooksPath scripts/git-hooks # # This is a convenience only. It can be bypassed with `git commit --no-verify`, diff --git a/scripts/lint-hook.sh b/scripts/lint-hook.sh new file mode 100755 index 00000000..c4589b0a --- /dev/null +++ b/scripts/lint-hook.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +# Script to configure a git pre-commit hook for linting + +set -euo pipefail + +# Set-up our environment +if [[ -z "${IRONFOX_SET_ENVS+x}" ]]; then + /bin/bash $(dirname $0)/env.sh +fi +source $(dirname $0)/env.sh + +# Include utilities +source "${IRONFOX_UTILS}" + +# Get our platform, OS, and architecture +source "${IRONFOX_ENV_HELPERS}" + +# Set verbosity +if [[ "${IRONFOX_VERBOSE}" == 1 ]]; then + set -x +else + set +x +fi + +# Check if the hook has already been set-up +if [[ -f "${IRONFOX_BUILD}/set-hook" ]]; then + echo_red_text 'It looks like the git pre-commit hook has already been set-up!' + read -p "Are you sure you want to continue? [y/N] " -n 1 -r + echo + if [[ "${REPLY}" =~ ^[Nn]$ ]]; then + exit 0 + else + "${IRONFOX_RM}" -f "${IRONFOX_BUILD}/set-hook" + fi +fi + +# Enable the pre-commit hook so shell scripts are linted (shellcheck + shfmt) +# before each commit. CI enforces the same checks, so this is just a fast local +# safeguard (and is bypassable with `git commit --no-verify`). +echo_red_text 'Configuring git pre-commit hook...' +"${IRONFOX_GIT}" -C "${IRONFOX_ROOT}" config core.hooksPath scripts/git-hooks +echo_green_text 'SUCCESS: Configured git pre-commit hook' + +# Indicate that the hook has been set-up +"${IRONFOX_MKDIR}" -p "${IRONFOX_BUILD}" +"${IRONFOX_TOUCH}" "${IRONFOX_BUILD}/set-hook" diff --git a/scripts/lint.sh b/scripts/lint.sh index 903483fc..4b8d02c2 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -4,8 +4,7 @@ # (formatting). This is the single source of truth used by CI, the pre-commit # hook, and manual runs. # -# It is intentionally SELF-CONTAINED: it does NOT source env.sh (which performs -# full OS/path bootstrap), so it runs unchanged in a minimal CI container. +# It is intended to run in a minimal CI container. # # Usage: # scripts/lint.sh Lint all tracked shell scripts (CI + manual) @@ -16,10 +15,25 @@ set -euo pipefail +# Set-up our environment +if [[ -z "${IRONFOX_SET_ENVS+x}" ]]; then + /bin/bash $(dirname $0)/env.sh +fi +source $(dirname $0)/env.sh + +# Include utilities +source "${IRONFOX_UTILS}" + +# Set verbosity +if [[ "${IRONFOX_VERBOSE}" == 1 ]]; then + set -x +else + set +x +fi + # Resolve and move to the repo root so relative paths and config discovery # (.shellcheckrc, .editorconfig) work regardless of the caller's cwd. -REPO_ROOT="$(git rev-parse --show-toplevel)" -cd "${REPO_ROOT}" +pushd "${IRONFOX_ROOT}" mode='all' if [[ "${1:-}" == '--staged' ]]; then @@ -32,11 +46,11 @@ declare -a targets=() if [[ "${mode}" == 'staged' ]]; then while IFS= read -r file; do [[ -n "${file}" ]] && targets+=("${file}") - done < <(git diff --cached --name-only --diff-filter=ACM -- 'scripts/*.sh') + done < <("${IRONFOX_GIT}" diff --cached --name-only --diff-filter=ACM -- 'scripts/*.sh') else while IFS= read -r file; do targets+=("${file}") - done < <(git ls-files 'scripts/*.sh') + done < <("${IRONFOX_GIT}" ls-files 'scripts/*.sh') fi if [[ ${#targets[@]} -eq 0 ]]; then @@ -53,19 +67,19 @@ for tool in shellcheck shfmt; do fi done if [[ "${missing}" -ne 0 ]]; then - echo 'lint: install the missing tool(s) (e.g. run scripts/bootstrap.sh) and retry.' >&2 + echo 'lint: install the missing tool(s) (e.g. run scripts/get_sources.sh shellcheck and scripts/get_sources.sh shfmt) and retry.' >&2 exit 127 fi status=0 echo "lint: shellcheck (${#targets[@]} file(s))..." -if ! shellcheck -x "${targets[@]}"; then +if ! "${IRONFOX_SHELLCHECK}" -x "${targets[@]}"; then status=1 fi echo 'lint: shfmt formatting check...' -if ! shfmt -d "${targets[@]}"; then +if ! "${IRONFOX_SHFMT}" -d "${targets[@]}"; then echo >&2 echo "lint: formatting issues found above. Fix with:" >&2 echo " git ls-files 'scripts/*.sh' | xargs shfmt -w" >&2 @@ -77,4 +91,7 @@ if [[ "${status}" -eq 0 ]]; then else echo 'lint: FAILED' >&2 fi + +popd + exit "${status}" diff --git a/scripts/versions.sh b/scripts/versions.sh index 39b7e0e2..b3c1f255 100644 --- a/scripts/versions.sh +++ b/scripts/versions.sh @@ -238,6 +238,24 @@ readonly IRONFOX_RUSTUP_VERSION='1.29.0' readonly IRONFOX_S3CMD_COMMIT='cee84f9c539a7bbf5ee73c7bf29a47632119c0c6' readonly IRONFOX_S3CMD_SHA512SUM='b1b7c792265dfa1ccdd40f816e3463617c168e4317acac930b251ce73fcd3b8eb479d966d4ba93fbe8c0cf251bada64bcd9caf30d1e5e94c20a87a36447c1263' +# -shellcheck +# Version: v0.11.0 +# https://github.com/koalaman/shellcheck +readonly IRONFOX_SHELLCHECK_SHA512SUM_LINUX_ARM64='de5e49175861ce567b98ec7ae0dd25f679c169d15b015bbad8f92ca22d07bb17c0fb906f7d80857e8450945f6a185d4de45e5883514e9aeb3cc155306060225e' +readonly IRONFOX_SHELLCHECK_SHA512SUM_LINUX_X86_64='25df28923d7d89cfdb9fa8aeef762a887f2bd4ebfbcd43ae71068c60e9458d66250b0f8d6fd66b4bc03723e6cdd47983c547e3ab4f3ea2cbc4bc4028842cc7b9' +readonly IRONFOX_SHELLCHECK_SHA512SUM_OSX_ARM64='d55817cd8d650f79ec5f163912bd9b05fc39cc1dfb2d0df93bd96ca90f204f0639c93fcfdf1990cf02b7b91bfca6f679ab50ce6b50816a0b76af108547103f35' +readonly IRONFOX_SHELLCHECK_SHA512SUM_OSX_X86_64='bf8e53f361e52fb9a368e4b75365b39940b620b76fc008ea94aec905f177a897013386902021523b62398417af29de2148e2e7c2aa9922831731d7a38b1c159d' +readonly IRONFOX_SHELLCHECK_VERSION='v0.11.0' + +# shfmt +# Version: v3.13.1 +# https://github.com/mvdan/sh +readonly IRONFOX_SHFMT_SHA512SUM_LINUX_ARM64='42bb4b842cdb7413336d797346e5c5ad202a3594c2f6313e4ffc82e9bce555771907d759667bdbe974c8b64b709c9e75051e77ac8cc1a870c8e00ee93df8c2a0' +readonly IRONFOX_SHFMT_SHA512SUM_LINUX_X86_64='c5a7fa05d4cbfe52322f758b925014e88e8eef269c2b69e20e31426eab3e92c88161822dbe334b2c843f68d612b38958cac0785b16ef1477679958a9dcdfb291' +readonly IRONFOX_SHFMT_SHA512SUM_OSX_ARM64='7dd7d98058d96f23dd183f8550c28d7039fb190e7d7eae758f4ca1c6903920640f67c2cdd627de918e7b74e878c2d0f7a2cbd1df8f26d12497f4c14bcdf6f927' +readonly IRONFOX_SHFMT_SHA512SUM_OSX_X86_64='35fe1c980157573923d96844eb0b1b42976dd484a878606874f091cc861aa5bc76dfa67e96f5db3ff6a6f7a0257a3fe33e0aee0c8ae75e5f2dcaad0def48c574' +readonly IRONFOX_SHFMT_VERSION='v3.13.1' + # uv # Version: 0.12.1 # https://github.com/astral-sh/uv