|
| 1 | +#!/usr/bin/env bash |
| 2 | +# |
| 3 | +# Create a GitHub Release for every published @exortek/* package at its |
| 4 | +# current version — tag + the package's top CHANGELOG entry as the notes. |
| 5 | +# Run this locally after `yarn release` (or the release.yml workflow) has |
| 6 | +# published to npm; it fills in the GitHub "Releases" page, which the CI |
| 7 | +# publish step does not touch. |
| 8 | +# |
| 9 | +# Idempotent: a package that already has a Release for its current version |
| 10 | +# is skipped, so re-runs and unchanged packages are no-ops. `gh release |
| 11 | +# create` creates AND pushes the tag atomically. |
| 12 | +# |
| 13 | +# Usage: |
| 14 | +# ./scripts/releases.sh # dry-run (default) — prints what it would create |
| 15 | +# ./scripts/releases.sh --apply # actually create the Releases |
| 16 | +# |
| 17 | +# Requires the `gh` CLI authenticated (check with `gh auth status`). |
| 18 | + |
| 19 | +set -euo pipefail |
| 20 | + |
| 21 | +REPO="ExorTek/auth" |
| 22 | +MODE="${1:-dry}" |
| 23 | +if [[ "$MODE" == "--apply" ]]; then |
| 24 | + ACTION="apply" |
| 25 | +else |
| 26 | + ACTION="dry-run" |
| 27 | +fi |
| 28 | + |
| 29 | +if [[ "$ACTION" == "apply" ]]; then |
| 30 | + if ! gh auth status >/dev/null 2>&1; then |
| 31 | + echo "gh CLI not authenticated. Run: gh auth login" >&2 |
| 32 | + exit 1 |
| 33 | + fi |
| 34 | +fi |
| 35 | + |
| 36 | +# Tags point at the currently checked-out commit — run from a checkout whose |
| 37 | +# package.json versions match what was published. |
| 38 | +sha="$(git rev-parse HEAD)" |
| 39 | +echo "==> releases.sh · mode=$ACTION · target=${sha:0:7}" |
| 40 | +echo |
| 41 | + |
| 42 | +created=0 |
| 43 | +skipped=0 |
| 44 | +for dir in packages/*/; do |
| 45 | + name="$(node -p "try{require('./${dir}package.json').name}catch{''}")" |
| 46 | + [[ -z "$name" ]] && continue |
| 47 | + private="$(node -p "try{require('./${dir}package.json').private?'y':'n'}catch{'y'}")" |
| 48 | + [[ "$private" == "y" ]] && continue # @exortek/shared is private — not published |
| 49 | + ver="$(node -p "require('./${dir}package.json').version")" |
| 50 | + tag="${name}@${ver}" |
| 51 | + |
| 52 | + if gh release view "$tag" -R "$REPO" >/dev/null 2>&1; then |
| 53 | + echo " skip (exists): $tag" |
| 54 | + skipped=$((skipped + 1)) |
| 55 | + continue |
| 56 | + fi |
| 57 | + |
| 58 | + if [[ "$ACTION" == "apply" ]]; then |
| 59 | + notes="$(mktemp)" |
| 60 | + # Top CHANGELOG block: from the first "## " up to (not including) the next. |
| 61 | + awk '/^## /{c++} c==1{print} c==2{exit}' "${dir}CHANGELOG.md" >"$notes" 2>/dev/null || true |
| 62 | + [[ -s "$notes" ]] || echo "Release $tag" >"$notes" |
| 63 | + gh release create "$tag" -R "$REPO" --target "$sha" --title "$tag" --notes-file "$notes" |
| 64 | + rm -f "$notes" |
| 65 | + echo " created: $tag" |
| 66 | + else |
| 67 | + echo " [dry] would create: $tag" |
| 68 | + fi |
| 69 | + created=$((created + 1)) |
| 70 | +done |
| 71 | + |
| 72 | +echo |
| 73 | +echo "==> ${created} to create · ${skipped} already present" |
| 74 | +[[ "$ACTION" == "dry-run" ]] && echo "dry-run complete. Re-run with --apply to create the Releases." |
0 commit comments