Skip to content

Commit b6ec3a4

Browse files
edburnsCopilot
andcommitted
Add release scripts (update-changelog.sh) for Java publishing
Copied verbatim from copilot-sdk-java. These scripts are called by java-publish-maven.yml to update CHANGELOG.md during release. Both scripts are marked executable. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent f5487fb commit b6ec3a4

2 files changed

Lines changed: 395 additions & 0 deletions

File tree

Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
#!/bin/bash
2+
# Test script for update-changelog.sh
3+
4+
set -e
5+
6+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7+
UPDATE_SCRIPT="${SCRIPT_DIR}/update-changelog.sh"
8+
TEST_DIR="/tmp/changelog-test-$$"
9+
10+
# Colors for output
11+
GREEN='\033[0;32m'
12+
RED='\033[0;31m'
13+
NC='\033[0m' # No Color
14+
15+
passed=0
16+
failed=0
17+
18+
# Setup test directory
19+
mkdir -p "$TEST_DIR"
20+
21+
# Cleanup on exit
22+
cleanup() {
23+
rm -rf "$TEST_DIR"
24+
}
25+
trap cleanup EXIT
26+
27+
# Helper function to run a test
28+
run_test() {
29+
local test_name="$1"
30+
local test_func="$2"
31+
32+
echo -n "Testing: $test_name ... "
33+
34+
if $test_func; then
35+
echo -e "${GREEN}PASSED${NC}"
36+
passed=$((passed + 1))
37+
else
38+
echo -e "${RED}FAILED${NC}"
39+
failed=$((failed + 1))
40+
fi
41+
}
42+
43+
# Test 1: Basic functionality - Replace Unreleased with version
44+
test_basic_replace() {
45+
local test_file="${TEST_DIR}/test1.md"
46+
cat > "$test_file" << 'EOF'
47+
# Changelog
48+
49+
## [Unreleased]
50+
51+
### Added
52+
- New feature
53+
54+
## [1.0.0] - 2026-01-01
55+
56+
### Added
57+
- Initial release
58+
59+
[1.0.0]: https://github.com/test/repo/releases/tag/1.0.0
60+
EOF
61+
62+
# Run the script
63+
CHANGELOG_FILE="$test_file" bash "$UPDATE_SCRIPT" 1.0.1 > /dev/null 2>&1
64+
65+
# Verify the changes
66+
if grep -q "## \[Unreleased\]" "$test_file" && \
67+
grep -q "## \[1.0.1\] - $(date +%Y-%m-%d)" "$test_file" && \
68+
grep -q "\[Unreleased\]: https://github.com/test/repo/compare/v1.0.1...HEAD" "$test_file" && \
69+
grep -q "\[1.0.1\]: https://github.com/test/repo/compare/v1.0.0...v1.0.1" "$test_file"; then
70+
return 0
71+
else
72+
return 1
73+
fi
74+
}
75+
76+
# Test 2: Handle CHANGELOG without Unreleased link
77+
test_no_unreleased_link() {
78+
local test_file="${TEST_DIR}/test2.md"
79+
cat > "$test_file" << 'EOF'
80+
# Changelog
81+
82+
## [Unreleased]
83+
84+
### Added
85+
- New feature
86+
87+
## [1.0.0] - 2026-01-01
88+
89+
[1.0.0]: https://github.com/test/repo/releases/tag/1.0.0
90+
EOF
91+
92+
CHANGELOG_FILE="$test_file" bash "$UPDATE_SCRIPT" 1.0.1 > /dev/null 2>&1
93+
94+
# Should add both Unreleased and version links
95+
if grep -q "\[Unreleased\]: https://github.com/test/repo/compare/v1.0.1...HEAD" "$test_file" && \
96+
grep -q "\[1.0.1\]: https://github.com/test/repo/compare/v1.0.0...v1.0.1" "$test_file"; then
97+
return 0
98+
else
99+
return 1
100+
fi
101+
}
102+
103+
# Test 3: Preserve content structure
104+
test_preserve_content() {
105+
local test_file="${TEST_DIR}/test3.md"
106+
cat > "$test_file" << 'EOF'
107+
# Changelog
108+
109+
## [Unreleased]
110+
111+
### Added
112+
- Feature A
113+
- Feature B
114+
115+
### Fixed
116+
- Bug fix
117+
118+
## [1.0.0] - 2026-01-01
119+
120+
[1.0.0]: https://github.com/test/repo/releases/tag/1.0.0
121+
EOF
122+
123+
CHANGELOG_FILE="$test_file" bash "$UPDATE_SCRIPT" 1.0.1 > /dev/null 2>&1
124+
125+
# Verify content is preserved under the new version
126+
if grep -A 6 "## \[1.0.1\]" "$test_file" | grep -q "Feature A" && \
127+
grep -A 6 "## \[1.0.1\]" "$test_file" | grep -q "Bug fix"; then
128+
return 0
129+
else
130+
return 1
131+
fi
132+
}
133+
134+
# Test 4: Error handling - no Unreleased section
135+
test_no_unreleased_section() {
136+
local test_file="${TEST_DIR}/test4.md"
137+
cat > "$test_file" << 'EOF'
138+
# Changelog
139+
140+
## [1.0.0] - 2026-01-01
141+
142+
[1.0.0]: https://github.com/test/repo/releases/tag/1.0.0
143+
EOF
144+
145+
# Should fail because there's no Unreleased section
146+
if ! CHANGELOG_FILE="$test_file" bash "$UPDATE_SCRIPT" 1.0.1 > /dev/null 2>&1; then
147+
return 0
148+
else
149+
return 1
150+
fi
151+
}
152+
153+
# Test 5: Multiple version handling
154+
test_multiple_versions() {
155+
local test_file="${TEST_DIR}/test5.md"
156+
cat > "$test_file" << 'EOF'
157+
# Changelog
158+
159+
## [Unreleased]
160+
161+
### Added
162+
- New feature
163+
164+
## [1.0.1] - 2026-02-01
165+
166+
## [1.0.0] - 2026-01-01
167+
168+
[1.0.1]: https://github.com/test/repo/compare/v1.0.0...v1.0.1
169+
[1.0.0]: https://github.com/test/repo/releases/tag/1.0.0
170+
EOF
171+
172+
CHANGELOG_FILE="$test_file" bash "$UPDATE_SCRIPT" 1.0.2 > /dev/null 2>&1
173+
174+
# Verify the new version is added and links are updated
175+
if grep -q "## \[1.0.2\] - $(date +%Y-%m-%d)" "$test_file" && \
176+
grep -q "\[1.0.2\]: https://github.com/test/repo/compare/v1.0.1...v1.0.2" "$test_file"; then
177+
return 0
178+
else
179+
return 1
180+
fi
181+
}
182+
183+
# Test 6: Beta-java version format (e.g., 1.0.0-beta-java.N)
184+
test_beta_java_version() {
185+
local test_file="${TEST_DIR}/test6.md"
186+
cat > "$test_file" << 'EOF'
187+
# Changelog
188+
189+
## [Unreleased]
190+
191+
### Added
192+
- New feature
193+
194+
## [1.0.0-beta-java.1] - 2026-05-01
195+
196+
[Unreleased]: https://github.com/test/repo/compare/v1.0.0-beta-java.1...HEAD
197+
[1.0.0-beta-java.1]: https://github.com/test/repo/compare/v0.3.0-java.2...v1.0.0-beta-java.1
198+
[0.3.0-java.2]: https://github.com/test/repo/releases/tag/0.3.0-java.2
199+
EOF
200+
201+
CHANGELOG_FILE="$test_file" bash "$UPDATE_SCRIPT" 1.0.0-beta-java.2 > /dev/null 2>&1
202+
203+
# The [Unreleased] link should now point to v1.0.0-beta-java.2
204+
# [1.0.0-beta-java.2] should compare from v1.0.0-beta-java.1
205+
if grep -q "\[Unreleased\]: https://github.com/test/repo/compare/v1.0.0-beta-java.2...HEAD" "$test_file" && \
206+
grep -q "\[1.0.0-beta-java.2\]: https://github.com/test/repo/compare/v1.0.0-beta-java.1...v1.0.0-beta-java.2" "$test_file"; then
207+
return 0
208+
else
209+
return 1
210+
fi
211+
}
212+
213+
# Test 7: No duplicate [Unreleased] links when existing [Unreleased] link is present
214+
test_no_duplicate_unreleased_links() {
215+
local test_file="${TEST_DIR}/test7.md"
216+
cat > "$test_file" << 'EOF'
217+
# Changelog
218+
219+
## [Unreleased]
220+
221+
### Added
222+
- New feature
223+
224+
## [1.0.0-beta-java.2] - 2026-05-08
225+
226+
## [1.0.0-beta-java.1] - 2026-05-05
227+
228+
[Unreleased]: https://github.com/test/repo/compare/v1.0.0-beta-java.2...HEAD
229+
[1.0.0-beta-java.2]: https://github.com/test/repo/compare/v1.0.0-beta-java.1...v1.0.0-beta-java.2
230+
[1.0.0-beta-java.1]: https://github.com/test/repo/compare/v0.3.0-java.2...v1.0.0-beta-java.1
231+
[0.3.0-java.2]: https://github.com/test/repo/releases/tag/0.3.0-java.2
232+
EOF
233+
234+
CHANGELOG_FILE="$test_file" bash "$UPDATE_SCRIPT" 1.0.0-beta-java.3 > /dev/null 2>&1
235+
236+
# Count [Unreleased] link definitions - there should be exactly one
237+
local unreleased_count
238+
unreleased_count=$(grep -c "^\[Unreleased\]:" "$test_file")
239+
if [ "$unreleased_count" -eq 1 ] && \
240+
grep -q "\[Unreleased\]: https://github.com/test/repo/compare/v1.0.0-beta-java.3...HEAD" "$test_file" && \
241+
grep -q "\[1.0.0-beta-java.3\]: https://github.com/test/repo/compare/v1.0.0-beta-java.2...v1.0.0-beta-java.3" "$test_file"; then
242+
return 0
243+
else
244+
return 1
245+
fi
246+
}
247+
248+
# Run all tests
249+
echo "Running CHANGELOG update script tests..."
250+
echo ""
251+
252+
run_test "Basic functionality - Replace Unreleased with version" test_basic_replace
253+
run_test "Handle CHANGELOG without Unreleased link" test_no_unreleased_link
254+
run_test "Preserve content structure" test_preserve_content
255+
run_test "Error handling - no Unreleased section" test_no_unreleased_section
256+
run_test "Multiple version handling" test_multiple_versions
257+
run_test "Beta-java version format (e.g., 1.0.0-beta-java.N)" test_beta_java_version
258+
run_test "No duplicate [Unreleased] links when existing link is present" test_no_duplicate_unreleased_links
259+
260+
echo ""
261+
echo "=========================================="
262+
echo -e "Tests passed: ${GREEN}${passed}${NC}"
263+
echo -e "Tests failed: ${RED}${failed}${NC}"
264+
echo "=========================================="
265+
266+
if [ $failed -eq 0 ]; then
267+
exit 0
268+
else
269+
exit 1
270+
fi
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# Script to update CHANGELOG.md during release process
5+
# Usage: ./update-changelog.sh <version> [reference-impl-hash]
6+
# Example: ./update-changelog.sh 1.0.8
7+
# Example: ./update-changelog.sh 1.0.8 05e3c46c8c23130c9c064dc43d00ec78f7a75eab
8+
9+
if [ -z "$1" ]; then
10+
echo "Error: Version argument required"
11+
echo "Usage: $0 <version> [reference-impl-hash]"
12+
exit 1
13+
fi
14+
15+
VERSION="$1"
16+
REFERENCE_IMPL_HASH="${2:-}"
17+
CHANGELOG_FILE="${CHANGELOG_FILE:-CHANGELOG.md}"
18+
RELEASE_DATE=$(date +%Y-%m-%d)
19+
20+
echo "Updating CHANGELOG.md for version ${VERSION} (${RELEASE_DATE})"
21+
if [ -n "$REFERENCE_IMPL_HASH" ]; then
22+
echo " Reference implementation SDK sync: ${REFERENCE_IMPL_HASH:0:7}"
23+
fi
24+
25+
# Check if CHANGELOG.md exists
26+
if [ ! -f "$CHANGELOG_FILE" ]; then
27+
echo "Error: CHANGELOG.md not found"
28+
exit 1
29+
fi
30+
31+
# Check if there's an [Unreleased] section
32+
if ! grep -q "## \[Unreleased\]" "$CHANGELOG_FILE"; then
33+
echo "Error: No [Unreleased] section found in CHANGELOG.md"
34+
exit 1
35+
fi
36+
37+
# Create a temporary file
38+
TEMP_FILE=$(mktemp)
39+
40+
# Process the CHANGELOG
41+
awk -v version="$VERSION" -v date="$RELEASE_DATE" -v REFERENCE_IMPL_HASH="$REFERENCE_IMPL_HASH" '
42+
BEGIN {
43+
unreleased_found = 0
44+
content_found = 0
45+
links_section = 0
46+
first_version_link = ""
47+
repo_url = ""
48+
unreleased_link_handled = 0
49+
}
50+
51+
# Track if we are in the links section at the bottom
52+
/^\[/ {
53+
links_section = 1
54+
}
55+
56+
# Capture the repository URL from the first version link
57+
links_section && repo_url == "" && /^\[[0-9]+\.[0-9]+\.[0-9]+(-(beta-)?java(-preview)?\.[0-9]+)?\]:/ {
58+
match($0, /(https:\/\/github\.com\/[^\/]+\/[^\/]+)\//, arr)
59+
if (arr[1] != "") {
60+
repo_url = arr[1]
61+
}
62+
}
63+
64+
# Replace [Unreleased] with the version and date
65+
/^## \[Unreleased\]/ {
66+
if (!unreleased_found) {
67+
print "## [Unreleased]"
68+
print ""
69+
if (REFERENCE_IMPL_HASH != "") {
70+
short_hash = substr(REFERENCE_IMPL_HASH, 1, 7)
71+
print "> **Reference implementation sync:** [`github/copilot-sdk@" short_hash "`](https://github.com/github/copilot-sdk/commit/" REFERENCE_IMPL_HASH ")"
72+
print ""
73+
}
74+
print "## [" version "] - " date
75+
if (REFERENCE_IMPL_HASH != "") {
76+
print ""
77+
print "> **Reference implementation sync:** [`github/copilot-sdk@" short_hash "`](https://github.com/github/copilot-sdk/commit/" REFERENCE_IMPL_HASH ")"
78+
}
79+
unreleased_found = 1
80+
skip_old_reference_impl = 1
81+
next
82+
}
83+
}
84+
85+
# Skip the old Reference implementation sync line and surrounding blank lines from the previous [Unreleased] section
86+
skip_old_reference_impl && /^[[:space:]]*$/ { next }
87+
skip_old_reference_impl && /^> \*\*Reference implementation sync:\*\*/ { next }
88+
skip_old_reference_impl && !/^[[:space:]]*$/ && !/^> \*\*Reference implementation sync:\*\*/ { skip_old_reference_impl = 0 }
89+
90+
# Update existing [Unreleased] link if present (must be checked before the first-version-link block)
91+
links_section && /^\[Unreleased\]:/ {
92+
# Get the previous version and repo URL from the existing link
93+
match($0, /(https:\/\/github\.com\/[^\/]+\/[^\/]+)\/compare\/v([0-9]+\.[0-9]+\.[0-9]+(-(beta-)?java(-preview)?\.[0-9]+)?)\.\.\.HEAD/, arr)
94+
if (arr[1] != "" && arr[2] != "") {
95+
print "[Unreleased]: " arr[1] "/compare/v" version "...HEAD"
96+
print "[" version "]: " arr[1] "/compare/v" arr[2] "...v" version
97+
unreleased_link_handled = 1
98+
next
99+
}
100+
}
101+
102+
# Capture the first version link to get the previous version
103+
# Only fires if the [Unreleased] link was not already handled above
104+
links_section && first_version_link == "" && !unreleased_link_handled && /^\[[0-9]+\.[0-9]+\.[0-9]+(-(beta-)?java(-preview)?\.[0-9]+)?\]:/ {
105+
match($0, /\[([0-9]+\.[0-9]+\.[0-9]+(-(beta-)?java(-preview)?\.[0-9]+)?)\]:/, arr)
106+
if (arr[1] != "" && repo_url != "") {
107+
first_version_link = arr[1]
108+
# Insert Unreleased and new version links before first version link
109+
print "[Unreleased]: " repo_url "/compare/v" version "...HEAD"
110+
print "[" version "]: " repo_url "/compare/v" arr[1] "...v" version
111+
}
112+
}
113+
114+
# Print all other lines unchanged
115+
{ print }
116+
' "$CHANGELOG_FILE" > "$TEMP_FILE"
117+
118+
# Replace the original file
119+
mv "$TEMP_FILE" "$CHANGELOG_FILE"
120+
121+
echo "✓ CHANGELOG.md updated successfully"
122+
echo " - Added version ${VERSION} with date ${RELEASE_DATE}"
123+
echo " - Created new [Unreleased] section"
124+
echo " - Updated version comparison links"
125+

0 commit comments

Comments
 (0)