Files
install-action/tools/publish.sh

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

204 lines
6.1 KiB
Bash
Raw Normal View History

#!/usr/bin/env bash
2023-06-05 22:58:32 +09:00
# SPDX-License-Identifier: Apache-2.0 OR MIT
set -CeEuo pipefail
2021-12-30 17:33:20 +09:00
IFS=$'\n\t'
trap -- 's=$?; printf >&2 "%s\n" "${0##*/}:${LINENO}: \`${BASH_COMMAND}\` exit with ${s}"; exit ${s}' ERR
cd -- "$(dirname -- "$0")"/..
2022-12-09 22:03:48 +09:00
2021-12-30 17:33:20 +09:00
# Publish a new release.
#
# USAGE:
# ./tools/publish.sh <VERSION>
#
2022-12-02 03:19:40 +09:00
# Note: This script requires the following tools:
# - parse-changelog <https://github.com/taiki-e/parse-changelog>
2021-12-30 17:33:20 +09:00
2023-10-25 00:13:32 +09:00
retry() {
for i in {1..10}; do
if "$@"; then
return 0
else
sleep "${i}"
fi
done
"$@"
}
2021-12-30 17:33:20 +09:00
bail() {
printf >&2 'error: %s\n' "$*"
2021-12-30 17:33:20 +09:00
exit 1
}
version="${1:?}"
version="${version#v}"
2023-01-15 18:33:24 +09:00
tag_prefix="v"
tag="${tag_prefix}${version}"
changelog="CHANGELOG.md"
2021-12-30 17:33:20 +09:00
if [[ ! "${version}" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z\.-]+)?(\+[0-9A-Za-z\.-]+)?$ ]]; then
2021-12-30 21:55:24 +09:00
bail "invalid version format '${version}'"
2021-12-30 17:33:20 +09:00
fi
if [[ $# -gt 1 ]]; then
2021-12-30 21:55:24 +09:00
bail "invalid argument '$2'"
2021-12-30 17:33:20 +09:00
fi
if { sed --help 2>&1 || true; } | grep -Eq -e '-i extension'; then
in_place=(-i '')
else
in_place=(-i)
fi
2021-12-30 17:33:20 +09:00
2021-12-30 21:55:24 +09:00
# Make sure there is no uncommitted change.
git diff --exit-code
git diff --exit-code --staged
2021-12-30 17:33:20 +09:00
2022-02-08 12:17:41 +09:00
# Make sure the same release has not been created in the past.
2022-03-02 12:17:34 +09:00
if gh release view "${tag}" &>/dev/null; then
2022-02-08 12:17:41 +09:00
bail "tag '${tag}' has already been created and pushed"
fi
2023-07-09 13:02:13 +09:00
# Make sure that the release was created from an allowed branch.
if ! git branch | grep -Eq '\* main$'; then
2022-05-06 07:52:13 +09:00
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
2022-05-06 07:52:13 +09:00
2023-01-15 18:33:24 +09:00
release_date=$(date -u '+%Y-%m-%d')
tags=$(git --no-pager tag | { grep -E "^${tag_prefix}[0-9]+" || true; })
2022-03-02 12:17:34 +09:00
if [[ -n "${tags}" ]]; then
2023-01-15 18:33:24 +09:00
# Make sure the same release does not exist in changelog.
if grep -Eq "^## \\[${version//./\\.}\\]" "${changelog}"; then
bail "release ${version} already exist in ${changelog}"
2022-03-02 12:17:34 +09:00
fi
2023-01-15 18:33:24 +09:00
if grep -Eq "^\\[${version//./\\.}\\]: " "${changelog}"; then
bail "link to ${version} already exist in ${changelog}"
2022-03-02 12:17:34 +09:00
fi
# Update changelog.
remote_url=$(grep -E '^\[Unreleased\]: https://' "${changelog}" | sed -E 's/^\[Unreleased\]: //; s/\.\.\.HEAD$//')
2024-01-27 23:57:26 +09:00
prev_tag="${remote_url#*/compare/}"
2022-12-28 21:18:38 +09:00
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}"
2023-01-15 18:33:24 +09:00
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}"
2022-03-02 12:17:34 +09:00
fi
2023-01-15 18:33:24 +09:00
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}"
2022-03-02 12:17:34 +09:00
fi
2022-02-08 12:17:41 +09:00
fi
2021-12-30 17:33:20 +09:00
# Make sure that a valid release note for this version exists.
# https://github.com/taiki-e/parse-changelog
2023-01-15 18:33:24 +09:00
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'
2024-04-21 03:28:30 +09:00
2022-03-02 12:17:34 +09:00
if [[ -n "${tags}" ]]; then
# Create a release commit.
2024-04-20 13:39:09 +09:00
(
set -x
git add "${changelog}"
git commit -m "Release ${version}"
)
2022-03-02 12:17:34 +09:00
fi
2021-12-30 17:33:20 +09:00
2024-04-21 03:28:30 +09:00
set -x
2024-04-21 03:28:30 +09:00
git tag "${tag}"
2025-03-02 16:32:48 +09:00
retry git push origin refs/heads/main
retry git push origin refs/tags/"${tag}"
2024-04-21 03:28:30 +09:00
major_version_tag="v${version%%.*}"
git checkout -b "${major_version_tag}"
retry git push origin refs/heads/"${major_version_tag}"
2025-03-02 16:32:48 +09:00
git tag -f "${major_version_tag}"
retry git push origin -f refs/tags/"${major_version_tag}"
2024-04-21 03:28:30 +09:00
git checkout main
git branch -d "${major_version_tag}"
tools=()
for tool in tools/codegen/base/*.json; do
tool="${tool##*/}"
tools+=("${tool%.*}")
done
2025-09-06 01:46:45 +09:00
# Aliases.
# NB: Update case for aliases in main.sh and tool input option in test-alias in .github/workflows/ci.yml.
2025-09-06 01:46:45 +09:00
tools+=(
nextest
taplo-cli
typos-cli
wasm-bindgen-cli
wasmtime-cli
2025-09-06 01:46:45 +09:00
)
# Non-manifest-based tools.
tools+=(valgrind)
2024-04-21 03:28:30 +09:00
for tool in "${tools[@]}"; do
git checkout -b "${tool}"
2025-02-17 02:16:54 +09:00
sed -E "${in_place[@]}" action.yml \
-e "s/required: true/required: false/g" \
-e "s/# default: #publish:tool/default: ${tool}/g"
2024-04-21 03:28:30 +09:00
git add action.yml
git commit -m "${tool}"
retry git push origin -f refs/heads/"${tool}"
2025-03-02 16:32:48 +09:00
git tag -f "${tool}"
retry git push origin -f refs/tags/"${tool}"
git checkout main
2024-04-21 03:28:30 +09:00
git branch -D "${tool}"
done
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 | wc -l)" != "0" ]]; then
git commit -m 'Update manifest schema'
2025-02-17 02:16:54 +09:00
retry git push origin HEAD
fi
)
rm -rf -- "${schema_workspace}"
git worktree prune
2025-02-17 02:16:54 +09:00
# TODO: get branch in schema_workspace dir instead
git branch -D "${schema_branch}" "${schema_workspace##*/}"