Skip to content

Commit 1fb2fe8

Browse files
feat(tag_release): initial commit for tag_release script
- needs testing and a few tweaks
1 parent 53af6e0 commit 1fb2fe8

File tree

1 file changed

+294
-0
lines changed

1 file changed

+294
-0
lines changed

.github/scripts/tag_release.sh

Lines changed: 294 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,294 @@
1+
#!/bin/bash
2+
3+
# Tag Release Script
4+
# Automatically detects modules that need tagging and creates release tags
5+
# Usage: ./tag_release.sh
6+
# Operates on the current checked-out commit
7+
8+
set -euo pipefail
9+
10+
usage() {
11+
echo "Usage: $0"
12+
echo ""
13+
echo "This script will:"
14+
echo " 1. Scan all modules in the registry"
15+
echo " 2. Check which modules need new release tags"
16+
echo " 3. Extract version information from README files"
17+
echo " 4. Generate a report for confirmation"
18+
echo " 5. Create and push release tags after confirmation"
19+
echo ""
20+
echo "The script operates on the current checked-out commit."
21+
echo "Make sure you have checked out the commit you want to tag before running."
22+
exit 1
23+
}
24+
25+
validate_version() {
26+
local version="$1"
27+
if ! [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
28+
echo "❌ Invalid version format: '$version'. Expected X.Y.Z format." >&2
29+
return 1
30+
fi
31+
return 0
32+
}
33+
34+
extract_version_from_readme() {
35+
local readme_path="$1"
36+
local namespace="$2"
37+
local module_name="$3"
38+
39+
if [ ! -f "$readme_path" ]; then
40+
echo "❌ README not found: $readme_path" >&2
41+
return 1
42+
fi
43+
44+
local version_line
45+
version_line=$(grep -E "source\s*=\s*\"registry\.coder\.com/${namespace}/${module_name}" "$readme_path" | head -1 || echo "")
46+
47+
if [ -n "$version_line" ]; then
48+
local version
49+
version=$(echo "$version_line" | sed -n 's/.*version\s*=\s*"\([^"]*\)".*/\1/p')
50+
if [ -n "$version" ]; then
51+
echo "$version"
52+
return 0
53+
fi
54+
fi
55+
56+
local fallback_version
57+
fallback_version=$(grep -E 'version\s*=\s*"[0-9]+\.[0-9]+\.[0-9]+"' "$readme_path" | head -1 | sed 's/.*version\s*=\s*"\([^"]*\)".*/\1/' || echo "")
58+
59+
if [ -n "$fallback_version" ]; then
60+
echo "$fallback_version"
61+
return 0
62+
fi
63+
64+
return 1
65+
}
66+
67+
check_module_needs_tagging() {
68+
local namespace="$1"
69+
local module_name="$2"
70+
local readme_version="$3"
71+
72+
local tag_name="release/${namespace}/${module_name}/v${readme_version}"
73+
74+
if git rev-parse --verify "$tag_name" >/dev/null 2>&1; then
75+
return 1
76+
else
77+
return 0
78+
fi
79+
}
80+
81+
detect_modules_needing_tags() {
82+
local modules_to_tag=()
83+
84+
echo "🔍 Scanning all modules for missing release tags..."
85+
echo ""
86+
87+
88+
local all_modules
89+
all_modules=$(find registry -type d -path "*/modules/*" -mindepth 3 -maxdepth 3 | sort -u || echo "")
90+
91+
if [ -z "$all_modules" ]; then
92+
echo "❌ No modules found to check"
93+
return 1
94+
fi
95+
96+
local total_checked=0
97+
local needs_tagging=0
98+
99+
while IFS= read -r module_path; do
100+
if [ -z "$module_path" ]; then continue; fi
101+
102+
local namespace
103+
namespace=$(echo "$module_path" | cut -d'/' -f2)
104+
local module_name
105+
module_name=$(echo "$module_path" | cut -d'/' -f4)
106+
107+
total_checked=$((total_checked + 1))
108+
109+
local readme_path="$module_path/README.md"
110+
local readme_version
111+
112+
if ! readme_version=$(extract_version_from_readme "$readme_path" "$namespace" "$module_name"); then
113+
echo "⚠️ $namespace/$module_name: No version found in README, skipping"
114+
continue
115+
fi
116+
117+
if ! validate_version "$readme_version"; then
118+
echo "⚠️ $namespace/$module_name: Invalid version format '$readme_version', skipping"
119+
continue
120+
fi
121+
122+
if check_module_needs_tagging "$namespace" "$module_name" "$readme_version"; then
123+
echo "📦 $namespace/$module_name: v$readme_version (needs tag)"
124+
modules_to_tag+=("$module_path:$namespace:$module_name:$readme_version")
125+
needs_tagging=$((needs_tagging + 1))
126+
else
127+
echo "$namespace/$module_name: v$readme_version (already tagged)"
128+
fi
129+
130+
done <<< "$all_modules"
131+
132+
echo ""
133+
echo "📊 Summary: $needs_tagging of $total_checked modules need tagging"
134+
echo ""
135+
136+
if [ $needs_tagging -eq 0 ]; then
137+
echo "🎉 All modules are up to date! No tags needed."
138+
return 0
139+
fi
140+
141+
142+
echo "## Tags to be created:"
143+
for module_info in "${modules_to_tag[@]}"; do
144+
IFS=':' read -r module_path namespace module_name version <<< "$module_info"
145+
echo "- \`release/$namespace/$module_name/v$version\`"
146+
done
147+
echo ""
148+
149+
150+
printf '%s\n' "${modules_to_tag[@]}" > /tmp/modules_to_tag.txt
151+
152+
return 0
153+
}
154+
155+
create_and_push_tags() {
156+
if [ ! -f /tmp/modules_to_tag.txt ]; then
157+
echo "❌ No modules to tag found"
158+
return 1
159+
fi
160+
161+
local current_commit
162+
current_commit=$(git rev-parse HEAD)
163+
164+
echo "🏷️ Creating release tags for commit: $current_commit"
165+
echo ""
166+
167+
local created_tags=0
168+
local failed_tags=0
169+
170+
while IFS= read -r module_info; do
171+
if [ -z "$module_info" ]; then continue; fi
172+
173+
IFS=':' read -r module_path namespace module_name version <<< "$module_info"
174+
175+
local tag_name="release/$namespace/$module_name/v$version"
176+
local tag_message="Release $namespace/$module_name v$version"
177+
178+
echo "Creating tag: $tag_name"
179+
180+
if git tag -a "$tag_name" -m "$tag_message" "$current_commit"; then
181+
echo "✅ Created: $tag_name"
182+
created_tags=$((created_tags + 1))
183+
else
184+
echo "❌ Failed to create: $tag_name"
185+
failed_tags=$((failed_tags + 1))
186+
fi
187+
188+
done < /tmp/modules_to_tag.txt
189+
190+
echo ""
191+
echo "📊 Tag creation summary:"
192+
echo " Created: $created_tags"
193+
echo " Failed: $failed_tags"
194+
echo ""
195+
196+
if [ $created_tags -eq 0 ]; then
197+
echo "❌ No tags were created successfully"
198+
return 1
199+
fi
200+
201+
echo "🚀 Pushing tags to origin..."
202+
203+
local pushed_tags=0
204+
local failed_pushes=0
205+
206+
while IFS= read -r module_info; do
207+
if [ -z "$module_info" ]; then continue; fi
208+
209+
IFS=':' read -r module_path namespace module_name version <<< "$module_info"
210+
211+
local tag_name="release/$namespace/$module_name/v$version"
212+
213+
if git rev-parse --verify "$tag_name" >/dev/null 2>&1; then
214+
echo "Pushing: $tag_name"
215+
if git push origin "$tag_name"; then
216+
echo "✅ Pushed: $tag_name"
217+
pushed_tags=$((pushed_tags + 1))
218+
else
219+
echo "❌ Failed to push: $tag_name"
220+
failed_pushes=$((failed_pushes + 1))
221+
fi
222+
fi
223+
224+
done < /tmp/modules_to_tag.txt
225+
226+
echo ""
227+
echo "📊 Push summary:"
228+
echo " Pushed: $pushed_tags"
229+
echo " Failed: $failed_pushes"
230+
echo ""
231+
232+
if [ $pushed_tags -gt 0 ]; then
233+
echo "🎉 Successfully created and pushed $pushed_tags release tags!"
234+
echo ""
235+
echo "📝 Next steps:"
236+
echo " - Tags will be automatically published to registry.coder.com"
237+
echo " - Monitor the registry website for updates"
238+
echo " - Check GitHub releases for any issues"
239+
fi
240+
241+
242+
rm -f /tmp/modules_to_tag.txt
243+
244+
return 0
245+
}
246+
247+
main() {
248+
if [ $# -gt 0 ]; then
249+
usage
250+
fi
251+
252+
echo "🚀 Coder Registry Tag Release Script"
253+
echo "Operating on commit: $(git rev-parse HEAD)"
254+
echo ""
255+
256+
257+
if ! git rev-parse --git-dir >/dev/null 2>&1; then
258+
echo "❌ Not in a git repository"
259+
exit 1
260+
fi
261+
262+
263+
if ! detect_modules_needing_tags; then
264+
exit 1
265+
fi
266+
267+
268+
if [ ! -f /tmp/modules_to_tag.txt ] || [ ! -s /tmp/modules_to_tag.txt ]; then
269+
echo "✨ No modules need tagging. All done!"
270+
exit 0
271+
fi
272+
273+
274+
echo ""
275+
echo "❓ Do you want to proceed with creating and pushing these release tags?"
276+
echo " This will create git tags and push them to the remote repository."
277+
echo ""
278+
read -p "Continue? [y/N]: " -r response
279+
280+
case "$response" in
281+
[yY]|[yY][eE][sS])
282+
echo ""
283+
create_and_push_tags
284+
;;
285+
*)
286+
echo ""
287+
echo "🚫 Operation cancelled by user"
288+
rm -f /tmp/modules_to_tag.txt
289+
exit 0
290+
;;
291+
esac
292+
}
293+
294+
main "$@"

0 commit comments

Comments
 (0)