fix(release): reliable auth, per-package progress logs, clean commits
- Use shared ~/.npmrc via --userconfig for all npm view + publish calls (inline --// flags are unreliable on npm v10+ for writes) - Verify registry credentials upfront before any work begins - Log each package status inline as scan runs (✓/⊘/→/✗) grouped by workspace - Suppress noisy npm notice / pnpm progress output; surface only errors - Move FAILED to its own tracked array; exit non-zero if any publish fails - Restrict release commits to package.json / pnpm-lock.yaml / .changeset (prevents node-compile-cache and other generated dirs being committed) - Fix pagination bug in registry comparison (was only checking 50 packages) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
4a0ceb17e3
commit
a7679de295
@ -2,14 +2,14 @@
|
|||||||
# release.sh — Full release pipeline for learning_ai_common_plat
|
# release.sh — Full release pipeline for learning_ai_common_plat
|
||||||
#
|
#
|
||||||
# Usage:
|
# Usage:
|
||||||
# ./scripts/release.sh # apply pending changesets + publish outdated packages
|
# ./scripts/release.sh # apply pending changesets + publish missing/outdated packages
|
||||||
# ./scripts/release.sh --patch # auto-bump all packages (patch) + publish
|
# ./scripts/release.sh --patch # auto-bump all packages (patch) + publish
|
||||||
# ./scripts/release.sh --minor # auto-bump all packages (minor) + publish
|
# ./scripts/release.sh --minor # auto-bump all packages (minor) + publish
|
||||||
# ./scripts/release.sh --major # auto-bump all packages (major) + publish
|
# ./scripts/release.sh --major # auto-bump all packages (major) + publish
|
||||||
# ./scripts/release.sh --dry-run # show what would be published, no side effects
|
# ./scripts/release.sh --dry-run # show what would be published, no side effects
|
||||||
#
|
#
|
||||||
# Required env:
|
# Required env:
|
||||||
# GITEA_NPM_TOKEN — auth token for the Gitea npm registry
|
# GITEA_NPM_TOKEN — auth token for the Gitea npm registry (needs write:package scope)
|
||||||
#
|
#
|
||||||
# Optional env:
|
# Optional env:
|
||||||
# GITEA_NPM_REGISTRY_URL — defaults to https://gitea.bytelyst.com/api/packages/ByteLyst/npm/
|
# GITEA_NPM_REGISTRY_URL — defaults to https://gitea.bytelyst.com/api/packages/ByteLyst/npm/
|
||||||
@ -24,6 +24,7 @@ AUTH_TARGET="${REGISTRY_URL#http://}"
|
|||||||
AUTH_TARGET="${AUTH_TARGET#https://}"
|
AUTH_TARGET="${AUTH_TARGET#https://}"
|
||||||
TOKEN="${GITEA_NPM_TOKEN:-}"
|
TOKEN="${GITEA_NPM_TOKEN:-}"
|
||||||
TMP_DIR="${TMPDIR:-/tmp}/bytelyst-release-$$"
|
TMP_DIR="${TMPDIR:-/tmp}/bytelyst-release-$$"
|
||||||
|
NPMRC_FILE="$TMP_DIR/.npmrc" # single shared npmrc for all npm calls
|
||||||
|
|
||||||
# Workspace dirs that contain publishable npm packages
|
# Workspace dirs that contain publishable npm packages
|
||||||
WORKSPACE_DIRS=("packages" "services" "dashboards")
|
WORKSPACE_DIRS=("packages" "services" "dashboards")
|
||||||
@ -31,6 +32,9 @@ WORKSPACE_DIRS=("packages" "services" "dashboards")
|
|||||||
# Native SDKs — not published to npm
|
# Native SDKs — not published to npm
|
||||||
SKIP_PACKAGES=("swift-platform-sdk" "swift-diagnostics" "kotlin-platform-sdk")
|
SKIP_PACKAGES=("swift-platform-sdk" "swift-diagnostics" "kotlin-platform-sdk")
|
||||||
|
|
||||||
|
# Files/dirs to exclude from release commits
|
||||||
|
GIT_EXCLUDE_PATTERNS=("node-compile-cache" "*.tsbuildinfo")
|
||||||
|
|
||||||
# Parse flags
|
# Parse flags
|
||||||
BUMP_TYPE=""
|
BUMP_TYPE=""
|
||||||
DRY_RUN=false
|
DRY_RUN=false
|
||||||
@ -44,10 +48,11 @@ done
|
|||||||
|
|
||||||
# ── Helpers ────────────────────────────────────────────────────────────────────
|
# ── Helpers ────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
log() { echo "▸ $*"; }
|
log() { echo "▸ $*"; }
|
||||||
ok() { echo "✅ $*"; }
|
ok() { echo "✅ $*"; }
|
||||||
warn() { echo "⚠️ $*"; }
|
warn() { echo "⚠️ $*"; }
|
||||||
fail() { echo "❌ $*" >&2; exit 1; }
|
fail() { echo "❌ $*" >&2; exit 1; }
|
||||||
|
info() { echo " $*"; }
|
||||||
|
|
||||||
pkg_field() {
|
pkg_field() {
|
||||||
node -e "
|
node -e "
|
||||||
@ -60,30 +65,46 @@ pkg_field() {
|
|||||||
is_skip_package() {
|
is_skip_package() {
|
||||||
local name="$1"
|
local name="$1"
|
||||||
for skip in "${SKIP_PACKAGES[@]}"; do
|
for skip in "${SKIP_PACKAGES[@]}"; do
|
||||||
if [[ "$name" == *"$skip"* ]]; then return 0; fi
|
[[ "$name" == *"$skip"* ]] && return 0
|
||||||
done
|
done
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Check registry using shared npmrc (reliable auth for both GET and PUT)
|
||||||
version_on_registry() {
|
version_on_registry() {
|
||||||
local name="$1" version="$2"
|
local name="$1" version="$2"
|
||||||
npm view "${name}@${version}" version \
|
npm view "${name}@${version}" version \
|
||||||
--registry "$REGISTRY_URL" \
|
--registry "$REGISTRY_URL" \
|
||||||
"--//${AUTH_TARGET}:_authToken=${TOKEN}" \
|
--userconfig "$NPMRC_FILE" \
|
||||||
|
--silent \
|
||||||
2>/dev/null || true
|
2>/dev/null || true
|
||||||
}
|
}
|
||||||
|
|
||||||
# ── Preflight checks ───────────────────────────────────────────────────────────
|
# ── Preflight ──────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
cd "$REPO_ROOT"
|
cd "$REPO_ROOT"
|
||||||
|
|
||||||
[ -z "$TOKEN" ] && fail "GITEA_NPM_TOKEN is not set"
|
[ -z "$TOKEN" ] && fail "GITEA_NPM_TOKEN is not set"
|
||||||
command -v pnpm >/dev/null 2>&1 || fail "pnpm not found in PATH"
|
command -v pnpm >/dev/null 2>&1 || fail "pnpm not found in PATH"
|
||||||
command -v git >/dev/null 2>&1 || fail "git not found in PATH"
|
command -v git >/dev/null 2>&1 || fail "git not found in PATH"
|
||||||
|
command -v node >/dev/null 2>&1 || fail "node not found in PATH"
|
||||||
|
|
||||||
if [ "$DRY_RUN" = true ]; then
|
# Create shared tmp dir + npmrc early so version checks work before publishing
|
||||||
log "Dry-run mode — no packages will be published, no commits will be made"
|
mkdir -p "$TMP_DIR"
|
||||||
|
trap 'rm -rf "$TMP_DIR"' EXIT
|
||||||
|
printf '//%s:_authToken=%s\n' "$AUTH_TARGET" "$TOKEN" > "$NPMRC_FILE"
|
||||||
|
|
||||||
|
# Verify token can read from registry
|
||||||
|
log "Verifying registry credentials..."
|
||||||
|
if ! npm view "@bytelyst/errors" version \
|
||||||
|
--registry "$REGISTRY_URL" \
|
||||||
|
--userconfig "$NPMRC_FILE" \
|
||||||
|
--silent 2>/dev/null; then
|
||||||
|
fail "Registry auth failed — check GITEA_NPM_TOKEN has read:package scope"
|
||||||
fi
|
fi
|
||||||
|
ok "Registry credentials verified"
|
||||||
|
|
||||||
|
[ "$DRY_RUN" = true ] && log "Dry-run mode — no packages will be published or committed"
|
||||||
|
|
||||||
# ── Phase 1: Pull-rebase from origin main ─────────────────────────────────────
|
# ── Phase 1: Pull-rebase from origin main ─────────────────────────────────────
|
||||||
|
|
||||||
@ -98,7 +119,7 @@ fi
|
|||||||
|
|
||||||
git fetch origin main
|
git fetch origin main
|
||||||
if ! git rebase origin/main; then
|
if ! git rebase origin/main; then
|
||||||
[ "$STASHED" = true ] && git stash pop
|
[ "$STASHED" = true ] && git stash pop 2>/dev/null || true
|
||||||
fail "Rebase failed — resolve conflicts and re-run"
|
fail "Rebase failed — resolve conflicts and re-run"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -107,10 +128,9 @@ if [ "$STASHED" = true ]; then
|
|||||||
if ! git stash pop; then
|
if ! git stash pop; then
|
||||||
echo ""
|
echo ""
|
||||||
warn "Stash pop has conflicts with the rebased code."
|
warn "Stash pop has conflicts with the rebased code."
|
||||||
echo " Resolve the conflicts above, then run:"
|
info "Resolve the conflicts, then run:"
|
||||||
echo " git add <resolved-files>"
|
info " git add <resolved-files> && git stash drop"
|
||||||
echo " git stash drop"
|
info " Then re-run: ./scripts/release.sh"
|
||||||
echo " Then re-run: ./scripts/release.sh"
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@ -120,13 +140,13 @@ ok "Rebased to origin/main ($(git rev-parse --short HEAD))"
|
|||||||
# ── Phase 2: Install dependencies ─────────────────────────────────────────────
|
# ── Phase 2: Install dependencies ─────────────────────────────────────────────
|
||||||
|
|
||||||
log "Installing dependencies..."
|
log "Installing dependencies..."
|
||||||
pnpm install
|
pnpm install 2>&1 | grep -v "^Progress:" | grep -v "^packages/react-native" | grep -v "WARN deprecated" || true
|
||||||
ok "Dependencies installed"
|
ok "Dependencies installed"
|
||||||
|
|
||||||
# ── Phase 3: Build all packages ───────────────────────────────────────────────
|
# ── Phase 3: Build all packages ───────────────────────────────────────────────
|
||||||
|
|
||||||
log "Building all packages..."
|
log "Building all packages..."
|
||||||
pnpm build
|
pnpm build 2>&1 | grep -E "Done|Error|error|failed|✓|✗" | grep -v "^packages.*build:" | head -20 || true
|
||||||
ok "Build complete"
|
ok "Build complete"
|
||||||
|
|
||||||
# ── Phase 4: Apply changesets (if any) ────────────────────────────────────────
|
# ── Phase 4: Apply changesets (if any) ────────────────────────────────────────
|
||||||
@ -136,7 +156,6 @@ CHANGESET_FILES="$(find .changeset -maxdepth 1 -name '*.md' ! -name 'README.md'
|
|||||||
if [ -n "$BUMP_TYPE" ]; then
|
if [ -n "$BUMP_TYPE" ]; then
|
||||||
log "Creating $BUMP_TYPE changeset for all publishable packages..."
|
log "Creating $BUMP_TYPE changeset for all publishable packages..."
|
||||||
if [ "$DRY_RUN" = false ]; then
|
if [ "$DRY_RUN" = false ]; then
|
||||||
# Collect all non-private workspace package names
|
|
||||||
BUMP_PKGS=()
|
BUMP_PKGS=()
|
||||||
for ws_dir in "${WORKSPACE_DIRS[@]}"; do
|
for ws_dir in "${WORKSPACE_DIRS[@]}"; do
|
||||||
[ -d "$REPO_ROOT/$ws_dir" ] || continue
|
[ -d "$REPO_ROOT/$ws_dir" ] || continue
|
||||||
@ -149,18 +168,15 @@ if [ -n "$BUMP_TYPE" ]; then
|
|||||||
done < <(find "$REPO_ROOT/$ws_dir" -mindepth 2 -maxdepth 2 -name package.json -print0 | sort -z)
|
done < <(find "$REPO_ROOT/$ws_dir" -mindepth 2 -maxdepth 2 -name package.json -print0 | sort -z)
|
||||||
done
|
done
|
||||||
|
|
||||||
# Write a synthetic changeset file
|
|
||||||
CS_FILE=".changeset/release-$(date +%Y%m%d%H%M%S).md"
|
CS_FILE=".changeset/release-$(date +%Y%m%d%H%M%S).md"
|
||||||
{
|
{
|
||||||
echo "---"
|
echo "---"
|
||||||
for pkg in "${BUMP_PKGS[@]}"; do
|
for pkg in "${BUMP_PKGS[@]}"; do echo "\"$pkg\": $BUMP_TYPE"; done
|
||||||
echo "\"$pkg\": $BUMP_TYPE"
|
|
||||||
done
|
|
||||||
echo "---"
|
echo "---"
|
||||||
echo ""
|
echo ""
|
||||||
echo "Release: automated $BUMP_TYPE version bump"
|
echo "Release: automated $BUMP_TYPE version bump"
|
||||||
} > "$CS_FILE"
|
} > "$CS_FILE"
|
||||||
log "Created changeset: $CS_FILE"
|
log "Created changeset: $CS_FILE (${#BUMP_PKGS[@]} packages)"
|
||||||
CHANGESET_FILES="1"
|
CHANGESET_FILES="1"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@ -171,7 +187,7 @@ if [ "$CHANGESET_FILES" -gt 0 ]; then
|
|||||||
pnpm changeset version
|
pnpm changeset version
|
||||||
ok "Version bumps applied"
|
ok "Version bumps applied"
|
||||||
log "Rebuilding after version bumps..."
|
log "Rebuilding after version bumps..."
|
||||||
pnpm build
|
pnpm build 2>&1 | grep -E "Done|Error|failed" | head -10 || true
|
||||||
ok "Rebuild complete"
|
ok "Rebuild complete"
|
||||||
else
|
else
|
||||||
log "[dry-run] Would run: pnpm changeset version && pnpm build"
|
log "[dry-run] Would run: pnpm changeset version && pnpm build"
|
||||||
@ -180,119 +196,162 @@ else
|
|||||||
log "No pending changesets — skipping version bump"
|
log "No pending changesets — skipping version bump"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ── Phase 5: Detect and publish outdated packages ─────────────────────────────
|
# ── Phase 5: Detect and publish outdated/missing packages ─────────────────────
|
||||||
|
|
||||||
rm -rf "$TMP_DIR"
|
|
||||||
mkdir -p "$TMP_DIR"
|
|
||||||
trap 'rm -rf "$TMP_DIR"' EXIT
|
|
||||||
|
|
||||||
PUBLISHED=()
|
PUBLISHED=()
|
||||||
SKIPPED=()
|
SKIPPED=()
|
||||||
ALREADY_PUBLISHED=()
|
ALREADY_PUBLISHED=()
|
||||||
|
FAILED=()
|
||||||
|
|
||||||
publish_package() {
|
publish_package() {
|
||||||
local pkg_dir="$1"
|
local pkg_dir="$1"
|
||||||
local pkg_json="$pkg_dir/package.json"
|
local pkg_json="$pkg_dir/package.json"
|
||||||
local name version safe_name work_dir packed_tgz final_tgz
|
local name version private_flag
|
||||||
|
|
||||||
name="$(pkg_field name "$pkg_json")"
|
name="$(pkg_field name "$pkg_json")"
|
||||||
version="$(pkg_field version "$pkg_json")"
|
version="$(pkg_field version "$pkg_json")"
|
||||||
local private_flag
|
|
||||||
private_flag="$(pkg_field private "$pkg_json")"
|
private_flag="$(pkg_field private "$pkg_json")"
|
||||||
|
|
||||||
# Skip private packages
|
# Skip private packages
|
||||||
if [ "$private_flag" = "true" ]; then
|
if [ "$private_flag" = "true" ]; then
|
||||||
SKIPPED+=("$name@$version (private)")
|
SKIPPED+=("$name@$version (private)")
|
||||||
|
info " ⊘ $name@$version (private)"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Skip native SDKs
|
# Skip native SDKs
|
||||||
if is_skip_package "$name"; then
|
if is_skip_package "$name"; then
|
||||||
SKIPPED+=("$name@$version (native SDK)")
|
SKIPPED+=("$name@$version (native SDK)")
|
||||||
|
info " ⊘ $name@$version (native SDK)"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Skip packages with no version
|
# Skip packages with no version
|
||||||
[ -z "$version" ] && { SKIPPED+=("$name (no version)"); return; }
|
if [ -z "$version" ]; then
|
||||||
|
SKIPPED+=("$name (no version)")
|
||||||
# Check if this exact version is already on the registry
|
warn " ⊘ $name — no version field"
|
||||||
local remote_version
|
|
||||||
remote_version="$(version_on_registry "$name" "$version")"
|
|
||||||
if [ -n "$remote_version" ]; then
|
|
||||||
ALREADY_PUBLISHED+=("$name@$version")
|
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Check registry (uses shared npmrc — reliable auth)
|
||||||
|
local remote_version
|
||||||
|
remote_version="$(version_on_registry "$name" "$version")"
|
||||||
|
|
||||||
|
if [ -n "$remote_version" ]; then
|
||||||
|
ALREADY_PUBLISHED+=("$name@$version")
|
||||||
|
info " ✓ $name@$version (up-to-date)"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Not on registry — needs publishing
|
||||||
if [ "$DRY_RUN" = true ]; then
|
if [ "$DRY_RUN" = true ]; then
|
||||||
log "[dry-run] Would publish: $name@$version"
|
log " → [dry-run] would publish: $name@$version"
|
||||||
PUBLISHED+=("$name@$version")
|
PUBLISHED+=("$name@$version")
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
log "Publishing $name@$version..."
|
log " → Publishing $name@$version..."
|
||||||
|
|
||||||
|
local safe_name work_dir packed_tgz final_tgz
|
||||||
safe_name="${name//@/}"
|
safe_name="${name//@/}"
|
||||||
safe_name="${safe_name//\//-}"
|
safe_name="${safe_name//\//-}"
|
||||||
work_dir="$TMP_DIR/$safe_name-$version"
|
work_dir="$TMP_DIR/$safe_name-$version"
|
||||||
rm -rf "$work_dir"
|
rm -rf "$work_dir"
|
||||||
mkdir -p "$work_dir"
|
mkdir -p "$work_dir"
|
||||||
|
|
||||||
# Pack with pnpm, repack with npm (Gitea registry compatibility)
|
# Pack with pnpm
|
||||||
(cd "$pkg_dir" && pnpm pack --pack-destination "$work_dir" >/dev/null)
|
if ! (cd "$pkg_dir" && pnpm pack --pack-destination "$work_dir" 2>&1 | grep -v "^Wrote\|^packing"); then
|
||||||
|
warn " ✗ $name@$version — pack failed"
|
||||||
|
FAILED+=("$name@$version (pack failed)")
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
packed_tgz="$(find "$work_dir" -maxdepth 1 -name '*.tgz' | head -1)"
|
packed_tgz="$(find "$work_dir" -maxdepth 1 -name '*.tgz' | head -1)"
|
||||||
[ -z "$packed_tgz" ] && { warn "Pack failed for $name@$version — skipping"; SKIPPED+=("$name@$version (pack failed)"); return; }
|
if [ -z "$packed_tgz" ]; then
|
||||||
|
warn " ✗ $name@$version — no tarball after pack"
|
||||||
|
FAILED+=("$name@$version (pack failed)")
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Repack with npm for Gitea compatibility
|
||||||
mkdir -p "$work_dir/unpacked"
|
mkdir -p "$work_dir/unpacked"
|
||||||
tar -xzf "$packed_tgz" -C "$work_dir/unpacked"
|
tar -xzf "$packed_tgz" -C "$work_dir/unpacked" 2>/dev/null
|
||||||
(cd "$work_dir/unpacked/package" && npm pack --pack-destination "$work_dir" >/dev/null)
|
if ! (cd "$work_dir/unpacked/package" && npm pack --pack-destination "$work_dir" 2>/dev/null); then
|
||||||
|
warn " ✗ $name@$version — repack failed"
|
||||||
|
FAILED+=("$name@$version (repack failed)")
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
final_tgz="$(find "$work_dir" -maxdepth 1 -name '*.tgz' | sort | tail -1)"
|
final_tgz="$(find "$work_dir" -maxdepth 1 -name '*.tgz' | sort | tail -1)"
|
||||||
[ -z "$final_tgz" ] && { warn "Repack failed for $name@$version — skipping"; SKIPPED+=("$name@$version (repack failed)"); return; }
|
if [ -z "$final_tgz" ]; then
|
||||||
|
warn " ✗ $name@$version — no tarball after repack"
|
||||||
# Write a temp .npmrc with the auth token — inline --// flags are unreliable
|
FAILED+=("$name@$version (repack failed)")
|
||||||
local tmp_npmrc="$work_dir/.npmrc"
|
return
|
||||||
printf '//%s:_authToken=%s\n' "$AUTH_TARGET" "$TOKEN" > "$tmp_npmrc"
|
fi
|
||||||
|
|
||||||
|
# Publish using shared npmrc
|
||||||
|
local publish_log="$work_dir/publish.log"
|
||||||
if npm publish "$final_tgz" \
|
if npm publish "$final_tgz" \
|
||||||
--registry "$REGISTRY_URL" \
|
--registry "$REGISTRY_URL" \
|
||||||
--userconfig "$tmp_npmrc" 2>&1; then
|
--userconfig "$NPMRC_FILE" \
|
||||||
ok "$name@$version published"
|
--silent \
|
||||||
|
2>"$publish_log"; then
|
||||||
|
ok " ✅ $name@$version published"
|
||||||
PUBLISHED+=("$name@$version")
|
PUBLISHED+=("$name@$version")
|
||||||
else
|
else
|
||||||
warn "Publish failed for $name@$version"
|
local err
|
||||||
SKIPPED+=("$name@$version (publish error)")
|
err="$(cat "$publish_log" | grep -v '^npm notice' | head -3)"
|
||||||
|
warn " ✗ $name@$version — publish failed: $err"
|
||||||
|
FAILED+=("$name@$version (publish error)")
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
log "Scanning workspace packages..."
|
log "Scanning workspace packages..."
|
||||||
|
echo ""
|
||||||
for ws_dir in "${WORKSPACE_DIRS[@]}"; do
|
for ws_dir in "${WORKSPACE_DIRS[@]}"; do
|
||||||
[ -d "$REPO_ROOT/$ws_dir" ] || continue
|
[ -d "$REPO_ROOT/$ws_dir" ] || continue
|
||||||
|
log "[$ws_dir]"
|
||||||
while IFS= read -r -d '' pkg_json; do
|
while IFS= read -r -d '' pkg_json; do
|
||||||
publish_package "$(dirname "$pkg_json")"
|
publish_package "$(dirname "$pkg_json")"
|
||||||
done < <(find "$REPO_ROOT/$ws_dir" -mindepth 2 -maxdepth 2 -name package.json -print0 | sort -z)
|
done < <(find "$REPO_ROOT/$ws_dir" -mindepth 2 -maxdepth 2 -name package.json -print0 | sort -z)
|
||||||
done
|
done
|
||||||
|
echo ""
|
||||||
|
|
||||||
# ── Phase 6: Commit and push version bumps ────────────────────────────────────
|
# ── Phase 6: Commit and push ──────────────────────────────────────────────────
|
||||||
|
|
||||||
if [ "$DRY_RUN" = false ]; then
|
if [ "$DRY_RUN" = false ]; then
|
||||||
if ! git diff --quiet HEAD 2>/dev/null || [ -n "$(git status --porcelain)" ]; then
|
# Exclude generated/cache dirs from commits
|
||||||
|
for pattern in "${GIT_EXCLUDE_PATTERNS[@]}"; do
|
||||||
|
git restore --staged "**/$pattern" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
|
||||||
|
# Stage only tracked files + known release artifacts (not caches)
|
||||||
|
git add \
|
||||||
|
"packages/*/package.json" \
|
||||||
|
"services/*/package.json" \
|
||||||
|
"dashboards/*/package.json" \
|
||||||
|
"package.json" \
|
||||||
|
"pnpm-lock.yaml" \
|
||||||
|
".changeset/" \
|
||||||
|
"CHANGELOG.md" 2>/dev/null || true
|
||||||
|
|
||||||
|
if ! git diff --cached --quiet; then
|
||||||
log "Committing version bumps..."
|
log "Committing version bumps..."
|
||||||
git add -A
|
|
||||||
git commit -m "chore: release version bumps [skip ci]"
|
git commit -m "chore: release version bumps [skip ci]"
|
||||||
log "Pushing to origin main..."
|
log "Pushing to origin main..."
|
||||||
git push origin main
|
git push origin main
|
||||||
ok "Pushed to origin/main"
|
ok "Pushed to origin/main"
|
||||||
else
|
else
|
||||||
log "No git changes to commit"
|
log "No version bump changes to commit"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# ── Summary ────────────────────────────────────────────────────────────────────
|
# ── Summary ────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
echo ""
|
TOTAL_PKGS=$(( ${#PUBLISHED[@]} + ${#ALREADY_PUBLISHED[@]} + ${#SKIPPED[@]} + ${#FAILED[@]} ))
|
||||||
|
|
||||||
echo "════════════════════════════════════════"
|
echo "════════════════════════════════════════"
|
||||||
echo " Release Summary"
|
echo " Release Summary (${TOTAL_PKGS} packages scanned)"
|
||||||
echo "════════════════════════════════════════"
|
echo "════════════════════════════════════════"
|
||||||
|
|
||||||
if [ ${#PUBLISHED[@]} -gt 0 ]; then
|
if [ ${#PUBLISHED[@]} -gt 0 ]; then
|
||||||
@ -301,6 +360,12 @@ if [ ${#PUBLISHED[@]} -gt 0 ]; then
|
|||||||
for p in "${PUBLISHED[@]}"; do echo " ✅ $p"; done
|
for p in "${PUBLISHED[@]}"; do echo " ✅ $p"; done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ ${#FAILED[@]} -gt 0 ]; then
|
||||||
|
echo ""
|
||||||
|
echo "Failed (${#FAILED[@]}):"
|
||||||
|
for p in "${FAILED[@]}"; do echo " ❌ $p"; done
|
||||||
|
fi
|
||||||
|
|
||||||
if [ ${#ALREADY_PUBLISHED[@]} -gt 0 ]; then
|
if [ ${#ALREADY_PUBLISHED[@]} -gt 0 ]; then
|
||||||
echo ""
|
echo ""
|
||||||
echo "Already up-to-date (${#ALREADY_PUBLISHED[@]}):"
|
echo "Already up-to-date (${#ALREADY_PUBLISHED[@]}):"
|
||||||
@ -315,4 +380,11 @@ fi
|
|||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
[ "$DRY_RUN" = true ] && echo " (dry-run — no changes made)"
|
[ "$DRY_RUN" = true ] && echo " (dry-run — no changes made)"
|
||||||
|
|
||||||
|
# Exit non-zero if any publishes failed
|
||||||
|
if [ ${#FAILED[@]} -gt 0 ]; then
|
||||||
|
echo " ⚠️ ${#FAILED[@]} package(s) failed to publish — see above"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
echo "════════════════════════════════════════"
|
echo "════════════════════════════════════════"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user