Railway Deployment Scripts

Documentation for Deployment

Railway Smart Deploy CLI

A smart deployment tool for Railway that handles git branches, work-in-progress, and automated merging without disrupting development work.

Overview

This CLI automates the process of deploying backend APIs to Railway using git branch-based deployments. It safely:

  1. Handles uncommitted changes (commit or stash)
  2. Merges your session branch INTO deploy branches (preserving deploy-specific commits)
  3. Pushes to trigger Railway builds
  4. Returns you to your original working state

Quick Start

# Interactive deployment (recommended)
yarn deploy

# Preview what will happen without executing
yarn deploy --dry-run

# Check current deployment status
yarn deploy --status

# Deploy specific APIs
yarn deploy --apis api,ai-api

# Deploy all APIs non-interactively
yarn deploy:all

Available Commands

Command Description
yarn deploy Interactive deployment with prompts
yarn deploy --dry-run Preview operations without executing
yarn deploy --status Show current branch/commit status
yarn deploy:api Deploy only backend-api
yarn deploy:ai-api Deploy only backend-ai-api
yarn deploy:docs-api Deploy only backend-docs-api
yarn deploy:vitto-api Deploy only backend-vitto-api
yarn deploy:sandbox-orchestrator Deploy sandbox-orchestrator (optional; see deployment/sandbox-orchestrator/RAILWAY.md)
yarn deploy:all Deploy all APIs at once
yarn deploy --help Show help and available APIs

CLI Flags

Flag Description
--dry-run Preview all operations without executing
--skip-health-check Don't wait and verify health endpoints after push
--no-interactive Use defaults (all APIs, include work)
--apis api,ai-api Pre-select specific APIs (comma-separated)
--include-work Pre-select to commit uncommitted changes
--stash-work Pre-select to stash uncommitted changes
--status Show deployment status and exit
--help Show help and exit

Deployment Targets

API Branch Health Check
api deploy/api /api/health
ai-api deploy/ai-api /ai-api/health
docs-api deploy/docs-api /docs-api/health
vitto-api deploy/vitto-api /vitto-api/health
sandbox-orchestrator deploy/sandbox-orchestrator /health

How It Works

Work-in-Progress Handling

When you have uncommitted changes, you can choose:

  1. Include Work - Commits your changes before deploying
  2. Stash Work - Temporarily stashes changes, deploys, then restores them

Merge Strategy (One-Way Flow)

The CLI merges your session branch INTO the deploy branches, not the other way around. This is a one-way merge by design.

┌─────────────────────────────────────────────────────────────┐
│  Session Branch (editor2-session-62)                        │
│  ├── All your development work                              │
│  └── railway.toml → default config                          │
└─────────────────────────────────────────────────────────────┘
            │
            │ merged INTO (one-way)
            ▼
┌─────────────────────────────────────────────────────────────┐
│  deploy/api         → has session code + backend-api config │
│  deploy/ai-api      → has session code + ai-api config      │
│  deploy/docs-api    → has session code + docs-api config    │
└─────────────────────────────────────────────────────────────┘

Branch Relationship (Important!)

Branch Contains Purpose
Session branch Development work Source of truth for code
deploy/api Session + api config Railway deployment target
deploy/ai-api Session + ai-api config Railway deployment target
deploy/docs-api Session + docs-api config Railway deployment target

Key Points:

Why No Merge Back?

The CLI intentionally does NOT merge deploy branches back to session because:

  1. Each deploy branch has different railway.toml - Merging back would cause conflicts
  2. Session is source of truth - It already has all the actual code
  3. Deploy branches are deployment targets - They're meant to diverge slightly with deploy-specific configs
  4. Cleaner git history - Avoids unnecessary merge commits in your development branch

After deployment, your session branch appears "behind" the deploy branches by 1 commit (the merge commit). This is correct and expected - you're not missing any actual code.

Safety Features

Stability Features (v2)

Workflow Diagram

┌─────────────────────────────────────────────────────────┐
│                      yarn deploy                         │
├─────────────────────────────────────────────────────────┤
│  1. Pre-Flight Checks                                   │
│     ├── Check for stale git locks                       │
│     ├── git fetch origin                                │
│     ├── Verify branches are in sync                     │
│     └── Check for uncommitted changes                   │
├─────────────────────────────────────────────────────────┤
│  2. API Selection (interactive or via --apis)           │
├─────────────────────────────────────────────────────────┤
│  3. Merge Feasibility Check                             │
│     └── Abort if conflicts detected                     │
├─────────────────────────────────────────────────────────┤
│  4. Handle Work-in-Progress                             │
│     ├── [Include] → Commit changes                      │
│     └── [Stash] → Create named stash                    │
├─────────────────────────────────────────────────────────┤
│  5. For Each Selected API:                              │
│     ├── git checkout deploy/[api]                       │
│     ├── git merge ${sessionBranch}                      │
│     └── git push origin deploy/[api]                    │
├─────────────────────────────────────────────────────────┤
│  6. Restore State                                       │
│     ├── Return to original branch                       │
│     └── Pop stash if used                               │
├─────────────────────────────────────────────────────────┤
│  7. Health Check (unless --skip-health-check)           │
│     ├── Wait 120s for Railway build                     │
│     └── Verify health endpoints                         │
└─────────────────────────────────────────────────────────┘

Troubleshooting

"Git lock exists" or "index.lock" error

The CLI detected a .git/index.lock file. This happens when:

Automatic handling: The CLI will:

  1. Check if the lock is stale (older than 60 seconds)
  2. Remove stale locks automatically
  3. Retry commands if locks appear during execution

Manual fix (if auto-cleanup fails):

rm -f .git/index.lock

"Merge conflicts detected"

The CLI detected that merging would cause conflicts. Options:

  1. Manually merge the branches and resolve conflicts
  2. Check which files conflict: git merge-tree $(git merge-base deploy/api HEAD) deploy/api HEAD

"Branch out of sync with remote"

Your local deploy branch differs from origin. Run:

git fetch origin
git checkout deploy/api
git reset --hard origin/deploy/api

Rollback after failure

If deployment fails, the CLI automatically rolls back. If you need manual recovery:

  1. Check for .deploy-rollback-state.json in project root
  2. Run yarn deploy - it will detect and offer rollback options

Health check fails

This means deployment succeeded but the API isn't responding. Check:

  1. Railway dashboard for build logs
  2. Wait longer (builds can take 2-5 minutes)
  3. Check API logs for startup errors

File Structure

tools/scripts/deployment/
├── railway-deploy-cli.js    # Main CLI entry point
├── lib/
│   ├── deployment-config.js # API configurations
│   ├── git-operations.js    # Safe git commands
│   ├── branch-manager.js    # Branch operations
│   └── state-manager.js     # Rollback state
└── README.md               # This file

Deployment History

Deployments are logged to deployment/deploy-history.json. View recent deployments:

cat deployment/deploy-history.json | head -50

Related Documentation