Skip to content

Staging Direct-Edit Workflow

Fast iteration loop for staging-only changes. Bypasses the 5-minute CI/CD deploy when you need to test a fix immediately, without giving up the safety of git history and PR review.

Staging only — never run on prod

dev-deploy.sh has a hard guard against the prod IP (89.116.31.109) but treat the workflow itself as staging-only by policy. Prod stays feature-branch → PR → main → CI/CD.

When to use this

Use direct-edit when:

  • You want to test a tiny code change in seconds, not minutes
  • You're debugging something that needs many small iterations
  • You're certain the change is staging-safe (e.g., dialplan tweak, log message, config tweak, behaviour flag)

Stick with the normal PR-first flow when:

  • The change touches the auth flow, billing, or anything irreversible
  • You need code review before deploy
  • You're going to leave staging running unattended for >24h after the edit (CI/CD redeploy will eventually overwrite untracked drift)

Setup (one-time, already done)

The staging VPS at 94.136.188.221 has:

Path Purpose
/root/astradial-platform/ Git-tracked clone of the monorepo (staging branch)
/root/astradial-platform/scripts/dev-deploy.sh Build + rsync + PM2 restart
/root/.ssh/github_deploy Ed25519 deploy key with write access to the repo
/root/.ssh/config Routes git@github.com through that key

The deploy key is registered in github.com/astradial/astradial-platform → Settings → Deploy keys. Title: staging-vps. Write access enabled.

The fast loop

ssh root@94.136.188.221
cd /root/astradial-platform

# 1. pull latest staging so you start clean
git pull origin staging

# 2. branch + edit
git checkout -b fix/whatever
vim api/src/server.js   # or whichever app

# 3. push the edit to /opt/<app> + restart PM2
./scripts/dev-deploy.sh api          # api only — ~5s
./scripts/dev-deploy.sh editor       # editor — ~3-4 min (Next.js build)
./scripts/dev-deploy.sh workflow     # workflow-engine — ~5s
./scripts/dev-deploy.sh pipecat      # pipecat-flow — ~5s
./scripts/dev-deploy.sh all          # all four, in order

# 4. test in browser / make a call / curl an endpoint

# 5. once the change works, commit + push + open PR
git add -p
git commit -m "fix(api): ..."
git push -u origin fix/whatever
gh pr create --base staging --title "..." --body "..."

# 6. squash-merge (CI/CD will redeploy the same code — harmless safety net)
gh pr merge --squash --delete-branch

What dev-deploy.sh does

For every app it rsync -a --deletes the source tree to /opt/<app>/, always excluding the server-side files that must never be overwritten:

  • .env (per-app secrets)
  • node_modules/, .venv/, __pycache__/
  • firebase-sa-key.json, google-credentials.json
  • .bak* and .backup* files (local snapshots)
  • .git/

Then it runs the appropriate build step (Next.js for editor, nothing for api/ workflow/pipecat) and pm2 restart <name> --update-env to pick up env changes.

App Target dir Build step PM2 name
api /opt/astrapbx none astrapbx
editor /opt/pipecat-flow-editor npm ci && npm run build editor
workflow /opt/workflow-engine none workflow-engine
pipecat /opt/pipecat-flow none pipecat-flow (if registered)

Drift checklist before you start

CI/CD's rsync --delete will silently revert anything in /opt/<app>/ that isn't in git. Before iterating, run:

cd /root/astradial-platform
git pull origin staging
diff -rq api /opt/astrapbx | grep -vE '\.env|node_modules|\.bak|\.backup|firebase-sa-key'
diff -rq editor /opt/pipecat-flow-editor | grep -vE '\.env|node_modules|\.next|\.bak|\.backup'
diff -rq workflow-engine /opt/workflow-engine | grep -vE '\.env|node_modules|\.bak|\.backup|package-lock'
diff -rq pipecat-flow /opt/pipecat-flow | grep -vE '\.env|\.venv|__pycache__|\.bak|\.backup|google-credentials|egg-info'

If anything shows up that isn't an env/lockfile/cache file, that's a server-only change someone made by hand. Commit it back to git (or delete it) before you start editing — otherwise your next dev-deploy plus the eventual CI/CD run will create confusion about what's actually deployed.

Known drift right now

  • pipecat-flow/uv.lock/opt/pipecat-flow/uv.lock uses aiomysql (revision 3); the repo still has aiosqlite (revision 2). Whoever switched the lib never committed it. Fix this in a follow-up PR by copying /opt/pipecat-flow/uv.lock back into the repo and pushing.

Interaction with CI/CD

Every push to staging still triggers Deploy API to staging and Deploy Editor to staging workflows (and the others). They run on the self-hosted runner that lives on the same VPS, build, and rsync into /opt/<app> — so they will overwrite /opt/<app> with whatever's in the pushed git ref.

This is intentional: CI/CD acts as a safety net that ensures /opt/<app> always matches the git tip of staging. As long as you commit + push every direct edit before the next CI/CD run kicks off, the runner just rsyncs the same code you already deployed locally — wasteful but harmless.

If you forget to commit and let CI/CD run, your direct edit gets reverted. Always git status before walking away.

Rolling back

If a direct edit breaks staging:

cd /root/astradial-platform
git checkout staging                  # back to the latest pushed staging
git pull origin staging
./scripts/dev-deploy.sh all           # redeploy clean

Or simply re-run the most recent successful CI/CD workflow from the Actions tab.