11#! /bin/bash
2- # Automated NPM Deployment Script
3- # Usage: ./scripts/deploy.sh [patch|minor|major|version]
2+ # StackMemory Deploy Script — NPM + Railway
3+ #
4+ # Usage:
5+ # ./scripts/deploy.sh [target] [version-type]
6+ #
7+ # Targets:
8+ # npm — Publish to NPM only (default)
9+ # railway — Deploy to Railway only
10+ # all — NPM publish + Railway deploy
11+ #
12+ # Version types (npm target only):
13+ # patch — Bump patch version (default)
14+ # minor — Bump minor version
15+ # major — Bump major version
16+ # x.y.z — Set explicit version
17+ #
18+ # Examples:
19+ # ./scripts/deploy.sh # NPM patch release
20+ # ./scripts/deploy.sh npm minor # NPM minor release
21+ # ./scripts/deploy.sh railway # Railway deploy only
22+ # ./scripts/deploy.sh all minor # NPM minor + Railway
23+ #
24+ # Environment:
25+ # DRY_RUN=true — Skip destructive steps (push, publish, deploy)
26+ # SKIP_TESTS=true — Skip quality checks (NOT recommended)
427
528set -e
629
7- # Color codes
30+ # ── Color codes ──────────────────────────────────
831RED=' \033[0;31m'
932GREEN=' \033[0;32m'
1033YELLOW=' \033[1;33m'
11- NC=' \033[0m' # No Color
34+ CYAN=' \033[0;36m'
35+ NC=' \033[0m'
1236
13- # Configuration
14- VERSION_TYPE=${1:- patch}
37+ # ── Configuration ────────────────────────────────
38+ TARGET=${1:- npm}
39+ VERSION_TYPE=${2:- patch}
1540DRY_RUN=${DRY_RUN:- false}
41+ SKIP_TESTS=${SKIP_TESTS:- false}
42+ RAILWAY_SERVICE=${RAILWAY_SERVICE:- stackmemory}
1643
17- echo -e " ${GREEN} 🚀 Starting deployment process...${NC} "
44+ # ── Helpers ──────────────────────────────────────
45+ info () { echo -e " ${CYAN} [info]${NC} $1 " ; }
46+ ok () { echo -e " ${GREEN} [ok]${NC} $1 " ; }
47+ warn () { echo -e " ${YELLOW} [warn]${NC} $1 " ; }
48+ fail () { echo -e " ${RED} [fail]${NC} $1 " ; exit 1; }
1849
19- # Check if we're on main branch
50+ prompt_yn () {
51+ local msg=" $1 "
52+ read -p " $( echo -e " ${YELLOW}${msg} [y/N]:${NC} " ) " answer
53+ [[ " $answer " =~ ^[Yy]$ ]]
54+ }
55+
56+ # ── Validate target ─────────────────────────────
57+ case " $TARGET " in
58+ npm|railway|all) ;;
59+ * )
60+ echo " Usage: $0 [npm|railway|all] [patch|minor|major|x.y.z]"
61+ echo " "
62+ echo " Options:"
63+ echo " 1) npm — Publish to NPM (default)"
64+ echo " 2) railway — Deploy to Railway"
65+ echo " 3) all — Both NPM + Railway"
66+ exit 1
67+ ;;
68+ esac
69+
70+ echo " "
71+ echo -e " ${GREEN} ======================================${NC} "
72+ echo -e " ${GREEN} StackMemory Deploy${NC} "
73+ echo -e " ${GREEN} ======================================${NC} "
74+ echo " "
75+ info " Target: $TARGET "
76+ info " Version: $VERSION_TYPE "
77+ info " Dry run: $DRY_RUN "
78+ echo " "
79+
80+ # ── Pre-flight checks ───────────────────────────
81+
82+ # 1. Must be on main
2083CURRENT_BRANCH=$( git branch --show-current)
2184if [ " $CURRENT_BRANCH " != " main" ]; then
22- echo -e " ${RED} ❌ You must be on main branch to deploy${NC} "
23- echo " Current branch: $CURRENT_BRANCH "
24- exit 1
85+ fail " Must be on main branch (currently: $CURRENT_BRANCH )"
2586fi
87+ ok " On main branch"
2688
27- # Check for uncommitted changes
89+ # 2. Clean working tree
2890if [ -n " $( git status --porcelain) " ]; then
29- echo -e " ${RED} ❌ You have uncommitted changes${NC} "
30- git status --short
31- exit 1
91+ fail " Uncommitted changes detected. Commit or stash first."
3292fi
93+ ok " Working tree clean"
3394
34- # Pull latest changes
35- echo -e " ${YELLOW} 📥 Pulling latest changes...${NC} "
36- git pull origin main
95+ # 3. Pull latest
96+ info " Pulling latest from origin/main..."
97+ git pull origin main --rebase
98+ ok " Up to date with origin/main"
3799
38- # Run quality checks
39- echo -e " ${YELLOW} 🧪 Running quality checks...${NC} "
40- npm run lint
41- npm run test:run
42- npm run build
43-
44- # Bump version
45- echo -e " ${YELLOW} 📦 Bumping version (${VERSION_TYPE} )...${NC} "
46- if [ " $VERSION_TYPE " = " patch" ] || [ " $VERSION_TYPE " = " minor" ] || [ " $VERSION_TYPE " = " major" ]; then
47- NEW_VERSION=$( npm version $VERSION_TYPE --no-git-tag-version)
100+ # ── Quality checks ───────────────────────────────
101+ if [ " $SKIP_TESTS " = " true" ]; then
102+ warn " Skipping quality checks (SKIP_TESTS=true)"
48103else
49- NEW_VERSION=$VERSION_TYPE
50- npm version $VERSION_TYPE --no-git-tag-version
104+ info " Running lint..."
105+ npm run lint
106+ ok " Lint passed"
107+
108+ info " Running tests..."
109+ npm run test:run
110+ ok " Tests passed"
111+
112+ info " Building..."
113+ npm run build
114+ ok " Build passed"
51115fi
52116
53- # Update CLI version constant
54- echo -e " ${YELLOW} ✏️ Updating CLI version...${NC} "
55- sed -i.bak " s/const VERSION = '[^']*'/const VERSION = '${NEW_VERSION# v} '/" src/cli/index.ts
56- rm src/cli/index.ts.bak
117+ # ══════════════════════════════════════════════════
118+ # NPM PUBLISH
119+ # ══════════════════════════════════════════════════
120+ deploy_npm () {
121+ echo " "
122+ echo -e " ${GREEN} ── NPM Publish ────────────────────${NC} "
123+
124+ # Bump version
125+ info " Bumping version ($VERSION_TYPE )..."
126+ if [ " $VERSION_TYPE " = " patch" ] || [ " $VERSION_TYPE " = " minor" ] || [ " $VERSION_TYPE " = " major" ]; then
127+ NEW_VERSION=$( npm version $VERSION_TYPE --no-git-tag-version)
128+ else
129+ NEW_VERSION=" v$VERSION_TYPE "
130+ npm version " $VERSION_TYPE " --no-git-tag-version
131+ fi
132+ ok " Version: $NEW_VERSION "
57133
58- # Build with new version
59- echo -e " ${YELLOW} 🔨 Building with new version...${NC} "
60- npm run build
134+ # Update CLI version constant
135+ info " Updating CLI version constant..."
136+ sed -i.bak " s/const VERSION = '[^']*'/const VERSION = '${NEW_VERSION# v} '/" src/cli/index.ts
137+ rm -f src/cli/index.ts.bak
138+ ok " CLI version updated"
61139
62- # Commit version changes
63- echo -e " ${YELLOW} 📝 Committing version changes...${NC} "
64- git add -A
65- git commit -m " chore: Release ${NEW_VERSION}
140+ # Rebuild with new version
141+ info " Rebuilding with $NEW_VERSION ..."
142+ npm run build
143+ ok " Build complete"
144+
145+ if [ " $DRY_RUN " = " true" ]; then
146+ warn " DRY RUN — skipping commit, tag, push, publish"
147+ return
148+ fi
149+
150+ # Commit + tag + push
151+ info " Committing version bump..."
152+ git add package.json package-lock.json src/cli/index.ts
153+ git commit -m " chore: bump version to ${NEW_VERSION}
66154
67155- Bump version to ${NEW_VERSION}
68- - Update CLI version constant
69- - Update package-lock.json"
156+ - Update CLI version constant"
157+
158+ info " Creating tag $NEW_VERSION ..."
159+ git tag " $NEW_VERSION "
160+
161+ info " Pushing to origin..."
162+ git push origin main
163+ git push origin " $NEW_VERSION "
164+
165+ ok " Pushed $NEW_VERSION to GitHub"
166+ echo " "
167+ info " GitHub Actions will auto-publish to NPM on tag push."
168+ info " Monitor: https://github.com/stackmemoryai/stackmemory/actions"
169+ echo " "
170+ echo " Manual publish (if Actions not configured):"
171+ echo " npm publish --access public"
172+ echo " "
173+ ok " NPM deploy complete"
174+ }
175+
176+ # ══════════════════════════════════════════════════
177+ # RAILWAY DEPLOY
178+ # ══════════════════════════════════════════════════
179+ deploy_railway () {
180+ echo " "
181+ echo -e " ${GREEN} ── Railway Deploy ─────────────────${NC} "
182+
183+ # Check Railway CLI
184+ if ! command -v railway & > /dev/null; then
185+ fail " Railway CLI not installed. Run: npm i -g @railway/cli"
186+ fi
187+ ok " Railway CLI found"
188+
189+ # Check Railway auth
190+ if ! railway whoami & > /dev/null 2>&1 ; then
191+ fail " Not logged in to Railway. Run: railway login"
192+ fi
193+ RAILWAY_USER=$( railway whoami 2> /dev/null || echo " unknown" )
194+ ok " Logged in as: $RAILWAY_USER "
70195
71- # Create and push tag
72- echo -e " ${YELLOW} 🏷️ Creating tag...${NC} "
73- git tag ${NEW_VERSION}
196+ # Check Railway project link
197+ if ! railway status & > /dev/null 2>&1 ; then
198+ warn " No Railway project linked."
199+ echo " "
200+ echo " Options:"
201+ echo " 1) railway link — Link existing project"
202+ echo " 2) railway init — Create new project"
203+ echo " "
204+ fail " Link a Railway project first, then re-run."
205+ fi
206+ ok " Railway project linked"
74207
75- # Push changes and tag
76- echo -e " ${YELLOW} 📤 Pushing to GitHub...${NC} "
77- git push origin main
78- git push origin ${NEW_VERSION}
208+ # Confirm
209+ echo " "
210+ info " Deploying to Railway..."
211+ if [ " $DRY_RUN " = " true" ]; then
212+ warn " DRY RUN — skipping railway up"
213+ return
214+ fi
79215
80- echo -e " ${GREEN} ✅ Deployment preparation complete!${NC} "
81- echo -e " ${GREEN} 📦 Version ${NEW_VERSION} has been tagged and pushed${NC} "
216+ if ! prompt_yn " Deploy to Railway production?" ; then
217+ info " Aborted."
218+ return
219+ fi
220+
221+ # Deploy
222+ railway up --detach
223+ ok " Railway deploy initiated"
224+
225+ echo " "
226+ info " Monitor deployment in Railway dashboard."
227+ echo " "
228+
229+ # Post-deploy health check
230+ RAILWAY_URL=${RAILWAY_URL:- " " }
231+ if [ -n " $RAILWAY_URL " ]; then
232+ info " Running health check against $RAILWAY_URL ..."
233+ sleep 10
234+ HTTP_STATUS=$( curl -s -o /dev/null -w " %{http_code}" " $RAILWAY_URL /health" || echo " 000" )
235+ if [ " $HTTP_STATUS " = " 200" ]; then
236+ ok " Health check passed (HTTP 200)"
237+ else
238+ warn " Health check returned HTTP $HTTP_STATUS — check logs"
239+ fi
240+ else
241+ info " Set RAILWAY_URL to enable post-deploy health check."
242+ fi
243+
244+ ok " Railway deploy complete"
245+ }
246+
247+ # ── Execute ──────────────────────────────────────
248+ case " $TARGET " in
249+ npm)
250+ deploy_npm
251+ ;;
252+ railway)
253+ deploy_railway
254+ ;;
255+ all)
256+ deploy_npm
257+ deploy_railway
258+ ;;
259+ esac
260+
261+ # ── Summary ──────────────────────────────────────
262+ echo " "
263+ echo -e " ${GREEN} ======================================${NC} "
264+ echo -e " ${GREEN} Deploy complete${NC} "
265+ echo -e " ${GREEN} ======================================${NC} "
82266echo " "
83- echo -e " ${YELLOW} Next steps:${NC} "
84- echo " 1. GitHub Actions will automatically publish to NPM"
85- echo " 2. Monitor the Actions tab for progress"
86- echo " 3. Or manually publish with: npm publish"
267+ echo " Next steps:"
268+ echo " 1) Verify NPM: npm info @stackmemoryai/stackmemory"
269+ echo " 2) Verify Railway: curl \$ RAILWAY_URL/health"
270+ echo " 3) Test install: npm i -g @stackmemoryai/stackmemory@latest"
271+ echo " 4) Update CHANGELOG.md if not auto-generated"
87272echo " "
88- echo -e " ${GREEN} GitHub Actions URL:${NC} "
89- echo " https://github.com/stackmemoryai/stackmemory/actions"
0 commit comments