|
| 1 | +#!/bin/bash |
| 2 | + |
| 3 | +set -eu -o pipefail |
| 4 | + |
| 5 | +# Check that we're not on the main branch |
| 6 | +current_branch=$(git branch --show-current) |
| 7 | +if [ "$current_branch" = "main" ]; then |
| 8 | + echo "Error: Releases should not be done directly on the main branch." |
| 9 | + echo "Please create a release branch and run this script from there." |
| 10 | + exit 1 |
| 11 | +fi |
| 12 | + |
| 13 | +# Fetch latest changes and check that we're not behind origin/main |
| 14 | +echo "Fetching from origin..." |
| 15 | +git fetch origin |
| 16 | + |
| 17 | +if ! git merge-base --is-ancestor origin/main HEAD; then |
| 18 | + echo "Error: Current branch is behind origin/main." |
| 19 | + echo "Please merge or rebase with origin/main before releasing." |
| 20 | + exit 1 |
| 21 | +fi |
| 22 | + |
| 23 | +changelog=$(cat CHANGELOG.md) |
| 24 | + |
| 25 | +# Match: ## X.Y.Z - YYYY-MM-DD |
| 26 | +regex='## ([0-9]+\.[0-9]+\.[0-9]+) - ([0-9]{4}-[0-9]{2}-[0-9]{2})' |
| 27 | + |
| 28 | +if [[ ! $changelog =~ $regex ]]; then |
| 29 | + echo "Could not find version/date line in CHANGELOG.md!" |
| 30 | + echo "Expected format: ## X.Y.Z - YYYY-MM-DD" |
| 31 | + exit 1 |
| 32 | +fi |
| 33 | + |
| 34 | +version="${BASH_REMATCH[1]}" |
| 35 | +date="${BASH_REMATCH[2]}" |
| 36 | + |
| 37 | +# Extract release notes (everything between first ## version and next ## version) |
| 38 | +notes=$(sed -n '/^## '"$version"'/,/^## [0-9]/p' CHANGELOG.md | sed '1d;$d') |
| 39 | + |
| 40 | +if [[ "$date" != $(date +"%Y-%m-%d") ]]; then |
| 41 | + echo "Release date $date is not today ($(date +"%Y-%m-%d"))!" |
| 42 | + exit 1 |
| 43 | +fi |
| 44 | + |
| 45 | +tag="v$version" |
| 46 | + |
| 47 | +if [ -n "$(git status --porcelain)" ]; then |
| 48 | + echo "Working directory is not clean." >&2 |
| 49 | + exit 1 |
| 50 | +fi |
| 51 | + |
| 52 | +# Update version in Cargo.toml |
| 53 | +current_cargo_version=$(grep -E '^version = "[0-9]+\.[0-9]+\.[0-9]+"' Cargo.toml | head -1 | sed 's/version = "\(.*\)"/\1/') |
| 54 | +if [ "$current_cargo_version" != "$version" ]; then |
| 55 | + echo "Updating Cargo.toml version from $current_cargo_version to $version" |
| 56 | + sed -i "s/^version = \"$current_cargo_version\"/version = \"$version\"/" Cargo.toml |
| 57 | +fi |
| 58 | + |
| 59 | +echo "Running tests..." |
| 60 | +cargo test |
| 61 | + |
| 62 | +echo $'\nDiff:' |
| 63 | +git diff |
| 64 | + |
| 65 | +echo $'\nRelease notes:' |
| 66 | +echo "$notes" |
| 67 | + |
| 68 | +read -r -p "Commit changes and push to origin? [y/N] " should_push |
| 69 | + |
| 70 | +if [ "$should_push" != "y" ]; then |
| 71 | + echo "Aborting" |
| 72 | + git checkout -- Cargo.toml |
| 73 | + exit 1 |
| 74 | +fi |
| 75 | + |
| 76 | +if [ -n "$(git status --porcelain)" ]; then |
| 77 | + git commit -m "Prepare $tag release" -a |
| 78 | +fi |
| 79 | + |
| 80 | +git push |
| 81 | + |
| 82 | +gh release create --target "$(git branch --show-current)" -t "$version" -n "$notes" "$tag" |
| 83 | + |
| 84 | +git push --tags |
0 commit comments