Skip to content

Commit 9aeb48c

Browse files
authored
feat: Add automation script for releasing the bindings (#44)
Added a script that automates the process of updating the API bindings.
1 parent 00aaefc commit 9aeb48c

File tree

2 files changed

+369
-0
lines changed

2 files changed

+369
-0
lines changed

CONTRIBUTING.MD

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,21 @@ Please refer to Cloudsmith's standard guide on [Open-Source Contributing](https:
44

55
## Updating bindings
66

7+
### Manual approach
8+
79
* Update `PKG_VERSION` in `bin/generate`
810
* Run `bin/generate` to generate bindings
911
* Create a PR specifing API and binding version
1012
* Create git tag and release in github
1113

14+
### Automated approach
15+
16+
* Run `./scripts/update-bindings.sh` to automatically update the bindings.
17+
* This will then provide you with the URL for the PR to release the updated bindings.
18+
* Preferred usage: `./scripts/update-bindings.sh`
19+
* For full options and usage examples, run: `./scripts/update-bindings.sh --help`
20+
* After PR is merged, follow the displayed instructions to create the git tag and GitHub release.
21+
1222
## Contributor License Agreement
1323

1424
By making any contributions to Cloudsmith Ltd projects you agree to be bound by the terms of the Cloudsmith Ltd [Contributor License Agreement](https://help.cloudsmith.io/docs/contributor-license-agreement).

scripts/update-bindings.sh

Lines changed: 359 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,359 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
REPO_NAME="cloudsmith-api-go"
6+
REPO_URL="https://github.com/cloudsmith-io/cloudsmith-api-go"
7+
BRANCH_PREFIX="update-bindings"
8+
GENERATE_SCRIPT="bin/generate"
9+
10+
RED='\033[0;31m'
11+
GREEN='\033[0;32m'
12+
YELLOW='\033[1;33m'
13+
BLUE='\033[0;34m'
14+
NC='\033[0m'
15+
16+
log_info() {
17+
echo -e "${BLUE}[INFO]${NC} $1"
18+
}
19+
20+
log_success() {
21+
echo -e "${GREEN}[SUCCESS]${NC} $1"
22+
}
23+
24+
log_warning() {
25+
echo -e "${YELLOW}[WARNING]${NC} $1"
26+
}
27+
28+
log_error() {
29+
echo -e "${RED}[ERROR]${NC} $1"
30+
}
31+
32+
check_dependencies() {
33+
log_info "Checking dependencies..."
34+
35+
local missing_deps=()
36+
37+
if ! command -v git &> /dev/null; then
38+
missing_deps+=("git")
39+
fi
40+
41+
if [ ${#missing_deps[@]} -ne 0 ]; then
42+
log_error "Missing dependencies: ${missing_deps[*]}"
43+
log_error "Please install the missing dependencies and try again."
44+
exit 1
45+
fi
46+
47+
log_success "All dependencies are installed"
48+
}
49+
50+
validate_version() {
51+
local version="$1"
52+
if [[ ! $version =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
53+
log_error "Invalid version format: $version"
54+
log_error "Version should be in format: X.Y.Z (e.g., 1.2.3)"
55+
exit 1
56+
fi
57+
}
58+
59+
get_current_version() {
60+
if [ ! -f "$GENERATE_SCRIPT" ]; then
61+
log_error "File $GENERATE_SCRIPT not found"
62+
exit 1
63+
fi
64+
65+
local current_version=$(grep -E "^PKG_VERSION=" "$GENERATE_SCRIPT" | cut -d'=' -f2 | tr -d '"' | tr -d "'")
66+
67+
# Handle cases where the version might be a parameter expansion like ${1:-"0.0.46"}
68+
if [[ $current_version =~ ^\$\{.*:-\"?([0-9]+\.[0-9]+\.[0-9]+)\"?\} ]]; then
69+
current_version="${BASH_REMATCH[1]}"
70+
fi
71+
72+
echo "$current_version"
73+
}
74+
75+
increment_patch_version() {
76+
local version="$1"
77+
local major minor patch
78+
79+
IFS='.' read -r major minor patch <<< "$version"
80+
patch=$((patch + 1))
81+
echo "${major}.${minor}.${patch}"
82+
}
83+
84+
get_api_version() {
85+
local api_url="https://api.cloudsmith.io/"
86+
log_info "Fetching current API version from Cloudsmith..." >&2
87+
88+
local api_version=$(curl -s "${api_url}status/check/basic/" 2>/dev/null | jq -r '.version' 2>/dev/null)
89+
90+
if [ "$api_version" = "null" ] || [ -z "$api_version" ]; then
91+
log_warning "Could not fetch API version from Cloudsmith API" >&2
92+
return 1
93+
fi
94+
95+
echo "$api_version"
96+
}
97+
98+
update_version() {
99+
local new_version="$1"
100+
local current_version=$(get_current_version)
101+
102+
log_info "Updating version from $current_version to $new_version"
103+
104+
log_info "Current PKG_VERSION line:"
105+
grep "PKG_VERSION" "$GENERATE_SCRIPT" || {
106+
log_error "No PKG_VERSION line found in $GENERATE_SCRIPT"
107+
exit 1
108+
}
109+
110+
cp "$GENERATE_SCRIPT" "$GENERATE_SCRIPT.backup"
111+
112+
# Update the parameter expansion to use the new version as the default
113+
sed -i.bak "s/PKG_VERSION=\${1:-\"[^\"]*\"}/PKG_VERSION=\${1:-\"$new_version\"}/" "$GENERATE_SCRIPT"
114+
115+
updated_version=$(get_current_version)
116+
if [ "$updated_version" != "$new_version" ]; then
117+
log_error "Failed to update version in $GENERATE_SCRIPT"
118+
log_error "Expected: $new_version, Got: $updated_version"
119+
120+
log_error "Updated PKG_VERSION line:"
121+
grep "PKG_VERSION" "$GENERATE_SCRIPT" || log_error "No PKG_VERSION line found"
122+
123+
mv "$GENERATE_SCRIPT.backup" "$GENERATE_SCRIPT"
124+
exit 1
125+
fi
126+
127+
rm "$GENERATE_SCRIPT.backup" "$GENERATE_SCRIPT.bak" 2>/dev/null || true
128+
log_success "Version updated successfully"
129+
}
130+
131+
generate_bindings() {
132+
log_info "Generating Go bindings..."
133+
134+
if [ ! -x "$GENERATE_SCRIPT" ]; then
135+
log_warning "Making $GENERATE_SCRIPT executable"
136+
chmod +x "$GENERATE_SCRIPT"
137+
fi
138+
139+
if ./"$GENERATE_SCRIPT"; then
140+
log_success "Go bindings generated successfully"
141+
else
142+
log_error "Failed to generate Go bindings"
143+
exit 1
144+
fi
145+
}
146+
147+
create_and_push_branch() {
148+
local version="$1"
149+
local api_version="$2"
150+
local branch_name="${BRANCH_PREFIX}-v${version}"
151+
152+
log_info "Creating branch: $branch_name"
153+
154+
if git show-ref --verify --quiet "refs/heads/$branch_name"; then
155+
log_warning "Branch $branch_name already exists locally. Deleting it."
156+
git branch -D "$branch_name"
157+
fi
158+
159+
if git ls-remote --heads origin "$branch_name" | grep -q "$branch_name"; then
160+
log_warning "Branch $branch_name already exists on remote."
161+
read -p "Do you want to delete the remote branch and create a new one? (y/N): " -n 1 -r
162+
echo
163+
if [[ $REPLY =~ ^[Yy]$ ]]; then
164+
log_info "Deleting remote branch $branch_name..."
165+
git push origin --delete "$branch_name" || {
166+
log_warning "Could not delete remote branch (it might not exist or you might not have permissions)"
167+
}
168+
else
169+
local timestamp=$(date +"%Y%m%d-%H%M%S")
170+
branch_name="${BRANCH_PREFIX}-v${version}-${timestamp}"
171+
log_info "Using unique branch name: $branch_name"
172+
fi
173+
fi
174+
175+
git checkout -b "$branch_name"
176+
git add .
177+
178+
if git diff --staged --quiet; then
179+
log_warning "No changes to commit. The bindings might already be up to date."
180+
return 1
181+
fi
182+
183+
git commit -m "Update Go API bindings to version $version
184+
185+
Binding version: $version
186+
Cloudsmith API version: $api_version
187+
188+
- Updated PKG_VERSION in bin/generate
189+
- Regenerated Go bindings
190+
- Ready for tagging and release"
191+
192+
log_info "Pushing branch to origin..."
193+
if ! git push origin "$branch_name"; then
194+
log_warning "Normal push failed, trying force push..."
195+
git push origin "$branch_name" --force-with-lease || {
196+
log_error "Failed to push branch even with force. Check your permissions."
197+
exit 1
198+
}
199+
fi
200+
201+
log_success "Branch created and pushed successfully"
202+
echo "$branch_name"
203+
}
204+
205+
create_tag_and_release_instructions() {
206+
local version="$1"
207+
local tag_name="v${version}"
208+
209+
echo ""
210+
log_info "After the PR is merged, create a git tag and release:"
211+
echo ""
212+
echo "1. Switch to master and pull latest changes:"
213+
echo " git checkout master"
214+
echo " git pull"
215+
echo ""
216+
echo "2. Create and push the tag:"
217+
echo " git tag -a $tag_name -m \"Release version $version\""
218+
echo " git push origin $tag_name"
219+
echo ""
220+
echo "3. Go to GitHub releases page and create a new release:"
221+
echo " - Select tag: $tag_name"
222+
echo " - Release title: Release $version"
223+
echo " - Add release notes as needed"
224+
echo ""
225+
}
226+
227+
usage() {
228+
echo "Usage: $0 [OPTIONS]"
229+
echo ""
230+
echo "Preferred usage (no arguments - auto-increments patch version):"
231+
echo " $0 # Auto-increment patch version and fetch latest API version"
232+
echo ""
233+
echo "Options:"
234+
echo " -v, --version VERSION Specific binding version (optional)"
235+
echo " -h, --help Show this help message"
236+
echo ""
237+
echo "Examples:"
238+
echo " $0 # Preferred: auto-increment patch version"
239+
echo " $0 -v 1.3.0 # Specify custom version (e.g. minor/major bump)"
240+
echo " $0 --version 1.2.5 # Long form"
241+
echo ""
242+
echo "Note:"
243+
echo " - When run without arguments, the script will:"
244+
echo " * Auto-increment the patch version (e.g. 1.2.3 -> 1.2.4)"
245+
echo " * Auto-fetch the latest Cloudsmith API version"
246+
echo " - Use -v only for larger version increments (minor/major bumps)"
247+
echo " - After PR is merged, you'll need to create a git tag and GitHub release"
248+
}
249+
250+
main() {
251+
local new_version=""
252+
local auto_increment=true
253+
254+
while [[ $# -gt 0 ]]; do
255+
case $1 in
256+
-v|--version)
257+
new_version="$2"
258+
auto_increment=false
259+
shift 2
260+
;;
261+
-h|--help)
262+
usage
263+
exit 0
264+
;;
265+
*)
266+
log_error "Unknown option: $1"
267+
usage
268+
exit 1
269+
;;
270+
esac
271+
done
272+
273+
check_dependencies
274+
275+
local current_version=$(get_current_version)
276+
log_info "Current version: $current_version"
277+
278+
if [ "$auto_increment" = true ]; then
279+
new_version=$(increment_patch_version "$current_version")
280+
log_info "Auto-incrementing patch version to: $new_version"
281+
else
282+
validate_version "$new_version"
283+
log_info "Using specified version: $new_version"
284+
fi
285+
286+
local api_version
287+
if api_version=$(get_api_version); then
288+
log_info "Auto-fetched API version: $api_version"
289+
else
290+
log_error "Failed to auto-fetch API version"
291+
log_error "Please check your internet connection and try again"
292+
exit 1
293+
fi
294+
295+
validate_version "$new_version"
296+
validate_version "$api_version"
297+
298+
log_info "Starting Cloudsmith Go API bindings update process..."
299+
log_info "New binding version: $new_version"
300+
log_info "API version: $api_version"
301+
302+
if [ "$current_version" = "$new_version" ]; then
303+
log_warning "Version $new_version is the same as current version"
304+
read -p "Do you want to continue anyway? (y/N): " -n 1 -r
305+
echo
306+
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
307+
log_info "Operation cancelled"
308+
exit 0
309+
fi
310+
fi
311+
312+
local current_branch=$(git branch --show-current)
313+
log_info "Current branch: $current_branch"
314+
315+
if [[ "$current_branch" == "main" || "$current_branch" == "master" ]]; then
316+
log_info "Already on main branch ($current_branch)"
317+
else
318+
if ! git diff-index --quiet HEAD --; then
319+
log_error "You have uncommitted changes. Please commit or stash them first:"
320+
git status --short
321+
exit 1
322+
fi
323+
324+
log_info "Switching to main branch..."
325+
326+
if git show-ref --verify --quiet refs/heads/main; then
327+
git checkout main || {
328+
log_error "Could not switch to main branch"
329+
exit 1
330+
}
331+
elif git show-ref --verify --quiet refs/heads/master; then
332+
git checkout master || {
333+
log_error "Could not switch to master branch"
334+
exit 1
335+
}
336+
else
337+
log_error "Neither 'main' nor 'master' branch found"
338+
log_error "Available branches:"
339+
git branch -a
340+
exit 1
341+
fi
342+
fi
343+
344+
log_info "Pulling latest changes..."
345+
git pull origin $(git branch --show-current)
346+
347+
update_version "$new_version"
348+
generate_bindings
349+
350+
local branch_name
351+
if branch_name=$(create_and_push_branch "$new_version" "$api_version"); then
352+
log_success "Automation completed successfully!"
353+
create_tag_and_release_instructions "$new_version"
354+
else
355+
log_warning "No changes detected. The bindings may already be up to date."
356+
fi
357+
}
358+
359+
main "$@"

0 commit comments

Comments
 (0)