Skip to content

ci: apply Cloud VM migrations on every main push that adds one - #13402

Open
austinywang wants to merge 3 commits into
mainfrom
migrate-on-main-push
Open

austinywang wants to merge 3 commits into
mainfrom
migrate-on-main-push

Conversation

@austinywang

@austinywang austinywang commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Since the 2026-09-21 03:03 PT production deploy, every Cloud New Machine (sheet and cmux vm new) fails in about 2 s with "The Cloud VM request failed". Production logs show POST /api/vm answering 503 vm_cloud_state_unavailable from beginCreate: #13329 made the create transaction insert into cloud_runtimes, and that table's migration (20260921030000_hive_runtime_registry) was never applied to production. The last production migration run was 2026-09-17T04:08Z; five migrations merged after it were pending (vm_coderouter_scope, push_e2e_keys, push_token_revocation, push_token_revocation_installation, hive_runtime_registry). The same logs show GET /api/device-tokens failing with column "installation_id" does not exist since #12924 shipped, and staging had the same relation errors.

Root cause: cloud-vm-migrate.yml only runs on manual dispatch, while Vercel deploys main on every push, so any PR that adds a migration ships code ahead of its schema until someone remembers to dispatch the workflow.

Change

  • cloud-vm-migrate.yml also triggers on a push to main that touches web/db/migrations/**. A push applies staging first, then the production job runs under the existing cloud-vm-production environment, whose three required reviewers must approve it, so production keeps a human decision, one click after the merge. Manual dispatch is unchanged; the checkout ref for a push is the pushed commit.
  • web/AGENTS.md (the database notes on main) records the rule so a PR that adds a migration is not treated as live until that run is approved and green.
  • tests/test_cloud_vm_migrate_workflow.py pins the trigger, the staging-then-production order, and that a dispatched staging-only run still stops before production. It lands as its own commit first (red), then the workflow change (green).

Remaining gap

A push still deploys and migrates concurrently, so a migration-dependent route can fail for the minutes between the deploy going live and the production job being approved. Closing that fully means running the migration inside the deploy (before next build) or gating the deploy on the run, which is a bigger change for the owner of the Vercel setup to decide.

Verified

  • Staging migration applied through the existing workflow (run 35591009743, staging PlanetScale migration applied); the production run is dispatched and waiting for reviewer approval.
  • python3 -m unittest tests/test_cloud_vm_migrate_workflow.py fails on the old workflow and passes on the new one; the YAML parses.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Database migrations pushed to main now run automatically when migration files change.
    • Migrations are applied to staging first, then promoted to production after required approval.
  • Documentation

    • Updated database provider guidance to explain the automatic migration workflow, staging-first process, and production approval requirement.
  • Tests

    • Added coverage to verify migration triggers, job ordering, environment protections, and staging-only dispatch behavior.

austinywang and others added 2 commits September 21, 2026 03:54
Regression pin only; it fails until the next commit. A migration merged to
main deployed to Vercel immediately but was only applied to the databases by
a manual dispatch, so production ran code against a schema without the
tables it needed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Vercel deploys main on each push, but cloud-vm-migrate.yml only ran when
someone dispatched it, and the last production run was 2026-09-17. Five
migrations merged since then were never applied: on 2026-09-21 the deploy
that made beginCreate insert into cloud_runtimes (#13329) turned every
Cloud create into a 503 vm_cloud_state_unavailable, and device-token reads
had been failing on missing columns since #12924 shipped.

The workflow now also triggers on a push to main that touches
web/db/migrations/**. A push applies staging first; the production job keeps
its cloud-vm-production environment, whose required reviewers must approve
the run, so production still gets a human decision, now one click after the
merge instead of a dispatch someone has to remember. Manual dispatch is
unchanged. CLAUDE.md records the rule.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@coderabbitai

coderabbitai Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

Review Change StackReview Change Stack

Understand this PR’s impact

Explore downstream dependencies and potential security impact with Blast Radius.

View blast radius →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: manaflow-ai/cmux/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 42904060-4e49-4680-9a62-55169ec9b771

📥 Commits

Reviewing files that changed from the base of the PR and between 0ddc6f4 and a7ba944.

📒 Files selected for processing (3)
  • .github/workflows/cloud-vm-migrate.yml
  • tests/test_cloud_vm_migrate_workflow.py
  • web/AGENTS.md

Included review availability: Your plan provides up to 10 included reviews per hour; 1 remains after this review.


📝 Walkthrough

Walkthrough

The migration workflow now runs for migration changes pushed to main, applies staging before production, and uses the pushed commit for push events. New tests validate trigger and job conditions. Documentation describes the updated execution path.

Changes

Cloud VM migration automation

Layer / File(s) Summary
Push-triggered migration execution
.github/workflows/cloud-vm-migrate.yml, web/AGENTS.md
The workflow triggers for migration changes on main, checks out the relevant commit, runs staging, and gates production with required reviewers. The documentation describes this sequence.
Workflow behavior validation
tests/test_cloud_vm_migrate_workflow.py
Tests verify push and manual triggers, job conditions, staging-to-production ordering, the production environment, and dispatch targets.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant GitHub
  participant CloudVMMigrationWorkflow
  participant Staging
  participant Production
  GitHub->>CloudVMMigrationWorkflow: Push migration changes to main
  CloudVMMigrationWorkflow->>Staging: Apply migrations at github.sha
  Staging->>Production: Complete staging migration
  CloudVMMigrationWorkflow->>Production: Await required approval, then apply migrations
Loading
🚥 Pre-merge checks | ✅ 24 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 1 files. (2 skipped: 2 … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (24 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Cmux Cloud Persistent Session And Early Input ✅ Passed PASS: The authoritative pull-request diff changes only the Cloud VM migration workflow, its YAML test, and documentation. It does not change Cloud terminal creation, persistent cmux-tui transport, man…
Cmux Swift Actor Isolation ✅ Passed PASS: The reviewed diff changes only a GitHub Actions workflow, a Python test, and Markdown documentation. It contains no Swift files or Swift actor-isolation changes. The custom check therefore does …
Cmux Swift Blocking Runtime ✅ Passed PASS: The authoritative PR diff changes only a GitHub Actions workflow, a Python test, and Markdown documentation. It introduces no Swift files or Swift runtime code, and the changed text contains non…
Cmux Browser Automation Off-Main ✅ Passed PASS. The pull request changes only .github/workflows/cloud-vm-migrate.yml, tests/test_cloud_vm_migrate_workflow.py, and web/AGENTS.md. The rule-scoped files Sources/TerminalController.swift, …
Cmux Expensive Synchronous Load ✅ Passed PASS: The authoritative pull-request diff changes only .github/workflows/cloud-vm-migrate.yml, tests/test_cloud_vm_migrate_workflow.py, and web/AGENTS.md. It contains no Swift changes and no age…
Cmux Cache Substitution Correctness ✅ Passed PASS: The pull request changes only .github/workflows/cloud-vm-migrate.yml, tests/test_cloud_vm_migrate_workflow.py, and web/AGENTS.md. The authoritative diff contains no Swift, TypeScript, or J…
Cmux No Hacky Sleeps ✅ Passed PASS: The PR changes only GitHub Actions YAML, a Python test, and documentation. The rule explicitly excludes GitHub Actions workflow YAML, and the Python test is outside the covered TypeScript, JavaS…
Cmux Algorithmic Complexity ✅ Passed PASS. The review-scoped diff changes only a GitHub Actions YAML workflow, a Python test, and documentation. It adds no production Swift, TypeScript, JavaScript, shell, or runtime implementation. The P…
Cmux Swift Concurrency ✅ Passed PASS. The authoritative PR diff changes only one YAML workflow, one Python test, and one Markdown file. It contains no Swift or Swift-related paths, so it does not introduce or expand any legacy Swift…
Cmux Swift @Concurrent ✅ Passed PASS: The pull-request diff changes only a GitHub Actions workflow, a Python test, and documentation. It contains no Swift files, Swift declarations, @concurrent annotations, nonisolated async work, o…
Cmux Swift Package Boundaries ✅ Passed PASS — The pull-request diff contains only a GitHub Actions workflow, a Python test, and documentation. It contains no production Swift or Xcode/package changes, so the Swift package-boundary failure …
Cmux Swiftpm Lockfiles ✅ Passed PASS: The authoritative PR diff changes only .github/workflows/cloud-vm-migrate.yml, tests/test_cloud_vm_migrate_workflow.py, and web/AGENTS.md. The workflow change adds migration triggers, chec…
Cmux Swift Logging ✅ Passed The pull request changes only a GitHub Actions workflow, a Python test, and documentation. It adds no Swift files or Swift logging statements. Therefore, the Swift logging failure conditions do not ap…
Cmux User-Facing Error Privacy ✅ Passed PASS. The pull request changes only a GitHub Actions migration workflow, a workflow test, and developer documentation. It adds no app UI, product CLI, or product API error or recovery text. The workfl…
Cmux Full Internationalization ✅ Passed PASS: The PR changes only a GitHub Actions workflow, a regression test, and web/AGENTS.md. The added workflow comments and web/AGENTS.md migration note are operational/developer documentation, and…
Cmux Swiftui State Layout ✅ Passed PASS: The pull request changes only a GitHub Actions workflow, a Python test, and web/AGENTS.md. The authoritative diff contains no Swift/SwiftUI paths and no new ObservableObject, @Published, `…
Cmux Architecture Rethink ✅ Passed PASS: The pull request changes only a GitHub Actions workflow, a Python test, and Markdown documentation. The authoritative diff contains no Swift files or SwiftUI/AppKit architecture changes, and it …
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PASS: The pull request changes only .github/workflows/cloud-vm-migrate.yml, tests/test_cloud_vm_migrate_workflow.py, and web/AGENTS.md. The authoritative diff contains no Swift files and no stan…
Cmux Source Artifacts ✅ Passed The diff changes only .github/workflows/cloud-vm-migrate.yml, tests/test_cloud_vm_migrate_workflow.py, and web/AGENTS.md. These are intentional workflow configuration, test source, and durable d…
Cmux No Test Or Debug Seam In Production Source ✅ Passed PASS. The reviewed range changes only .github/workflows/cloud-vm-migrate.yml, tests/test_cloud_vm_migrate_workflow.py, and web/AGENTS.md. It changes no Swift file under a production Sources/ p…
Title check ✅ Passed The title clearly and concisely describes the primary workflow change: applying Cloud VM migrations on relevant pushes to main.
Description check ✅ Passed The description clearly explains the problem, root cause, workflow changes, remaining gap, and test results. It does not use every template heading and omits the review trigger and checklist, but it c…
Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 1 files. (2 skipped: 2 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…roval

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 4/5

The workflow change appears safe to merge, with the non-blocking caveat that its new regression test should be wired into CI to provide the intended protection.

Findings

  1. P2 Regression Test Never Runs ▶

Summary

This PR makes PlanetScale Cloud VM migrations run when a migration reaches main, applying the pushed revision to staging before opening the environment-gated production job. It also documents the deployment requirement and adds regression assertions for the workflow structure.

  • Adds a main push trigger scoped to web/db/migrations/**.
  • Pins staging and production migration jobs to the preflight-resolved pushed SHA.
  • Preserves manual staging-only and production dispatch behavior.
  • Adds a regression test, but does not currently execute it in CI.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Push to main touching web/db/migrations] --> B[Preflight and pin pushed SHA]
  B --> C[Apply migrations to staging]
  C --> D{Production environment approval}
  D -->|Approved| E[Apply same revision to production]
  D -->|Waiting| F[Production migration remains pending]
  G[Manual dispatch] --> B
Loading

Reviews (1) · Last reviewed commit: "docs: note that migrations apply on main..."

Comment on lines +27 to +45
def test_push_to_main_with_a_migration_triggers_the_workflow(self) -> None:
on = load()[True] if True in load() else load()["on"]
self.assertIn("workflow_dispatch", on, "manual dispatch stays available")
push = on.get("push")
self.assertIsNotNone(push, "a main push must run the migration workflow")
self.assertEqual(push.get("branches"), ["main"])
self.assertIn("web/db/migrations/**", push.get("paths", []))

def test_push_applies_staging_then_production(self) -> None:
jobs = load()["jobs"]
staging = jobs["migrate-staging"]
production = jobs["migrate-production"]
self.assertIn("github.event_name == 'push'", staging["if"])
self.assertIn("github.event_name == 'push'", production["if"])
self.assertIn("migrate-staging", production["needs"])
self.assertEqual(production["environment"], "cloud-vm-production")
# A dispatched staging-only run must still stop before production.
self.assertIn("inputs.target == 'production'", production["if"])
self.assertNotIn("inputs.target == 'staging'", production["if"])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Regression Test Never Runs

This regression test is not executed by CI. The repository invokes workflow tests individually from .github/workflows/ci.yml, while the broad Python check only compiles test files without running their assertions. As a result, removing the migration push trigger or production ordering would still pass CI. Add this test to the workflow-guard test job alongside the existing workflow tests.

@github-actions

Copy link
Copy Markdown
Contributor

Automatic catch-up: main is green again and this branch needed it.

I tried to catch this branch up with main (6f3af0a69ffb), but these files need a person:

  • .github/workflows/cloud-vm-migrate.yml: not a generated file; needs a person

Nothing was pushed. Merge main locally, fix those, and push; /catch-up is there again whenever you want it.

Automatic catch-up will not try this head again; a new push or /catch-up does.
Label the pull request no-auto-catch-up to opt out.

Catch-up run

@teamleaderleo teamleaderleo added area: build-and-ci Build system, CI workflows, test infrastructure S1: critical Data loss, a build that will not start, or a security exposure difficulty:3 Systems: multiple components or a runtime lifecycle labels Sep 30, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: build-and-ci Build system, CI workflows, test infrastructure difficulty:3 Systems: multiple components or a runtime lifecycle S1: critical Data loss, a build that will not start, or a security exposure

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants