From cc0bc6c8aacd73752d499a70e04c7bf17d2c0443 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E6=A9=98?= Date: Mon, 11 May 2026 12:21:07 +0000 Subject: [PATCH] chore: add release.sh script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Automates: version bump → workspace:* replace → npm publish (topo order) → restore workspace:* → dashboard build+deploy → git commit+push. Env: GITEA_TOKEN, CLOUDFLARE_API_TOKEN (from cfg). 小橘 --- scripts/release.sh | 190 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100755 scripts/release.sh diff --git a/scripts/release.sh b/scripts/release.sh new file mode 100755 index 0000000..f0839a3 --- /dev/null +++ b/scripts/release.sh @@ -0,0 +1,190 @@ +#!/usr/bin/env bash +# release.sh — Publish all @uncaged/workflow-* packages + deploy dashboard +# +# Usage: +# ./scripts/release.sh # e.g. ./scripts/release.sh 0.4.0 +# ./scripts/release.sh patch # auto-bump patch (0.3.1 → 0.3.2) +# ./scripts/release.sh minor # auto-bump minor (0.3.1 → 0.4.0) +# +# Required env (via `cfg` or export): +# GITEA_TOKEN — Gitea npm registry auth +# CLOUDFLARE_API_TOKEN — Cloudflare Pages deploy +# +# What it does: +# 1. Bump version in all non-private package.json +# 2. Replace workspace:* with concrete version for publishing +# 3. npm publish in dependency order to Gitea registry +# 4. Restore workspace:* for local dev +# 5. Build & deploy dashboard to Cloudflare Pages +# 6. Git commit & push +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +cd "$REPO_ROOT" + +# ─── Env check ─────────────────────────────────────────────────────────────── +GITEA_TOKEN="${GITEA_TOKEN:?GITEA_TOKEN is required}" +CLOUDFLARE_API_TOKEN="${CLOUDFLARE_API_TOKEN:?CLOUDFLARE_API_TOKEN is required}" + +GITEA_NPM_REGISTRY="https://git.shazhou.work/api/packages/uncaged/npm/" + +# ─── Version resolution ───────────────────────────────────────────────────── +current_version() { + node -e "console.log(require('./packages/workflow-protocol/package.json').version)" +} + +bump_version() { + local cur="$1" kind="$2" + IFS='.' read -r major minor patch <<< "$cur" + case "$kind" in + patch) echo "${major}.${minor}.$((patch + 1))" ;; + minor) echo "${major}.$((minor + 1)).0" ;; + major) echo "$((major + 1)).0.0" ;; + *) echo "$kind" ;; # explicit version + esac +} + +CURRENT=$(current_version) +VERSION_ARG="${1:?Usage: release.sh }" +VERSION=$(bump_version "$CURRENT" "$VERSION_ARG") + +echo "📦 Release: $CURRENT → $VERSION" + +# ─── Publish order (topological) ───────────────────────────────────────────── +PUBLISH_ORDER=( + workflow-protocol + workflow-util + workflow-cas + workflow-runtime + workflow-reactor + workflow-register + workflow-execute + cli-workflow + workflow-util-agent + workflow-agent-cursor + workflow-agent-hermes + workflow-agent-llm + workflow-template-develop + workflow-template-solve-issue +) + +# ─── Step 1: Bump version ──────────────────────────────────────────────────── +echo "🔢 Bumping versions to $VERSION..." +for dir in packages/*/; do + pkg="$dir/package.json" + [[ -f "$pkg" ]] || continue + is_private=$(node -e "console.log(require('./$pkg').private || false)") + [[ "$is_private" == "true" ]] && continue + # Replace version + node -e " + const fs = require('fs'); + const pkg = JSON.parse(fs.readFileSync('$pkg', 'utf8')); + pkg.version = '$VERSION'; + fs.writeFileSync('$pkg', JSON.stringify(pkg, null, 2) + '\n'); + " +done + +# ─── Step 2: Replace workspace:* ───────────────────────────────────────────── +echo "🔗 Replacing workspace:* with $VERSION..." +for dir in packages/*/; do + pkg="$dir/package.json" + [[ -f "$pkg" ]] || continue + node -e " + const fs = require('fs'); + const pkg = JSON.parse(fs.readFileSync('$pkg', 'utf8')); + let changed = false; + for (const key of ['dependencies', 'peerDependencies', 'devDependencies']) { + const deps = pkg[key]; + if (!deps) continue; + for (const [name, ver] of Object.entries(deps)) { + if (name.startsWith('@uncaged/') && ver === 'workspace:*') { + deps[name] = '$VERSION'; + changed = true; + } + } + } + if (changed) fs.writeFileSync('$pkg', JSON.stringify(pkg, null, 2) + '\n'); + " +done + +# ─── Step 3: Build ─────────────────────────────────────────────────────────── +echo "🔨 Building..." +npm run build + +# ─── Step 4: Publish ───────────────────────────────────────────────────────── +echo "🚀 Publishing to Gitea npm registry..." + +# Write temporary .npmrc for publish auth +NPMRC="$REPO_ROOT/.npmrc" +cat > "$NPMRC" <&1); then + echo " ✅ @uncaged/$pkg_dir@$VERSION" + else + echo " ❌ @uncaged/$pkg_dir failed" + FAIL=1 + fi +done + +# ─── Step 5: Restore workspace:* ───────────────────────────────────────────── +echo "🔄 Restoring workspace:* for local dev..." +for dir in packages/*/; do + pkg="$dir/package.json" + [[ -f "$pkg" ]] || continue + node -e " + const fs = require('fs'); + const pkg = JSON.parse(fs.readFileSync('$pkg', 'utf8')); + let changed = false; + for (const key of ['dependencies', 'peerDependencies', 'devDependencies']) { + const deps = pkg[key]; + if (!deps) continue; + for (const [name, ver] of Object.entries(deps)) { + if (name.startsWith('@uncaged/') && ver === '$VERSION') { + deps[name] = 'workspace:*'; + changed = true; + } + } + } + if (changed) fs.writeFileSync('$pkg', JSON.stringify(pkg, null, 2) + '\n'); + " +done + +# ─── Step 6: Deploy dashboard ──────────────────────────────────────────────── +echo "🌐 Building & deploying dashboard..." +DASHBOARD_DIR="packages/workflow-dashboard" +if [[ -d "$DASHBOARD_DIR" ]]; then + (cd "$DASHBOARD_DIR" && npm run build) + # wrangler is only available via npx in the gateway package (has it as devDep) + (cd packages/workflow-gateway && npx wrangler pages deploy \ + "../workflow-dashboard/dist" \ + --project-name workflow-dashboard 2>&1) && \ + echo " ✅ Dashboard deployed" || \ + echo " ⚠️ Dashboard deploy failed (non-fatal)" +fi + +# ─── Step 7: Git commit & push ─────────────────────────────────────────────── +echo "📝 Committing..." +git add -A +git commit -m "chore: release v${VERSION} + +Published ${#PUBLISH_ORDER[@]} packages to Gitea npm registry. +Dashboard deployed to Cloudflare Pages. + +小橘 " +git push + +# ─── Done ──────────────────────────────────────────────────────────────────── +if [[ "$FAIL" -eq 0 ]]; then + echo "" + echo "✅ Released v${VERSION} — ${#PUBLISH_ORDER[@]} packages published" +else + echo "" + echo "⚠️ Released v${VERSION} with some failures — check output above" +fi