-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdump-version.sh
More file actions
executable file
·438 lines (378 loc) · 15.9 KB
/
Copy pathdump-version.sh
File metadata and controls
executable file
·438 lines (378 loc) · 15.9 KB
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
#!/bin/bash
#
# dump-version.sh - Prepare a new release version for gopher-mcp-python
#
# Usage:
# ./dump-version.sh [VERSION]
#
# Arguments:
# VERSION - Optional. Format: X.Y.Z or X.Y.Z.E
# If not provided, uses latest gopher-orch release version (X.Y.Z)
# If provided as X.Y.Z.E, X.Y.Z must match gopher-orch version
#
# This script will:
# 1. Fetch latest version from gopher-orch releases
# 2. Validate and determine the target version
# 3. Update pyproject.toml (main and platform packages)
# 4. Auto-populate CHANGELOG.md [Unreleased] section from:
# - git log of this repo since the previous tag
# - the gopher-orch GitHub release notes for the new version
# (manual entries already in [Unreleased] are preserved and shown first)
# 5. Update __init__.py files and platform packages
# 6. Promote [Unreleased] -> [X.Y.Z] - date
# 7. Commit the changes
#
# After running this script:
# 1. Review the changes: git diff HEAD~1
# 2. Push to release: git push origin br_release
#
set -e
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m'
# Get script directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
# Files
PYPROJECT_TOML="pyproject.toml"
CHANGELOG_FILE="CHANGELOG.md"
PACKAGES_DIR="packages"
INIT_PY="gopher_mcp_python/__init__.py"
echo -e "${CYAN}========================================${NC}"
echo -e "${CYAN} gopher-mcp-python Release Version Dump${NC}"
echo -e "${CYAN}========================================${NC}"
echo ""
# -----------------------------------------------------------------------------
# Step 1: Fetch latest gopher-orch version from GitHub releases
# -----------------------------------------------------------------------------
echo -e "${YELLOW}Step 1: Fetching latest gopher-orch version...${NC}"
# Check if gh CLI is available
if ! command -v gh &> /dev/null; then
echo -e "${RED}Error: GitHub CLI (gh) is not installed${NC}"
echo "Install it with: brew install gh"
echo "Then authenticate: gh auth login"
exit 1
fi
# Fetch latest release from gopher-orch using gh CLI (handles private repo auth)
GOPHER_ORCH_TAG=$(gh release view --repo GopherSecurity/gopher-orch --json tagName -q '.tagName' 2>/dev/null)
if [ -z "$GOPHER_ORCH_TAG" ]; then
echo -e "${RED}Error: Could not fetch latest gopher-orch release${NC}"
echo "Make sure you have access to GopherSecurity/gopher-orch repository."
echo "Run 'gh auth login' to authenticate if needed."
exit 1
fi
# Remove 'v' prefix if present (e.g., v0.1.1 -> 0.1.1)
GOPHER_ORCH_VERSION="${GOPHER_ORCH_TAG#v}"
if [ -z "$GOPHER_ORCH_VERSION" ]; then
echo -e "${RED}Error: Could not parse gopher-orch version from release${NC}"
exit 1
fi
echo -e " Latest gopher-orch version: ${GREEN}$GOPHER_ORCH_VERSION${NC}"
# Validate gopher-orch version format (X.Y.Z)
if ! echo "$GOPHER_ORCH_VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$'; then
echo -e "${RED}Error: gopher-orch version '$GOPHER_ORCH_VERSION' is not in X.Y.Z format${NC}"
exit 1
fi
# -----------------------------------------------------------------------------
# Step 2: Determine target version
# -----------------------------------------------------------------------------
echo ""
echo -e "${YELLOW}Step 2: Determining target version...${NC}"
INPUT_VERSION="$1"
if [ -z "$INPUT_VERSION" ]; then
# No argument provided, use gopher-orch version directly
TARGET_VERSION="$GOPHER_ORCH_VERSION"
echo -e " No version argument provided"
echo -e " Using gopher-orch version: ${GREEN}$TARGET_VERSION${NC}"
else
# Version argument provided, validate it
# Format should be X.Y.Z or X.Y.Z.E
if echo "$INPUT_VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$'; then
# X.Y.Z format - must match gopher-orch exactly
if [ "$INPUT_VERSION" != "$GOPHER_ORCH_VERSION" ]; then
echo -e "${RED}Error: Version $INPUT_VERSION does not match gopher-orch version $GOPHER_ORCH_VERSION${NC}"
exit 1
fi
TARGET_VERSION="$INPUT_VERSION"
elif echo "$INPUT_VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'; then
# X.Y.Z.E format - first 3 parts must match gopher-orch
INPUT_BASE=$(echo "$INPUT_VERSION" | sed -E 's/^([0-9]+\.[0-9]+\.[0-9]+)\.[0-9]+$/\1/')
if [ "$INPUT_BASE" != "$GOPHER_ORCH_VERSION" ]; then
echo -e "${RED}Error: Version base $INPUT_BASE does not match gopher-orch version $GOPHER_ORCH_VERSION${NC}"
echo "Extended version X.Y.Z.E must have X.Y.Z matching gopher-orch."
exit 1
fi
TARGET_VERSION="$INPUT_VERSION"
else
echo -e "${RED}Error: Invalid version format '$INPUT_VERSION'${NC}"
echo "Expected format: X.Y.Z or X.Y.Z.E"
exit 1
fi
echo -e " Using provided version: ${GREEN}$TARGET_VERSION${NC}"
fi
# -----------------------------------------------------------------------------
# Step 3: Read current version from pyproject.toml
# -----------------------------------------------------------------------------
echo ""
echo -e "${YELLOW}Step 3: Reading current version...${NC}"
if [ ! -f "$PYPROJECT_TOML" ]; then
echo -e "${RED}Error: $PYPROJECT_TOML not found${NC}"
exit 1
fi
CURRENT_VERSION=$(grep -E '^version\s*=' "$PYPROJECT_TOML" | head -1 | sed -E 's/.*"([^"]+)".*/\1/')
echo -e " Current version: ${CYAN}$CURRENT_VERSION${NC}"
echo -e " Target version: ${GREEN}$TARGET_VERSION${NC}"
if [ "$CURRENT_VERSION" = "$TARGET_VERSION" ]; then
echo -e "${YELLOW}Warning: Version is already $TARGET_VERSION${NC}"
echo "If you want to re-release, please update the version manually first."
exit 0
fi
# -----------------------------------------------------------------------------
# Step 4: Build release notes from git log + gopher-orch release notes
# -----------------------------------------------------------------------------
echo ""
echo -e "${YELLOW}Step 4: Building release notes...${NC}"
if [ ! -f "$CHANGELOG_FILE" ]; then
echo -e "${RED}Error: $CHANGELOG_FILE not found${NC}"
exit 1
fi
# Fetch tags so PREV_TAG resolution is accurate even on shallow clones
git fetch --tags --quiet 2>/dev/null || true
# Previous Python tag (anything matching v*, sorted by semver)
PREV_TAG=$(git tag -l 'v*' --sort=-v:refname | head -1)
if [ -n "$PREV_TAG" ]; then
echo -e " Previous Python tag: ${CYAN}$PREV_TAG${NC}"
PY_RANGE="$PREV_TAG..HEAD"
else
echo -e " Previous Python tag: ${YELLOW}none (first release)${NC}"
PY_RANGE="HEAD"
fi
# Previous gopher-orch version recorded in the previous release commit
PREV_GOPHER_ORCH_VERSION=""
if [ -n "$PREV_TAG" ]; then
PREV_GOPHER_ORCH_VERSION=$(git log -1 --format=%B "$PREV_TAG" 2>/dev/null | \
grep -oE 'gopher-orch version: [0-9]+\.[0-9]+\.[0-9]+' | \
awk '{print $NF}' | head -1)
fi
if [ -n "$PREV_GOPHER_ORCH_VERSION" ]; then
echo -e " Previous gopher-orch: ${CYAN}v$PREV_GOPHER_ORCH_VERSION${NC}"
else
echo -e " Previous gopher-orch: ${YELLOW}unknown${NC}"
fi
echo -e " New gopher-orch: ${GREEN}v$GOPHER_ORCH_VERSION${NC}"
# Preserve any manually-authored entries already under [Unreleased]
MANUAL_CONTENT=$(awk '
/^## \[Unreleased\]/ { capture = 1; next }
/^## \[/ && capture { capture = 0 }
capture { print }
' "$CHANGELOG_FILE" | sed -e '/^[[:space:]]*$/d')
# Collect Python repo commits since previous tag (skip merges + prior release commits)
PY_COMMITS=$(git log --no-merges --pretty=format:'- %s' \
--invert-grep --grep='^Release version' --grep='^\[release\]' \
$PY_RANGE 2>/dev/null || true)
PY_COMMIT_COUNT=0
if [ -n "$PY_COMMITS" ]; then
PY_COMMIT_COUNT=$(printf '%s\n' "$PY_COMMITS" | wc -l | tr -d ' ')
fi
echo -e " Python commits in range:${GREEN} $PY_COMMIT_COUNT${NC}"
# Extract the "What's Changed" block from the gopher-orch release notes,
# stripping the Build Information preamble and the trailing Full Changelog link.
GOPHER_ORCH_NOTES=$(gh release view "v$GOPHER_ORCH_VERSION" \
--repo GopherSecurity/gopher-orch \
--json body -q '.body' 2>/dev/null | \
awk '
/^## What.s Changed/ { capture = 1; next }
/^\*\*Full Changelog\*\*/ { capture = 0 }
capture { print }
' | sed -e '/^---$/d')
if [ -n "$GOPHER_ORCH_NOTES" ]; then
echo -e " gopher-orch notes: ${GREEN}fetched${NC}"
else
echo -e " gopher-orch notes: ${YELLOW}empty (using link only)${NC}"
fi
# Build the new [Unreleased] body
RELEASE_NOTES_FILE=$(mktemp)
{
if [ -n "$MANUAL_CONTENT" ]; then
printf '%s\n\n' "$MANUAL_CONTENT"
fi
echo "### Changed"
echo ""
if [ -n "$PREV_GOPHER_ORCH_VERSION" ] && \
[ "$PREV_GOPHER_ORCH_VERSION" != "$GOPHER_ORCH_VERSION" ]; then
echo "- Bump \`gopher-orch\` native library from v$PREV_GOPHER_ORCH_VERSION to [v$GOPHER_ORCH_VERSION](https://github.com/GopherSecurity/gopher-orch/releases/tag/v$GOPHER_ORCH_VERSION)."
else
echo "- Pin \`gopher-orch\` native library to [v$GOPHER_ORCH_VERSION](https://github.com/GopherSecurity/gopher-orch/releases/tag/v$GOPHER_ORCH_VERSION)."
fi
echo ""
if [ -n "$PY_COMMITS" ]; then
if [ -n "$PREV_TAG" ]; then
echo "#### SDK changes since $PREV_TAG"
else
echo "#### SDK changes"
fi
echo ""
printf '%s\n' "$PY_COMMITS"
echo ""
fi
if [ -n "$GOPHER_ORCH_NOTES" ]; then
echo "#### gopher-orch v$GOPHER_ORCH_VERSION highlights"
echo ""
printf '%s\n' "$GOPHER_ORCH_NOTES"
fi
} > "$RELEASE_NOTES_FILE"
# Splice the generated body in: replace everything between
# "## [Unreleased]" and the next "## [" with the new content.
CHANGELOG_TMP="${CHANGELOG_FILE}.gen"
awk -v notes_file="$RELEASE_NOTES_FILE" '
BEGIN {
while ((getline line < notes_file) > 0) {
notes = notes (notes ? "\n" : "") line
}
close(notes_file)
}
/^## \[Unreleased\]/ {
print
print ""
print notes
print ""
skipping = 1
next
}
/^## \[/ && skipping { skipping = 0 }
skipping { next }
{ print }
' "$CHANGELOG_FILE" > "$CHANGELOG_TMP"
mv "$CHANGELOG_TMP" "$CHANGELOG_FILE"
rm -f "$RELEASE_NOTES_FILE"
# Recompute UNRELEASED_CONTENT for the eventual commit message
UNRELEASED_CONTENT=$(awk '
/^## \[Unreleased\]/ { capture = 1; next }
/^## \[/ && capture { capture = 0 }
capture { print }
' "$CHANGELOG_FILE" | sed -e '/^[[:space:]]*$/d')
echo -e " ${GREEN}[Unreleased] section populated${NC}"
echo " Preview:"
printf '%s\n' "$UNRELEASED_CONTENT" | head -12 | sed 's/^/ /'
# -----------------------------------------------------------------------------
# Step 5: Update version files
# -----------------------------------------------------------------------------
echo ""
echo -e "${YELLOW}Step 5: Updating version files...${NC}"
# Update main pyproject.toml
sed -i.bak -E "s/^version[[:space:]]*=[[:space:]]*\"[^\"]*\"/version = \"$TARGET_VERSION\"/" "$PYPROJECT_TOML"
rm -f "${PYPROJECT_TOML}.bak"
echo -e " ${GREEN}Updated $PYPROJECT_TOML${NC}"
# Update GOPHER_ORCH_VERSION in CI workflow
WORKFLOW_FILE=".github/workflows/publish-packages.yml"
if [ -f "$WORKFLOW_FILE" ]; then
sed -i.bak -E "s/GOPHER_ORCH_VERSION: 'v[^']*'/GOPHER_ORCH_VERSION: 'v$GOPHER_ORCH_VERSION'/" "$WORKFLOW_FILE"
rm -f "${WORKFLOW_FILE}.bak"
echo -e " ${GREEN}Updated $WORKFLOW_FILE (GOPHER_ORCH_VERSION: v$GOPHER_ORCH_VERSION)${NC}"
fi
# Update gopher_mcp_python/__init__.py
if [ -f "$INIT_PY" ]; then
sed -i.bak -E "s/__version__[[:space:]]*=[[:space:]]*\"[^\"]*\"/__version__ = \"$TARGET_VERSION\"/" "$INIT_PY"
rm -f "${INIT_PY}.bak"
echo -e " ${GREEN}Updated $INIT_PY${NC}"
fi
# Update platform packages
for platform in darwin-arm64 darwin-x64 linux-arm64 linux-x64 win32-arm64 win32-x64; do
pkg_dir="$PACKAGES_DIR/$platform"
if [ -d "$pkg_dir" ]; then
# Update pyproject.toml
pkg_pyproject="$pkg_dir/pyproject.toml"
if [ -f "$pkg_pyproject" ]; then
sed -i.bak -E "s/^version[[:space:]]*=[[:space:]]*\"[^\"]*\"/version = \"$TARGET_VERSION\"/" "$pkg_pyproject"
rm -f "${pkg_pyproject}.bak"
echo -e " ${GREEN}Updated $pkg_pyproject${NC}"
fi
# Update __init__.py
pkg_name="gopher_mcp_python_native_${platform//-/_}"
pkg_init="$pkg_dir/$pkg_name/__init__.py"
if [ -f "$pkg_init" ]; then
sed -i.bak -E "s/__version__[[:space:]]*=[[:space:]]*\"[^\"]*\"/__version__ = \"$TARGET_VERSION\"/" "$pkg_init"
rm -f "${pkg_init}.bak"
echo -e " ${GREEN}Updated $pkg_init${NC}"
fi
fi
done
# -----------------------------------------------------------------------------
# Step 6: Update CHANGELOG.md
# -----------------------------------------------------------------------------
echo ""
echo -e "${YELLOW}Step 6: Updating CHANGELOG.md...${NC}"
TODAY=$(date +%Y-%m-%d)
# Create backup
cp "$CHANGELOG_FILE" "${CHANGELOG_FILE}.bak"
# Update CHANGELOG.md:
# 1. Replace [Unreleased] with [X.Y.Z] - YYYY-MM-DD
# 2. Add new [Unreleased] section after the header
# Create the new content
{
# Header (first 7 lines typically)
head -7 "$CHANGELOG_FILE"
echo ""
echo "## [Unreleased]"
echo ""
# Content from old [Unreleased] but with version header replaced
tail -n +8 "$CHANGELOG_FILE" | sed "s/^## \[Unreleased\]/## [$TARGET_VERSION] - $TODAY/"
} > "${CHANGELOG_FILE}.new"
# Update the links section at the bottom
# Update [Unreleased] link to point to new version
sed -i.tmp "s|\[Unreleased\]: \(.*\)/compare/v[^.]*\.\.\.\(.*\)|[Unreleased]: \1/compare/v$TARGET_VERSION...\2|" "${CHANGELOG_FILE}.new"
# Check if version link exists, if not add it after [Unreleased] link
if ! grep -q "^\[$TARGET_VERSION\]:" "${CHANGELOG_FILE}.new"; then
# Find the previous version from the old [Unreleased] link
PREV_VERSION=$(grep "^\[Unreleased\]:" "$CHANGELOG_FILE" | sed -E 's/.*compare\/v([^.]+\.[^.]+\.[^.]+[^.]*)\.\.\.HEAD/\1/' | head -1)
if [ -n "$PREV_VERSION" ]; then
# Add version link after [Unreleased] link
sed -i.tmp "/^\[Unreleased\]:/a\\
[$TARGET_VERSION]: https://github.com/GopherSecurity/gopher-mcp-python/compare/v${PREV_VERSION}...v$TARGET_VERSION" "${CHANGELOG_FILE}.new"
fi
fi
mv "${CHANGELOG_FILE}.new" "$CHANGELOG_FILE"
rm -f "${CHANGELOG_FILE}.new.tmp" "${CHANGELOG_FILE}.bak"
echo -e " ${GREEN}CHANGELOG.md updated${NC}"
# -----------------------------------------------------------------------------
# Step 7: Show changes and commit
# -----------------------------------------------------------------------------
echo ""
echo -e "${YELLOW}Step 7: Committing changes...${NC}"
# Show what changed
echo ""
echo -e "${CYAN}Changes to be committed:${NC}"
git diff --stat
echo ""
echo -e "${CYAN}Committing...${NC}"
git add "$PYPROJECT_TOML" "$INIT_PY" "$CHANGELOG_FILE" "$PACKAGES_DIR" "$WORKFLOW_FILE"
git commit -m "Release version $TARGET_VERSION
Prepare release v$TARGET_VERSION:
- Update pyproject.toml to version $TARGET_VERSION
- Update platform packages to version $TARGET_VERSION
- Update CHANGELOG.md: [Unreleased] -> [$TARGET_VERSION] - $TODAY
gopher-orch version: $GOPHER_ORCH_VERSION
Changes in this release:
$(echo "$UNRELEASED_CONTENT" | head -10)
"
echo ""
echo -e "${GREEN}========================================${NC}"
echo -e "${GREEN} Release preparation complete!${NC}"
echo -e "${GREEN}========================================${NC}"
echo ""
echo -e "Version: ${CYAN}$TARGET_VERSION${NC}"
echo -e "Tag: ${CYAN}v$TARGET_VERSION${NC}"
echo -e "gopher-orch: ${CYAN}$GOPHER_ORCH_VERSION${NC}"
echo ""
echo -e "${YELLOW}Next steps:${NC}"
echo " 1. Review the commit: git show HEAD"
echo " 2. Push to release: git push origin br_release"
echo ""
echo -e "${CYAN}The CI workflow will:${NC}"
echo " - Download gopher-orch binaries for v$TARGET_VERSION"
echo " - Build and publish platform packages to PyPI"
echo " - Build and publish main package to PyPI"
echo " - Create GitHub Release with tag v$TARGET_VERSION"