Compare commits

...

7 Commits

Author SHA1 Message Date
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
7 changed files with 524 additions and 228 deletions

View File

@@ -31,6 +31,7 @@ rdme
rootfs
sccache
SHASUMS
shortstat
sigstore
syft
tombi

View File

@@ -4,18 +4,209 @@ 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}
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.
retry git fetch origin &>/dev/null
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,24 +216,230 @@ 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.
retry git fetch origin &>/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
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##*/}"
)
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
with:
crates: tools/manifest-schema
changelog: tools/manifest-schema/CHANGELOG.md
title: $prefix $version
prefix: install-action-manifest-schema
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: inherit
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

View File

@@ -10,6 +10,16 @@ Note: In this file, do not use the hard wrap in the middle of a sentence for com
## [Unreleased]
## [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.
@@ -6031,7 +6041,9 @@ 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.10...HEAD
[Unreleased]: https://github.com/taiki-e/install-action/compare/v2.69.12...HEAD
[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

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": {

32
manifests/mise.json generated
View File

@@ -28,13 +28,39 @@
},
"license_markdown": "[MIT](https://github.com/jdx/mise/blob/main/LICENSE)",
"latest": {
"version": "2026.3.15"
"version": "2026.3.16"
},
"2026": {
"version": "2026.3.15"
"version": "2026.3.16"
},
"2026.3": {
"version": "2026.3.15"
"version": "2026.3.16"
},
"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": {

42
manifests/uv.json generated
View File

@@ -40,10 +40,48 @@
},
"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.11.1"
"version": "0.11.2"
},
"0.11": {
"version": "0.11.1"
"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": {

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##*/}"