set -euo pipefail
autoload -U colors && colors
if [[ -n ${DEBUG:-} ]]; then
set -x
fi
project_dir=${0:a:h:h}
cd $project_dir
export RUSTFLAGS="-D warnings"
export RUST_LOG=up=trace
stty -tostop
caffeinate -ds -w $$ &
binary_name=up
macos_binary=build/$binary_name-Darwin
linux_amd64_binary=build/$binary_name-Linux
linux_arm64_binary=build/$binary_name-Linux_arm64
task_schema_json=build/$binary_name-task-schema.json
main() {
echo -e "${fg[magenta]}Publishing new version of the ${binary_name} CLI...${reset_color}"
(( $+commands[cargo-nextest] )) || brew install cargo-nextest
(( $+commands[git-cliff] )) || brew install git-cliff
(( $+commands[gh] )) || brew install gh
log_section "Cleaning up files from last release..."
rm -rfv build/
rm -fv target/universal-apple-darwin/release/$binary_name
mkdir -p build/
if [[ $(git branch --show-current) != main ]]; then
error "Not currently on the main branch."
fi
if [[ -n ${SKIP_GIT_DIFF_CHECK:-} ]]; then
log_section "Skipping it changed file check as SKIP_GIT_DIFF_CHECK env var was set."
else
diff=$(git diff --color=always)
if [[ -n $diff ]]; then
error "${fg[cyan]}-> Repo has uncommitted diffs:${reset_color}
$diff"
fi
fi
if [[ -n ${SKIP_GIT_UNTRACKED_CHECK:-} ]]; then
log_section "Skipping git untracked file check as SKIP_GIT_UNTRACKED_CHECK env var was set."
else
untracked=$(git ls-files . --exclude-standard --others | head)
if [[ -n $untracked ]]; then
error "Repo has untracked files:\n$untracked"
fi
fi
changelog_version=$(awk <CHANGELOG.md '{ if ($1 == "##") { print $2; exit; }}' | sed -E 's/\[([^]]+)].*/\1/')
last_release=$(gh release list -L 1 | awk '{print $1}')
cargo_toml_version=$(awk -F\" '/^version = /{print $2; exit}' Cargo.toml)
if [[ $changelog_version != $last_release && $last_release != $cargo_toml_version ]]; then
new_version=$changelog_version
if [[ $(git log -1 --pretty=%s) == "chore: bump version to ${new_version?}" ]]; then
log_section "Last commit bumped us to ${new_version?}, skipping changelog update..."
else
error "If you generated a bump version commit and then pushed another change to the branch,
delete and recreate the bump version commit."
fi
else
log_section "Updating changelog..."
case ${1:-} in
major | minor | patch) new_version=$(bump_version $1 $last_release) ;;
"")
default_new_release=$(bump_version patch $last_release)
read "new_version?New version (current version: ${last_release?}, default new version: ${default_new_release}): "
[[ -z $new_version ]] && new_version=$default_new_release
;;
*) error "Unrecognized input ${1}" ;;
esac
git cliff --tag="${new_version?}" --prepend CHANGELOG.md "${last_release}"..
log_section "Updating Cargo.toml..."
gsed -i -E "0,/^version = \"${last_release?}\"\$/s//version = \"${new_version?}\"/" Cargo.toml
log_and_run cargo check --release
cargo run -- doc markdown >docs/CommandLineHelp-macOS.md
meta/cargo-docker --pull -- cargo run --color=always -- doc markdown >docs/CommandLineHelp-Linux.md
log_section "Committing version updates..."
git add Cargo.toml Cargo.lock CHANGELOG.md docs/CommandLineHelp-macOS.md docs/CommandLineHelp-Linux.md
git commit -m "chore: bump version to ${new_version?}"
git show --stat | cat echo >&2 "Does this look correct?"
fi
if [[ -n ${SKIP_CARGO_TEST_CHECK:-} ]]; then
log_section "Skipping tests as SKIP_CARGO_TEST_CHECK env var was set."
else
log_and_run cargo nextest run --release --run-ignored=all --no-fail-fast
fi
cargo run -- doc schema $task_schema_json
log_section "Running end-to-end tests..."
log_and_run meta/bootstrap-test
log_and_run meta/build_macos
cp target/universal-apple-darwin/release/up $macos_binary
cp target/x86_64-unknown-linux-musl/release/up $linux_amd64_binary
cp target/aarch64-unknown-linux-musl/release/up $linux_arm64_binary
latest_crate_version=$(curl https://crates.io/api/v1/crates/up | jq -r .crate.newest_version)
if [[ $latest_crate_version == $new_version ]]; then
prompt_to_skip "Skipping cargo publish as latest release is already $latest_crate_version."
else
log_and_run cargo publish
fi
log_and_run git push up main
log_and_run gh release create "${new_version?}" --target=main \
--notes="$(git cliff --tag="${new_version?}" --strip=all "${last_release}"..)" \
$macos_binary \
$linux_amd64_binary \
$linux_arm64_binary \
$task_schema_json
new_release=$(gh release list -L 1 | awk '{print $1}')
gh release view $new_release
if [[ $new_release != $new_version ]]; then
error "Something went wrong, latest GitHub version is not what the script just released."
fi
log_section "Fetching just-created tag..."
git fetch --all
}
bump_version() {
case $1 in
major) awk -F '.' '{print $1+1 ".0.0"}' <<<$2 ;;
minor) awk -F '.' '{print $1 "." $2+1 ".0"}' <<<$2 ;;
patch) awk -F '.' '{print $1 "." $2 "." $3+1}' <<<$2 ;;
*) error "bump_version: unknown input ${2}" ;;
esac
}
log_section() {
echo "
${fg[cyan]}=> $*${reset_color}" >&2
}
log_and_run() {
log_section "Running $*"
time "$@"
}
error() {
echo -e "${fg[red]}ERROR${reset_color}: $1" >&2
exit "${2:-1}"
}
prompt_to_skip() {
read "user_input?$1
Press Enter to continue, type anything or press Ctrl-C to cancel: "
if [[ -n ${user_input:-} ]]; then
error "User entered text."
fi
}
main "$@"