Compare commits

...

56 Commits

Author SHA1 Message Date
Taiki Endo
e9e8e031bc Release 2.70.2 2026-03-30 01:34:03 +00:00
Taiki Endo
f225969a9e Update vacuum@latest to 0.25.3 2026-03-30 00:57:06 +00:00
Taiki Endo
2e8700ad0b Update tombi@latest to 0.9.11 2026-03-29 19:25:13 +00:00
Taiki Endo
41213fbc0e zizmor: Apply more lints 2026-03-30 01:56:27 +09:00
Taiki Endo
fd0f63e180 Release 2.70.1 2026-03-29 08:34:38 +00:00
Taiki Endo
7487d4091f Update cargo-insta@latest to 1.47.1 2026-03-29 06:46:40 +00:00
Taiki Endo
ea3bdd400e Update cargo-binstall@latest to 1.17.9 2026-03-29 06:46:40 +00:00
Taiki Endo
7d31177690 ci: Test ubuntu 26.04 container 2026-03-29 12:55:04 +09:00
Taiki Endo
b933e429e1 Update tombi@latest to 0.9.10 2026-03-28 21:25:56 +00:00
Taiki Endo
3eeb0f944d tools: Update tidy.sh 2026-03-29 02:56:38 +09:00
Taiki Endo
0fde6d128a Release 2.70.0 2026-03-28 16:26:52 +00:00
Taiki Endo
6abbc18f77 Install uv, uvw, and uvx binaries when installing uv 2026-03-29 01:20:06 +09:00
Taiki Endo
cd20062255 ci: Update config 2026-03-29 00:12:26 +09:00
Taiki Endo
a164de717a Release 2.69.14 2026-03-28 05:53:56 +00:00
Taiki Endo
cd919aa8c5 Update just@latest to 1.48.1 2026-03-28 05:43:54 +00:00
Taiki Endo
8f41066dca Update wasm-bindgen@latest to 0.2.115 2026-03-28 00:50:38 +00:00
Taiki Endo
704f92c11d Release 2.69.13 2026-03-27 14:39:03 +00:00
Taiki Endo
38b59bc959 ci: Fix release workflow 2026-03-27 23:22:50 +09:00
Taiki Endo
a20bdf712d Update mise@latest to 2026.3.17 2026-03-27 12:35:37 +00:00
Taiki Endo
cc73724b43 Update cargo-insta@latest to 1.47.0 2026-03-27 01:51:56 +00:00
Taiki Endo
80a23c5ba9 Release 2.69.12 2026-03-27 01:37:17 +00:00
Taiki Endo
5c17a3192f Update uv@latest to 0.11.2 2026-03-27 00:57:43 +00:00
Taiki Endo
4bb73acd2d ci: Fix release workflow 2026-03-27 02:22:49 +09:00
Taiki Endo
80779d0b81 Release 2.69.11 2026-03-26 17:17:31 +00:00
Taiki Endo
a69eea0c9b ci: Update to new release workflow 2026-03-27 02:00:56 +09:00
Taiki Endo
0ce9fed251 Update dprint@latest to 0.53.1 2026-03-26 16:00:50 +00:00
Taiki Endo
c0f7516d26 Update mise@latest to 2026.3.16 2026-03-26 12:39:38 +00:00
Taiki Endo
7627fb428e Release 2.69.10 2026-03-26 00:57:12 +09:00
Taiki Endo
5f2d29f673 Update biome@latest to 2.4.9 2026-03-25 15:46:32 +00:00
Taiki Endo
3bf59f7ecc Update mise@latest to 2026.3.15 2026-03-25 12:39:05 +00:00
Taiki Endo
328a871ad8 Release 2.69.9 2026-03-25 10:30:39 +09:00
Taiki Endo
b8df13537a Update uv@latest to 0.11.1 2026-03-25 00:56:46 +00:00
Taiki Endo
09ab1d9849 Update osv-scanner@latest to 2.3.5 2026-03-25 00:56:46 +00:00
Taiki Endo
4168e018ba Update mise@latest to 2026.3.14 2026-03-25 00:56:46 +00:00
Taiki Endo
7bc99eee1f Release 2.69.8 2026-03-24 20:57:21 +09:00
♫ Christian Krause ♫
b3b4c93c56 Fix error message grammar (#1616) 2026-03-24 20:17:45 +09:00
Taiki Endo
1558ceeaae Update just@latest to 1.48.0 2026-03-24 05:35:50 +00:00
Taiki Endo
26d156ba84 Update uv@latest to 0.11.0 2026-03-24 00:47:22 +00:00
Taiki Endo
f2b7c0747d Update rclone@latest to 1.73.3 2026-03-24 00:47:22 +00:00
Taiki Endo
cc168bc1a8 Update mise@latest to 2026.3.13 2026-03-23 15:41:14 +00:00
Taiki Endo
0d865d5cc6 Release 2.69.7 2026-03-23 23:19:45 +09:00
Taiki Endo
78e479f933 Update prek@latest to 0.3.8 2026-03-23 13:47:38 +00:00
Taiki Endo
3da8dc3058 Update cspell dictionary 2026-03-23 22:31:39 +09:00
Taiki Endo
dcad28ece2 Update mise@latest to 2026.3.12 2026-03-23 00:55:49 +00:00
Taiki Endo
2c637c3acd Remove duplicated retry 2026-03-22 22:21:56 +09:00
Taiki Endo
ef1e8ec3f0 ci: Update config 2026-03-22 22:20:46 +09:00
Taiki Endo
0673e7604e Update cargo-valgrind@latest to 2.4.1 2026-03-22 12:28:36 +00:00
Taiki Endo
06203676c6 Release 2.69.6 2026-03-22 02:50:18 +09:00
Taiki Endo
c35d18270e Support signature verification for mise and syft 2026-03-22 01:51:55 +09:00
Taiki Endo
525387f706 codegen: Clean up error handling and move some checks to appropriate
place

Unless error handling is done in particular care, in private tools this
approach tends to make debugging easier when failed.
2026-03-22 00:24:42 +09:00
Taiki Endo
7a6eff0bac Update cargo-binstall@latest to 1.17.8 2026-03-21 09:24:46 +00:00
Taiki Endo
458413b553 Update tombi@latest to 0.9.9 2026-03-21 05:38:52 +00:00
Taiki Endo
b988c18e3d Release 2.69.5 2026-03-21 12:38:29 +09:00
Taiki Endo
5fe6797db0 Update cargo-nextest@latest to 0.9.132 2026-03-21 00:46:56 +00:00
Taiki Endo
a7e592b247 Release 2.69.4 2026-03-21 06:23:44 +09:00
Taiki Endo
a4d6c73c76 manifest-schema: Update changelog 2026-03-21 06:19:53 +09:00
34 changed files with 1734 additions and 449 deletions

View File

@@ -20,6 +20,7 @@ libicu
linkcheck
mdbook
microdnf
minisig
mirrorlist
nextest
pluginconf
@@ -30,6 +31,9 @@ rclone
rdme
rootfs
sccache
SHASUMS
shortstat
sigstore
syft
tombi
udeps

View File

@@ -1,6 +1,6 @@
version: 2
updates:
- package-ecosystem: cargo
- package-ecosystem: cargo # zizmor: ignore[dependabot-cooldown] # Unless dependencies are pinned/locked, the effect is limited.
directory: /
schedule:
interval: daily
@@ -14,6 +14,8 @@ updates:
directory: /
schedule:
interval: daily
cooldown:
default-days: 7
commit-message:
prefix: ''
labels: []

View File

@@ -11,7 +11,7 @@ on:
- dev
- ci-*
schedule:
- cron: '0 0 * * *'
- cron: '0 2 * * *'
workflow_dispatch:
env:
@@ -51,7 +51,8 @@ jobs:
contents: write # for creating branch for pr
pull-requests: write # unused (used in `codegen-automerge: true` case)
security-events: write # for github/codeql-action/*
secrets: inherit
secrets:
PR_TOKEN_APP_PRIVATE_KEY: ${{ secrets.PR_TOKEN_APP_PRIVATE_KEY }}
test:
strategy:
@@ -99,7 +100,11 @@ jobs:
- run: rm -- Cargo.toml
- name: Generate tool list
id: tool-list
run: tools/ci/tool-list.sh "${{ matrix.tool }}" "${{ matrix.os }}" "${{ matrix.bash }}" >>"${GITHUB_OUTPUT}"
run: tools/ci/tool-list.sh "${TOOL}" "${OS}" "${BASH}" >>"${GITHUB_OUTPUT}"
env:
TOOL: ${{ matrix.tool }}
OS: ${{ matrix.os }}
BASH: ${{ matrix.bash }}
- run: |
printf '%s\n' 'C:\msys64\mingw32\bin' >>"${GITHUB_PATH}"
printf '%s\n' 'C:\msys64\usr\bin' >>"${GITHUB_PATH}"
@@ -155,7 +160,7 @@ jobs:
- run: env
- uses: ./
with:
# NB: Update alias list in tools/publish.rs, case for aliases in main.sh,
# NB: Update alias list in release.yml, case for aliases in main.sh,
# and match for alias for tools/codegen/src/tools-markdown.rs.
tool: |
nextest
@@ -215,6 +220,7 @@ jobs:
- ubuntu:20.04 # glibc 2.31
- ubuntu:22.04 # glibc 2.35
- ubuntu:24.04 # glibc 2.39
- ubuntu:26.04 # glibc 2.42
- debian:9-slim # glibc 2.24
- debian:10-slim # glibc 2.28
- debian:11-slim # glibc 2.31
@@ -263,7 +269,7 @@ jobs:
sed -i /etc/yum.repos.d/*.repo -e 's!^mirrorlist!#mirrorlist!' \
-e 's!^#baseurl=http://mirror.centos.org/!baseurl=https://vault.centos.org/!'
sed -i 's/enabled=1/enabled=0/' /etc/yum/pluginconf.d/fastestmirror.conf
if [[ "${{ matrix.container }}" == "centos:6" ]]; then
if [[ "${CONTAINER}" == "centos:6" ]]; then
# CentOS 6's curl (7.19.7) has no curl has no --proto/--tlsv1.2.
yum install -y gcc openssl-devel
curl -fsSL --retry 10 https://curl.se/download/curl-7.34.0.tar.gz | tar xzf -
@@ -277,13 +283,17 @@ jobs:
https://vault.ius.io/el6/x86_64/packages/p/perl-Git18-1.8.5.5-4.ius.el6.noarch.rpm \
https://vault.ius.io/el6/x86_64/packages/g/git18-1.8.5.5-4.ius.el6.x86_64.rpm
fi
env:
CONTAINER: ${{ matrix.container }}
if: startsWith(matrix.container, 'centos')
- uses: taiki-e/checkout-action@v1
# cross attempts to install rust-src when Cargo.toml is available even if `cross --version`
- run: rm -- Cargo.toml
- name: Generate tool list
id: tool-list
run: tools/ci/tool-list.sh "" "${{ matrix.container }}" >>"${GITHUB_OUTPUT}"
run: tools/ci/tool-list.sh "" "${CONTAINER}" >>"${GITHUB_OUTPUT}"
env:
CONTAINER: ${{ matrix.container }}
# remove bash installed by checkout-action
- run: apk --no-cache del bash
shell: sh

View File

@@ -37,7 +37,8 @@ jobs:
permissions:
contents: write # for creating branch for pr
pull-requests: write # for gh pr review --approve
secrets: inherit
secrets:
PR_TOKEN_APP_PRIVATE_KEY: ${{ secrets.PR_TOKEN_APP_PRIVATE_KEY }}
with:
script: tools/manifest.sh
commit-script: tools/ci/manifest.sh

View File

@@ -4,18 +4,212 @@ permissions:
contents: read
on:
push:
tags:
- v[0-9]+.[0-9]+.*
- install-action-manifest-schema-[0-9]+.[0-9]+.*
workflow_dispatch:
inputs:
target:
description: Package to be released
required: true
type: choice
options:
- install-action
- install-action-manifest-schema
version:
description: Version to be increased
required: true
type: choice
options:
- patch
- minor
- major
defaults:
run:
shell: bash --noprofile --norc -CeEuxo pipefail {0}
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false
jobs:
create-release:
if: github.repository_owner == 'taiki-e' && !startsWith(github.ref_name, 'install-action-manifest-schema-')
prepare:
if: github.repository_owner == 'taiki-e' && inputs.target == 'install-action'
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: taiki-e/checkout-action@v1
- uses: taiki-e/install-action@v2
with:
tool: parse-changelog
fallback: none
- id: check
run: |
set +x
IFS=$'\n\t'
trap -- 's=$?; printf >&2 "%s\n" "${0##*/}:${LINENO}: \`${BASH_COMMAND}\` exit with ${s}"; exit ${s}' ERR
retry() {
for i in {1..10}; do
if "$@"; then
return 0
else
sleep "${i}"
fi
done
"$@"
}
bail() {
printf '::error::%s\n' "$*"
exit 1
}
normalize_comma_or_space_separated() {
# Normalize whitespace characters into space because it's hard to handle single input contains lines with POSIX sed alone.
local list="${1//[$'\r\n\t']/ }"
if [[ "${list}" == *","* ]]; then
# If a comma is contained, consider it is a comma-separated list.
# Drop leading and trailing whitespaces in each element.
sed -E 's/ *, */,/g; s/^.//' <<<",${list},"
else
# Otherwise, consider it is a whitespace-separated list.
# Convert whitespace characters into comma.
sed -E 's/ +/,/g; s/^.//' <<<" ${list} "
fi
}
if { sed --help 2>&1 || true; } | grep -Eq -e '-i extension'; then
in_place=(-i '')
else
in_place=(-i)
fi
# shellcheck disable=SC2153
version="${VERSION}"
printf '%s\n' "version(input): ${version}"
# shellcheck disable=SC2153
tag_prefix="${TAG_PREFIX}"
printf '%s\n' "tag_prefix: ${tag_prefix}"
# shellcheck disable=SC2153
changelog="${CHANGELOG}"
printf '%s\n' "changelog: ${changelog}"
# Get the current date.
release_date=$(date -u '+%Y-%m-%d')
printf '%s\n' "release-date: ${release_date}"
printf '%s\n' "release-date=${release_date}" >>"${GITHUB_OUTPUT}"
# Get the current revision.
rev=$(git rev-parse HEAD)
printf '%s\n' "rev: ${rev}"
printf '%s\n' "rev=${rev}" >>"${GITHUB_OUTPUT}"
prev_version=$(parse-changelog --title-no-link "${changelog}" | cut -d' ' -f1)
# Determine the new version number and tag name.
case "${version}" in
major | minor | patch)
if [[ ! "${prev_version}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
bail "pre-release/build-metadata"
fi
major="${prev_version%%.*}"
minor_patch="${prev_version#*.}"
minor="${minor_patch%%.*}"
patch="${minor_patch#*.}"
case "${version}" in
major) version="$((major+1)).0.0" ;;
minor) version="${major}.$((minor+1)).0" ;;
patch) version="${major}.${minor}.$((patch+1))" ;;
esac
;;
*) version="${version#v}" ;;
esac
if [[ ! "${version}" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z\.-]+)?(\+[0-9A-Za-z\.-]+)?$ ]]; then
bail "invalid version format '${version}'"
fi
printf '%s\n' "version: ${version}"
printf '%s\n' "version=${version}" >>"${GITHUB_OUTPUT}"
tag="${tag_prefix}${version}"
printf '%s\n' "tag: ${tag}"
printf '%s\n' "tag=${tag}" >>"${GITHUB_OUTPUT}"
# Make sure the same release has not been created in the past.
if gh release view "${tag}" &>/dev/null; then
bail "tag '${tag}' has already been created and pushed"
fi
# Make sure that the release was created from an allowed branch.
if ! git branch | grep -Eq '\* '"${BRANCH}"'$'; then
bail "current branch is not '${BRANCH}'"
fi
changed_paths=()
retry git fetch origin --tags &>/dev/null
tags=$(git --no-pager tag | { grep -E "^${tag_prefix}[0-9]+" || true; })
if [[ -n "${tags}" ]]; then
printf 'has-tags=true\n' >>"${GITHUB_OUTPUT}"
# Make sure the same release does not exist in changelog.
if grep -Eq "^## \\[${version//./\\.}\\]" "${changelog}"; then
bail "release ${version} already exist in ${changelog}"
fi
if grep -Eq "^\\[${version//./\\.}\\]: " "${changelog}"; then
bail "link to ${version} already exist in ${changelog}"
fi
# Update changelog.
changed_paths+=("${changelog}")
remote_url=$(grep -E '^\[Unreleased\]: https://' "${changelog}" | sed -E 's/^\[Unreleased\]: //; s/\.\.\.HEAD$//')
prev_tag="${remote_url#*/compare/}"
remote_url="${remote_url%/compare/*}"
sed -E "${in_place[@]}" \
-e "s/^## \\[Unreleased\\]/## [Unreleased]\\n\\n## [${version}] - ${release_date}/" \
-e "s#^\[Unreleased\]: https://.*#[Unreleased]: ${remote_url}/compare/${tag}...HEAD\\n[${version}]: ${remote_url}/compare/${prev_tag}...${tag}#" "${changelog}"
if ! grep -Eq "^## \\[${version//./\\.}\\] - ${release_date}$" "${changelog}"; then
bail "failed to update ${changelog}"
fi
if ! grep -Eq "^\\[${version//./\\.}\\]: " "${changelog}"; then
bail "failed to update ${changelog}"
fi
else
# Make sure the release exists in changelog.
if ! grep -Eq "^## \\[${version//./\\.}\\] - ${release_date}$" "${changelog}"; then
bail "release ${version} does not exist in ${changelog} or has wrong release date"
fi
if ! grep -Eq "^\\[${version//./\\.}\\]: " "${changelog}"; then
bail "link to ${version} does not exist in ${changelog}"
fi
fi
# Make sure that a valid release note for this version exists.
# https://github.com/taiki-e/parse-changelog
changes=$(parse-changelog "${changelog}" "${version}")
if [[ -z "${changes}" ]]; then
bail "changelog for ${version} has no body"
fi
printf '============== CHANGELOG ==============\n'
printf '%s\n' "${changes}"
printf '=======================================\n'
if [[ -n "${tags}" ]]; then
git -c color.ui=always diff "${changed_paths[@]}"
git add "${changed_paths[@]}"
fi
# Make sure that there is no unintended change.
git add -N .
git -c color.ui=always diff --exit-code
(
set -x
git show HEAD --shortstat
)
env:
VERSION: ${{ inputs.version }}
TAG_PREFIX: v
CHANGELOG: CHANGELOG.md
BRANCH: main
outputs:
has-tags: ${{ steps.check.outputs.has-tags }}
release-date: ${{ steps.check.outputs.release-date }}
rev: ${{ steps.check.outputs.rev }}
tag: ${{ steps.check.outputs.tag }}
version: ${{ steps.check.outputs.version }}
release:
if: github.repository_owner == 'taiki-e' && inputs.target == 'install-action'
needs: prepare
runs-on: ubuntu-latest
timeout-minutes: 60
environment:
@@ -25,23 +219,232 @@ jobs:
contents: write # for taiki-e/create-gh-release-action
steps:
- uses: taiki-e/checkout-action@v1
- uses: taiki-e/install-action@v2
with:
tool: parse-changelog
fallback: none
- name: Create and push release commit and tag
id: push
run: |
set +x
IFS=$'\n\t'
trap -- 's=$?; printf >&2 "%s\n" "${0##*/}:${LINENO}: \`${BASH_COMMAND}\` exit with ${s}"; exit ${s}' ERR
retry() {
for i in {1..10}; do
if "$@"; then
return 0
else
sleep "${i}"
fi
done
"$@"
}
bail() {
printf '::error::%s\n' "$*"
exit 1
}
if { sed --help 2>&1 || true; } | grep -Eq -e '-i extension'; then
in_place=(-i '')
else
in_place=(-i)
fi
git config user.name 'Taiki Endo'
git config user.email 'te316e89@gmail.com'
# shellcheck disable=SC2153
version="${VERSION}"
# shellcheck disable=SC2153
tag="${TAG}"
# shellcheck disable=SC2153
changelog="${CHANGELOG}"
# shellcheck disable=SC2153
release_date="${RELEASE_DATE}"
# Make sure the current revision is same as prepare step.
# --unshallow is necessary to successfully push the
# "releases/${major_version_tag}" branch in the subsequent step.
retry git fetch origin --unshallow &>/dev/null
rev=$(git rev-parse HEAD)
if [[ "${rev}" != "${PREPARE_REV}" ]]; then
bail "revision difference between prepare step"
fi
# Make sure the same release has not been created in the past.
if gh release view "${tag}" &>/dev/null; then
bail "tag '${tag}' has already been created and pushed"
fi
# Make sure that the release was created from an allowed branch.
if ! git branch | grep -Eq '\* '"${BRANCH}"'$'; then
bail "current branch is not '${BRANCH}'"
fi
changed_paths=()
if [[ "${HAS_TAGS}" == "true" ]]; then
# Update changelog.
changed_paths+=("${changelog}")
remote_url=$(grep -E '^\[Unreleased\]: https://' "${changelog}" | sed -E 's/^\[Unreleased\]: //; s/\.\.\.HEAD$//')
prev_tag="${remote_url#*/compare/}"
remote_url="${remote_url%/compare/*}"
sed -E "${in_place[@]}" \
-e "s/^## \\[Unreleased\\]/## [Unreleased]\\n\\n## [${version}] - ${release_date}/" \
-e "s#^\[Unreleased\]: https://.*#[Unreleased]: ${remote_url}/compare/${tag}...HEAD\\n[${version}]: ${remote_url}/compare/${prev_tag}...${tag}#" "${changelog}"
if ! grep -Eq "^## \\[${version//./\\.}\\] - ${release_date}$" "${changelog}"; then
bail "failed to update ${changelog}"
fi
if ! grep -Eq "^\\[${version//./\\.}\\]: " "${changelog}"; then
bail "failed to update ${changelog}"
fi
fi
changes=$(parse-changelog "${changelog}" "${version}")
printf '============== CHANGELOG ==============\n'
printf '%s\n' "${changes}"
printf '=======================================\n'
if [[ "${HAS_TAGS}" == "true" ]]; then
# Create a release commit.
(
set -x
git add "${changed_paths[@]}"
git commit -m "Release ${version}"
)
fi
prev_credential_helper=$(git config get --global credential.helper || true)
if [[ -n "${prev_credential_helper}" ]]; then
printf 'credential helper is already set (%s)\n' "${prev_credential_helper}"
else
(
set -x
git config --global credential.helper store
)
protocol="${GITHUB_SERVER_URL%%://*}"
hostname="${GITHUB_SERVER_URL#*://}"
printf '%s\n' "${protocol}://${GITHUB_ACTOR}:${PUSH_TOKEN}@${hostname}" >~/.git-credentials
# Remove credential helper config on exit.
trap -- '(set -x; rm -f -- ~/.git-credentials; git config --global --unset credential.helper || true)' EXIT
fi
(
set -x
git tag "${tag}"
retry git push origin HEAD
major_version_tag="v${version%%.*}"
git branch "releases/${major_version_tag}"
git tag -f "${major_version_tag}"
refs=("refs/tags/${tag}" "refs/heads/releases/${major_version_tag}" "+refs/tags/${major_version_tag}")
tools=()
for tool in tools/codegen/base/*.json; do
tool="${tool##*/}"
tools+=("${tool%.*}")
done
# Aliases.
# NB: Update case for aliases in main.sh, tool input option in test-alias job
# in .github/workflows/ci.yml, and match for alias for tools/codegen/src/tools-markdown.rs.
tools+=(
nextest
taplo-cli
typos-cli
wasm-bindgen-cli
wasmtime-cli
)
# Non-manifest-based tools.
tools+=(valgrind)
branches=()
for tool in "${tools[@]}"; do
git checkout -b "releases/${tool}"
sed -E "${in_place[@]}" action.yml \
-e "s/required: true/required: false/g" \
-e "s/# default: #publish:tool/default: ${tool}/g"
git add action.yml
git commit -m "${tool}"
git tag -f "${tool}"
git checkout refs/tags/"${tag}"
refs+=("+refs/heads/releases/${tool}" "+refs/tags/${tool}")
branches+=("releases/${tool}")
done
retry git push origin --atomic "${refs[@]}"
git branch -d "releases/${major_version_tag}"
git branch -D "${branches[@]}"
schema_workspace=/tmp/workspace
rm -rf -- "${schema_workspace}"
# Checkout manifest-schema branch
schema_version="$(cargo metadata --format-version=1 --no-deps | jq -r '.packages[] | select(.name == "install-action-manifest-schema") | .version')"
if [[ "${schema_version}" == "0."* ]]; then
schema_version="0.$(cut -d. -f2 <<<"${schema_version}")"
else
schema_version="$(cut -d. -f1 <<<"${schema_version}")"
fi
schema_branch="manifest-schema-${schema_version}"
git worktree add --force "${schema_workspace}"
(
cd -- "${schema_workspace}"
if git fetch origin "${schema_branch}"; then
git checkout "origin/${schema_branch}" -B "${schema_branch}"
elif ! git checkout "${schema_branch}"; then
# New branch with no history. Credit: https://stackoverflow.com/a/13969482
git checkout --orphan "${schema_branch}"
git rm -rf -- . || true
git commit -m 'Initial commit' --allow-empty
fi
)
# Copy over schema
cp -- ./manifests/* "${schema_workspace}"
(
cd -- "${schema_workspace}"
# Stage changes
git add .
# Detect changes, then commit and push if changes exist
if [[ "$(git status --porcelain=v1 | LC_ALL=C wc -l)" != "0" ]]; then
git commit -m 'Update manifest schema'
retry git push origin HEAD
fi
)
rm -rf -- "${schema_workspace}"
git worktree prune
# TODO: get branch in schema_workspace dir instead
git branch -D "${schema_branch}" "${schema_workspace##*/}"
)
env:
VERSION: ${{ needs.prepare.outputs.version }}
RELEASE_DATE: ${{ needs.prepare.outputs.release-date }}
HAS_TAGS: ${{ needs.prepare.outputs.has-tags }}
TAG: ${{ needs.prepare.outputs.tag }}
CHANGELOG: CHANGELOG.md
BRANCH: main
PREPARE_REV: ${{ needs.prepare.outputs.rev }}
# Note that if we use secrets.GITHUB_TOKEN, the pushed commit/tag cannot trigger other workflows.
PUSH_TOKEN: ${{ secrets.PUSH_TOKEN }}
- uses: taiki-e/create-gh-release-action@v1
with:
changelog: CHANGELOG.md
title: $version
branch: 'main|v[0-9]+'
branch: main
token: ${{ secrets.GITHUB_TOKEN }}
ref: refs/tags/${{ needs.prepare.outputs.tag }}
create-release-manifest-schema:
if: github.repository_owner == 'taiki-e' && startsWith(github.ref_name, 'install-action-manifest-schema-')
# TODO: use new rust-release workflow
uses: taiki-e/github-actions/.github/workflows/create-release.yml@853cebf868aa2dce1470668df24176803e05adc8
release-manifest-schema:
if: github.repository_owner == 'taiki-e' && inputs.target == 'install-action-manifest-schema'
uses: taiki-e/github-actions/.github/workflows/rust-release.yml@main
permissions:
contents: write # for taiki-e/create-gh-release-action
id-token: write # for rust-lang/crates-io-auth-action
attestations: write # unused (used when options for uploading binaries are set)
secrets:
PUSH_TOKEN: ${{ secrets.PUSH_TOKEN }}
with:
version: ${{ inputs.version }}
tag-prefix: install-action-manifest-schema-
crates: tools/manifest-schema
changelog: tools/manifest-schema/CHANGELOG.md
title: $prefix $version
prefix: install-action-manifest-schema
permissions:
contents: write # for taiki-e/create-gh-release-action
id-token: write # for rust-lang/crates-io-auth-action
secrets: inherit

4
.github/zizmor.yml vendored
View File

@@ -2,10 +2,8 @@
# https://docs.zizmor.sh/configuration/
rules:
dependabot-cooldown: { disable: true } # Unless dependencies are pinned/locked, the effect is limited.
secrets-inherit: { disable: true }
anonymous-definition: { disable: true }
unpinned-uses:
config:
policies:
taiki-e/*: any
'*': ref-pin

View File

@@ -10,6 +10,96 @@ Note: In this file, do not use the hard wrap in the middle of a sentence for com
## [Unreleased]
## [2.70.2] - 2026-03-30
- Update `vacuum@latest` to 0.25.3.
- Update `tombi@latest` to 0.9.11.
## [2.70.1] - 2026-03-29
- Update `cargo-insta@latest` to 1.47.1.
- Update `cargo-binstall@latest` to 1.17.9.
- Update `tombi@latest` to 0.9.10.
## [2.70.0] - 2026-03-28
- Install `uv`, `uvw` (Windows-only), and `uvx` binaries when installing `uv`. Previously, only `uv` binary was installed. ([#1632](https://github.com/taiki-e/install-action/pull/1632))
## [2.69.14] - 2026-03-28
- Update `just@latest` to 1.48.1.
- Update `wasm-bindgen@latest` to 0.2.115.
## [2.69.13] - 2026-03-27
- Update `mise@latest` to 2026.3.17.
- Update `cargo-insta@latest` to 1.47.0.
## [2.69.12] - 2026-03-27
- Update `uv@latest` to 0.11.2.
## [2.69.11] - 2026-03-26
- Update `dprint@latest` to 0.53.1.
- Update `mise@latest` to 2026.3.16.
## [2.69.10] - 2026-03-25
- Update `biome@latest` to 2.4.9.
- Update `mise@latest` to 2026.3.15.
## [2.69.9] - 2026-03-25
- Update `uv@latest` to 0.11.1.
- Update `osv-scanner@latest` to 2.3.5.
- Update `mise@latest` to 2026.3.14.
## [2.69.8] - 2026-03-24
- Update `just@latest` to 1.48.0.
- Update `uv@latest` to 0.11.0.
- Update `rclone@latest` to 1.73.3.
- Update `mise@latest` to 2026.3.13.
## [2.69.7] - 2026-03-23
- Update `prek@latest` to 0.3.8.
- Update `mise@latest` to 2026.3.12.
- Update `cargo-valgrind@latest` to 2.4.1.
## [2.69.6] - 2026-03-21
- Support signature verification for `mise` and `syft`. ([#1611](https://github.com/taiki-e/install-action/pull/1611))
- Update `mise@latest` to 2026.3.10.
- Update `knope@latest` to 0.22.4.
- Update `cargo-binstall@latest` to 1.17.8.
- Update `tombi@latest` to 0.9.9.
## [2.69.5] - 2026-03-21
- Update `cargo-nextest@latest` to 0.9.132.
## [2.69.4] - 2026-03-20
- Support artifact attestations verification for `biome`, `cargo-cyclonedx`, `cargo-hack`, `cargo-llvm-cov`, `cargo-minimal-versions`, `cargo-no-dev-deps`, `martin`, `parse-changelog`, `parse-dockerfile`, `prek`, `uv`, `wasmtime`, `zizmor`, and `zola`. ([#1606](https://github.com/taiki-e/install-action/pull/1606))
- Update `biome@latest` to 2.4.8.
@@ -5981,7 +6071,21 @@ Note: This release is considered a breaking change because installing on version
Initial release
[Unreleased]: https://github.com/taiki-e/install-action/compare/v2.69.3...HEAD
[Unreleased]: https://github.com/taiki-e/install-action/compare/v2.70.2...HEAD
[2.70.2]: https://github.com/taiki-e/install-action/compare/v2.70.1...v2.70.2
[2.70.1]: https://github.com/taiki-e/install-action/compare/v2.70.0...v2.70.1
[2.70.0]: https://github.com/taiki-e/install-action/compare/v2.69.14...v2.70.0
[2.69.14]: https://github.com/taiki-e/install-action/compare/v2.69.13...v2.69.14
[2.69.13]: https://github.com/taiki-e/install-action/compare/v2.69.12...v2.69.13
[2.69.12]: https://github.com/taiki-e/install-action/compare/v2.69.11...v2.69.12
[2.69.11]: https://github.com/taiki-e/install-action/compare/v2.69.10...v2.69.11
[2.69.10]: https://github.com/taiki-e/install-action/compare/v2.69.9...v2.69.10
[2.69.9]: https://github.com/taiki-e/install-action/compare/v2.69.8...v2.69.9
[2.69.8]: https://github.com/taiki-e/install-action/compare/v2.69.7...v2.69.8
[2.69.7]: https://github.com/taiki-e/install-action/compare/v2.69.6...v2.69.7
[2.69.6]: https://github.com/taiki-e/install-action/compare/v2.69.5...v2.69.6
[2.69.5]: https://github.com/taiki-e/install-action/compare/v2.69.4...v2.69.5
[2.69.4]: https://github.com/taiki-e/install-action/compare/v2.69.3...v2.69.4
[2.69.3]: https://github.com/taiki-e/install-action/compare/v2.69.2...v2.69.3
[2.69.2]: https://github.com/taiki-e/install-action/compare/v2.69.1...v2.69.2
[2.69.1]: https://github.com/taiki-e/install-action/compare/v2.69.0...v2.69.1

View File

@@ -56,7 +56,7 @@ download_and_checksum() {
checksum=''
fi
info "downloading ${url}"
retry curl --proto '=https' --tlsv1.2 -fsSL --retry 10 "${url}" -o tmp
retry curl --proto '=https' --tlsv1.2 -fsSL "${url}" -o tmp
if [[ -n "${checksum}" ]]; then
info "verifying sha256 checksum for $(basename -- "${url}")"
if type -P sha256sum >/dev/null; then
@@ -179,7 +179,7 @@ download_and_extract() {
else
case "${url}" in
*.zip)
unzip -q tmp "${bin_in_archive#\./}"
unzip -q tmp
for tmp in "${bin_in_archive[@]}"; do
case "${tool}" in
editorconfig-checker) mv -- "${tmp}" "${bin_dir}/${tool}${exe}" ;;
@@ -233,7 +233,7 @@ read_manifest() {
# TODO: don't hardcode tool name and use 'immediate_yank_reflection' field in base manifest.
case "${tool}" in
cargo-nextest)
crate_info=$(curl -v --user-agent "${ACTION_USER_AGENT}" --proto '=https' --tlsv1.2 -fsSL --retry 10 "https://crates.io/api/v1/crates/${rust_crate}" || true)
crate_info=$(retry curl --user-agent "${ACTION_USER_AGENT}" --proto '=https' --tlsv1.2 -fsSL "https://crates.io/api/v1/crates/${rust_crate}" || true)
if [[ -n "${crate_info}" ]]; then
while true; do
yanked=$(jq -r ".versions[] | select(.num == \"${exact_version}\") | .yanked" <<<"${crate_info}")
@@ -763,7 +763,7 @@ for tool in "${tools[@]}"; do
;;
*)
# Handle aliases.
# NB: Update alias list in tools/publish.rs, tool input option in test-alias in .github/workflows/ci.yml,
# NB: Update alias list in .github/workflows/release.yml, tool input option in test-alias in .github/workflows/ci.yml,
# and match for alias for tools/codegen/src/tools-markdown.rs.
# TODO(codegen): auto-detect cases where crate name and tool name are different.
case "${tool}" in

44
manifests/biome.json generated
View File

@@ -3,13 +3,51 @@
"template": null,
"license_markdown": "[Apache-2.0](https://github.com/biomejs/biome/blob/main/LICENSE-APACHE) OR [MIT](https://github.com/biomejs/biome/blob/main/LICENSE-MIT)",
"latest": {
"version": "2.4.8"
"version": "2.4.9"
},
"2": {
"version": "2.4.8"
"version": "2.4.9"
},
"2.4": {
"version": "2.4.8"
"version": "2.4.9"
},
"2.4.9": {
"x86_64_linux_musl": {
"url": "https://github.com/biomejs/biome/releases/download/%40biomejs/biome%402.4.9/biome-linux-x64-musl",
"etag": "0x8DE8A6B77551800",
"hash": "fe2fd12c1e0b84f7e91d1357ed5ff1ebc8325b21bcf31935d3722fb3ae77889a",
"bin": "biome"
},
"x86_64_macos": {
"url": "https://github.com/biomejs/biome/releases/download/%40biomejs/biome%402.4.9/biome-darwin-x64",
"etag": "0x8DE8A6B77782FF8",
"hash": "f5b7e584d1e993157638ce2d32335dbe754c4be94c4774f43aaf569918161c15",
"bin": "biome"
},
"x86_64_windows": {
"url": "https://github.com/biomejs/biome/releases/download/%40biomejs/biome%402.4.9/biome-win32-x64.exe",
"etag": "0x8DE8A6B77E6A243",
"hash": "b33519e33e6807e37d57767f7c49fc8fe5205819d267924a8fe8a20d7ce296cf",
"bin": "biome.exe"
},
"aarch64_linux_musl": {
"url": "https://github.com/biomejs/biome/releases/download/%40biomejs/biome%402.4.9/biome-linux-arm64-musl",
"etag": "0x8DE8A6B77627675",
"hash": "5a4040483af06396d5c687e03d2a7f1c6a4e1ca97a3d765c6beee4532debdd88",
"bin": "biome"
},
"aarch64_macos": {
"url": "https://github.com/biomejs/biome/releases/download/%40biomejs/biome%402.4.9/biome-darwin-arm64",
"etag": "0x8DE8A6B77476BBF",
"hash": "8d40e92275fcbaf0a157b5146f71b8c71ce61e50102ac4385170022e76938d85",
"bin": "biome"
},
"aarch64_windows": {
"url": "https://github.com/biomejs/biome/releases/download/%40biomejs/biome%402.4.9/biome-win32-arm64.exe",
"etag": "0x8DE8A6B77737A54",
"hash": "975f30393b2914d66e0d54eac9573dd27704922a8361c462cbb0521543f67691",
"bin": "biome.exe"
}
},
"2.4.8": {
"x86_64_linux_musl": {

View File

@@ -22,32 +22,32 @@
},
"license_markdown": "[GPL-3.0](https://github.com/cargo-bins/cargo-binstall/blob/HEAD/crates/bin/LICENSE)",
"latest": {
"version": "1.17.7"
"version": "1.17.9"
},
"1.17.7": {
"1.17.9": {
"x86_64_linux_musl": {
"etag": "0x8DE7C5AC0E4497E",
"hash": "29b5ecfb6e03c2511a617c77d312b06df0c54717644fbfda3d465ec8240532f0"
"etag": "0x8DE8D54CBD7C8ED",
"hash": "bdea3fd820b118576316bf69c8240f454857287717809e6ecef010faace901ff"
},
"x86_64_macos": {
"etag": "0x8DE7C5AC5E5BC1B",
"hash": "aa7174fb938e668dea4b4c3d22fe6cefed97642cc3a7a419ba96d63d63fd729b"
"etag": "0x8DE8D54D0C7EA49",
"hash": "1d4fbd74c15274a029dd92e19a0ead8e1831b6e6b60f0f5c3690ef517022c41c"
},
"x86_64_windows": {
"etag": "0x8DE7C5AC441ACDB",
"hash": "c5cb2444ee04480502a8ac73d96abd9f97af8300ec04ea1c1f2a9e959c02e4d6"
"etag": "0x8DE8D54CF270B9E",
"hash": "d17b413a19592af2cf57f9f742d49bef8837099e1407d73e79de5bc7834c4fd6"
},
"aarch64_linux_musl": {
"etag": "0x8DE7C5ACC95E091",
"hash": "b0658b0a7f0959bc1dbb4ab665931c31c7dd1109ff01cb8772af17dfdc52a9af"
"etag": "0x8DE8D54D9B48785",
"hash": "89df253cc00a307209daee7648272bba4d8a342fce084d5922f6b3f4e4db0e25"
},
"aarch64_macos": {
"etag": "0x8DE7C5AD2545078",
"hash": "1ad3c0c56fa3970634cce5009ed0ce61b943515f9115f8e480fd0e41d8d89085"
"etag": "0x8DE8D54DF4E885F",
"hash": "021d537caa2071bbcd8ec50b210ea45af68a6983cca7780918b3603ef68d2585"
},
"aarch64_windows": {
"etag": "0x8DE7C5AD068DA1E",
"hash": "e876543c9aad23968d1123c0d959309937894bbfd267bb0878109fb253217878"
"etag": "0x8DE8D54DD746155",
"hash": "37295aa1c3aed07bda2b757f613477c8ca2de1208ec360c7d00238b6886de780"
}
}
}

View File

@@ -20,10 +20,49 @@
},
"license_markdown": "[Apache-2.0](https://github.com/mitsuhiko/insta/blob/master/LICENSE)",
"latest": {
"version": "1.46.3"
"version": "1.47.1"
},
"1": {
"version": "1.46.3"
"version": "1.47.1"
},
"1.47": {
"version": "1.47.1"
},
"1.47.1": {
"x86_64_linux_musl": {
"etag": "0x8DE8D549F25E618",
"hash": "b5c162d25f477f0a7989edc5b82297a63c69d764c3c6f2839f12a546a00c188a"
},
"x86_64_macos": {
"etag": "0x8DE8D549EDE5832",
"hash": "3197c099ca857e36211b7b10d383404f305e036181ca2cb42495c8d08e4dcc86"
},
"x86_64_windows": {
"etag": "0x8DE8D549EF37620",
"hash": "7d6cad4a8768abc2bda8f0ea244f51ae077d426e6e7bc6561503876b4eba18e8"
},
"aarch64_macos": {
"etag": "0x8DE8D549ED08513",
"hash": "b92971f37be1e22401de1187ee842a7e15f936838bdce06fb9d3582dd538efa7"
}
},
"1.47.0": {
"x86_64_linux_musl": {
"etag": "0x8DE8B9FBE3D26E2",
"hash": "fcd8a57fb21e5446c12002c0f967e7630a9e4f317814427dbf35faff3797c1d9"
},
"x86_64_macos": {
"etag": "0x8DE8B9FBDBE4C61",
"hash": "55db1160ab8db370d3a03491a291f04e52837b4bea13b2919068a10700b085b2"
},
"x86_64_windows": {
"etag": "0x8DE8B9FBDFA9C5D",
"hash": "ecdab0fe43537a15ef6bd4628d91cddd3c26ddb3fd60f9c89d5d40904139649e"
},
"aarch64_macos": {
"etag": "0x8DE8B9FBDB8AD65",
"hash": "579f62ab41187c8494ca8572b4d0db51e0c9b9275064758999b27fc900c9c60c"
}
},
"1.46": {
"version": "1.46.3"

View File

@@ -28,10 +28,45 @@
},
"license_markdown": "[Apache-2.0](https://github.com/nextest-rs/nextest/blob/main/LICENSE-APACHE) OR [MIT](https://github.com/nextest-rs/nextest/blob/main/LICENSE-MIT)",
"latest": {
"version": "0.9.131"
"version": "0.9.132"
},
"0.9": {
"version": "0.9.131"
"version": "0.9.132"
},
"0.9.132": {
"previous_stable_version": "0.9.131",
"x86_64_linux_gnu": {
"etag": "0x8DE86DAD99145E2",
"hash": "e22f14ecaff5519dbfe521e8717d64e9989648bddc23eb1f71bb0053518a52e7"
},
"x86_64_linux_musl": {
"etag": "0x8DE86DB277E6673",
"hash": "5e93f3b4244e2f8bffe5818b2a7cbd6a59f32d262dcb6017905e345cc74227af"
},
"x86_64_macos": {
"etag": "0x8DE86DB84D52D01",
"hash": "6ce5c844ae3cdac3f6f42fd86bf71a8bf99aecd76bab9f6743c808223d31fad1"
},
"x86_64_windows": {
"etag": "0x8DE86DBA597EDA0",
"hash": "6f934574f621613d7d759547401a04619b3e1ebe1f4e8f624880197d566fa6ad"
},
"aarch64_linux_gnu": {
"etag": "0x8DE86DBC5227BB5",
"hash": "592db3fa3d3ee62f109dc149554811eb8ecdc68e1514be5af79986b1560e2e0d"
},
"aarch64_linux_musl": {
"etag": "0x8DE86DAF803192A",
"hash": "2497ddfd2a0c6805f7c5514ff680c6ca9c1ffc5b9ab30af43e85830b768c129a"
},
"aarch64_windows": {
"etag": "0x8DE86DBA23732E6",
"hash": "3c519d128909fba6829a318476bcbd9777d97ec066b4d973a3f1e04da049ef0b"
},
"riscv64_linux_gnu": {
"etag": "0x8DE86DAD1A09377",
"hash": "82d1f0c4b7733e0a852e2e8b3f1a3f65b89e7ffd165121127ac356f0c9f7b5d2"
}
},
"0.9.131": {
"previous_stable_version": "0.9.130",

View File

@@ -13,13 +13,27 @@
},
"license_markdown": "[MIT](https://github.com/jfrimmel/cargo-valgrind/blob/master/LICENSE-MIT) OR [Apache-2.0](https://github.com/jfrimmel/cargo-valgrind/blob/master/LICENSE-APACHE)",
"latest": {
"version": "2.4.0"
"version": "2.4.1"
},
"2": {
"version": "2.4.0"
"version": "2.4.1"
},
"2.4": {
"version": "2.4.0"
"version": "2.4.1"
},
"2.4.1": {
"x86_64_linux_musl": {
"etag": "0x8DE88031FA217E4",
"hash": "85f0aba2bdde0d30bafa814a02229a56fd63b27623c25dfba57f49c40eeda762"
},
"x86_64_macos": {
"etag": "0x8DE88031F98D375",
"hash": "80b1477c1eb35410b40b842aa655b37233416f9cad86f6a11c6107b8b97ddc22"
},
"x86_64_windows": {
"etag": "0x8DE88031F98D375",
"hash": "c9f36f03de6ae0cb773b3796f4dd738ebb85e00a59c1cb72bec49a267d83c5cf"
}
},
"2.4.0": {
"x86_64_linux_musl": {

30
manifests/dprint.json generated
View File

@@ -28,10 +28,36 @@
},
"license_markdown": "[MIT](https://github.com/dprint/dprint/blob/main/LICENSE)",
"latest": {
"version": "0.53.0"
"version": "0.53.1"
},
"0.53": {
"version": "0.53.0"
"version": "0.53.1"
},
"0.53.1": {
"x86_64_linux_musl": {
"etag": "0x8DE8B3F9B6F4770",
"hash": "f2815a5c217bb63ff54356c4a6e1e5393a126b29c46116ae57a08ec97c29cb85"
},
"x86_64_macos": {
"etag": "0x8DE8B3F9B08E273",
"hash": "b35e91afe0f7f2217128b8edcebd63d789b00f9c1b0300e4907a115106d857fd"
},
"x86_64_windows": {
"etag": "0x8DE8B3F9B1F10A2",
"hash": "db21e2f7a09dc9b3a2fbe2faac34a9f0733a4cc3cb8c78dd13dae6f081e13d4c"
},
"aarch64_linux_musl": {
"etag": "0x8DE8B3F9B268256",
"hash": "559cbd7aff707d461627c46f817cd06c28828458ef4a21eb18801f588bc94e89"
},
"aarch64_macos": {
"etag": "0x8DE8B3F9B08E273",
"hash": "4c822f9d4c692b0f0cd53d14bc82057488e1c4db2df1122b1aceb0a660795ac8"
},
"riscv64_linux_gnu": {
"etag": "0x8DE8B3F9B259909",
"hash": "035c6e63d47b68f86b859dca7628cdb5006737b8b472df64cb51036594dd7247"
}
},
"0.53.0": {
"x86_64_linux_musl": {

59
manifests/just.json generated
View File

@@ -22,10 +22,65 @@
},
"license_markdown": "[CC0-1.0](https://github.com/casey/just/blob/master/LICENSE)",
"latest": {
"version": "1.47.1"
"version": "1.48.1"
},
"1": {
"version": "1.47.1"
"version": "1.48.1"
},
"1.48": {
"version": "1.48.1"
},
"1.48.1": {
"x86_64_linux_musl": {
"etag": "0x8DE8C6D748DA58F",
"hash": "9293e553ce401d1b524bf4e104918f72f268e3f9c6827e0055fe98d84a1b2522"
},
"x86_64_macos": {
"etag": "0x8DE8C6D697B40B5",
"hash": "4c3e9c880b8fc93d7fc24abfde3c36b0cc59f6e9f8b31f7175095700f64125a7"
},
"x86_64_windows": {
"etag": "0x8DE8C6DC96FB40D",
"hash": "368cd9ca827cba04d9e6fc00f7ad840773c4605b6f64b9f87bdb00325d351029"
},
"aarch64_linux_musl": {
"etag": "0x8DE8C6D791ED527",
"hash": "3308721b991cf88cf2b9bbb3b31ac40550ec61a0c9b6fc011564e25e87964030"
},
"aarch64_macos": {
"etag": "0x8DE8C6D73E04DFD",
"hash": "03a73339ff55bcf7411a3c940cdcb0a726d98134b87203c83a9008575434e2a8"
},
"aarch64_windows": {
"etag": "0x8DE8C6DB1FA1AAD",
"hash": "ed9cd54e46d65770bf0b79c051761b29f0b89a88e56e8cae4454ec7246c82160"
}
},
"1.48.0": {
"x86_64_linux_musl": {
"etag": "0x8DE893FDA35D240",
"hash": "a62e100de2922519ff3d6128f580837b4c0e197aa61a6fb448f43e50e7dd9b9b"
},
"x86_64_macos": {
"etag": "0x8DE893FD7207196",
"hash": "9c4a018665ede3167db8210a6c846e59b675ecce71a35d2f802035fbc9199627"
},
"x86_64_windows": {
"etag": "0x8DE89405E00E226",
"hash": "06000d1e1f97155c6dff316f20fad029aa70f69c4ecbe2fbe5b821d9bb79aef0"
},
"aarch64_linux_musl": {
"etag": "0x8DE893FE55F2345",
"hash": "3c28914f0059161bc263c41db0ed3f786866cfb9632d1ee7809f529c8f18835e"
},
"aarch64_macos": {
"etag": "0x8DE893FEEDF61A3",
"hash": "507edd5cbe97e13f048f650e52ae6cf3fd6c7464b18abe64fb01eca1bd65f8a2"
},
"aarch64_windows": {
"etag": "0x8DE894023163D15",
"hash": "5fc53507e86334e3f0111b674c72fbcf7d9c53fe6a0f5d7dc6c6afc8903d44b2"
}
},
"1.47": {
"version": "1.47.1"

36
manifests/knope.json generated
View File

@@ -3,10 +3,42 @@
"template": null,
"license_markdown": "[MIT](https://github.com/knope-dev/knope/blob/main/LICENSE)",
"latest": {
"version": "0.22.3"
"version": "0.22.4"
},
"0.22": {
"version": "0.22.3"
"version": "0.22.4"
},
"0.22.4": {
"x86_64_linux_musl": {
"url": "https://github.com/knope-dev/knope/releases/download/knope/v0.22.4/knope-x86_64-unknown-linux-musl.tgz",
"etag": "0x8DE8761D8F513DE",
"hash": "45a74925ae9f4c9c2c33b51992ae50241ec4fa836bf8d2977c0b8e8172dd69cf",
"bin": "knope-x86_64-unknown-linux-musl/knope"
},
"x86_64_macos": {
"url": "https://github.com/knope-dev/knope/releases/download/knope/v0.22.4/knope-x86_64-apple-darwin.tgz",
"etag": "0x8DE8761D8E4D27D",
"hash": "010dc197bf159bbd9d60e897252248ba2b0e204beae7250ce54a9deae1ec4876",
"bin": "knope-x86_64-apple-darwin/knope"
},
"x86_64_windows": {
"url": "https://github.com/knope-dev/knope/releases/download/knope/v0.22.4/knope-x86_64-pc-windows-msvc.tgz",
"etag": "0x8DE8761D8EAE61C",
"hash": "09f735b2da42cd594189042d1379c0a3a350a8c0ccb741015a84c6ff334543b1",
"bin": "knope-x86_64-pc-windows-msvc/knope.exe"
},
"aarch64_linux_musl": {
"url": "https://github.com/knope-dev/knope/releases/download/knope/v0.22.4/knope-aarch64-unknown-linux-musl.tgz",
"etag": "0x8DE8761D8EE649C",
"hash": "95e882afdb4154c5baaba91f7bbd1fb1d41cec6898363a2b30e7abad4057b83b",
"bin": "knope-aarch64-unknown-linux-musl/knope"
},
"aarch64_macos": {
"url": "https://github.com/knope-dev/knope/releases/download/knope/v0.22.4/knope-aarch64-apple-darwin.tgz",
"etag": "0x8DE8761D8EC1D47",
"hash": "02131f284315c8ece8a4ef69a0aff5f658309d4df73b95cfdfbe0fbd9e9ce259",
"bin": "knope-aarch64-apple-darwin/knope"
}
},
"0.22.3": {
"x86_64_linux_musl": {

188
manifests/mise.json generated
View File

@@ -28,13 +28,195 @@
},
"license_markdown": "[MIT](https://github.com/jdx/mise/blob/main/LICENSE)",
"latest": {
"version": "2026.3.9"
"version": "2026.3.17"
},
"2026": {
"version": "2026.3.9"
"version": "2026.3.17"
},
"2026.3": {
"version": "2026.3.9"
"version": "2026.3.17"
},
"2026.3.17": {
"x86_64_linux_musl": {
"etag": "0x8DE8BF1812CA605",
"hash": "f416a2d27f69173b22551429d2bc712c40fc3fb639112cf76ae817baae3772e2"
},
"x86_64_macos": {
"etag": "0x8DE8BF1834954DF",
"hash": "bd120908c1476f6f27ae27f4214bdbc3fb0e81b9671aaba720b994a217d28e39"
},
"x86_64_windows": {
"etag": "0x8DE8BF1841058BD",
"hash": "a5e0a77fe5ac6397d6bd3413b6c9b39ac06f24649a88eed526173062960f7b85"
},
"aarch64_linux_musl": {
"etag": "0x8DE8BF17E0B455B",
"hash": "7ef20440c3e1d9f0db69e57e68e6833a9cade44fd1e97384a279660e48091f97"
},
"aarch64_macos": {
"etag": "0x8DE8BF18293F06F",
"hash": "6d98cedb9c92bd7a1694c9efedc035288da87f6e19c79d15bf91449474c37ce9"
},
"aarch64_windows": {
"etag": "0x8DE8BF183D566EE",
"hash": "98772d1d68d23e8f1040c62501bcd0d136cf2db3b995a5e7b6f77aca93aef060"
}
},
"2026.3.16": {
"x86_64_linux_musl": {
"etag": "0x8DE8B299B139FB6",
"hash": "7b10cc988cdfdc434791a6102bdc18edbd1909243e05ed5a37ddc12c9ed53167"
},
"x86_64_macos": {
"etag": "0x8DE8B299E855DE3",
"hash": "a6f6f320b547dec3eff321e301fa05268dfc73a620d35ec3292603fbab1c4c29"
},
"x86_64_windows": {
"etag": "0x8DE8B299F39B21C",
"hash": "a7b6aaa23804418799d5d33e77e1d08144fec0efadcc38d138b68eaa214080f5"
},
"aarch64_linux_musl": {
"etag": "0x8DE8B2995D2AD4D",
"hash": "1d33037f6eb3c6e67b62e951825764836b530213b8acce8667ab2c2bcf3775e9"
},
"aarch64_macos": {
"etag": "0x8DE8B299D508381",
"hash": "9d6e2bfea3e00ffb566ad1a369914cb029c32a28eb4b699e8655cf3c3d4ef87e"
},
"aarch64_windows": {
"etag": "0x8DE8B299EFE726F",
"hash": "f6293578bae263614c8af6c1664bd4c28f741f902f45bcbdad922bee6d04d7e6"
}
},
"2026.3.15": {
"x86_64_linux_musl": {
"etag": "0x8DE8A614808BB17",
"hash": "4e70734eeef3e664f1616be83ed0d2ee6114ecd10539ca6abdb1f6d66c29559d"
},
"x86_64_macos": {
"etag": "0x8DE8A614A5EFDC6",
"hash": "4dbc8750ce3833050321b0c0deb61db7fc76681aa958df6786b999b588e42d1d"
},
"x86_64_windows": {
"etag": "0x8DE8A614AD83926",
"hash": "ad1229ef84f664bc8a1a6b3fb96245ce29cb6f735ab6f512a12573a95ab53d6f"
},
"aarch64_linux_musl": {
"etag": "0x8DE8A61442166F3",
"hash": "25d1f0d880e47f7478d93ee0e8344e25b7eb9cbd841ddb6231836c9ff86868bc"
},
"aarch64_macos": {
"etag": "0x8DE8A6149A11766",
"hash": "e500c437e4b8679b4c65e91925f86c17e6be76d0e218012bd40ec695ae4cf78e"
},
"aarch64_windows": {
"etag": "0x8DE8A614AC8BA38",
"hash": "cab591781d7d3e2cba9b719a2e9c525424d4bafda0b52e091bc0f4a4d3953a8f"
}
},
"2026.3.14": {
"x86_64_linux_musl": {
"etag": "0x8DE89F2A845625B",
"hash": "b34d9179dcf3622b9aa1aa9c4d8361cce743314612b11bf62fa8589a4d52a5db"
},
"x86_64_macos": {
"etag": "0x8DE89F2ABB3F018",
"hash": "8ab0deb1e839b9a12b6520fe7e7377523de2140811baa90b98aef27cfe2ffc32"
},
"x86_64_windows": {
"etag": "0x8DE89F2ACEC2233",
"hash": "fc91b0b301dc4d2f914afb6f71ef46b01eee47ba1f5ec1084413c2e197480509"
},
"aarch64_linux_musl": {
"etag": "0x8DE89F2A3C1BA78",
"hash": "42c80e03ac14591a9fc73864da0b46e9529822c84e0b6d7834fc65d5fe3ff1f7"
},
"aarch64_macos": {
"etag": "0x8DE89F2AA7AFB84",
"hash": "dd9296e67a58cd119dba83e8ed4c6c4d566ae94827c4ee4a24c7b7001f6054ec"
},
"aarch64_windows": {
"etag": "0x8DE89F2AC9479C3",
"hash": "7c3bddf4ef2206ef08aa0e73426f6619ea5ccd7f0d92dfafb6ff482a88e14dde"
}
},
"2026.3.13": {
"x86_64_linux_musl": {
"etag": "0x8DE88EB0574D86B",
"hash": "2b409c40dc02bd3b1ba4061760aa81f3b4734fa7d7de8c5e1db4c6ca5ede70d8"
},
"x86_64_macos": {
"etag": "0x8DE88EB09453B8C",
"hash": "af5610f5abbc67581d04559f65ea2afbf04c5a15d1eef1eb27ca985f52424153"
},
"x86_64_windows": {
"etag": "0x8DE88EB09D4CBF0",
"hash": "8879a21bdaab28f52f8981a452cb67c83de9cac863eabe878574076f986ad6ba"
},
"aarch64_linux_musl": {
"etag": "0x8DE88EAFF42F4FF",
"hash": "d98665273a14eb2c599ec0fc66f4a5e6ac0b9fad624d55d8a32b7dc9017693c5"
},
"aarch64_macos": {
"etag": "0x8DE88EB07D092EF",
"hash": "14de0cc332f4effae9c06e201b32adc17368a169485ce1cbfa2e25c3a006d6a7"
},
"aarch64_windows": {
"etag": "0x8DE88EB09C2DEBC",
"hash": "f55ce0e157606ae20c3ea5f91c7b8c5390888bb00143d043ed58131c89161f5d"
}
},
"2026.3.12": {
"x86_64_linux_musl": {
"etag": "0x8DE886122F1FBF4",
"hash": "b6bdc23b08bccfcc77b61d35b286e20de1e0192447e8fda64b2bf60c5328b452"
},
"x86_64_macos": {
"etag": "0x8DE88612512C4AA",
"hash": "4f65f7f72c14641ad78670ec2c403d3eb9a4681e2fa064385e80a22a109bfe2c"
},
"x86_64_windows": {
"etag": "0x8DE886125F154A2",
"hash": "528d5f9bfabb8eae06964c0e112f9711a4af4315bfed96f6f50b6c4b67ec6f37"
},
"aarch64_linux_musl": {
"etag": "0x8DE88611FFB72E8",
"hash": "c27dd6a06053f6884c3f46763b64ef9c5e95fac7a9af89edea087b13cc68c521"
},
"aarch64_macos": {
"etag": "0x8DE88612449EE2B",
"hash": "c9622be7ea2badc7bf3501cd9b5600e0bf993bf33c162844a4a6d79a2209e1f8"
},
"aarch64_windows": {
"etag": "0x8DE8861257AFC36",
"hash": "a65bea150a477f21faa62e24d45f811d2ede69da20aac43ad17ef3134bc516f4"
}
},
"2026.3.10": {
"x86_64_linux_musl": {
"etag": "0x8DE8749F9B8C65D",
"hash": "b0c2fd25fe95cd1ed3f178b95690608472aa8a27ce2f6e63eaebda52a238e570"
},
"x86_64_macos": {
"etag": "0x8DE8749FBD637A3",
"hash": "5ed1a2a6a79aab33e67d21156ec42b22d3cde1ceef09eb08c0ccd9b429795e6a"
},
"x86_64_windows": {
"etag": "0x8DE8749FC98ACBC",
"hash": "bf5e86077f652caca0413155e33886c3459d3f2963f9f186be76c8c05c2accb6"
},
"aarch64_linux_musl": {
"etag": "0x8DE8749F6470833",
"hash": "9730abf52c93c7945f907f4fe6f731b79d74671705656fa36fa45008933e88c7"
},
"aarch64_macos": {
"etag": "0x8DE8749FB48C7AB",
"hash": "85b5e577a5ed34431718091122ea7ec9cf7d4e1d8e5e4dc298cdb02d8dbd97b3"
},
"aarch64_windows": {
"etag": "0x8DE8749FC8C37A5",
"hash": "82a702481c9e877b28f82eb60a0d3be2d393fc9b7915283992b1cd0263724d2b"
}
},
"2026.3.9": {
"x86_64_linux_musl": {

View File

@@ -3,13 +3,45 @@
"template": null,
"license_markdown": "[Apache-2.0](https://github.com/google/osv-scanner/blob/main/LICENSE)",
"latest": {
"version": "2.3.3"
"version": "2.3.5"
},
"2": {
"version": "2.3.3"
"version": "2.3.5"
},
"2.3": {
"version": "2.3.3"
"version": "2.3.5"
},
"2.3.5": {
"x86_64_linux_musl": {
"url": "https://github.com/google/osv-scanner/releases/download/v2.3.5/osv-scanner_linux_amd64",
"etag": "0x8DE896B96DE50D8",
"hash": "bb30c580afe5e757d3e959f4afd08a4795ea505ef84c46962b9a738aa573b41b"
},
"x86_64_macos": {
"url": "https://github.com/google/osv-scanner/releases/download/v2.3.5/osv-scanner_darwin_amd64",
"etag": "0x8DE896B96B9DA4A",
"hash": "3b1c72d59dcbad99fa4eb2c72bf2e82017f83e0268340e4b00af76a1fea32c85"
},
"x86_64_windows": {
"url": "https://github.com/google/osv-scanner/releases/download/v2.3.5/osv-scanner_windows_amd64.exe",
"etag": "0x8DE896B94AF3EDE",
"hash": "b165d33c08bda663119a459f5187e096d2525f888503495f5f34925741e981a2"
},
"aarch64_linux_musl": {
"url": "https://github.com/google/osv-scanner/releases/download/v2.3.5/osv-scanner_linux_arm64",
"etag": "0x8DE896B94B77302",
"hash": "fa46ad2b3954db5d5335303d45de921613393285d9a93c140b63b40e35e9ce50"
},
"aarch64_macos": {
"url": "https://github.com/google/osv-scanner/releases/download/v2.3.5/osv-scanner_darwin_arm64",
"etag": "0x8DE896B94F4856E",
"hash": "b740efe0b08fb817865e818a498997d5f042f14b8eeafb6393176ce84dd09cf6"
},
"aarch64_windows": {
"url": "https://github.com/google/osv-scanner/releases/download/v2.3.5/osv-scanner_windows_arm64.exe",
"etag": "0x8DE896B94B1AD12",
"hash": "a3d2ffa712fd2376e88a02c98b917a87885c761d0d21980b8f5eabfb910cbcb8"
}
},
"2.3.3": {
"x86_64_linux_musl": {

38
manifests/prek.json generated
View File

@@ -40,10 +40,44 @@
},
"license_markdown": "[MIT](https://github.com/j178/prek/blob/master/LICENSE)",
"latest": {
"version": "0.3.6"
"version": "0.3.8"
},
"0.3": {
"version": "0.3.6"
"version": "0.3.8"
},
"0.3.8": {
"x86_64_linux_musl": {
"etag": "0x8DE88B58DEC3E03",
"hash": "732cfb03960e6dfd5df2cb67906797aa8831750ef3a6f6340ec2b90ee8b7a59f"
},
"x86_64_macos": {
"etag": "0x8DE88B58D79B1EF",
"hash": "010198daf4e99a76d03a911973320542ffd7a04091cf7e86c60ac861187577f6"
},
"x86_64_windows": {
"etag": "0x8DE88B58DA4B02B",
"hash": "1da2735c31548dacd2751f90c15b5f643aa72f3053f366636f95153ee2c7186e"
},
"aarch64_linux_musl": {
"etag": "0x8DE88B58C3D8D01",
"hash": "b88d96aef4ea84999d12958c390611d3a26194ee57225fe2ff15a9855e3a71bf"
},
"aarch64_macos": {
"etag": "0x8DE88B58BFA193A",
"hash": "702fde4399fafb054ce85d0a64367689e3668b6475d732c4a46aae50cec0a4be"
},
"aarch64_windows": {
"etag": "0x8DE88B58BF4A12E",
"hash": "5ceb73fe9e18a987a498ced9b98a183d4110e3fdb534070d2d9911f860319e9f"
},
"riscv64_linux_gnu": {
"etag": "0x8DE88B58D4F0179",
"hash": "4c3677090f90f325b1f472e8b2db6f56647db794333ab0ee2656a91139ce9a27"
},
"s390x_linux_gnu": {
"etag": "0x8DE88B58D875E2B",
"hash": "cec915a22e4385110e2de8498d14c199ce6936d03d9d8340d166c57071ac1de8"
}
},
"0.3.6": {
"x86_64_linux_musl": {

32
manifests/rclone.json generated
View File

@@ -28,13 +28,39 @@
},
"license_markdown": "[MIT](https://github.com/rclone/rclone/blob/master/COPYING)",
"latest": {
"version": "1.73.2"
"version": "1.73.3"
},
"1": {
"version": "1.73.2"
"version": "1.73.3"
},
"1.73": {
"version": "1.73.2"
"version": "1.73.3"
},
"1.73.3": {
"x86_64_linux_musl": {
"etag": "0x8DE892EC705086A",
"hash": "70278c22b98c7d02aed01828b70053904dbce4c8a1a15d7781d836c6fdb036ea"
},
"x86_64_macos": {
"etag": "0x8DE892FB5F06D97",
"hash": "aaf209187baf40a4f6b732104121f81eedc0264aaa91186952ec3e78b82025b1"
},
"x86_64_windows": {
"etag": "0x8DE892FF61A990A",
"hash": "1c51142576194d124ffa9654f45bab972530da22a3a339509bf9bed399f9dea3"
},
"aarch64_linux_musl": {
"etag": "0x8DE892EE33A9BF9",
"hash": "ed2a638b4cb15abe4f01d6d9c015f3a1cb41aa7a17c96db2725542c61f353b8e"
},
"aarch64_macos": {
"etag": "0x8DE892FBFE9C4F0",
"hash": "ef046e9facd10d1fb39d0ef865d7fab9b5c6ca1597ac7c9167f3aa0c7747393f"
},
"aarch64_windows": {
"etag": "0x8DE892FFEC4A4E3",
"hash": "1ecc1da556965f678909390e723e52a5d53fa783fe0a4f224cfa818697c7a6c5"
}
},
"1.73.2": {
"x86_64_linux_musl": {

82
manifests/tombi.json generated
View File

@@ -22,10 +22,88 @@
},
"license_markdown": "[MIT](https://github.com/tombi-toml/tombi/blob/main/LICENSE)",
"latest": {
"version": "0.9.8"
"version": "0.9.11"
},
"0.9": {
"version": "0.9.8"
"version": "0.9.11"
},
"0.9.11": {
"x86_64_linux_musl": {
"etag": "0x8DE8D9EC510FD7C",
"hash": "a26165a20198b7af772c1abafebac31fe70ea76de438cdc14975d451ef9282a3"
},
"x86_64_macos": {
"etag": "0x8DE8D9EC4ABF6BC",
"hash": "80c70ef17dc76a0f997d8284911a178f90d4c3d04354eaa653b5dd3e15efff44"
},
"x86_64_windows": {
"etag": "0x8DE8D9EC53C498A",
"hash": "f073c5aa5cfdf291023207a58390a4593b7774ccd8a49d12fdefa2d859285f95"
},
"aarch64_linux_musl": {
"etag": "0x8DE8D9EC4A89F22",
"hash": "1a4cdb63e5ab57d0eb12f170493a7902c3244572b6a3052ae894d06c082d4ddc"
},
"aarch64_macos": {
"etag": "0x8DE8D9EC4AC1DA5",
"hash": "1c3b3335f3feeda3f7676d90ffb6463ee2bca5a5393b1bbae76926e3fdb2b514"
},
"aarch64_windows": {
"etag": "0x8DE8D9EC4BA8C4E",
"hash": "85624e7e2f0bac43d8267c88a767afbb18ca338b72cf45c879046fc3a23a2e89"
}
},
"0.9.10": {
"x86_64_linux_musl": {
"etag": "0x8DE8CEDFE4FEBC7",
"hash": "eddad889a7194e6b993015475ccd6303edb06f076b632b3a1b134936e280b103"
},
"x86_64_macos": {
"etag": "0x8DE8CEDFECFAF7A",
"hash": "8421af429bec96ec09b621267d3ad505d202dc1ac8e3e5f2677dca0efa348395"
},
"x86_64_windows": {
"etag": "0x8DE8CEDFE5E3394",
"hash": "f6a722ef9f1a5d3656338cf45f88a35aebd29d6bf045b1dd2e91d0dcb356a92e"
},
"aarch64_linux_musl": {
"etag": "0x8DE8CEDFE539126",
"hash": "5373de8f10af1e626bbedc2beb46fbc7dd8bb3ccd73517b45108e165469e69e6"
},
"aarch64_macos": {
"etag": "0x8DE8CEDFE6E9BDE",
"hash": "1c7fcccf0c14d4c3189cfc405357f524b8db0ac7278bee434212f6c113070eb4"
},
"aarch64_windows": {
"etag": "0x8DE8CEDFED8CCF3",
"hash": "e3a5ce5bb2f4071974250b27dd8cc9df76c1feaa1be7c5a7e814191d9999311f"
}
},
"0.9.9": {
"x86_64_linux_musl": {
"etag": "0x8DE86ED14380D61",
"hash": "4317ffc3e08fc6e3ba92953af85b6ad361493fd79916949aec5b5b7af471922f"
},
"x86_64_macos": {
"etag": "0x8DE86ED1495C95E",
"hash": "7f43d90e17f0a6406b5c53bb2773ea1f51e9aba00d47e76d6a55f70ba6e519e0"
},
"x86_64_windows": {
"etag": "0x8DE86ED1433F34E",
"hash": "efb2e3bd949435d244368179476658b5bed9bf35b662face2c00920faf97f247"
},
"aarch64_linux_musl": {
"etag": "0x8DE86ED1432BC2D",
"hash": "75d32d6d17a35c5307f7b67c4f80eca8d43b4d5bdacf86505a4bb87dcb3100d0"
},
"aarch64_macos": {
"etag": "0x8DE86ED149A3137",
"hash": "4e49e41a2f3bd7a26e11c0ce936ac0b75d60c9068798b951ea925cea04ce4a5b"
},
"aarch64_windows": {
"etag": "0x8DE86ED14385B2B",
"hash": "138047f5a495629a1fe60734706ab1d89fc8ed68eeab3dbd0b1865eab108f7b6"
}
},
"0.9.8": {
"x86_64_linux_musl": {

168
manifests/uv.json generated
View File

@@ -1,46 +1,192 @@
{
"rust_crate": null,
"rust_crate": "uv",
"template": {
"x86_64_linux_musl": {
"url": "https://github.com/astral-sh/uv/releases/download/${version}/uv-x86_64-unknown-linux-musl.tar.gz",
"bin": "uv-x86_64-unknown-linux-musl/uv"
"bin": [
"uv-x86_64-unknown-linux-musl/uv",
"uv-x86_64-unknown-linux-musl/uvx"
]
},
"x86_64_macos": {
"url": "https://github.com/astral-sh/uv/releases/download/${version}/uv-x86_64-apple-darwin.tar.gz",
"bin": "uv-x86_64-apple-darwin/uv"
"bin": [
"uv-x86_64-apple-darwin/uv",
"uv-x86_64-apple-darwin/uvx"
]
},
"x86_64_windows": {
"url": "https://github.com/astral-sh/uv/releases/download/${version}/uv-x86_64-pc-windows-msvc.zip",
"bin": "uv.exe"
"bin": [
"uv.exe",
"uvw.exe",
"uvx.exe"
]
},
"aarch64_linux_musl": {
"url": "https://github.com/astral-sh/uv/releases/download/${version}/uv-aarch64-unknown-linux-musl.tar.gz",
"bin": "uv-aarch64-unknown-linux-musl/uv"
"bin": [
"uv-aarch64-unknown-linux-musl/uv",
"uv-aarch64-unknown-linux-musl/uvx"
]
},
"aarch64_macos": {
"url": "https://github.com/astral-sh/uv/releases/download/${version}/uv-aarch64-apple-darwin.tar.gz",
"bin": "uv-aarch64-apple-darwin/uv"
"bin": [
"uv-aarch64-apple-darwin/uv",
"uv-aarch64-apple-darwin/uvx"
]
},
"aarch64_windows": {
"url": "https://github.com/astral-sh/uv/releases/download/${version}/uv-aarch64-pc-windows-msvc.zip",
"bin": "uv.exe"
"bin": [
"uv.exe",
"uvw.exe",
"uvx.exe"
]
},
"powerpc64le_linux_gnu": {
"url": "https://github.com/astral-sh/uv/releases/download/${version}/uv-powerpc64le-unknown-linux-gnu.tar.gz",
"bin": "uv-powerpc64le-unknown-linux-gnu/uv"
"bin": [
"uv-powerpc64le-unknown-linux-gnu/uv",
"uv-powerpc64le-unknown-linux-gnu/uvx"
]
},
"riscv64_linux_gnu": {
"url": "https://github.com/astral-sh/uv/releases/download/${version}/uv-riscv64gc-unknown-linux-gnu.tar.gz",
"bin": "uv-riscv64gc-unknown-linux-gnu/uv"
"bin": [
"uv-riscv64gc-unknown-linux-gnu/uv",
"uv-riscv64gc-unknown-linux-gnu/uvx"
]
},
"s390x_linux_gnu": {
"url": "https://github.com/astral-sh/uv/releases/download/${version}/uv-s390x-unknown-linux-gnu.tar.gz",
"bin": "uv-s390x-unknown-linux-gnu/uv"
"bin": [
"uv-s390x-unknown-linux-gnu/uv",
"uv-s390x-unknown-linux-gnu/uvx"
]
}
},
"license_markdown": "[Apache-2.0](https://github.com/astral-sh/uv/blob/main/LICENSE-APACHE) OR [MIT](https://github.com/astral-sh/uv/blob/main/LICENSE-MIT)",
"latest": {
"version": "0.10.12"
"version": "0.11.2"
},
"0.11": {
"version": "0.11.2"
},
"0.11.2": {
"x86_64_linux_musl": {
"etag": "0x8DE8B7F323A25EC",
"hash": "4700d9fc75734247587deb3e25dd2c6c24f4ac69e8fe91d6acad4a6013115c06"
},
"x86_64_macos": {
"etag": "0x8DE8B7F31C027DB",
"hash": "a9c3653245031304c50dd60ac0301bf6c112e12c38c32302a71d4fa6a63ba2cb"
},
"x86_64_windows": {
"etag": "0x8DE8B7F323790C2",
"hash": "171b7ccda1bbd562da6babeffcf533a1c6cc7862cf998da826e1db534fc43e48"
},
"aarch64_linux_musl": {
"etag": "0x8DE8B7F2F886D82",
"hash": "275d91dd1f1955136591e7ec5e1fa21e84d0d37ead7da7c35c3683df748d9855"
},
"aarch64_macos": {
"etag": "0x8DE8B7F2EE6C8C0",
"hash": "4beaa9550f93ef7f0fc02f7c28c9c48cd61fe30db00f5ac8947e0a425c3fb282"
},
"aarch64_windows": {
"etag": "0x8DE8B7F2F211F2C",
"hash": "ffdded8338205f53727b51d404563a5ac8eaa9aea53279a7b7c42177e11d478c"
},
"powerpc64le_linux_gnu": {
"etag": "0x8DE8B7F30FB6B17",
"hash": "3f3a50e99364efc8ff7add10e79757a2b8458700a38180ec5f313524481b9fbc"
},
"riscv64_linux_gnu": {
"etag": "0x8DE8B7F313C97AB",
"hash": "e56a93f0ff21d6908461a6ecbf465beae19ae22719f900284abb7680bd07ec41"
},
"s390x_linux_gnu": {
"etag": "0x8DE8B7F3185D17B",
"hash": "42ebe40775f2a77a514fa47399fde86473bf35bd33b6896c6410a0309fc4d205"
}
},
"0.11.1": {
"x86_64_linux_musl": {
"etag": "0x8DE89FB8460A78F",
"hash": "4e949471a95b37088a1ff1a585f69abed4d3cd3f921f50709a46b6ba62986d38"
},
"x86_64_macos": {
"etag": "0x8DE89FB83BE673F",
"hash": "2103670e8e949605e51926c7b953923ff6f6befbfb55aee928f5e760c9c910f8"
},
"x86_64_windows": {
"etag": "0x8DE89FB83DC2E07",
"hash": "6659250cebbd3bb6ee48bcb21a3f0c6656450d63fb97f0f069bcb532bdb688ed"
},
"aarch64_linux_musl": {
"etag": "0x8DE89FB817388B2",
"hash": "bd04ffce77ee8d77f39823c13606183581847c2f5dcd704f2ea0f15e376b1a27"
},
"aarch64_macos": {
"etag": "0x8DE89FB80F6A7B9",
"hash": "f7815f739ed5d0e4202e6292acedb8659b9ae7de663d07188d8c6cbd7f96303f"
},
"aarch64_windows": {
"etag": "0x8DE89FB8121316A",
"hash": "b789db0c1504dd3b02c090bd5783487497cc46cc2eb71754874cdd1ef59eb52a"
},
"powerpc64le_linux_gnu": {
"etag": "0x8DE89FB82F0DAD3",
"hash": "e42d2abfac46f57564789e2bfa6dbea4ae3135892e36ae066ba0ae77b69bb676"
},
"riscv64_linux_gnu": {
"etag": "0x8DE89FB8329D330",
"hash": "5e2c757b35dab015ad37f74ee3e060208390b5f4defb6684876f1be0664f3f6e"
},
"s390x_linux_gnu": {
"etag": "0x8DE89FB838E8C5E",
"hash": "4208173c74e29572b799178709b5ed5828b24888659f944a4b47c0aaf78b42d2"
}
},
"0.11.0": {
"x86_64_linux_musl": {
"etag": "0x8DE8928B52FBBAD",
"hash": "bf6b0757c73d1726faa2a819b155d4d864919a95766720215d78fdcd09d42d26"
},
"x86_64_macos": {
"etag": "0x8DE8928B4D6406A",
"hash": "31aaec764166af8885cf99321fd6ed24fef80225a6f26ed1ae8ce04111688a7e"
},
"x86_64_windows": {
"etag": "0x8DE8928B4E8A258",
"hash": "e21d00b172df83531564a95e75a2bdc0c59b471dbb3515f0c1b4d6ef657dc451"
},
"aarch64_linux_musl": {
"etag": "0x8DE8928B283EFC0",
"hash": "658be4b8ec905635f1295468d4d5120d9e1ab1722eec9a104473ce993590babe"
},
"aarch64_macos": {
"etag": "0x8DE8928B1C32610",
"hash": "0c0f32c6a3473c5928aff96c3233715edfc79290e892f255cac93710cde7b91a"
},
"aarch64_windows": {
"etag": "0x8DE8928B21C538F",
"hash": "95419e04a3ef5f13fb2a06bd6d787ba80a9d8981d6f097780e5a979817a2879d"
},
"powerpc64le_linux_gnu": {
"etag": "0x8DE8928B425DF0C",
"hash": "29f17fb43595492b1a36cda57df7adad74183132df32799d32897268ff4e26dd"
},
"riscv64_linux_gnu": {
"etag": "0x8DE8928B411AA71",
"hash": "84ef37dda1003c5b65fa6c8f84242d35a7fcc84cc5ea9490d702edc36cad1f67"
},
"s390x_linux_gnu": {
"etag": "0x8DE8928B46BC14C",
"hash": "b25be62f3b642348a2fece5c658624586661b8d1103891ab6903768b0529edc4"
}
},
"0.10": {
"version": "0.10.12"

30
manifests/vacuum.json generated
View File

@@ -22,10 +22,36 @@
},
"license_markdown": "[MIT](https://github.com/daveshanley/vacuum/blob/main/LICENSE)",
"latest": {
"version": "0.25.2"
"version": "0.25.3"
},
"0.25": {
"version": "0.25.2"
"version": "0.25.3"
},
"0.25.3": {
"x86_64_linux_musl": {
"etag": "0x8DE8DEA35C78445",
"hash": "dbcd9ea50b0ac74c181d905a1d162e2457f8bbc619d0f8e974ff3b38dcd23384"
},
"x86_64_macos": {
"etag": "0x8DE8DEA3675C50B",
"hash": "450964b9f2cbe9b63403bfe7b07cd2b3fb16eded4668c9e5749b9b469d288290"
},
"x86_64_windows": {
"etag": "0x8DE8DEA35DB442D",
"hash": "00a1a230fe2dbd45ee11e579d7d8d00daf83fa83a083fd66044514fdfd73e993"
},
"aarch64_linux_musl": {
"etag": "0x8DE8DEA35C7AB2A",
"hash": "a2db87faa3e04c2e0f8b5dd2c9162a33829eda0a1196ed49e3562a1a9434d3e0"
},
"aarch64_macos": {
"etag": "0x8DE8DEA367A7AB1",
"hash": "9ab96a00628c69c6aa4a62fcafb6d8cb8de792db94adb53c00344d19ff0c4af6"
},
"aarch64_windows": {
"etag": "0x8DE8DEA36512824",
"hash": "ed70ee1e9af46ba69c79b8d4bddea59c0bcc37613f92d12a77fe327f4832089d"
}
},
"0.25.2": {
"x86_64_linux_musl": {

View File

@@ -44,10 +44,32 @@
},
"license_markdown": "[MIT](https://github.com/wasm-bindgen/wasm-bindgen/blob/main/LICENSE-MIT) OR [Apache-2.0](https://github.com/wasm-bindgen/wasm-bindgen/blob/main/LICENSE-APACHE)",
"latest": {
"version": "0.2.114"
"version": "0.2.115"
},
"0.2": {
"version": "0.2.114"
"version": "0.2.115"
},
"0.2.115": {
"x86_64_linux_musl": {
"etag": "0x8DE8C5096D0CA3A",
"hash": "494df943e4e30a48ea2832e5a299e0e0f52d23f1e037b052cf401f467b820316"
},
"x86_64_macos": {
"etag": "0x8DE8C5096BDCCC1",
"hash": "bc9ba4f200a7a7132b61a28d0fc93692caeb880c1547fb4369f18baa3285eb91"
},
"x86_64_windows": {
"etag": "0x8DE8C5096A81344",
"hash": "370ebd36ffc110346956407793064e3d0b5e77c83ca69ef127a286a665d13636"
},
"aarch64_linux_gnu": {
"etag": "0x8DE8C5096CD7296",
"hash": "f4cc35232554e04d72b61158bcd314ef2b1aa28e7c45d7aad8e76eb01b42c299"
},
"aarch64_macos": {
"etag": "0x8DE8C5096F6C51A",
"hash": "1184392b5468ca63b65f75f95f38110005aa168f6d9c39ca70c0585044d6508b"
}
},
"0.2.114": {
"x86_64_linux_musl": {

View File

@@ -4,6 +4,9 @@
"rust_crate": "${package}",
"bin": "mise/bin/${package}${exe}",
"version_range": ">= 2025.9.7",
"signing": {
"kind": "custom"
},
"platform": {
"x86_64_linux_musl": {
"asset_name": "${package}-v${version}-${rust_target_os}-x64-musl.tar.gz"

View File

@@ -3,6 +3,10 @@
"tag_prefix": "v",
"bin": "${package}${exe}",
"version_range": ">= 0.83.0",
"signing": {
"version_range": ">= 0.104.0",
"kind": "custom"
},
"platform": {
"x86_64_linux_musl": {
"asset_name": "${package}_${version}_linux_amd64.tar.gz"

View File

@@ -2,6 +2,7 @@
"repository": "https://github.com/astral-sh/uv",
"license_markdown": "[Apache-2.0](https://github.com/astral-sh/uv/blob/main/LICENSE-APACHE) OR [MIT](https://github.com/astral-sh/uv/blob/main/LICENSE-MIT)",
"tag_prefix": "",
"rust_crate": "${package}",
"version_range": ">= 0.8.16",
"signing": {
"version_range": ">= 0.9.13",
@@ -11,42 +12,26 @@
}
}
},
"asset_name": "${package}-${rust_target}.tar.gz",
"bin": [
"${package}-${rust_target}/${package}${exe}",
"${package}-${rust_target}/${package}x${exe}"
],
"platform": {
"x86_64_linux_musl": {
"asset_name": "${package}-x86_64-unknown-linux-musl.tar.gz",
"bin": "${package}-x86_64-unknown-linux-musl/${package}${exe}"
},
"x86_64_macos": {
"asset_name": "${package}-x86_64-apple-darwin.tar.gz",
"bin": "${package}-x86_64-apple-darwin/${package}${exe}"
},
"x86_64_linux_musl": {},
"x86_64_macos": {},
"x86_64_windows": {
"asset_name": "${package}-x86_64-pc-windows-msvc.zip",
"bin": "${package}${exe}"
},
"aarch64_linux_musl": {
"asset_name": "${package}-aarch64-unknown-linux-musl.tar.gz",
"bin": "${package}-aarch64-unknown-linux-musl/${package}${exe}"
},
"aarch64_macos": {
"asset_name": "${package}-aarch64-apple-darwin.tar.gz",
"bin": "${package}-aarch64-apple-darwin/${package}${exe}"
"asset_name": "${package}-${rust_target}.zip",
"bin": ["${package}${exe}", "${package}w${exe}", "${package}x${exe}"]
},
"aarch64_linux_musl": {},
"aarch64_macos": {},
"aarch64_windows": {
"asset_name": "${package}-aarch64-pc-windows-msvc.zip",
"bin": "${package}${exe}"
"asset_name": "${package}-${rust_target}.zip",
"bin": ["${package}${exe}", "${package}w${exe}", "${package}x${exe}"]
},
"powerpc64le_linux_gnu": {
"asset_name": "${package}-powerpc64le-unknown-linux-gnu.tar.gz",
"bin": "${package}-powerpc64le-unknown-linux-gnu/${package}${exe}"
},
"riscv64_linux_gnu": {
"asset_name": "${package}-riscv64gc-unknown-linux-gnu.tar.gz",
"bin": "${package}-riscv64gc-unknown-linux-gnu/${package}${exe}"
},
"s390x_linux_gnu": {
"asset_name": "${package}-s390x-unknown-linux-gnu.tar.gz",
"bin": "${package}-s390x-unknown-linux-gnu/${package}${exe}"
}
"powerpc64le_linux_gnu": {},
"riscv64_linux_gnu": {},
"s390x_linux_gnu": {}
}
}

View File

@@ -61,6 +61,18 @@ impl BaseManifest {
if self.platform.is_empty() {
panic!("At least one platform must be specified");
}
if let Some(website) = &self.website {
if website.is_empty() || *website == self.repository {
panic!(
"Please do not put the repository in website, or set website to an empty value"
);
}
}
if let Some(license_markdown) = &self.license_markdown {
if license_markdown.is_empty() {
panic!("license_markdown can not be an empty value");
}
}
}
}
@@ -83,6 +95,8 @@ pub enum SigningKind {
/// public key: package.metadata.binstall.signing.pubkey at Cargo.toml
/// <https://github.com/cargo-bins/cargo-binstall/blob/HEAD/SIGNING.md>
MinisignBinstall,
/// tool-specific
Custom,
}
#[derive(Debug, Deserialize)]

View File

@@ -9,7 +9,7 @@ use std::{
env,
ffi::OsStr,
io::Read as _,
path::Path,
path::{Path, PathBuf},
sync::{LazyLock, RwLock},
time::Duration,
};
@@ -20,9 +20,10 @@ use install_action_internal_codegen::{
BaseManifest, HostPlatform, Manifest, ManifestDownloadInfo, ManifestRef, ManifestTemplate,
ManifestTemplateDownloadInfo, Manifests, SigningKind, Version, workspace_root,
};
use serde::de::DeserializeOwned;
use spdx::expression::{ExprNode, ExpressionReq, Operator};
fn main() -> Result<()> {
fn main() {
let args: Vec<_> = env::args().skip(1).collect();
if args.is_empty() || args.iter().any(|arg| arg.starts_with('-')) {
println!(
@@ -30,7 +31,7 @@ fn main() -> Result<()> {
);
std::process::exit(1);
}
let package = &args[0];
let package = &*args[0];
let version_req = args.get(1);
let version_req_given = version_req.is_some();
let skip_existing_manifest_versions = std::env::var("SKIP_EXISTING_MANIFEST_VERSIONS").is_ok();
@@ -38,23 +39,25 @@ fn main() -> Result<()> {
let workspace_root = workspace_root();
let manifest_path = &workspace_root.join("manifests").join(format!("{package}.json"));
let download_cache_dir = &workspace_root.join("tools/codegen/tmp/cache").join(package);
fs::create_dir_all(manifest_path.parent().unwrap())?;
fs::create_dir_all(download_cache_dir)?;
fs::create_dir_all(manifest_path.parent().unwrap()).unwrap();
fs::create_dir_all(download_cache_dir).unwrap();
eprintln!("download cache: {}", download_cache_dir.display());
let mut base_info: BaseManifest = serde_json::from_slice(&fs::read(
workspace_root.join("tools/codegen/base").join(format!("{package}.json")),
)?)?;
let mut base_info: BaseManifest = serde_json::from_slice(
&fs::read(workspace_root.join("tools/codegen/base").join(format!("{package}.json")))
.unwrap(),
)
.unwrap();
base_info.validate();
let repo = base_info
.repository
.strip_prefix("https://github.com/")
.context("repository must start with https://github.com/")?;
.context("repository must start with https://github.com/")
.unwrap();
eprintln!("downloading metadata from {GITHUB_API_START}repos/{repo}");
let repo_info: github::RepoMetadata =
download(&format!("{GITHUB_API_START}repos/{repo}"))?.into_json()?;
let repo_info: github::RepoMetadata = download_json(&format!("{GITHUB_API_START}repos/{repo}"));
eprintln!("downloading releases from {GITHUB_API_START}repos/{repo}/releases");
let mut releases: github::Releases = vec![];
@@ -62,10 +65,9 @@ fn main() -> Result<()> {
// is greater than 100, multiple fetches are needed.
for page in 1.. {
let per_page = 100;
let mut r: github::Releases = download(&format!(
let mut r: github::Releases = download_json(&format!(
"{GITHUB_API_START}repos/{repo}/releases?per_page={per_page}&page={page}"
))?
.into_json()?;
));
// If version_req is latest, it is usually sufficient to look at the latest 100 releases.
if r.len() < per_page || version_req.is_some_and(|req| req == "latest") {
releases.append(&mut r);
@@ -103,23 +105,25 @@ fn main() -> Result<()> {
.rust_crate
.as_ref()
.map(|s| replace_vars(s, package, None, None, base_info.rust_crate.as_deref()))
.transpose()?;
.transpose()
.unwrap();
if let Some(crate_name) = &base_info.rust_crate {
eprintln!("downloading crate info from https://crates.io/api/v1/crates/{crate_name}");
let info = download(&format!("https://crates.io/api/v1/crates/{crate_name}"))?
.into_json::<crates_io::Crate>()?;
let info: crates_io::Crate =
download_json(&format!("https://crates.io/api/v1/crates/{crate_name}"));
let latest_version = &info.versions[0].num;
crates_io_version_detail = Some(
download(&format!("https://crates.io/api/v1/crates/{crate_name}/{latest_version}"))?
.into_json::<crates_io::VersionMetadata>()?
.version,
download_json::<crates_io::VersionMetadata>(&format!(
"https://crates.io/api/v1/crates/{crate_name}/{latest_version}"
))
.version,
);
if let Some(crate_repository) = info.crate_.repository.clone() {
if !crate_repository.to_lowercase().starts_with(&base_info.repository.to_lowercase()) {
panic!("repository {crate_repository} from crates.io differs from base manifest");
}
} else if crate_name != "zola" {
} else {
panic!("crate metadata does not include a repository");
}
@@ -139,7 +143,7 @@ fn main() -> Result<()> {
if manifest_path.is_file() {
println!("loading pre-existing manifest {}", manifest_path.display());
match serde_json::from_slice(&fs::read(manifest_path)?) {
match serde_json::from_slice(&fs::read(manifest_path).unwrap()) {
Ok(m) => {
manifests = m;
for (k, manifest) in &mut manifests.map {
@@ -165,18 +169,8 @@ fn main() -> Result<()> {
}
}
// Check website
if let Some(website) = base_info.website {
if website.is_empty() || website == base_info.repository {
panic!("Please do not put the repository in website, or set website to an empty value");
}
}
// Populate license_markdown from the base manifest if present.
if let Some(license_markdown) = base_info.license_markdown {
if license_markdown.is_empty() {
panic!("license_markdown can not be an empty value");
}
manifests.license_markdown = license_markdown;
}
@@ -184,7 +178,7 @@ fn main() -> Result<()> {
if !manifests.license_markdown.is_empty() {
let urls = get_license_markdown_urls(&manifests.license_markdown);
if urls.is_empty() {
bail!("Could not find URLs in license_markdown: {}.", manifests.license_markdown);
panic!("Could not find URLs in license_markdown: {}.", manifests.license_markdown);
}
for url in urls {
if let Err(err) = github_head(&url) {
@@ -207,7 +201,7 @@ fn main() -> Result<()> {
spdx_id
}
_ => {
bail!(
panic!(
"No license SPDX found in crates.io or GitHub metadata.\n\
Please set license_markdown in the base manifest"
);
@@ -218,7 +212,7 @@ fn main() -> Result<()> {
{
manifests.license_markdown = license_markdown;
} else {
bail!(
panic!(
"Unable to verify license file(s) in the repo for license {license}.\n\
Please set license_markdown in the base manifest"
);
@@ -227,13 +221,13 @@ fn main() -> Result<()> {
let version_req: semver::VersionReq = match version_req {
_ if latest_only => {
let req = format!("={}", releases.first_key_value().unwrap().0.0).parse()?;
let req = format!("={}", releases.first_key_value().unwrap().0.0).parse().unwrap();
eprintln!("update manifest for versions '{req}'");
req
}
None => match base_info.version_range {
Some(version_range) => version_range.parse()?,
None => ">= 0.0.1".parse()?, // HACK: ignore pre-releases
Some(version_range) => version_range.parse().unwrap(),
None => ">= 0.0.1".parse().unwrap(), // HACK: ignore pre-releases
},
Some(version_req) => {
for version in manifests.map.keys() {
@@ -249,18 +243,26 @@ fn main() -> Result<()> {
let req = if version_req == "latest" {
// TODO: this should check all missing versions
if manifests.map.is_empty() {
format!("={}", releases.first_key_value().unwrap().0.0).parse()?
format!("={}", releases.first_key_value().unwrap().0.0).parse().unwrap()
} else {
format!(">={}", semver_versions.last().unwrap()).parse()?
format!(">={}", semver_versions.last().unwrap()).parse().unwrap()
}
} else {
version_req.parse()?
version_req.parse().unwrap()
};
eprintln!("update manifest for versions '{req}'");
req
}
};
let signing_version_req: Option<semver::VersionReq> =
base_info.signing.as_ref().map(|signing| {
match &signing.version_range {
Some(version_range) => version_range.parse().unwrap(),
None => ">= 0.0.1".parse().unwrap(), // HACK: ignore pre-releases
}
});
let mut buf = vec![];
let mut buf2 = vec![];
for (Reverse(semver_version), (version, release)) in &releases {
@@ -282,11 +284,154 @@ fn main() -> Result<()> {
continue;
}
let signing_version_req: Option<semver::VersionReq> = match &base_info.signing {
let mut verified_checksum: Option<Vec<_>> = None;
match &base_info.signing {
Some(signing) => {
match &signing.version_range {
Some(version_range) => Some(version_range.parse()?),
None => Some(">= 0.0.1".parse()?), // HACK: ignore pre-releases
if let SigningKind::Custom = signing.kind {
match package {
_ if !signing_version_req.as_ref().unwrap().matches(semver_version) => {}
"mise" => {
// Refs: https://github.com/jdx/mise/blob/v2026.3.9/src/minisign.rs
let crates_io_info = crates_io_info.as_ref().unwrap();
let [checksum, sig] =
["SHASUMS256.txt", "SHASUMS256.txt.minisig"].map(|f| {
let Some(asset) =
release.assets.iter().find(|asset| asset.name == f)
else {
// There is broken release which has no release assets: https://github.com/jdx/mise/releases/tag/v2026.2.14
return PathBuf::new();
};
let download_cache =
download_cache_dir.join(format!("{version}-{f}"));
let url = &asset.browser_download_url;
eprint!("downloading {url} for signature verification ... ");
if download_cache.is_file() {
eprintln!("already downloaded");
} else {
download_to_buf(url, &mut buf);
eprintln!("download complete");
fs::write(&download_cache, &buf).unwrap();
buf.clear();
}
download_cache
});
if checksum.as_os_str().is_empty() || sig.as_os_str().is_empty() {
continue;
}
let v = crates_io_info
.versions
.iter()
.find(|v| v.num == *semver_version)
.unwrap();
let url = format!("https://crates.io{}", v.dl_path);
let pubkey_download_cache =
&download_cache_dir.join(format!("{version}-minisign.pub"));
eprint!("downloading {url} for signature verification ... ");
if pubkey_download_cache.is_file() {
eprintln!("already downloaded");
} else {
download_to_buf(&url, &mut buf);
let hash = ring::digest::digest(&ring::digest::SHA256, &buf);
if format!("{hash:?}").strip_prefix("SHA256:").unwrap()
!= v.checksum
{
panic!("checksum mismatch for {url}");
}
let decoder = flate2::read::GzDecoder::new(&*buf);
let mut archive = tar::Archive::new(decoder);
for entry in archive.entries().unwrap() {
let mut entry = entry.unwrap();
let path = entry.path().unwrap();
if path.file_name() == Some(OsStr::new("minisign.pub")) {
entry.unpack(pubkey_download_cache).unwrap();
break;
}
}
buf.clear();
eprintln!("download complete");
}
let pubkey =
minisign_verify::PublicKey::from_file(pubkey_download_cache)
.unwrap();
eprint!("verifying checksum file for {package}@{version} ... ");
let allow_legacy = false;
pubkey
.verify(
&fs::read(&checksum).unwrap(),
&minisign_verify::Signature::from_file(sig).unwrap(),
allow_legacy,
)
.unwrap();
verified_checksum = Some(
fs::read_to_string(checksum)
.unwrap()
.lines()
.filter_map(|l| l.split_once(" "))
.map(|(h, f)| {
(f.trim_ascii().to_owned(), h.trim_ascii().to_owned())
})
.collect(),
);
eprintln!("done");
}
"syft" => {
// Refs: https://oss.anchore.com/docs/installation/verification/
let [checksum, certificate, signature] =
["checksums.txt", "checksums.txt.pem", "checksums.txt.sig"].map(
|f| {
let asset = release
.assets
.iter()
.find(|asset| asset.name.ends_with(f))
.unwrap();
let download_cache =
download_cache_dir.join(format!("{version}-{f}"));
let url = &asset.browser_download_url;
eprint!(
"downloading {url} for signature verification ... "
);
if download_cache.is_file() {
eprintln!("already downloaded");
} else {
download_to_buf(url, &mut buf);
eprintln!("download complete");
fs::write(&download_cache, &buf).unwrap();
buf.clear();
}
download_cache
},
);
eprint!("verifying checksum file for {package}@{version} ... ");
cmd!(
"cosign",
"verify-blob",
&checksum,
"--certificate",
certificate,
"--signature",
signature,
"--certificate-identity-regexp",
format!("https://github\\.com/{repo}/\\.github/workflows/.+"),
"--certificate-oidc-issuer",
"https://token.actions.githubusercontent.com"
)
.run()
.unwrap();
verified_checksum = Some(
fs::read_to_string(checksum)
.unwrap()
.lines()
.filter_map(|l| l.split_once(" "))
.map(|(h, f)| {
(f.trim_ascii().to_owned(), h.trim_ascii().to_owned())
})
.collect(),
);
eprintln!("done");
}
_ => {}
}
}
}
None => {
@@ -294,24 +439,29 @@ fn main() -> Result<()> {
asset.name.contains(".asc")
|| asset.name.contains(".gpg")
|| asset.name.contains(".sig")
|| asset.name.contains(".minisig")
|| asset.name.contains(".pem")
|| asset.name.contains(".crt")
|| asset.name.contains(".key")
|| asset.name.contains(".pub")
}) {
eprintln!(
"{package} may supports other signing verification method using {}",
"{package} may support other signature verification methods using {}",
asset.name
);
}
None
}
};
}
let mut download_info = BTreeMap::new();
let mut pubkey = None;
let mut minisign_binstall_pubkey = None;
for (&platform, base_download_info) in &base_info.platform {
let asset_names = base_download_info
.asset_name
.as_ref()
.or(base_info.asset_name.as_ref())
.with_context(|| format!("asset_name is needed for {package} on {platform:?}"))?
.with_context(|| format!("asset_name is needed for {package} on {platform:?}"))
.unwrap()
.as_slice()
.iter()
.map(|asset_name| {
@@ -323,7 +473,8 @@ fn main() -> Result<()> {
base_info.rust_crate.as_deref(),
)
})
.collect::<Result<Vec<_>>>()?;
.collect::<Result<Vec<_>>>()
.unwrap();
let (url, digest, asset_name) = match asset_names.iter().find_map(|asset_name| {
release
.assets
@@ -345,7 +496,7 @@ fn main() -> Result<()> {
"{version}-{platform:?}-{}",
Path::new(&url).file_name().unwrap().to_str().unwrap()
));
let response = download(&url)?;
let response = download(&url).unwrap();
let etag =
response.header("etag").expect("binary should have an etag").replace('\"', "");
@@ -365,11 +516,11 @@ fn main() -> Result<()> {
if download_cache.is_file() {
eprintln!("already downloaded");
fs::File::open(download_cache)?.read_to_end(&mut buf)?; // Not buffered because it is read at once.
fs::File::open(download_cache).unwrap().read_to_end(&mut buf).unwrap(); // Not buffered because it is read at once.
} else {
response.into_reader().read_to_end(&mut buf)?;
response.into_reader().read_to_end(&mut buf).unwrap();
eprintln!("download complete");
fs::write(download_cache, &buf)?;
fs::write(download_cache, &buf).unwrap();
}
eprintln!("getting sha256 hash for {url}");
@@ -377,7 +528,7 @@ fn main() -> Result<()> {
let hash = format!("{hash:?}").strip_prefix("SHA256:").unwrap().to_owned();
if let Some(digest) = digest {
if hash != digest.strip_prefix("sha256:").unwrap() {
bail!(
panic!(
"digest mismatch between GitHub release page and actually downloaded file"
);
}
@@ -401,9 +552,15 @@ fn main() -> Result<()> {
signer_workflow,
&download_cache
)
.run()?;
.run()
.unwrap();
}
SigningKind::MinisignBinstall => {
let Some(crates_io_info) = &crates_io_info else {
panic!(
"signing kind minisign-binstall is supported only for rust crate"
);
};
let url = url.clone() + ".sig";
let sig_download_cache = &download_cache.with_extension(format!(
"{}.sig",
@@ -412,19 +569,14 @@ fn main() -> Result<()> {
eprint!("downloading {url} for signature validation ... ");
let sig = if sig_download_cache.is_file() {
eprintln!("already downloaded");
minisign_verify::Signature::from_file(sig_download_cache)?
minisign_verify::Signature::from_file(sig_download_cache).unwrap()
} else {
let buf = download(&url)?.into_string()?;
let buf = download(&url).unwrap().into_string().unwrap();
eprintln!("download complete");
fs::write(sig_download_cache, &buf)?;
minisign_verify::Signature::decode(&buf)?
fs::write(sig_download_cache, &buf).unwrap();
minisign_verify::Signature::decode(&buf).unwrap()
};
let Some(crates_io_info) = &crates_io_info else {
bail!(
"signing kind minisign-binstall is supported only for rust crate"
);
};
let v = crates_io_info
.versions
.iter()
@@ -437,28 +589,29 @@ fn main() -> Result<()> {
if crate_download_cache.is_file() {
eprintln!("already downloaded");
} else {
download(&url)?.into_reader().read_to_end(&mut buf2)?;
download_to_buf(&url, &mut buf2);
let hash = ring::digest::digest(&ring::digest::SHA256, &buf2);
if format!("{hash:?}").strip_prefix("SHA256:").unwrap() != v.checksum {
bail!("checksum mismatch for {url}");
panic!("checksum mismatch for {url}");
}
let decoder = flate2::read::GzDecoder::new(&*buf2);
let mut archive = tar::Archive::new(decoder);
for entry in archive.entries()? {
let mut entry = entry?;
let path = entry.path()?;
for entry in archive.entries().unwrap() {
let mut entry = entry.unwrap();
let path = entry.path().unwrap();
if path.file_name() == Some(OsStr::new("Cargo.toml")) {
entry.unpack(crate_download_cache)?;
entry.unpack(crate_download_cache).unwrap();
break;
}
}
buf2.clear();
eprintln!("download complete");
}
if pubkey.is_none() {
if minisign_binstall_pubkey.is_none() {
let cargo_manifest = toml::de::from_str::<cargo_manifest::Manifest>(
&fs::read_to_string(crate_download_cache)?,
)?;
&fs::read_to_string(crate_download_cache).unwrap(),
)
.unwrap();
eprintln!(
"algorithm: {}",
cargo_manifest.package.metadata.binstall.signing.algorithm
@@ -471,16 +624,42 @@ fn main() -> Result<()> {
cargo_manifest.package.metadata.binstall.signing.algorithm,
"minisign"
);
pubkey = Some(minisign_verify::PublicKey::from_base64(
&cargo_manifest.package.metadata.binstall.signing.pubkey,
)?);
minisign_binstall_pubkey = Some(
minisign_verify::PublicKey::from_base64(
&cargo_manifest.package.metadata.binstall.signing.pubkey,
)
.unwrap(),
);
}
let pubkey = pubkey.as_ref().unwrap();
let pubkey = minisign_binstall_pubkey.as_ref().unwrap();
eprint!("verifying signature for {bin_url} ... ");
let allow_legacy = false;
pubkey.verify(&buf, &sig, allow_legacy)?;
pubkey.verify(&buf, &sig, allow_legacy).unwrap();
eprintln!("done");
}
SigningKind::Custom => {
if let Some(verified_checksum) = &verified_checksum {
let asset_name_cwd = format!("./{asset_name}");
let mut checked = false;
for (f, h) in verified_checksum {
if *f == asset_name || *f == asset_name_cwd {
checked = true;
assert_eq!(
hash, *h,
"verified checksum doesn't match with sha256 hash of {asset_name} in {package}@{version}"
);
}
}
assert!(
checked,
"{asset_name} not found in verified checksum for {package}@{version}"
);
} else {
unimplemented!(
"unimplemented tool-specific signing handling for {package}"
);
}
}
}
}
@@ -563,7 +742,7 @@ fn main() -> Result<()> {
// update an existing manifests.json to avoid discarding work done in the event of a fetch error.
if existing_manifest.is_some() && !version_req_given {
write_manifests(manifest_path, &manifests.clone())?;
write_manifests(manifest_path, &manifests.clone()).unwrap();
eprintln!("wrote {} with incomplete data", manifest_path.display());
}
}
@@ -636,7 +815,7 @@ fn main() -> Result<()> {
.values()
.any(|m| matches!(m, ManifestRef::Real(m) if m.download_info.contains_key(&p)))
{
bail!(
panic!(
"platform list in base manifest for {package} contains {p:?}, \
but result manifest doesn't contain it; \
consider removing {p:?} from platform list in base manifest"
@@ -680,7 +859,7 @@ fn main() -> Result<()> {
// until 2027-08, people aren't paying much attention to it at this time.
continue;
}
bail!(
panic!(
"platform list in base manifest for {package} contains {p:?}, \
but latest release ({latest_version}) doesn't contain it; \
consider marking {latest_version} as broken by adding 'broken' field to base manifest"
@@ -720,10 +899,8 @@ fn main() -> Result<()> {
manifests.rust_crate = base_info.rust_crate;
write_manifests(manifest_path, &manifests)?;
write_manifests(manifest_path, &manifests).unwrap();
eprintln!("wrote {}", manifest_path.display());
Ok(())
}
fn write_manifests(manifest_path: &Path, manifests: &Manifests) -> Result<()> {
@@ -858,6 +1035,16 @@ fn download(url: &str) -> Result<ureq::Response> {
Err(last_error.unwrap().into())
}
#[track_caller]
fn download_to_buf(url: &str, buf: &mut Vec<u8>) {
download(url).unwrap().into_reader().read_to_end(buf).unwrap();
}
#[track_caller]
fn download_json<T: DeserializeOwned>(url: &str) -> T {
download(url).unwrap().into_json().unwrap()
}
fn github_head(url: &str) -> Result<()> {
eprintln!("fetching head of {url} ..");
let mut token = GITHUB_TOKENS.get(url);

View File

@@ -6,7 +6,6 @@ use std::{
path::PathBuf,
};
use anyhow::Result;
use fs_err as fs;
use install_action_internal_codegen::{BaseManifest, Manifests, workspace_root};
@@ -32,7 +31,7 @@ const FOOTER: &str = "
[cargo-binstall]: https://github.com/cargo-bins/cargo-binstall
";
fn main() -> Result<()> {
fn main() {
let args: Vec<_> = env::args().skip(1).collect();
if !args.is_empty() || args.iter().any(|arg| arg.starts_with('-')) {
println!(
@@ -72,9 +71,10 @@ fn main() -> Result<()> {
name.set_extension("");
let name = name.to_string_lossy().to_string();
let base_info: BaseManifest =
serde_json::from_slice(&fs::read(base_info_dir.join(file_name.clone()))?)?;
serde_json::from_slice(&fs::read(base_info_dir.join(file_name.clone())).unwrap())
.unwrap();
let manifests: Manifests =
serde_json::from_slice(&fs::read(manifest_dir.join(file_name))?)?;
serde_json::from_slice(&fs::read(manifest_dir.join(file_name)).unwrap()).unwrap();
let website = match base_info.website {
Some(website) => website,
@@ -135,9 +135,7 @@ fn main() -> Result<()> {
}
file.write_all(FOOTER.as_bytes()).expect("Unable to write footer");
file.flush()?;
Ok(())
file.flush().unwrap();
}
#[derive(Debug)]

View File

@@ -22,6 +22,8 @@ Note: In this file, do not use the hard wrap in the middle of a sentence for com
- Remove `BaseManifest` and related types since they are unrelated to public manifests.
- Enable [release immutability](https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/immutable-releases).
## [0.1.1] - 2025-09-20
- Add `HostPlatform::{powerpc64le_linux_gnu,powerpc64le_linux_musl,riscv64_linux_gnu,riscv64_linux_musl,s390x_linux_gnu,s390x_linux_musl}` ([#1133](https://github.com/taiki-e/install-action/pull/1133))

View File

@@ -11,6 +11,11 @@ cd -- "$(dirname -- "$0")"/..
# ./tools/manifest.sh [PACKAGE [VERSION_REQ]]
# ./tools/manifest.sh full
if [[ -n "${GITHUB_ACTIONS:-}" ]] && ! type -P cosign; then
go install github.com/sigstore/cosign/v3/cmd/cosign@latest
sudo mv -- ~/go/bin/cosign /usr/local/bin
fi
if [[ $# -eq 1 ]] && [[ "$1" == "full" ]]; then
for manifest in tools/codegen/base/*.json; do
package="${manifest##*/}"

View File

@@ -1,204 +0,0 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: Apache-2.0 OR MIT
set -CeEuo pipefail
IFS=$'\n\t'
trap -- 's=$?; printf >&2 "%s\n" "${0##*/}:${LINENO}: \`${BASH_COMMAND}\` exit with ${s}"; exit ${s}' ERR
cd -- "$(dirname -- "$0")"/..
# Publish a new release.
#
# USAGE:
# ./tools/publish.sh <VERSION>
#
# Note: This script requires the following tools:
# - parse-changelog <https://github.com/taiki-e/parse-changelog>
retry() {
for i in {1..10}; do
if "$@"; then
return 0
else
sleep "${i}"
fi
done
"$@"
}
bail() {
printf >&2 'error: %s\n' "$*"
exit 1
}
version="${1:?}"
version="${version#v}"
tag_prefix="v"
tag="${tag_prefix}${version}"
changelog="CHANGELOG.md"
if [[ ! "${version}" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z\.-]+)?(\+[0-9A-Za-z\.-]+)?$ ]]; then
bail "invalid version format '${version}'"
fi
if [[ $# -gt 1 ]]; then
bail "invalid argument '$2'"
fi
if { sed --help 2>&1 || true; } | grep -Eq -e '-i extension'; then
in_place=(-i '')
else
in_place=(-i)
fi
# Make sure there is no uncommitted change.
git diff --exit-code
git diff --exit-code --staged
# Make sure the same release has not been created in the past.
if gh release view "${tag}" &>/dev/null; then
bail "tag '${tag}' has already been created and pushed"
fi
# Make sure that the release was created from an allowed branch.
if ! git branch | grep -Eq '\* main$'; then
bail "current branch is not 'main'"
fi
if ! git remote -v | grep -F origin | grep -Eq 'github\.com[:/]taiki-e/'; then
bail "cannot publish a new release from fork repository"
fi
release_date=$(date -u '+%Y-%m-%d')
tags=$(git --no-pager tag | { grep -E "^${tag_prefix}[0-9]+" || true; })
if [[ -n "${tags}" ]]; then
# Make sure the same release does not exist in changelog.
if grep -Eq "^## \\[${version//./\\.}\\]" "${changelog}"; then
bail "release ${version} already exist in ${changelog}"
fi
if grep -Eq "^\\[${version//./\\.}\\]: " "${changelog}"; then
bail "link to ${version} already exist in ${changelog}"
fi
# Update changelog.
remote_url=$(grep -E '^\[Unreleased\]: https://' "${changelog}" | sed -E 's/^\[Unreleased\]: //; s/\.\.\.HEAD$//')
prev_tag="${remote_url#*/compare/}"
remote_url="${remote_url%/compare/*}"
sed -E "${in_place[@]}" \
-e "s/^## \\[Unreleased\\]/## [Unreleased]\\n\\n## [${version}] - ${release_date}/" \
-e "s#^\[Unreleased\]: https://.*#[Unreleased]: ${remote_url}/compare/${tag}...HEAD\\n[${version}]: ${remote_url}/compare/${prev_tag}...${tag}#" "${changelog}"
if ! grep -Eq "^## \\[${version//./\\.}\\] - ${release_date}$" "${changelog}"; then
bail "failed to update ${changelog}"
fi
if ! grep -Eq "^\\[${version//./\\.}\\]: " "${changelog}"; then
bail "failed to update ${changelog}"
fi
else
# Make sure the release exists in changelog.
if ! grep -Eq "^## \\[${version//./\\.}\\] - ${release_date}$" "${changelog}"; then
bail "release ${version} does not exist in ${changelog} or has wrong release date"
fi
if ! grep -Eq "^\\[${version//./\\.}\\]: " "${changelog}"; then
bail "link to ${version} does not exist in ${changelog}"
fi
fi
# Make sure that a valid release note for this version exists.
# https://github.com/taiki-e/parse-changelog
changes=$(parse-changelog "${changelog}" "${version}")
if [[ -z "${changes}" ]]; then
bail "changelog for ${version} has no body"
fi
printf '============== CHANGELOG ==============\n'
printf '%s\n' "${changes}"
printf '=======================================\n'
if [[ -n "${tags}" ]]; then
# Create a release commit.
(
set -x
git add "${changelog}"
git commit -m "Release ${version}"
)
fi
set -x
git tag "${tag}"
retry git push origin refs/heads/main
retry git push origin refs/tags/"${tag}"
major_version_tag="v${version%%.*}"
git branch "releases/${major_version_tag}"
git tag -f "${major_version_tag}"
refs=("refs/heads/releases/${major_version_tag}" "+refs/tags/${major_version_tag}")
tools=()
for tool in tools/codegen/base/*.json; do
tool="${tool##*/}"
tools+=("${tool%.*}")
done
# Aliases.
# NB: Update case for aliases in main.sh, tool input option in test-alias job
# in .github/workflows/ci.yml, and match for alias for tools/codegen/src/tools-markdown.rs.
tools+=(
nextest
taplo-cli
typos-cli
wasm-bindgen-cli
wasmtime-cli
)
# Non-manifest-based tools.
tools+=(valgrind)
branches=()
for tool in "${tools[@]}"; do
git checkout -b "releases/${tool}"
sed -E "${in_place[@]}" action.yml \
-e "s/required: true/required: false/g" \
-e "s/# default: #publish:tool/default: ${tool}/g"
git add action.yml
git commit -m "${tool}"
git tag -f "${tool}"
git checkout main
refs+=("+refs/heads/releases/${tool}" "+refs/tags/${tool}")
branches+=("releases/${tool}")
done
retry git push origin --atomic "${refs[@]}"
git branch -d "releases/${major_version_tag}"
git branch -D "${branches[@]}"
schema_workspace=/tmp/workspace
rm -rf -- "${schema_workspace}"
# Checkout manifest-schema branch
schema_version="$(cargo metadata --format-version=1 --no-deps | jq -r '.packages[] | select(.name == "install-action-manifest-schema") | .version')"
if [[ "${schema_version}" == "0."* ]]; then
schema_version="0.$(cut -d. -f2 <<<"${schema_version}")"
else
schema_version="$(cut -d. -f1 <<<"${schema_version}")"
fi
schema_branch="manifest-schema-${schema_version}"
git worktree add --force "${schema_workspace}"
(
cd -- "${schema_workspace}"
if git fetch origin "${schema_branch}"; then
git checkout "origin/${schema_branch}" -B "${schema_branch}"
elif ! git checkout "${schema_branch}"; then
# New branch with no history. Credit: https://stackoverflow.com/a/13969482
git checkout --orphan "${schema_branch}"
git rm -rf -- . || true
git commit -m 'Initial commit' --allow-empty
fi
)
# Copy over schema
cp -- ./manifests/* "${schema_workspace}"
(
cd -- "${schema_workspace}"
# Stage changes
git add .
# Detect changes, then commit and push if changes exist
if [[ "$(git status --porcelain=v1 | LC_ALL=C wc -l)" != "0" ]]; then
git commit -m 'Update manifest schema'
retry git push origin HEAD
fi
)
rm -rf -- "${schema_workspace}"
git worktree prune
# TODO: get branch in schema_workspace dir instead
git branch -D "${schema_branch}" "${schema_workspace##*/}"

View File

@@ -7,13 +7,13 @@ trap -- 'printf >&2 "%s\n" "${0##*/}: trapped SIGINT"; exit 1' SIGINT
cd -- "$(dirname -- "$0")"/..
# USAGE:
# GH_TOKEN=$(gh auth token) ./tools/tidy.sh
# GITHUB_TOKEN=$(gh auth token) ./tools/tidy.sh
#
# Note: This script requires the following tools:
# - git 1.8+
# - jq 1.6+
# - npm (node 18+)
# - python 3.6+, pipx
# - python 3.6+, uv
# - shfmt
# - shellcheck
# - zizmor
@@ -86,11 +86,6 @@ check_config() {
check_install() {
for tool in "$@"; do
if ! type -P "${tool}" >/dev/null; then
if [[ "${tool}" == 'python3' ]]; then
if type -P python >/dev/null; then
continue
fi
fi
error "'${tool}' is required to run this check"
return 1
fi
@@ -132,12 +127,8 @@ EOF
exit 1
fi
py_suffix=''
if type -P python3 >/dev/null; then
py_suffix=3
fi
yq() { pipx run yq "$@"; }
tomlq() { pipx run --spec yq tomlq "$@"; }
yq() { uvx yq "$@"; }
tomlq() { uvx --from yq tomlq "$@"; }
case "$(uname -s)" in
Linux)
if [[ "$(uname -o)" == 'Android' ]]; then
@@ -190,8 +181,8 @@ case "$(uname -s)" in
else
jq() { command jq "$@" | tr -d '\r'; }
fi
yq() { pipx run yq "$@" | tr -d '\r'; }
tomlq() { pipx run --spec yq tomlq "$@" | tr -d '\r'; }
yq() { uvx yq "$@" | tr -d '\r'; }
tomlq() { uvx --from yq tomlq "$@" | tr -d '\r'; }
fi
fi
;;
@@ -248,7 +239,7 @@ if [[ ${#rust_files[@]} -gt 0 ]]; then
info "checking Rust code style"
check_config .rustfmt.toml "; consider adding with reference to https://github.com/taiki-e/cargo-hack/blob/HEAD/.rustfmt.toml"
check_config .clippy.toml "; consider adding with reference to https://github.com/taiki-e/cargo-hack/blob/HEAD/.clippy.toml"
if check_install cargo jq pipx; then
if check_install cargo jq uv; then
# `cargo fmt` cannot recognize files not included in the current workspace and modules
# defined inside macros, so run rustfmt directly.
# We need to use nightly rustfmt because we use the unstable formatting options of rustfmt.
@@ -700,7 +691,7 @@ elif check_install shellcheck; then
# Exclude SC2096 due to the way the temporary script is created.
shellcheck_exclude=SC2096
info "running \`shellcheck --exclude ${shellcheck_exclude}\` for scripts in \`\$(git ls-files '*Dockerfile*')\`"
if check_install jq python3 parse-dockerfile; then
if check_install jq parse-dockerfile; then
shellcheck_for_dockerfile() {
local text=$1
local shell=$2
@@ -833,7 +824,7 @@ elif check_install shellcheck; then
# Exclude SC2096 due to the way the temporary script is created.
shellcheck_exclude=SC2086,SC2096,SC2129
info "running \`shellcheck --exclude ${shellcheck_exclude}\` for scripts in .github/workflows/*.yml and **/action.yml"
if check_install jq python3 pipx; then
if check_install jq uv; then
shellcheck_for_gha() {
local text=$1
local shell=$2
@@ -846,16 +837,8 @@ elif check_install shellcheck; then
*) return ;;
esac
text="#!/usr/bin/env ${shell%' {0}'}"$'\n'"${text}"
# Use python because sed doesn't support .*?.
text=$(
"python${py_suffix}" - <<EOF
import re
text = re.sub(r"\\\${{.*?}}", "\${__GHA_SYNTAX__}", r'''${text}''')
print(text)
EOF
)
case "${ostype}" in
windows) text=${text//$'\r'/} ;; # Python print emits \r\n.
windows) text=${text//$'\r'/} ;; # Parse error on git bash/msys2 bash.
esac
local color=auto
if [[ -t 1 ]] || [[ -n "${GITHUB_ACTIONS:-}" ]]; then
@@ -988,11 +971,12 @@ if [[ ${#zizmor_targets[@]} -gt 0 ]]; then
if [[ "${ostype}" =~ ^(netbsd|openbsd|dragonfly|illumos|solaris)$ ]] && [[ -n "${CI:-}" ]] && ! type -P zizmor >/dev/null; then
warn "this check is skipped on NetBSD/OpenBSD/Dragonfly/illumos/Solaris due to installing zizmor is hard on these platform"
elif check_install zizmor; then
# zizmor can also be used via pipx, but old version will be installed if glibc version is old.
# zizmor can also be used via uvx, but old version will be installed if glibc version is old.
# Do not use `zizmor .` here because it also attempts to check submodules.
IFS=' '
info "running \`zizmor -q ${zizmor_targets[*]}\`"
info "running \`zizmor -q --pedantic ${zizmor_targets[*]}\`"
IFS=$'\n\t'
zizmor -q "${zizmor_targets[@]}"
zizmor -q --pedantic "${zizmor_targets[@]}"
fi
fi
printf '\n'
@@ -1045,7 +1029,7 @@ fi
if [[ -f .cspell.json ]]; then
info "spell checking"
project_dictionary=.github/.cspell/project-dictionary.txt
if check_install npm jq pipx; then
if check_install npm jq uv; then
has_rust=''
if [[ -n "$(ls_files '*Cargo.toml')" ]]; then
has_rust=1