Skip to content

Commit 42adc1a

Browse files
feat: add manual release script + fix debug token logic (#238)
* debug: fix inconsistent token checking logic The debug step was mixing direct secret interpolation with environment variables. Now consistently uses environment variables for both PAT_TOKEN and GITHUB_TOKEN detection. * feat: add manual release script Provides a reliable local alternative to GitHub Actions for releases: - Pre-flight checks (git status, auth, tests) - Interactive confirmations at each step - Uses cargo-workspaces for version bump and publishing - Comprehensive error handling and cleanup - No branch protection issues Usage: ./scripts/release.sh [patch|minor|major]
1 parent 49cdf36 commit 42adc1a

File tree

2 files changed

+251
-4
lines changed

2 files changed

+251
-4
lines changed

.github/workflows/cargo-workspaces-release.yml

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,25 +53,26 @@ jobs:
5353
fi
5454
5555
- name: Debug token configuration
56+
env:
57+
PAT_TOKEN: ${{ secrets.PAT_TOKEN }}
58+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
5659
run: |
5760
echo "=== Token Debug Information ==="
58-
if [ -n "${{ secrets.PAT_TOKEN }}" ]; then
61+
if [ -n "$PAT_TOKEN" ]; then
5962
echo "✅ PAT_TOKEN is available"
6063
echo "PAT_TOKEN length: ${#PAT_TOKEN}"
6164
else
6265
echo "❌ PAT_TOKEN is NOT available"
6366
fi
6467
65-
if [ -n "${{ secrets.GITHUB_TOKEN }}" ]; then
68+
if [ -n "$GITHUB_TOKEN" ]; then
6669
echo "✅ GITHUB_TOKEN is available"
6770
else
6871
echo "❌ GITHUB_TOKEN is NOT available"
6972
fi
7073
echo "Current git remote:"
7174
git remote -v
7275
echo "=== End Debug ==="
73-
env:
74-
PAT_TOKEN: ${{ secrets.PAT_TOKEN }}
7576
7677
- name: Configure git
7778
env:

scripts/release.sh

Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
#!/bin/bash
2+
3+
set -euo pipefail
4+
5+
# redisctl Manual Release Script
6+
# Usage: ./scripts/release.sh [patch|minor|major]
7+
8+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
9+
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
10+
11+
# Colors for output
12+
RED='\033[0;31m'
13+
GREEN='\033[0;32m'
14+
YELLOW='\033[1;33m'
15+
BLUE='\033[0;34m'
16+
NC='\033[0m' # No Color
17+
18+
# Default to patch if no argument provided
19+
VERSION_TYPE="${1:-patch}"
20+
21+
log() {
22+
echo -e "${GREEN}[INFO]${NC} $1"
23+
}
24+
25+
warn() {
26+
echo -e "${YELLOW}[WARN]${NC} $1"
27+
}
28+
29+
error() {
30+
echo -e "${RED}[ERROR]${NC} $1"
31+
exit 1
32+
}
33+
34+
header() {
35+
echo -e "${BLUE}=== $1 ===${NC}"
36+
}
37+
38+
confirm() {
39+
local prompt="$1"
40+
local response
41+
echo -e "${YELLOW}$prompt${NC}"
42+
read -p "Continue? (y/N): " response
43+
case "$response" in
44+
[yY]|[yY][eS]|[yY][eE][sS])
45+
return 0
46+
;;
47+
*)
48+
echo "Aborted by user"
49+
exit 1
50+
;;
51+
esac
52+
}
53+
54+
check_requirements() {
55+
header "Checking Requirements"
56+
57+
# Check if we're in the right directory
58+
if [[ ! -f "$PROJECT_ROOT/Cargo.toml" ]]; then
59+
error "Not in project root directory"
60+
fi
61+
62+
# Check if cargo-workspaces is installed
63+
if ! command -v cargo-workspaces &> /dev/null; then
64+
warn "cargo-workspaces not found. Installing..."
65+
cargo install cargo-workspaces
66+
fi
67+
68+
# Check git status
69+
if [[ -n $(git status --porcelain) ]]; then
70+
warn "Working directory has uncommitted changes"
71+
git status --short
72+
confirm "Continue with uncommitted changes?"
73+
fi
74+
75+
# Check if we're on main branch
76+
local current_branch=$(git branch --show-current)
77+
if [[ "$current_branch" != "main" ]]; then
78+
warn "Not on main branch (currently on: $current_branch)"
79+
confirm "Continue from $current_branch?"
80+
fi
81+
82+
# Check if we can push to origin
83+
log "Checking git remote access..."
84+
git fetch origin
85+
86+
log "✓ All requirements satisfied"
87+
}
88+
89+
show_version_info() {
90+
header "Current Version Information"
91+
92+
echo "Current versions:"
93+
for pkg in redis-cloud redis-enterprise redisctl; do
94+
version=$(cargo metadata --no-deps --format-version 1 | jq -r ".packages[] | select(.name == \"$pkg\") | .version")
95+
echo " $pkg: $version"
96+
done
97+
98+
echo ""
99+
echo "Workspace members:"
100+
cargo metadata --no-deps --format-version 1 | jq -r '.workspace_members[]'
101+
102+
echo ""
103+
echo "Version bump: $VERSION_TYPE"
104+
cargo workspaces version $VERSION_TYPE --no-git-commit --yes 2>/dev/null | grep "Changes:" -A 10 | head -5
105+
106+
# Reset any changes made by the dry run
107+
git checkout HEAD -- Cargo.toml crates/*/Cargo.toml 2>/dev/null || true
108+
}
109+
110+
check_crates_io_auth() {
111+
header "Checking crates.io Authentication"
112+
113+
if [[ -z "${CARGO_REGISTRY_TOKEN:-}" ]]; then
114+
error "CARGO_REGISTRY_TOKEN environment variable not set"
115+
fi
116+
117+
# Test authentication with a small crate
118+
log "Testing crates.io authentication..."
119+
cd "$PROJECT_ROOT/crates/redis-cloud"
120+
if cargo publish --dry-run &>/dev/null; then
121+
log "✓ crates.io authentication working"
122+
else
123+
error "crates.io authentication failed"
124+
fi
125+
cd "$PROJECT_ROOT"
126+
}
127+
128+
run_tests() {
129+
header "Running Tests"
130+
131+
log "Running workspace tests..."
132+
if cargo test --workspace --all-features; then
133+
log "✓ All tests passed"
134+
else
135+
error "Tests failed - aborting release"
136+
fi
137+
138+
log "Running clippy..."
139+
if cargo clippy --all-targets --all-features -- -D warnings; then
140+
log "✓ Clippy passed"
141+
else
142+
error "Clippy failed - aborting release"
143+
fi
144+
}
145+
146+
create_release() {
147+
header "Creating Release"
148+
149+
log "Bumping versions and publishing..."
150+
151+
# Use cargo-workspaces to version, commit, tag, and publish in one command
152+
if cargo workspaces publish \
153+
--yes \
154+
--no-verify \
155+
--allow-branch main \
156+
--force '*' \
157+
"$VERSION_TYPE"; then
158+
159+
NEW_VERSION=$(git describe --tags --abbrev=0)
160+
log "✓ Successfully released $NEW_VERSION"
161+
162+
return 0
163+
else
164+
error "Release failed"
165+
fi
166+
}
167+
168+
post_release_info() {
169+
header "Release Complete!"
170+
171+
local new_version=$(git describe --tags --abbrev=0)
172+
173+
echo -e "${GREEN}🎉 Successfully released $new_version${NC}"
174+
echo ""
175+
echo "What happened:"
176+
echo " ✓ Versions bumped in all crates"
177+
echo " ✓ Changes committed to git"
178+
echo " ✓ Git tag created and pushed: $new_version"
179+
echo " ✓ All crates published to crates.io"
180+
echo ""
181+
echo "What's happening next:"
182+
echo " 🔄 cargo-dist will build binaries (triggered by tag)"
183+
echo " 🔄 Docker images will be built (triggered by tag)"
184+
echo ""
185+
echo "Check status at:"
186+
echo " 📦 crates.io: https://crates.io/crates/redisctl"
187+
echo " 🏷️ GitHub: https://github.com/joshrotenberg/redisctl/releases"
188+
echo " 🐳 Docker: https://hub.docker.com/r/joshrotenberg/redisctl"
189+
echo ""
190+
echo -e "${BLUE}Release completed successfully!${NC} 🚀"
191+
}
192+
193+
cleanup_on_failure() {
194+
header "Cleaning up after failure..."
195+
196+
# Get the version that might have been created
197+
local latest_tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
198+
199+
if [[ -n "$latest_tag" ]]; then
200+
warn "Found tag: $latest_tag"
201+
confirm "Delete the failed release tag $latest_tag?"
202+
203+
# Delete local and remote tags
204+
git tag -d "$latest_tag" 2>/dev/null || true
205+
git push --delete origin "$latest_tag" 2>/dev/null || true
206+
207+
log "Cleaned up tag: $latest_tag"
208+
fi
209+
210+
warn "Release failed. You may need to:"
211+
echo " 1. Check the error messages above"
212+
echo " 2. Ensure CARGO_REGISTRY_TOKEN is valid"
213+
echo " 3. Verify git push access to origin"
214+
echo " 4. Check crates.io authentication"
215+
}
216+
217+
main() {
218+
echo -e "${BLUE}redisctl Release Script${NC}"
219+
echo -e "${BLUE}=====================${NC}"
220+
echo ""
221+
222+
# Validate version type argument
223+
case "$VERSION_TYPE" in
224+
patch|minor|major)
225+
;;
226+
*)
227+
error "Invalid version type: $VERSION_TYPE. Use: patch, minor, or major"
228+
;;
229+
esac
230+
231+
# Set up error handling
232+
trap cleanup_on_failure ERR
233+
234+
# Run release process
235+
check_requirements
236+
show_version_info
237+
confirm "Proceed with $VERSION_TYPE release?"
238+
check_crates_io_auth
239+
run_tests
240+
confirm "All checks passed. Create the release?"
241+
create_release
242+
post_release_info
243+
}
244+
245+
# Run main function
246+
main "$@"

0 commit comments

Comments
 (0)