Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 62 additions & 2 deletions .config/mise/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,69 @@ case "$(uname -m)" in
esac

tarball="mise-v${MISE_VERSION}-linux-${arch}.tar.gz"
base_url="https://github.com/jdx/mise/releases/download/v${MISE_VERSION}"

# curl needs the header passed explicitly, and plain `-L` drops it on a cross-host redirect.
curl_auth=()
github_token="${MISE_GITHUB_TOKEN:-${GITHUB_TOKEN:-}}"
if [[ -n ${github_token} ]]; then
curl_auth=(--header "Authorization: Bearer ${github_token}")
fi

# Downloads $1 to $2. `--fail` is deliberately omitted so that the response body
# survives to be printed: a bare `curl: (22)` explains nothing about why a build broke.
# `--retry-max-time` bounds the series: curl prefers a server `Retry-After`, and GitHub sends 60.
fetch() {
local url=$1 output=$2
local headers="${output}.headers"
local status=000 curl_status=0

status=$(
curl -sS -L \
--retry 5 --retry-all-errors --retry-delay 2 --retry-max-time 60 \
--connect-timeout 10 --max-time 300 \
${curl_auth[@]+"${curl_auth[@]}"} \
--dump-header "${headers}" \
--write-out '%{http_code}' \
--output "${output}" \
"${url}"
) || curl_status=$?

if [[ ${curl_status} -ne 0 || ${status} -lt 200 || ${status} -ge 300 ]]; then
{
echo "error: failed to download ${url}"
echo " curl exit code: ${curl_status}"
echo " http status: ${status}"
# `--dump-header` appends, so keep only the headers following the last status line.
awk '
/^[Hh][Tt][Tt][Pp]\// { count = 0; next }
tolower($0) ~ /^(retry-after|x-ratelimit-[a-z-]+):/ { header[++count] = $0 }
END { for (i = 1; i <= count; i++) print header[i] }
' "${headers}" 2> /dev/null | tr -d '\r' | sed 's/^/ /' || true
echo " response body (first 2000 bytes):"
head -c 2000 "${output}" 2> /dev/null | tr -d '\r' | tr -c '[:print:]\n\t' '.' | sed 's/^/ /'
echo
} >&2
return 1
fi
}

cd "$(mktemp -d)"
curl -fsSL -O "https://github.com/jdx/mise/releases/download/v${MISE_VERSION}/${tarball}"
curl -fsSL "https://github.com/jdx/mise/releases/download/v${MISE_VERSION}/SHASUMS256.txt" | grep " \./${tarball}$" | sha256sum -c -

fetch "${base_url}/${tarball}" "${tarball}"
fetch "${base_url}/SHASUMS256.txt" SHASUMS256.txt

# Extract the entry first, so a bad response is reported as such and not as a parse failure.
if ! grep -E "^[0-9a-f]{64} (\./)?${tarball}$" SHASUMS256.txt > "${tarball}.sha256"; then
{
echo "error: no checksum entry for ${tarball} in ${base_url}/SHASUMS256.txt"
echo " received (first 2000 bytes):"
head -c 2000 SHASUMS256.txt | tr -d '\r' | tr -c '[:print:]\n\t' '.' | sed 's/^/ /'
echo
} >&2
exit 1
fi

sha256sum -c "${tarball}.sha256"
tar --no-same-owner --strip-components=2 -C /usr/local/bin -xzf "${tarball}" mise/bin/mise
rm "${tarball}"
27 changes: 27 additions & 0 deletions .github/actions/install-tools/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,12 @@ runs:
using: composite

steps:
# `mise install` builds the Rust toolchain by shelling out to `rustup`, so mise's own
# `http_retries` does not cover that download. Non-fatal here, retried below.
- name: Run `mise install` with `ci` environment
id: mise-install
uses: jdx/mise-action@146a28175021df8ca24f8ee1828cc2a60f980bd5 # v3.5.1
continue-on-error: true
with:
# renovate: datasource=github-releases depName=jdx/mise
version: 2026.7.14
Expand All @@ -32,6 +36,29 @@ runs:
MISE_VERBOSE: 1
GITHUB_TOKEN: ${{ inputs.token }}

# Without `mise` on `PATH` there is no install to retry, only five minutes of `not found`.
- name: Fail fast if `mise` itself is missing
if: ${{ steps.mise-install.outcome != 'success' }}
shell: bash
run: |
command -v mise > /dev/null || {
echo "::error::mise is not on PATH: jdx/mise-action failed during its own setup, so there is no install to retry"
exit 1
}

# Skipped on the happy path; `!= 'success'` so an unresolved `outcome` retries too.
- name: Retry `mise install` if it failed
if: ${{ steps.mise-install.outcome != 'success' }}
uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3.0.2
with:
timeout_minutes: 20
max_attempts: 5
retry_wait_seconds: 60
command: mise install --env ci --jobs 1 --locked
env:
MISE_VERBOSE: 1
GITHUB_TOKEN: ${{ inputs.token }}

- name: Install package manager via corepack
uses: $/.github/actions/install-corepack

Expand Down
Loading