apdev-js 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +120 -0
- package/dist/cli.js +556 -0
- package/dist/index.cjs +550 -0
- package/dist/index.d.cts +41 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.js +508 -0
- package/package.json +57 -0
- package/release.sh +542 -0
package/release.sh
ADDED
|
@@ -0,0 +1,542 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Interactive release script for TypeScript/JavaScript projects
|
|
3
|
+
# Usage: ./release.sh [--yes|-y] [version]
|
|
4
|
+
# Example: ./release.sh 0.2.0
|
|
5
|
+
# ./release.sh --yes # silent mode, auto-accept defaults
|
|
6
|
+
# ./release.sh --yes 0.2.0 # silent mode with specific version
|
|
7
|
+
#
|
|
8
|
+
# Auto-detects project name from package.json and GitHub repo from git remote.
|
|
9
|
+
# Override with environment variables: PROJECT_NAME, GITHUB_REPO
|
|
10
|
+
|
|
11
|
+
# Note: set -e is disabled to allow step-by-step execution
|
|
12
|
+
# Individual steps will handle their own error handling
|
|
13
|
+
|
|
14
|
+
# Silent mode flag (--yes or -y to auto-accept all defaults)
|
|
15
|
+
SILENT=false
|
|
16
|
+
POSITIONAL_ARGS=()
|
|
17
|
+
for arg in "$@"; do
|
|
18
|
+
case "$arg" in
|
|
19
|
+
--yes|-y) SILENT=true ;;
|
|
20
|
+
*) POSITIONAL_ARGS+=("$arg") ;;
|
|
21
|
+
esac
|
|
22
|
+
done
|
|
23
|
+
set -- "${POSITIONAL_ARGS[@]}"
|
|
24
|
+
|
|
25
|
+
# Colors for output
|
|
26
|
+
RED='\033[0;31m'
|
|
27
|
+
GREEN='\033[0;32m'
|
|
28
|
+
YELLOW='\033[1;33m'
|
|
29
|
+
BLUE='\033[0;34m'
|
|
30
|
+
CYAN='\033[0;36m'
|
|
31
|
+
NC='\033[0m' # No Color
|
|
32
|
+
|
|
33
|
+
# Auto-detect project name from package.json (unless set via env)
|
|
34
|
+
if [ -z "$PROJECT_NAME" ]; then
|
|
35
|
+
PROJECT_NAME=$(node -e "console.log(require('./package.json').name)" 2>/dev/null)
|
|
36
|
+
if [ -z "$PROJECT_NAME" ]; then
|
|
37
|
+
echo -e "${RED}Error: Could not determine project name from package.json${NC}"
|
|
38
|
+
echo -e "${YELLOW}Set PROJECT_NAME environment variable or check package.json${NC}"
|
|
39
|
+
exit 1
|
|
40
|
+
fi
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
# Auto-detect GitHub repo from git remote (unless set via env)
|
|
44
|
+
if [ -z "$GITHUB_REPO" ]; then
|
|
45
|
+
REMOTE_URL=$(git remote get-url origin 2>/dev/null)
|
|
46
|
+
if [ -n "$REMOTE_URL" ]; then
|
|
47
|
+
GITHUB_REPO=$(echo "$REMOTE_URL" | sed -E 's|.*github\.com[:/]||; s|\.git$||')
|
|
48
|
+
fi
|
|
49
|
+
if [ -z "$GITHUB_REPO" ]; then
|
|
50
|
+
echo -e "${YELLOW}Warning: Could not detect GitHub repo from git remote${NC}"
|
|
51
|
+
echo -e "${YELLOW}Set GITHUB_REPO environment variable (e.g. owner/repo)${NC}"
|
|
52
|
+
fi
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
# Get version from argument or package.json
|
|
56
|
+
if [ -z "$1" ]; then
|
|
57
|
+
VERSION=$(node -e "console.log(require('./package.json').version)" 2>/dev/null)
|
|
58
|
+
if [ -z "$VERSION" ]; then
|
|
59
|
+
echo -e "${RED}Error: Could not determine version from package.json${NC}"
|
|
60
|
+
exit 1
|
|
61
|
+
fi
|
|
62
|
+
else
|
|
63
|
+
VERSION="$1"
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
TAG="typescript/v${VERSION}"
|
|
67
|
+
|
|
68
|
+
echo -e "${CYAN}╔══════════════════════════════════════════════════════════╗${NC}"
|
|
69
|
+
echo -e "${CYAN}║ ${PROJECT_NAME} Release Script v${VERSION}${NC}"
|
|
70
|
+
echo -e "${CYAN}╚══════════════════════════════════════════════════════════╝${NC}"
|
|
71
|
+
echo -e " Project: ${CYAN}${PROJECT_NAME}${NC}"
|
|
72
|
+
[ -n "$GITHUB_REPO" ] && echo -e " GitHub: ${CYAN}${GITHUB_REPO}${NC}"
|
|
73
|
+
echo ""
|
|
74
|
+
|
|
75
|
+
# Function to check if step is already done
|
|
76
|
+
check_tag_exists() {
|
|
77
|
+
if git rev-parse "${TAG}" >/dev/null 2>&1; then
|
|
78
|
+
if git ls-remote --tags origin | grep -q "refs/tags/${TAG}$"; then
|
|
79
|
+
return 0 # Tag exists on remote
|
|
80
|
+
fi
|
|
81
|
+
fi
|
|
82
|
+
return 1 # Tag doesn't exist
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
check_npm_uploaded() {
|
|
86
|
+
# Check if version exists on npm registry
|
|
87
|
+
npm view "${PROJECT_NAME}" versions --json 2>/dev/null \
|
|
88
|
+
| grep -qF "\"${VERSION}\"" && return 0 || return 1
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
check_release_exists() {
|
|
92
|
+
if command -v gh &> /dev/null; then
|
|
93
|
+
gh release view "${TAG}" &>/dev/null && return 0 || return 1
|
|
94
|
+
fi
|
|
95
|
+
return 1
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
# Function to ask yes/no with default
|
|
99
|
+
ask_yn() {
|
|
100
|
+
local prompt="$1"
|
|
101
|
+
local default="$2"
|
|
102
|
+
local answer
|
|
103
|
+
|
|
104
|
+
# Silent mode: auto-accept default
|
|
105
|
+
if [ "$SILENT" = true ]; then
|
|
106
|
+
if [ "$default" = "y" ]; then
|
|
107
|
+
echo -e "${YELLOW}${prompt} [Y/n] y (auto)${NC}"
|
|
108
|
+
return 0
|
|
109
|
+
else
|
|
110
|
+
echo -e "${YELLOW}${prompt} [y/N] n (auto)${NC}"
|
|
111
|
+
return 1
|
|
112
|
+
fi
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
if [ "$default" = "y" ]; then
|
|
116
|
+
prompt="${prompt} [Y/n]"
|
|
117
|
+
else
|
|
118
|
+
prompt="${prompt} [y/N]"
|
|
119
|
+
fi
|
|
120
|
+
|
|
121
|
+
read -p "$(echo -e "${YELLOW}${prompt}${NC}") " answer
|
|
122
|
+
answer=${answer:-$default}
|
|
123
|
+
[[ $answer =~ ^[Yy]$ ]]
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
# Function to show main menu with all steps
|
|
127
|
+
show_main_menu() {
|
|
128
|
+
# Silent mode: auto-select "all"
|
|
129
|
+
if [ "$SILENT" = true ]; then
|
|
130
|
+
echo -e "${CYAN}Silent mode: auto-selecting all steps${NC}"
|
|
131
|
+
MENU_SELECTION="all"
|
|
132
|
+
return
|
|
133
|
+
fi
|
|
134
|
+
|
|
135
|
+
echo ""
|
|
136
|
+
echo -e "${CYAN}╔══════════════════════════════════════════════════════════╗${NC}"
|
|
137
|
+
echo -e "${CYAN}║ Release Steps Selection ║${NC}"
|
|
138
|
+
echo -e "${CYAN}╚══════════════════════════════════════════════════════════╝${NC}"
|
|
139
|
+
echo ""
|
|
140
|
+
|
|
141
|
+
echo -e "${CYAN}Select a step to execute:${NC}"
|
|
142
|
+
echo -e " ${CYAN}all) Execute all steps (with interactive prompts)${NC}"
|
|
143
|
+
echo -e " ${CYAN}1) Step 1: Version Verification${NC}"
|
|
144
|
+
echo -e " ${CYAN}2) Step 2: Check Current Status${NC}"
|
|
145
|
+
echo -e " ${CYAN}3) Step 3: Clean Build Files${NC}"
|
|
146
|
+
echo -e " ${CYAN}4) Step 4: Build Package${NC}"
|
|
147
|
+
echo -e " ${CYAN}5) Step 5: Check Package${NC}"
|
|
148
|
+
echo -e " ${CYAN}6) Step 6: Git Tag${NC}"
|
|
149
|
+
echo -e " ${CYAN}7) Step 6.5: Create GitHub Release${NC}"
|
|
150
|
+
echo -e " ${CYAN}8) Step 7: Upload to npm${NC}"
|
|
151
|
+
echo -e " ${CYAN}9) Show Summary${NC}"
|
|
152
|
+
echo -e " ${CYAN}0) Exit${NC}"
|
|
153
|
+
echo ""
|
|
154
|
+
|
|
155
|
+
read -p "$(echo -e "${YELLOW}Select option [all]:${NC} ") " MENU_SELECTION
|
|
156
|
+
MENU_SELECTION=${MENU_SELECTION:-all}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
# Step functions
|
|
160
|
+
step1_version_verification() {
|
|
161
|
+
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
162
|
+
echo -e "${BLUE}Step 1: Version Verification${NC}"
|
|
163
|
+
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
164
|
+
|
|
165
|
+
PKG_VERSION=$(node -e "console.log(require('./package.json').version)" 2>/dev/null)
|
|
166
|
+
|
|
167
|
+
echo -e " package.json: ${CYAN}${PKG_VERSION}${NC}"
|
|
168
|
+
echo -e " Script version: ${CYAN}${VERSION}${NC}"
|
|
169
|
+
|
|
170
|
+
if [ "$PKG_VERSION" != "$VERSION" ]; then
|
|
171
|
+
echo -e "${RED}Version mismatch detected!${NC}"
|
|
172
|
+
return 1
|
|
173
|
+
fi
|
|
174
|
+
|
|
175
|
+
echo -e "${GREEN}All versions match${NC}"
|
|
176
|
+
echo ""
|
|
177
|
+
return 0
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
step2_check_status() {
|
|
181
|
+
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
182
|
+
echo -e "${BLUE}Step 2: Checking Current Status${NC}"
|
|
183
|
+
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
184
|
+
|
|
185
|
+
# Check Git tag
|
|
186
|
+
if check_tag_exists; then
|
|
187
|
+
echo -e " Git Tag: ${GREEN}Tag ${TAG} exists on remote${NC}"
|
|
188
|
+
else
|
|
189
|
+
echo -e " Git Tag: Tag ${TAG} not found on remote"
|
|
190
|
+
fi
|
|
191
|
+
|
|
192
|
+
# Check build files
|
|
193
|
+
if [ -d "dist" ] && [ "$(ls -A dist/*.js dist/*.cjs 2>/dev/null | wc -l)" -gt 0 ]; then
|
|
194
|
+
echo -e " Build Files: ${GREEN}Found in dist/${NC}"
|
|
195
|
+
ls -lh dist/ | tail -n +2 | sed 's/^/ /'
|
|
196
|
+
else
|
|
197
|
+
echo -e " Build Files: Not found"
|
|
198
|
+
fi
|
|
199
|
+
|
|
200
|
+
# Check npm registry
|
|
201
|
+
if command -v npm &> /dev/null; then
|
|
202
|
+
if check_npm_uploaded; then
|
|
203
|
+
echo -e " npm Upload: ${GREEN}Version ${VERSION} found on npm${NC}"
|
|
204
|
+
else
|
|
205
|
+
echo -e " npm Upload: Version ${VERSION} not found on npm"
|
|
206
|
+
fi
|
|
207
|
+
else
|
|
208
|
+
echo -e " npm Upload: (cannot check - npm not available)"
|
|
209
|
+
fi
|
|
210
|
+
|
|
211
|
+
echo ""
|
|
212
|
+
return 0
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
step3_clean_build() {
|
|
216
|
+
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
217
|
+
echo -e "${BLUE}Step 3: Clean Build Files${NC}"
|
|
218
|
+
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
219
|
+
|
|
220
|
+
if [ -d "dist" ]; then
|
|
221
|
+
echo -e "${YELLOW}Found existing build files${NC}"
|
|
222
|
+
if ask_yn "Clean build files? (dist/, node_modules/.cache/)" "y"; then
|
|
223
|
+
rm -rf dist/ node_modules/.cache/
|
|
224
|
+
echo -e "${GREEN}Cleaned${NC}"
|
|
225
|
+
else
|
|
226
|
+
echo -e "${YELLOW}Skipped cleaning${NC}"
|
|
227
|
+
fi
|
|
228
|
+
else
|
|
229
|
+
echo -e "${GREEN}No build files to clean${NC}"
|
|
230
|
+
fi
|
|
231
|
+
echo ""
|
|
232
|
+
return 0
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
step4_build_package() {
|
|
236
|
+
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
237
|
+
echo -e "${BLUE}Step 4: Build Package${NC}"
|
|
238
|
+
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
239
|
+
|
|
240
|
+
if [ -d "dist" ] && [ "$(ls -A dist/*.js 2>/dev/null | wc -l)" -gt 0 ]; then
|
|
241
|
+
echo -e "${GREEN}Build files already exist${NC}"
|
|
242
|
+
if ask_yn "Rebuild package?" "n"; then
|
|
243
|
+
SKIP_BUILD=false
|
|
244
|
+
else
|
|
245
|
+
SKIP_BUILD=true
|
|
246
|
+
fi
|
|
247
|
+
else
|
|
248
|
+
SKIP_BUILD=false
|
|
249
|
+
fi
|
|
250
|
+
|
|
251
|
+
if [ "$SKIP_BUILD" = false ]; then
|
|
252
|
+
if [ ! -d "node_modules" ]; then
|
|
253
|
+
echo -e "${YELLOW}Installing dependencies...${NC}"
|
|
254
|
+
if ! pnpm install; then
|
|
255
|
+
echo -e "${RED}Dependency installation failed${NC}"
|
|
256
|
+
return 1
|
|
257
|
+
fi
|
|
258
|
+
fi
|
|
259
|
+
echo -e "${YELLOW}Building package...${NC}"
|
|
260
|
+
if ! pnpm build; then
|
|
261
|
+
echo -e "${RED}Build failed${NC}"
|
|
262
|
+
return 1
|
|
263
|
+
fi
|
|
264
|
+
echo -e "${GREEN}Package built successfully${NC}"
|
|
265
|
+
|
|
266
|
+
echo ""
|
|
267
|
+
echo -e "${CYAN}Built files:${NC}"
|
|
268
|
+
ls -lh dist/ | tail -n +2 | sed 's/^/ /'
|
|
269
|
+
else
|
|
270
|
+
echo -e "${YELLOW}Skipped build (using existing files)${NC}"
|
|
271
|
+
fi
|
|
272
|
+
echo ""
|
|
273
|
+
return 0
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
step5_check_package() {
|
|
277
|
+
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
278
|
+
echo -e "${BLUE}Step 5: Check Package${NC}"
|
|
279
|
+
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
280
|
+
|
|
281
|
+
if ask_yn "Check package with npm pack --dry-run?" "y"; then
|
|
282
|
+
if ! npm pack --dry-run; then
|
|
283
|
+
echo -e "${RED}Package check failed${NC}"
|
|
284
|
+
return 1
|
|
285
|
+
fi
|
|
286
|
+
echo -e "${GREEN}Package check passed${NC}"
|
|
287
|
+
else
|
|
288
|
+
echo -e "${YELLOW}Skipped package check${NC}"
|
|
289
|
+
fi
|
|
290
|
+
echo ""
|
|
291
|
+
return 0
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
step6_git_tag() {
|
|
295
|
+
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
296
|
+
echo -e "${BLUE}Step 6: Git Tag${NC}"
|
|
297
|
+
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
298
|
+
|
|
299
|
+
if check_tag_exists; then
|
|
300
|
+
echo -e "${GREEN}Tag ${TAG} already exists on remote${NC}"
|
|
301
|
+
if ask_yn "Create/update tag anyway?" "n"; then
|
|
302
|
+
SKIP_TAG=false
|
|
303
|
+
else
|
|
304
|
+
SKIP_TAG=true
|
|
305
|
+
fi
|
|
306
|
+
else
|
|
307
|
+
SKIP_TAG=false
|
|
308
|
+
if git rev-parse "${TAG}" >/dev/null 2>&1; then
|
|
309
|
+
echo -e "${YELLOW}Tag ${TAG} exists locally but not on remote${NC}"
|
|
310
|
+
if ask_yn "Push existing tag to remote?" "y"; then
|
|
311
|
+
git push origin "${TAG}"
|
|
312
|
+
echo -e "${GREEN}Tag pushed${NC}"
|
|
313
|
+
SKIP_TAG=true
|
|
314
|
+
fi
|
|
315
|
+
fi
|
|
316
|
+
fi
|
|
317
|
+
|
|
318
|
+
if [ "$SKIP_TAG" = false ]; then
|
|
319
|
+
if ask_yn "Create Git tag ${TAG}?" "y"; then
|
|
320
|
+
if ! git diff-index --quiet HEAD --; then
|
|
321
|
+
echo -e "${YELLOW}Warning: You have uncommitted changes${NC}"
|
|
322
|
+
git status --short
|
|
323
|
+
if ! ask_yn "Continue anyway?" "n"; then
|
|
324
|
+
return 1
|
|
325
|
+
fi
|
|
326
|
+
fi
|
|
327
|
+
|
|
328
|
+
git tag -a "${TAG}" -m "Release version ${VERSION}"
|
|
329
|
+
echo -e "${GREEN}Tag created${NC}"
|
|
330
|
+
|
|
331
|
+
if ask_yn "Push tag to remote?" "y"; then
|
|
332
|
+
git push origin "${TAG}"
|
|
333
|
+
echo -e "${GREEN}Tag pushed to remote${NC}"
|
|
334
|
+
else
|
|
335
|
+
echo -e "${YELLOW}Tag not pushed. Push manually with: git push origin ${TAG}${NC}"
|
|
336
|
+
fi
|
|
337
|
+
else
|
|
338
|
+
echo -e "${YELLOW}Skipped tag creation${NC}"
|
|
339
|
+
fi
|
|
340
|
+
fi
|
|
341
|
+
echo ""
|
|
342
|
+
return 0
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
step6_5_create_github_release() {
|
|
346
|
+
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
347
|
+
echo -e "${BLUE}Step 6.5: Create GitHub Release${NC}"
|
|
348
|
+
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
349
|
+
|
|
350
|
+
if [ -z "$GITHUB_REPO" ]; then
|
|
351
|
+
echo -e "${YELLOW}GitHub repo not detected. Set GITHUB_REPO env variable (e.g. owner/repo)${NC}"
|
|
352
|
+
echo ""
|
|
353
|
+
return 0
|
|
354
|
+
fi
|
|
355
|
+
|
|
356
|
+
SKIP_RELEASE=false
|
|
357
|
+
|
|
358
|
+
if ! command -v gh &> /dev/null; then
|
|
359
|
+
echo -e "${YELLOW}GitHub CLI (gh) not found. Install with: brew install gh${NC}"
|
|
360
|
+
echo -e "${CYAN}Create release manually at: https://github.com/${GITHUB_REPO}/releases/new${NC}"
|
|
361
|
+
SKIP_RELEASE=true
|
|
362
|
+
else
|
|
363
|
+
if ! gh auth status &>/dev/null; then
|
|
364
|
+
echo -e "${YELLOW}GitHub CLI not authenticated. Run: gh auth login${NC}"
|
|
365
|
+
SKIP_RELEASE=true
|
|
366
|
+
fi
|
|
367
|
+
fi
|
|
368
|
+
|
|
369
|
+
if [ "$SKIP_RELEASE" = false ]; then
|
|
370
|
+
if check_release_exists; then
|
|
371
|
+
echo -e "${GREEN}Release ${TAG} already exists${NC}"
|
|
372
|
+
if ! ask_yn "Update existing release?" "n"; then
|
|
373
|
+
SKIP_RELEASE=true
|
|
374
|
+
fi
|
|
375
|
+
fi
|
|
376
|
+
fi
|
|
377
|
+
|
|
378
|
+
if [ "$SKIP_RELEASE" = false ]; then
|
|
379
|
+
if ask_yn "Create GitHub Release ${TAG}?" "y"; then
|
|
380
|
+
RELEASE_NOTES=""
|
|
381
|
+
if [ -f "CHANGELOG.md" ]; then
|
|
382
|
+
RELEASE_NOTES=$(awk "
|
|
383
|
+
/^## \[${VERSION}\]/ {found=1; next}
|
|
384
|
+
found && /^## \[/ {exit}
|
|
385
|
+
found {print}
|
|
386
|
+
" CHANGELOG.md)
|
|
387
|
+
RELEASE_NOTES=$(echo "$RELEASE_NOTES" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
|
|
388
|
+
fi
|
|
389
|
+
|
|
390
|
+
if [ -z "$RELEASE_NOTES" ]; then
|
|
391
|
+
RELEASE_NOTES="Release version ${VERSION}"
|
|
392
|
+
fi
|
|
393
|
+
|
|
394
|
+
NOTES_FILE=$(mktemp)
|
|
395
|
+
echo "$RELEASE_NOTES" > "$NOTES_FILE"
|
|
396
|
+
|
|
397
|
+
if gh release create "${TAG}" \
|
|
398
|
+
--title "Release ${VERSION}" \
|
|
399
|
+
--notes-file "$NOTES_FILE" \
|
|
400
|
+
--repo "${GITHUB_REPO}"; then
|
|
401
|
+
echo -e "${GREEN}GitHub Release created successfully${NC}"
|
|
402
|
+
echo -e "${CYAN}https://github.com/${GITHUB_REPO}/releases/tag/${TAG}${NC}"
|
|
403
|
+
else
|
|
404
|
+
echo -e "${RED}Failed to create GitHub Release${NC}"
|
|
405
|
+
fi
|
|
406
|
+
|
|
407
|
+
rm -f "$NOTES_FILE"
|
|
408
|
+
fi
|
|
409
|
+
fi
|
|
410
|
+
|
|
411
|
+
echo ""
|
|
412
|
+
return 0
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
step7_upload_npm() {
|
|
416
|
+
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
417
|
+
echo -e "${BLUE}Step 7: Upload to npm${NC}"
|
|
418
|
+
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
419
|
+
|
|
420
|
+
if check_npm_uploaded; then
|
|
421
|
+
echo -e "${GREEN}Version ${VERSION} already exists on npm${NC}"
|
|
422
|
+
if ! ask_yn "Upload anyway? (will fail if version exists)" "n"; then
|
|
423
|
+
echo -e "${YELLOW}Skipped npm upload (version already exists)${NC}"
|
|
424
|
+
echo ""
|
|
425
|
+
return 0
|
|
426
|
+
fi
|
|
427
|
+
fi
|
|
428
|
+
|
|
429
|
+
if ask_yn "Upload to npm?" "y"; then
|
|
430
|
+
echo -e "${YELLOW}Publishing to npm...${NC}"
|
|
431
|
+
if ! npm publish --access public; then
|
|
432
|
+
echo -e "${RED}Upload to npm failed${NC}"
|
|
433
|
+
return 1
|
|
434
|
+
fi
|
|
435
|
+
echo -e "${GREEN}Successfully published to npm!${NC}"
|
|
436
|
+
else
|
|
437
|
+
echo -e "${YELLOW}Skipped npm upload${NC}"
|
|
438
|
+
echo -e "${CYAN}Upload manually with: npm publish --access public${NC}"
|
|
439
|
+
fi
|
|
440
|
+
echo ""
|
|
441
|
+
return 0
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
step_summary() {
|
|
445
|
+
echo -e "${CYAN}╔══════════════════════════════════════════════════════════╗${NC}"
|
|
446
|
+
echo -e "${CYAN}║ Release Summary ║${NC}"
|
|
447
|
+
echo -e "${CYAN}╚══════════════════════════════════════════════════════════╝${NC}"
|
|
448
|
+
echo ""
|
|
449
|
+
echo -e " Version: ${CYAN}${VERSION}${NC}"
|
|
450
|
+
echo -e " Tag: ${CYAN}${TAG}${NC}"
|
|
451
|
+
echo ""
|
|
452
|
+
|
|
453
|
+
if [ -n "$GITHUB_REPO" ]; then
|
|
454
|
+
if check_release_exists; then
|
|
455
|
+
echo -e " ${GREEN}GitHub Release:${NC}"
|
|
456
|
+
echo -e " https://github.com/${GITHUB_REPO}/releases/tag/${TAG}"
|
|
457
|
+
else
|
|
458
|
+
echo -e " GitHub Release: Not created yet"
|
|
459
|
+
fi
|
|
460
|
+
fi
|
|
461
|
+
|
|
462
|
+
if [ -d "dist" ] && [ "$(ls -A dist/*.js 2>/dev/null | wc -l)" -gt 0 ]; then
|
|
463
|
+
echo -e " ${GREEN}Package built: dist/${NC}"
|
|
464
|
+
else
|
|
465
|
+
echo -e " Package: Not built"
|
|
466
|
+
fi
|
|
467
|
+
|
|
468
|
+
if check_npm_uploaded; then
|
|
469
|
+
echo -e " ${GREEN}npm: https://www.npmjs.com/package/${PROJECT_NAME}/v/${VERSION}${NC}"
|
|
470
|
+
else
|
|
471
|
+
echo -e " npm: Not uploaded yet"
|
|
472
|
+
fi
|
|
473
|
+
|
|
474
|
+
echo ""
|
|
475
|
+
echo -e "${GREEN}Release script completed!${NC}"
|
|
476
|
+
echo ""
|
|
477
|
+
echo -e "${CYAN}Next steps:${NC}"
|
|
478
|
+
echo " 1. Verify installation: npm install ${PROJECT_NAME}@${VERSION}"
|
|
479
|
+
echo " 2. Update CHANGELOG.md with [Unreleased] section for next version"
|
|
480
|
+
echo ""
|
|
481
|
+
return 0
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
# Main execution logic
|
|
485
|
+
while true; do
|
|
486
|
+
show_main_menu
|
|
487
|
+
|
|
488
|
+
SELECTION="$MENU_SELECTION"
|
|
489
|
+
|
|
490
|
+
if [ -z "$SELECTION" ]; then
|
|
491
|
+
echo -e "${RED}No selection made. Please try again.${NC}"
|
|
492
|
+
continue
|
|
493
|
+
fi
|
|
494
|
+
|
|
495
|
+
case "$SELECTION" in
|
|
496
|
+
all|ALL|a|A)
|
|
497
|
+
echo ""
|
|
498
|
+
echo -e "${CYAN}Executing all steps with interactive prompts...${NC}"
|
|
499
|
+
echo ""
|
|
500
|
+
|
|
501
|
+
# Helper: run a step, abort in silent mode on failure
|
|
502
|
+
run_step() {
|
|
503
|
+
local step_name="$1"
|
|
504
|
+
shift
|
|
505
|
+
if ! "$@"; then
|
|
506
|
+
if [ "$SILENT" = true ]; then
|
|
507
|
+
echo -e "${RED}${step_name} failed. Aborting (silent mode).${NC}"
|
|
508
|
+
exit 1
|
|
509
|
+
else
|
|
510
|
+
echo -e "${YELLOW}${step_name} failed, continuing...${NC}"
|
|
511
|
+
fi
|
|
512
|
+
fi
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
if ! step1_version_verification; then
|
|
516
|
+
echo -e "${RED}Version verification failed. Exiting.${NC}"
|
|
517
|
+
exit 1
|
|
518
|
+
fi
|
|
519
|
+
|
|
520
|
+
step2_check_status
|
|
521
|
+
run_step "Step 3" step3_clean_build
|
|
522
|
+
run_step "Step 4" step4_build_package
|
|
523
|
+
run_step "Step 5" step5_check_package
|
|
524
|
+
run_step "Step 6" step6_git_tag
|
|
525
|
+
run_step "Step 6.5" step6_5_create_github_release
|
|
526
|
+
run_step "Step 7" step7_upload_npm
|
|
527
|
+
step_summary
|
|
528
|
+
break
|
|
529
|
+
;;
|
|
530
|
+
1) step1_version_verification || echo -e "${RED}Version verification failed.${NC}" ;;
|
|
531
|
+
2) step2_check_status ;;
|
|
532
|
+
3) step3_clean_build ;;
|
|
533
|
+
4) step4_build_package ;;
|
|
534
|
+
5) step5_check_package ;;
|
|
535
|
+
6) step6_git_tag ;;
|
|
536
|
+
7) step6_5_create_github_release ;;
|
|
537
|
+
8) step7_upload_npm ;;
|
|
538
|
+
9) step_summary ;;
|
|
539
|
+
0) echo -e "${CYAN}Exiting...${NC}"; exit 0 ;;
|
|
540
|
+
*) echo -e "${RED}Invalid selection. Please choose a valid option.${NC}" ;;
|
|
541
|
+
esac
|
|
542
|
+
done
|