-
Notifications
You must be signed in to change notification settings - Fork 54
/
Copy pathrelease.sh
executable file
·180 lines (146 loc) · 5.86 KB
/
release.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#!/usr/bin/env bash
###################################################################################################
# USAGE:
# 1. on a release branch: ./release.sh <version> (example: ./release.sh 0.1.0)
# 2. on main branch (after merging release branch): ./release.sh
###################################################################################################
# This is a script to automate a large portion of the release process for the crates we publish to
# crates.io. Currently only `delta_kernel` (in the kernel/ dir) and `delta_kernel_derive` (in the
# derive-macros/ dir) are released.
# Exit on error, undefined variables, and pipe failures
set -euo pipefail
# print commands before executing them for debugging
# set -x
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # no color
log_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
check_requirements() {
log_info "Checking required tools..."
command -v cargo >/dev/null 2>&1 || log_error "cargo is required but not installed"
command -v git >/dev/null 2>&1 || log_error "git is required but not installed"
command -v cargo-release >/dev/null 2>&1 || log_error "cargo-release is required but not installed. Install with: cargo install cargo-release"
command -v git-cliff >/dev/null 2>&1 || log_error "git-cliff is required but not installed. Install with: cargo install git-cliff"
command -v jq >/dev/null 2>&1 || log_error "jq is required but not installed."
log_success "All required tools are available"
}
is_main_branch() {
local current_branch
current_branch=$(git rev-parse --abbrev-ref HEAD)
[[ "$current_branch" == "main" ]]
}
is_working_tree_clean() {
git diff --quiet && git diff --cached --quiet
}
# check if the version is already published on crates.io
is_version_published() {
local crate_name="$1"
local version
version=get_current_version "$crate_name"
if [[ -z "$version" ]]; then
log_error "Could not find crate '$crate_name' in workspace"
fi
if cargo search "$crate_name" | grep -q "^$crate_name = \"$version\""; then
return 0
else
return 1
fi
}
# get current version from Cargo.toml
get_current_version() {
local crate_name="$1"
cargo metadata --no-deps --format-version 1 | \
jq -r --arg name "$crate_name" '.packages[] | select(.name == $name) | .version'
}
# Prompt user for confirmation
confirm() {
local prompt="$1"
local response
echo -e -n "${YELLOW}${prompt} [y/N]${NC} "
read -r response
[[ "$response" =~ ^[Yy] ]]
}
# handle release branch workflow (CHANGELOG updates, README updates, PR to main)
handle_release_branch() {
local version="$1"
log_info "Starting release preparation for version $version..."
# Update CHANGELOG and README
log_info "Updating CHANGELOG.md and README.md..."
if ! cargo release --workspace "$version" --no-publish --no-push --no-tag --execute; then
log_error "Failed to update CHANGELOG and README"
fi
if confirm "Print diff of CHANGELOG/README changes?"; then
git diff --stat HEAD^
git diff HEAD^
fi
if confirm "Would you like to push these changes to 'origin' remote?"; then
local current_branch
current_branch=$(git rev-parse --abbrev-ref HEAD)
log_info "Pushing changes to remote..."
git push origin "$current_branch"
if confirm "Would you like to create a PR to merge this release into 'main'?"; then
if command -v gh >/dev/null 2>&1; then
gh pr create --title "release $version" --body "release $version"
log_success "PR created successfully"
else
log_warning "GitHub CLI not found. Please create a PR manually."
fi
fi
fi
}
# Handle main branch workflow (publish and tag)
handle_main_branch() {
# could potentially just use full 'cargo release' command here
publish "delta_kernel_derive" "$current_version"
publish "delta_kernel" "$current_version"
if confirm "Would you like to tag this release?"; then
log_info "Tagging release $current_version..."
git tag -a "v$current_version" -m "Release $current_version"
git push upstream "v$current_version"
log_success "Tagged release $current_version"
fi
}
publish() {
local crate_name="$1"
local current_version
current_version=$(get_current_version "$crate_name")
if is_version_published "delta_kernel_derive"; then
log_error "delta_kernel_derive version $current_version is already published to crates.io"
fi
log_info "[DRY RUN] Publishing $crate_name version $version to crates.io..."
if ! cargo publish --dry-run -p "$crate_name"; then
log_error "Failed to publish $crate_name to crates.io"
fi
if confirm "Dry run complete. Continue with publishing?"; then
log_info "Publishing $crate_name version $version to crates.io..."
if ! cargo publish -p "$crate_name"; then
log_error "Failed to publish $crate_name to crates.io"
fi
log_success "Successfully published $crate_name version $version to crates.io"
fi
}
validate_version() {
local version=$1
# Check if version starts with a number
if [[ ! $version =~ ^[0-9] ]]; then
log_error "Version must start with a number (e.g., '0.1.1'). Got: '$version'"
fi
}
check_requirements
if is_main_branch; then
if [[ $# -ne 0 ]]; then
log_error "Version argument not expected on main branch\nUsage: $0"
fi
handle_main_branch
else
if [[ $# -ne 1 ]]; then
log_error "Version argument required when on release branch\nUsage: $0 <version>"
fi
validate_version "$1"
handle_release_branch "$1"
fi