Skip to content

Commit

Permalink
Clean up scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e committed Sep 7, 2024
1 parent 2c6ee1c commit 5e8eb27
Show file tree
Hide file tree
Showing 5 changed files with 674 additions and 307 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ env:

defaults:
run:
shell: bash
shell: bash --noprofile --norc -CeEuxo pipefail {0}

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
Expand Down Expand Up @@ -61,7 +61,7 @@ jobs:
steps:
- uses: taiki-e/checkout-action@v1
- name: Install Rust
run: rustup toolchain add ${{ matrix.rust }} --no-self-update && rustup default ${{ matrix.rust }}
run: rustup toolchain add "${{ matrix.rust }}" --no-self-update && rustup default "${{ matrix.rust }}"
- run: rustup toolchain add nightly --no-self-update
- uses: taiki-e/install-action@cargo-hack
- uses: taiki-e/install-action@cargo-minimal-versions
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ on:

defaults:
run:
shell: bash
shell: bash --noprofile --norc -CeEuxo pipefail {0}

jobs:
create-release:
Expand Down
27 changes: 24 additions & 3 deletions .shellcheckrc
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,34 @@
# https://github.com/koalaman/shellcheck/blob/HEAD/shellcheck.1.md#rc-files

# See also:
# https://www.shellcheck.net/wiki/Optional
# https://github.com/koalaman/shellcheck/wiki/Optional
# https://google.github.io/styleguide/shellguide.html

# https://www.shellcheck.net/wiki/SC2292
# https://github.com/koalaman/shellcheck/wiki/SC2249
# enable=add-default-case

# https://github.com/koalaman/shellcheck/wiki/SC2244
enable=avoid-nullary-conditions

# https://github.com/koalaman/shellcheck/wiki/SC2312
# enable=check-extra-masked-returns

# https://github.com/koalaman/shellcheck/wiki/SC2310
# https://github.com/koalaman/shellcheck/wiki/SC2311
# enable=check-set-e-suppressed

# enable=check-unassigned-uppercase

# https://github.com/koalaman/shellcheck/wiki/SC2230
enable=deprecate-which

# https://github.com/koalaman/shellcheck/wiki/SC2248
enable=quote-safe-variables

# https://github.com/koalaman/shellcheck/wiki/SC2292
# https://google.github.io/styleguide/shellguide.html#s6.3-tests
enable=require-double-brackets

# https://www.shellcheck.net/wiki/SC2250
# https://github.com/koalaman/shellcheck/wiki/SC2250
# https://google.github.io/styleguide/shellguide.html#s5.6-variable-expansion
enable=require-variable-braces
103 changes: 53 additions & 50 deletions tools/publish.sh
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: Apache-2.0 OR MIT
set -eEuo pipefail
set -CeEuo pipefail
IFS=$'\n\t'
cd "$(dirname "$0")"/..

# shellcheck disable=SC2154
trap 's=$?; echo >&2 "$0: error on line "${LINENO}": ${BASH_COMMAND}"; exit ${s}' ERR
trap -- 's=$?; printf >&2 "%s\n" "${0##*/}:${LINENO}: \`${BASH_COMMAND}\` exit with ${s}"; exit ${s}' ERR
cd -- "$(dirname -- "$0")"/..

# Publish a new release.
#
Expand All @@ -26,7 +24,7 @@ retry() {
"$@"
}
bail() {
echo >&2 "error: $*"
printf >&2 'error: %s\n' "$*"
exit 1
}

Expand All @@ -41,6 +39,11 @@ 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
Expand All @@ -52,12 +55,15 @@ if gh release view "${tag}" &>/dev/null; then
fi

# Make sure that the release was created from an allowed branch.
if ! git branch | grep -q '\* main$'; then
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))
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
Expand All @@ -67,11 +73,12 @@ if [[ -n "${tags}" ]]; then
bail "link to ${version} already exist in ${changelog}"
fi
# Update changelog.
remote_url=$(grep -E '^\[Unreleased\]: https://' "${changelog}" | sed 's/^\[Unreleased\]: //; s/\.\.\.HEAD$//')
remote_url=$(grep -E '^\[Unreleased\]: https://' "${changelog}" | sed -E 's/^\[Unreleased\]: //; s/\.\.\.HEAD$//')
prev_tag="${remote_url#*/compare/}"
remote_url="${remote_url%/compare/*}"
sed -i "s/^## \\[Unreleased\\]/## [Unreleased]\\n\\n## [${version}] - ${release_date}/" "${changelog}"
sed -i "s#^\[Unreleased\]: https://.*#[Unreleased]: ${remote_url}/compare/${tag}...HEAD\\n[${version}]: ${remote_url}/compare/${prev_tag}...${tag}#" "${changelog}"
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
Expand All @@ -94,84 +101,80 @@ changes=$(parse-changelog "${changelog}" "${version}")
if [[ -z "${changes}" ]]; then
bail "changelog for ${version} has no body"
fi
echo "============== CHANGELOG =============="
echo "${changes}"
echo "======================================="
printf '============== CHANGELOG ==============\n'
printf '%s\n' "${changes}"
printf '=======================================\n'

metadata=$(cargo metadata --format-version=1 --no-deps)
prev_version=''
docs=()
for readme in $(git ls-files '*README.md'); do
docs+=("${readme}")
lib="$(dirname "${readme}")/src/lib.rs"
lib="$(dirname -- "${readme}")/src/lib.rs"
if [[ -f "${lib}" ]]; then
docs+=("${lib}")
fi
done
changed_paths=("${changelog}" "${docs[@]}")
for id in $(jq <<<"${metadata}" '.workspace_members[]'); do
pkg=$(jq <<<"${metadata}" ".packages[] | select(.id == ${id})")
publish=$(jq <<<"${pkg}" -r '.publish')
# Publishing is unrestricted if null, and forbidden if an empty array.
if [[ "${publish}" == "[]" ]]; then
continue
fi
name=$(jq <<<"${pkg}" -r '.name')
actual_version=$(jq <<<"${pkg}" -r '.version')
if [[ -z "${prev_version:-}" ]]; then
prev_version="${actual_version}"
# Publishing is unrestricted if null, and forbidden if an empty array.
for pkg in $(jq -c '. as $metadata | .workspace_members[] as $id | $metadata.packages[] | select(.id == $id and .publish != [])' <<<"${metadata}"); do
eval "$(jq -r '@sh "NAME=\(.name) ACTUAL_VERSION=\(.version) manifest_path=\(.manifest_path)"' <<<"${pkg}")"
if [[ -z "${prev_version}" ]]; then
prev_version="${ACTUAL_VERSION}"
fi
# Make sure that the version number of all publishable workspace members matches.
if [[ "${actual_version}" != "${prev_version}" ]]; then
bail "publishable workspace members must be version '${prev_version}', but package '${name}' is version '${actual_version}'"
if [[ "${ACTUAL_VERSION}" != "${prev_version}" ]]; then
bail "publishable workspace members must be version '${prev_version}', but package '${NAME}' is version '${ACTUAL_VERSION}'"
fi

manifest_path=$(jq <<<"${pkg}" -r '.manifest_path')
changed_paths+=("${manifest_path}")
# Update version in Cargo.toml.
sed -i -e "s/^version = \"${prev_version}\" #publish:version/version = \"${version}\" #publish:version/g" "${manifest_path}"
if ! grep -Eq "^version = \"${prev_version}\" #publish:version" "${manifest_path}"; then
bail "not found '#publish:version' in version in ${manifest_path}"
fi
sed -E "${in_place[@]}" "s/^version = \"${prev_version}\" #publish:version/version = \"${version}\" #publish:version/g" "${manifest_path}"
# Update '=' requirement in Cargo.toml.
for manifest in $(git ls-files '*Cargo.toml'); do
if grep -Eq "^${name} = \\{ version = \"=${prev_version}\"" "${manifest}"; then
sed -i -E -e "s/^${name} = \\{ version = \"=${prev_version}\"/${name} = { version = \"=${version}\"/g" "${manifest}"
if grep -Eq "^${NAME} = \\{ version = \"=${prev_version}\"" "${manifest}"; then
sed -E "${in_place[@]}" "s/^${NAME} = \\{ version = \"=${prev_version}\"/${NAME} = { version = \"=${version}\"/g" "${manifest}"
fi
done
# Update version in readme and lib.rs.
for path in "${docs[@]}"; do
# TODO: handle pre-release
if [[ "${version}" == "0.0."* ]]; then
# 0.0.x -> 0.0.x2
if grep -Eq "^${name} = \"${prev_version}\"" "${path}"; then
sed -i -E -e "s/^${name} = \"${prev_version}\"/${name} = \"${version}\"/g" "${path}"
# 0.0.x -> 0.0.y
if grep -Eq "^${NAME} = \"${prev_version}\"" "${path}"; then
sed -E "${in_place[@]}" "s/^${NAME} = \"${prev_version}\"/${NAME} = \"${version}\"/g" "${path}"
fi
if grep -Eq "^${name} = \\{ version = \"${prev_version}\"" "${path}"; then
sed -i -E -e "s/^${name} = \\{ version = \"${prev_version}\"/${name} = { version = \"${version}\"/g" "${path}"
if grep -Eq "^${NAME} = \\{ version = \"${prev_version}\"" "${path}"; then
sed -E "${in_place[@]}" "s/^${NAME} = \\{ version = \"${prev_version}\"/${NAME} = { version = \"${version}\"/g" "${path}"
fi
elif [[ "${version}" == "0."* ]]; then
prev_major_minor="${prev_version%.*}"
major_minor="${version%.*}"
if [[ "${prev_major_minor}" != "${major_minor}" ]]; then
# 0.x -> 0.x2
# 0.x.* -> 0.x2
if grep -Eq "^${name} = \"${prev_major_minor}(\\.[0-9]+)?\"" "${path}"; then
sed -i -E -e "s/^${name} = \"${prev_major_minor}(\\.[0-9]+)?\"/${name} = \"${major_minor}\"/g" "${path}"
# 0.x -> 0.y
# 0.x.* -> 0.y
if grep -Eq "^${NAME} = \"${prev_major_minor}(\\.[0-9]+)?\"" "${path}"; then
sed -E "${in_place[@]}" "s/^${NAME} = \"${prev_major_minor}(\\.[0-9]+)?\"/${NAME} = \"${major_minor}\"/g" "${path}"
fi
if grep -Eq "^${name} = \\{ version = \"${prev_major_minor}(\\.[0-9]+)?\"" "${path}"; then
sed -i -E -e "s/^${name} = \\{ version = \"${prev_major_minor}(\\.[0-9]+)?\"/${name} = { version = \"${major_minor}\"/g" "${path}"
if grep -Eq "^${NAME} = \\{ version = \"${prev_major_minor}(\\.[0-9]+)?\"" "${path}"; then
sed -E "${in_place[@]}" "s/^${NAME} = \\{ version = \"${prev_major_minor}(\\.[0-9]+)?\"/${NAME} = { version = \"${major_minor}\"/g" "${path}"
fi
fi
else
prev_major="${prev_version%%.*}"
major="${version%%.*}"
if [[ "${prev_major}" != "${major}" ]]; then
# x -> x2
# x.* -> x2
# x.*.* -> x2
if grep -Eq "^${name} = \"${prev_major}(\\.[0-9]+(\\.[0-9]+)?)?\"" "${path}"; then
sed -i -E -e "s/^${name} = \"${prev_major}(\\.[0-9]+(\\.[0-9]+)?)?\"/${name} = \"${major}\"/g" "${path}"
# x -> y
# x.* -> y
# x.*.* -> y
if grep -Eq "^${NAME} = \"${prev_major}(\\.[0-9]+(\\.[0-9]+)?)?\"" "${path}"; then
sed -E "${in_place[@]}" "s/^${NAME} = \"${prev_major}(\\.[0-9]+(\\.[0-9]+)?)?\"/${NAME} = \"${major}\"/g" "${path}"
fi
if grep -Eq "^${name} = \\{ version = \"${prev_major}(\\.[0-9]+(\\.[0-9]+)?)?\"" "${path}"; then
sed -i -E -e "s/^${name} = \\{ version = \"${prev_major}(\\.[0-9]+(\\.[0-9]+)?)?\"/${name} = { version = \"${major}\"/g" "${path}"
if grep -Eq "^${NAME} = \\{ version = \"${prev_major}(\\.[0-9]+(\\.[0-9]+)?)?\"" "${path}"; then
sed -E "${in_place[@]}" "s/^${NAME} = \\{ version = \"${prev_major}(\\.[0-9]+(\\.[0-9]+)?)?\"/${NAME} = { version = \"${major}\"/g" "${path}"
fi
fi
fi
Expand Down
Loading

0 comments on commit 5e8eb27

Please sign in to comment.