-
Notifications
You must be signed in to change notification settings - Fork 5k
Expand file tree
/
Copy pathregenerate_lts_table.sh
More file actions
executable file
·324 lines (256 loc) · 8.86 KB
/
regenerate_lts_table.sh
File metadata and controls
executable file
·324 lines (256 loc) · 8.86 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
#!/bin/bash
set -e
# Configuration
DOCKER_REPO="tooljet/tooljet"
MARKDOWN_FILE="docs/versioned_docs/version-3.16.0-LTS/setup/overview/choose-your-tooljet.mdx"
TABLE_HEADER="| Version | Release Date | Docker Pull Command |"
TABLE_DIVIDER="|---------|--------------|----------------------|"
DRY_RUN=false
# Current LTS line — update CURRENT_LTS_PREFIX when a new LTS series starts (e.g. v3.21)
CURRENT_LTS_PREFIX="v3.20"
CURRENT_LTS_TAG_PATTERN="^v3\\.20\\.[0-9]+-lts$"
CURRENT_LTS_MAX=6
# Enhanced logging function
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >&2
}
log_error() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $1" >&2
}
# Check if required tools are available
check_dependencies() {
log "🔧 Checking dependencies..."
if ! command -v curl &> /dev/null; then
log_error "curl is not installed"
exit 1
fi
if ! command -v jq &> /dev/null; then
log_error "jq is not installed"
exit 1
fi
log "✅ All dependencies available"
}
# Cross-platform date formatting
format_date() {
local input_date="$1"
if [[ -z "$input_date" || "$input_date" == "null" ]]; then
echo "INVALID_DATE"
return 1
fi
# Try different date command formats (macOS vs Linux)
if date --version >/dev/null 2>&1; then
# GNU date (Linux)
date -d "$input_date" "+%B %e, %Y" 2>/dev/null || echo "INVALID_DATE"
else
# BSD date (macOS)
date -jf "%Y-%m-%d" "$input_date" "+%B %e, %Y" 2>/dev/null || echo "INVALID_DATE"
fi
}
if [[ "$1" == "--dry-run" ]]; then
DRY_RUN=true
log "💡 Dry run mode ON — no file will be modified"
fi
# Fetch all LTS tags with enhanced error handling
get_lts_tags() {
log "🌐 Fetching LTS tags from DockerHub..."
local tags=()
local url="https://hub.docker.com/v2/repositories/${DOCKER_REPO}/tags?page_size=100"
local page_count=0
while [ -n "$url" ]; do
((page_count++))
log "🔍 Fetching page $page_count: $url"
local resp
if ! resp=$(curl -sS --fail --max-time 30 "$url" 2>/dev/null); then
log_error "Failed to fetch tags from DockerHub API"
return 1
fi
if ! echo "$resp" | jq . >/dev/null 2>&1; then
log_error "Invalid JSON response from DockerHub API"
return 1
fi
local page_tags
page_tags=$(echo "$resp" | jq -r --arg pat "$CURRENT_LTS_TAG_PATTERN" '.results[]? | select(.name | test($pat)) | .name' 2>/dev/null)
if [[ -n "$page_tags" ]]; then
while IFS= read -r tag; do
[[ -n "$tag" ]] && tags+=("$tag")
done <<< "$page_tags"
fi
url=$(echo "$resp" | jq -r '.next // empty' 2>/dev/null)
[[ "$url" == "null" || -z "$url" ]] && break
# Stop early once we have enough tags to avoid unnecessary pages
if [[ ${#tags[@]} -ge $CURRENT_LTS_MAX ]]; then
log "✅ Collected enough tags (${#tags[@]}), stopping pagination"
break
fi
# Safety check to prevent infinite loops
if [[ $page_count -gt 10 ]]; then
log "⚠️ Reached maximum page limit (10), stopping pagination"
break
fi
done
if [[ ${#tags[@]} -eq 0 ]]; then
log_error "No LTS tags found"
return 1
fi
log "✅ Found ${#tags[@]} LTS tags"
# Sort tags by version (reverse) and cap to CURRENT_LTS_MAX
IFS=$'\n' tags=($(printf '%s\n' "${tags[@]}" | sort -Vr))
if [[ ${#tags[@]} -gt $CURRENT_LTS_MAX ]]; then
tags=("${tags[@]:0:$CURRENT_LTS_MAX}")
log "✂️ Capped to ${CURRENT_LTS_MAX} most recent ${CURRENT_LTS_PREFIX} tags"
fi
log "📋 LTS tags (sorted):"
printf ' %s\n' "${tags[@]}"
printf '%s\n' "${tags[@]}"
}
# Get SHA and formatted release date for a tag
get_tag_metadata() {
local tag="$1"
local url="https://hub.docker.com/v2/repositories/${DOCKER_REPO}/tags/${tag}"
log "📦 Fetching metadata for $tag"
local data
if ! data=$(curl -sS --fail --max-time 30 "$url" 2>/dev/null); then
log_error "Failed to fetch metadata for $tag"
echo "SKIP"
return 1
fi
if ! echo "$data" | jq . >/dev/null 2>&1; then
log_error "Invalid JSON response for $tag metadata"
echo "SKIP"
return 1
fi
local sha
sha=$(echo "$data" | jq -r '.images[0]?.digest // empty' 2>/dev/null | cut -d: -f2)
if [[ -z "$sha" ]]; then
log_error "No SHA found for $tag"
echo "SKIP"
return 1
fi
local raw_date
raw_date=$(echo "$data" | jq -r '.last_updated // empty' 2>/dev/null | sed 's/T.*//')
if [[ -z "$raw_date" ]]; then
log "⚠️ No release date found for $tag, skipping"
echo "SKIP"
return 1
fi
local formatted_date
formatted_date=$(format_date "$raw_date")
if [[ "$formatted_date" == "INVALID_DATE" ]]; then
log "⚠️ Invalid date format for $tag: $raw_date, skipping"
echo "SKIP"
return 1
fi
log "✅ $tag: SHA=${sha:0:12}..., Date=$formatted_date"
echo "$sha|$formatted_date"
}
# Build table rows
build_table_rows() {
local tags=("$@")
local rows=()
log "📋 Generating markdown table rows for ${#tags[@]} tags:"
for tag in "${tags[@]}"; do
local meta
meta=$(get_tag_metadata "$tag")
if [[ "$meta" == "SKIP" ]]; then
log "⏭️ Skipped $tag"
continue
fi
local sha date
sha=$(echo "$meta" | cut -d'|' -f1)
date=$(echo "$meta" | cut -d'|' -f2)
log "➕ Adding row: $tag → $date"
local row="| [${tag}](https://hub.docker.com/layers/tooljet/tooljet/${tag}/images/sha256-${sha}?context=explore) | ${date} | \`docker pull tooljet/tooljet:${tag}\` |"
rows+=("$row")
done
if [[ ${#rows[@]} -eq 0 ]]; then
log_error "No valid rows generated"
return 1
fi
log "📝 Generated ${#rows[@]} table rows"
printf "%s\n" "${rows[@]}"
}
# Replace old table in the markdown
replace_table_in_file() {
local tags=("$@")
if [[ ! -f "$MARKDOWN_FILE" ]]; then
log_error "Markdown file not found: $MARKDOWN_FILE"
return 1
fi
log "📄 Processing markdown file: $MARKDOWN_FILE"
local table_body
if ! table_body=$(build_table_rows "${tags[@]}"); then
log_error "Failed to build table rows"
return 1
fi
log ""
log "🧪 Preview of updated table:"
log "--------------------------------"
echo "$TABLE_HEADER"
echo "$TABLE_DIVIDER"
echo "$table_body"
log "--------------------------------"
if $DRY_RUN; then
log "✅ Dry run finished — no file changes made."
return 0
fi
log "✍️ Writing to $MARKDOWN_FILE..."
local tmp_md="${MARKDOWN_FILE}.tmp"
# Extract preserved rows — older LTS lines that are NOT part of the current LTS series.
# These rows sit below the current LTS entries and are never auto-updated.
local preserved_rows
preserved_rows=$(awk '
/^### Latest Patch$/ { in_section=1; next }
/^### Base Versions$/ { in_section=0 }
in_section && /^\| \[/ { print }
' "$MARKDOWN_FILE" | grep -v "${CURRENT_LTS_PREFIX}\.")
# Combine: new current-LTS rows on top, preserved older-LTS rows below
local full_body
if [[ -n "$preserved_rows" ]]; then
full_body="${table_body}
${preserved_rows}"
else
full_body="$table_body"
fi
local new_table="${TABLE_HEADER}
${TABLE_DIVIDER}
${full_body}"
awk -v tbl="$new_table" '
/^### Latest Patch$/ { print; print ""; print tbl; skip=1; next }
/^### Base Versions$/ { skip=0 }
!skip { print }
' "$MARKDOWN_FILE" > "$tmp_md"
if ! mv "$tmp_md" "$MARKDOWN_FILE"; then
log_error "Failed to move temporary file to $MARKDOWN_FILE"
return 1
fi
log "✅ Markdown updated successfully"
}
main() {
log "🚀 Starting ToolJet LTS table regeneration..."
# Check dependencies first
check_dependencies
# Get LTS tags
local tags_output
if ! tags_output=$(get_lts_tags); then
log_error "Failed to fetch LTS tags"
exit 1
fi
# Convert output to array
local tags=()
while IFS= read -r tag; do
[[ -n "$tag" ]] && tags+=("$tag")
done <<< "$tags_output"
if [[ ${#tags[@]} -eq 0 ]]; then
log_error "No tags to process"
exit 1
fi
log "🎯 Processing ${#tags[@]} tags total"
# Replace table in file
if ! replace_table_in_file "${tags[@]}"; then
log_error "Failed to update markdown file"
exit 1
fi
log "🎉 Done! Successfully processed ${#tags[@]} tags"
}
# Run main function
main "$@"