Skip to content

Commit cdb6ecb

Browse files
committed
automatic rel sh
1 parent 1909845 commit cdb6ecb

1 file changed

Lines changed: 147 additions & 59 deletions

File tree

scripts/sh/make_release.sh

Lines changed: 147 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ set -Eeuo pipefail
88
# 🔧 CONFIG
99
#######################################
1010
SCRIPT_NAME="$(basename "$0")"
11-
SCRIPT_VERSION="2.5.0"
11+
SCRIPT_VERSION="2.6.1"
1212
SCRIPT_AUTHOR="Federico Girolami"
1313
SCRIPT_TEAM="Pytorchia™ Developers"
1414
SCRIPT_LICENSE="MIT License"
15-
SCRIPT_DESCRIPTION="Create a GitHub Release from package.json version, with guard-checks, optional auto-commit, tests, build, version bump, push + tags, and optional npm publish."
15+
SCRIPT_DESCRIPTION="Create a GitHub Release from package.json version, with guard-checks, optional auto-commit, tests, build, version bump, push + tags, optional npm publish, and changelog extraction from README."
1616
REPO_ROOT_DIR="./"
1717

1818
# Release
@@ -37,19 +37,23 @@ COMMIT_FILES=() # se vuoi selezionare file specifici
3737
COMMIT_MESSAGE="" # messaggio commit, se vuoto verrà chiesto
3838

3939
RUN_TESTS=false
40-
TEST_SCRIPT="test:samples" # es . test o test:samples
40+
TEST_SCRIPT="test:samples" # es. test o test:samples
4141

4242
RUN_BUILD=false
4343
BUILD_SCRIPT="build"
4444

4545
BUMP_KIND="none" # none | patch | minor | major | prepatch | preminor | premajor | prerelease
46-
BUMP_PREID="" # es . alpha , beta , rc
46+
BUMP_PREID="" # es. alpha , beta , rc
4747

4848
PUSH_AFTER=true
4949

5050
NPM_PUBLISH=false
5151
NPM_ACCESS="public" # public | restricted
52-
NPM_TAG="" # es . next
52+
NPM_TAG="" # es. latest / next
53+
54+
# Changelog from README
55+
CHANGELOG_FROM_README=false
56+
CHANGELOG_FILE="README.md"
5357

5458
#######################################
5559
# 🎨 ANSI
@@ -95,11 +99,12 @@ die() {
9599
}
96100

97101
run() {
102+
# esegue i comandi preservando gli argomenti (niente eval)
98103
local -a cmd=("$@")
99104
if [[ "$DRY_RUN" == true ]]; then
100105
warn "DRY-RUN → ${cmd[*]}"
101106
else
102-
dbg "exec → ${cmd[*]}"
107+
#dbg "exec → ${cmd[*]}"
103108
"${cmd[@]}"
104109
fi
105110
}
@@ -112,7 +117,7 @@ trap 'err "Errore a riga $LINENO . Uscita ." ' ERR
112117
banner() {
113118
cat <<EOF
114119
${GOLD}${BOLD}┌──────────────────────────────────────────────────────────┐${RESET}
115-
${GOLD}${BOLD}${SOFT}Pytorchia™ Release Helper${RESET}${GOLD}${BOLD} ${RESET}
120+
${GOLD}${BOLD}${SOFT}Pytorchia™ Release Helper${RESET}${GOLD}${BOLD}${RESET}
116121
${GOLD}${BOLD}└──────────────────────────────────────────────────────────┘${RESET}
117122
${BOLD}$SCRIPT_NAME ${RESET}${ITA}v$SCRIPT_VERSION${RESET} ${DIM}by $SCRIPT_AUTHOR · $SCRIPT_TEAM${RESET}
118123
${DIM}License:${RESET} $SCRIPT_LICENSE
@@ -142,39 +147,60 @@ ${BOLD}Flow / Guardie${RESET} :
142147
-d , --debug Log verboso
143148
--force Bypassa guardie
144149
--allow-dirty-tag Consente tag con tree sporco
145-
--auto-chain Se tree sporco , esegui catena commit → test → build → bump → push
150+
--auto-chain Se tree sporco: commit → test → build → bump → push
151+
--auto-chain-nobump Se tree sporco: commit → test → build → push
146152
147153
${BOLD}Commit / Test / Build${RESET} :
148-
--commit-files "A B" File da aggiungere al commit ( disattiva --commit-all )
149-
--no-commit-all Non usare git add -A ( default è on )
154+
--commit-files "A B" File per il commit (disattiva --commit-all)
155+
--no-commit-all Non usare git add -A
150156
--commit-message "msg" Messaggio commit
151-
--run-tests Esegui test ( npm run <script> )
152-
--test-script <name> Script test ( default : $TEST_SCRIPT )
153-
--run-build Esegui build ( npm run <script> )
154-
--build-script <name> Script build ( default : $BUILD_SCRIPT )
157+
--run-tests Esegui test (npm run <script>)
158+
--test-script <name> Script test (default: test:samples)
159+
--run-build Esegui build (npm run <script>)
160+
--build-script <name> Script build (default: build)
155161
156162
${BOLD}Version bump${RESET} :
157163
--bump <kind> none | patch | minor | major | prepatch | preminor | premajor | prerelease
158-
--preid <id> Pre-id per prerelease , es . alpha , beta , rc
164+
--preid <id> Pre-id per prerelease (alpha/beta/rc)
159165
160166
${BOLD}Push / Publish${RESET} :
161-
--no-push Non pushare dopo commit / bump
167+
--no-push Non pushare dopo commit/bump
162168
--npm-publish Pubblica su npm
163-
--npm-access <mode> public | restricted ( default : $NPM_ACCESS )
164-
--npm-tag <tag> npm dist-tag , es . next
169+
--npm-access <mode> public | restricted (default: public)
170+
--npm-tag <tag> npm dist-tag (es. latest/next)
171+
172+
${BOLD}Changelog${RESET} :
173+
--changelog-from-readme Estrai le note dal README per la versione (### vX.Y.Z o ### X.Y.Z)
174+
--changelog-file <path> README alternativo (default: README.md)
175+
176+
${BOLD}Preset${RESET} :
177+
--preset node-lib Abilita: --auto-chain --run-tests --run-build --bump patch --npm-publish --npm-access public --npm-tag latest --yes
165178
166179
${BOLD}Varie${RESET} :
167180
-V , --version-script Stampa versione script
168181
-h , --help Aiuto
169182
170183
${BOLD}Esempio${RESET} :
171-
$SCRIPT_NAME --auto-chain --run-tests --run-build --bump patch --npm-publish --yes
184+
$SCRIPT_NAME --preset node-lib --version 1.0.12 --changelog-from-readme --assets "dist/*"
172185
EOF
173186
}
174187

175188
#######################################
176-
# 🧮 Arg parsing
189+
# 🧮 Arg parsing + preset
177190
#######################################
191+
set_preset_node_lib() {
192+
AUTO_CHAIN=true
193+
RUN_TESTS=true
194+
TEST_SCRIPT="test:samples"
195+
RUN_BUILD=true
196+
BUILD_SCRIPT="build"
197+
BUMP_KIND="patch"
198+
NPM_PUBLISH=true
199+
NPM_ACCESS="public"
200+
NPM_TAG="latest"
201+
YES_ALL=true
202+
}
203+
178204
parse_args() {
179205
while (($#)); do
180206
case "$1" in
@@ -238,7 +264,11 @@ parse_args() {
238264
AUTO_CHAIN=true
239265
shift
240266
;;
241-
267+
--auto-chain-nobump)
268+
AUTO_CHAIN=true
269+
BUMP_KIND="none"
270+
shift
271+
;;
242272
--commit-files)
243273
IFS=' ' read -r -a COMMIT_FILES <<<"${2:?}"
244274
COMMIT_ALL=false
@@ -296,6 +326,22 @@ parse_args() {
296326
shift 2
297327
;;
298328

329+
--changelog-from-readme)
330+
CHANGELOG_FROM_README=true
331+
shift
332+
;;
333+
--changelog-file)
334+
CHANGELOG_FILE="${2:?}"
335+
shift 2
336+
;;
337+
338+
--preset)
339+
case "${2:?}" in
340+
node-lib) set_preset_node_lib ;;
341+
*) die "Preset sconosciuto: $2" ;;
342+
esac
343+
shift 2
344+
;;
299345
--)
300346
shift
301347
break
@@ -306,7 +352,7 @@ parse_args() {
306352
}
307353

308354
#######################################
309-
# 🧪 Guard-checks
355+
# 🧪 Guard-checks / helpers
310356
#######################################
311357
require_bin() { command -v "$1" >/dev/null 2>&1 || die "Manca dipendenza : $1"; }
312358

@@ -380,13 +426,9 @@ resolve_version() {
380426
is_semver "$VERSION_TAG" || die "Versione non in formato semver : $VERSION_TAG"
381427
}
382428

383-
detect_prerelease_flag() {
384-
[[ "$VERSION_TAG" == *"-"* ]] && echo "--prerelease" || echo ""
385-
}
429+
detect_prerelease_flag() { [[ "$VERSION_TAG" == *"-"* ]] && echo "--prerelease" || echo ""; }
386430

387-
tag_exists() {
388-
git -C "$REPO_ROOT_DIR" show-ref --tags --verify --quiet "refs/tags/v$VERSION_TAG"
389-
}
431+
tag_exists() { git -C "$REPO_ROOT_DIR" show-ref --tags --verify --quiet "refs/tags/v$VERSION_TAG"; }
390432

391433
ensure_tag() {
392434
if tag_exists; then
@@ -402,6 +444,33 @@ ensure_tag() {
402444
fi
403445
}
404446

447+
#######################################
448+
# 🧾 Changelog extraction (README)
449+
#######################################
450+
extract_changelog_from_readme() {
451+
local file="$1" ver="$2"
452+
[[ -f "$file" ]] || die "README non trovato: $file"
453+
454+
# Estrae dalla riga '### vX.Y.Z' o '### X.Y.Z' fino alla riga della prossima '### '
455+
local content
456+
content="$(awk -v ver="$ver" '
457+
BEGIN{ start=0 }
458+
# Se abbiamo iniziato e troviamo una nuova sezione ###, fermiamo l output
459+
start==1 && $0 ~ /^###[[:space:]]/ { exit }
460+
# Riconosci l intestazione della versione (con o senza v)
461+
$0 ~ "^###[[:space:]]*(v)?" ver "[[:space:]]*$" { start=1; print; next }
462+
# Se siamo all interno della sezione, stampa
463+
start==1 { print }
464+
' "$file")"
465+
466+
if [[ -z "$content" ]]; then
467+
warn "Nessuna sezione changelog trovata per ${ver} in $file (cerco anche v${ver})"
468+
echo ""
469+
else
470+
echo "$content"
471+
fi
472+
}
473+
405474
#######################################
406475
# 🔗 Catena su tree sporco
407476
#######################################
@@ -417,12 +486,12 @@ auto_chain_if_needed() {
417486
fi
418487

419488
if [[ "$AUTO_CHAIN" != true ]]; then
420-
die "Working tree sporco . Committa o usa --allow-dirty-tag / --force . ( oppure passa --auto-chain )"
489+
die "Working tree sporco . Committa o usa --allow-dirty-tag / --force . (oppure passa --auto-chain)"
421490
fi
422491

423492
info "Avvio catena automatica su working tree sporco …"
424493

425-
# 1 . Commit
494+
# Commit
426495
if [[ -z "$COMMIT_MESSAGE" ]]; then
427496
if [[ "$YES_ALL" == true ]]; then
428497
COMMIT_MESSAGE="chore: prepare release"
@@ -442,34 +511,32 @@ auto_chain_if_needed() {
442511

443512
run git -C "$REPO_ROOT_DIR" commit -m "$COMMIT_MESSAGE" || warn "Nessuna modifica da committare"
444513

445-
# 2 . Tests
514+
# Tests
446515
if [[ "$RUN_TESTS" == true ]]; then
447516
info "Eseguo test : npm run $TEST_SCRIPT"
448517
run bash -lc "cd \"$REPO_ROOT_DIR\" && npm run \"$TEST_SCRIPT\""
449518
fi
450519

451-
# 3 . Build
520+
# Build
452521
if [[ "$RUN_BUILD" == true ]]; then
453522
info "Eseguo build : npm run $BUILD_SCRIPT"
454523
run bash -lc "cd \"$REPO_ROOT_DIR\" && npm run \"$BUILD_SCRIPT\""
455524
fi
456525

457-
# 4 . Bump
526+
# Bump
458527
if [[ "$BUMP_KIND" != "none" ]]; then
459-
local -a bump_cmd=(npm version "$BUMP_KIND")
460-
[[ -n "$BUMP_PREID" ]] && bump_cmd+=(--preid "$BUMP_PREID")
461-
bump_cmd+=(-m "chore(release): v%s — $COMMIT_MESSAGE")
462-
info "Bump versione : ${bump_cmd[*]}"
463-
run bash -lc "cd \"$REPO_ROOT_DIR\" && ${bump_cmd[*]}"
464-
465-
# aggiorna VERSION_TAG dalla nuova package.json
528+
local bump_cmd="npm version \"$BUMP_KIND\""
529+
[[ -n "$BUMP_PREID" ]] && bump_cmd+=" --preid \"$BUMP_PREID\""
530+
bump_cmd+=" -m \"chore(release): v%s — $COMMIT_MESSAGE\""
531+
info "Bump versione : $bump_cmd"
532+
run bash -lc "cd \"$REPO_ROOT_DIR\" && $bump_cmd"
466533
VERSION_TAG="$(get_pkg_version)"
467534
ok "Nuova versione : v$VERSION_TAG"
468535
else
469536
info "Bump versione disattivato"
470537
fi
471538

472-
# 5 . Push
539+
# Push
473540
if [[ "$PUSH_AFTER" == true ]]; then
474541
run git -C "$REPO_ROOT_DIR" push
475542
run git -C "$REPO_ROOT_DIR" push --tags || true
@@ -486,40 +553,61 @@ do_release() {
486553
require_bin node
487554
require_bin npm
488555

489-
REPO_ROOT_DIR="${REPO_ROOT_DIR:-$(find_git_root)}"
556+
if [[ "$REPO_ROOT_DIR" == "./" || -z "$REPO_ROOT_DIR" ]]; then
557+
REPO_ROOT_DIR="$(find_git_root)"
558+
fi
490559
[[ -z "$REPO_ROOT_DIR" ]] && die "Non è stata trovata una repo Git valida"
491560
assert_repo
492561
cd "$REPO_ROOT_DIR"
493-
494562
assert_branch
495-
# Se serve , esegue commit → test → build → bump → push
563+
564+
# Se serve, esegue commit → test → build → bump → push
496565
auto_chain_if_needed
497566

498-
# Se non abbiamo bumpato , risolvi la versione attuale
567+
# Se non abbiamo bumpato, risolvi la versione corrente
499568
[[ -z "$VERSION_TAG" ]] && resolve_version
500569

570+
# Changelog extraction (se richiesto e non già passato via --notes/--notes-file)
571+
if [[ "$CHANGELOG_FROM_README" == true && -z "$RELEASE_NOTES" && -z "$RELEASE_NOTES_FILE" ]]; then
572+
local file_path="$CHANGELOG_FILE"
573+
[[ ! -f "$file_path" ]] && file_path="$REPO_ROOT_DIR/$CHANGELOG_FILE"
574+
local md
575+
md="$(extract_changelog_from_readme "$file_path" "$VERSION_TAG")"
576+
if [[ -n "$md" ]]; then
577+
RELEASE_NOTES="$md"
578+
ok "Note di rilascio estratte da $file_path → sezione ${BOLD}### v$VERSION_TAG${RESET}"
579+
else
580+
warn "Impossibile estrarre note da README . Valuta --notes-file o --generate-notes"
581+
fi
582+
fi
583+
501584
read_notes
502585
local preflag
503586
preflag="$(detect_prerelease_flag)"
504587

505-
# Tag GH : se npm version ha già creato il tag , lo vedremo esistente
588+
# Tag GH: se npm version ha già creato il tag, lo vedremo esistente
506589
ensure_tag
507590

508-
# Assets
591+
# Assets (compat bash 3.2; niente mapfile, niente echo; safe con spazi)
509592
local -a assets_arg=()
510593
if [[ -n "$ASSETS_GLOB" ]]; then
511-
shopt -s nullglob
512-
mapfile -t files < <(cd "$REPO_ROOT_DIR" && compgen -G "$ASSETS_GLOB" || true)
513-
shopt -u nullglob
514-
if ((${#files[@]})); then
515-
for f in "${files[@]}"; do assets_arg+=(--attach "$f"); done
516-
info "Allegati : ${files[*]}"
594+
# compgen -G espande il glob in maniera robusta (0..N righe, una per match)
595+
local -a matches=()
596+
while IFS= read -r line; do
597+
matches+=("$line")
598+
done < <(compgen -G -- "$ASSETS_GLOB")
599+
600+
if ((${#matches[@]})); then
601+
for f in "${matches[@]}"; do
602+
assets_arg+=(--attach "$f")
603+
done
604+
info "Allegati : ${matches[*]}"
517605
else
518606
warn "Nessun file combacia con glob : $ASSETS_GLOB"
519607
fi
520608
fi
521609

522-
# Note
610+
# Notes
523611
local -a notes_arg=()
524612
if [[ -n "$RELEASE_NOTES" ]]; then
525613
notes_arg=(--notes "$RELEASE_NOTES")
@@ -542,10 +630,10 @@ do_release() {
542630

543631
# NPM publish opzionale
544632
if [[ "$NPM_PUBLISH" == true ]]; then
545-
local -a pub=(npm publish --access "$NPM_ACCESS")
546-
[[ -n "$NPM_TAG" ]] && pub+=(--tag "$NPM_TAG")
547-
info "Pubblico su npm : ${pub[*]}"
548-
run bash -lc "cd \"$REPO_ROOT_DIR\" && ${pub[*]}"
633+
local pub="npm publish --access \"$NPM_ACCESS\""
634+
[[ -n "$NPM_TAG" ]] && pub+=" --tag \"$NPM_TAG\""
635+
info "Pubblico su npm : $pub"
636+
run bash -lc "cd \"$REPO_ROOT_DIR\" && $pub"
549637
ok "npm publish completato"
550638
fi
551639
}
@@ -557,5 +645,5 @@ main() {
557645
parse_args "$@"
558646
do_release
559647
}
560-
561648
main "$@"
649+
#######################################

0 commit comments

Comments
 (0)