Skip to content

Drive the proto → deploy cascade

When you change soundverse-proto, the new contract has to reach every consumer: the generated SDKs, the Go data services, the Python gateway/workers, and the web app. That propagation is partly automated and partly manual, and knowing which is which is the difference between a clean rollout and a “deployed but nothing changed” afternoon.

flowchart TD
    dev[Edit proto on a feature branch] --> pr[Open PR]
    pr --> ci["ci.yml — buf format + lint + full-generation smoke"]
    ci --> merge[Merge to staging]
    merge --> rel["staging-release.yml — regenerate + publish SDKs @staging"]
    rel --> pub["soundverse-proto-{go,python,web,swift,kotlin}@staging"]
    rel --> disp["repository_dispatch: proto_updated → grep '^core' + soundverse-py"]

    disp --> pyDirect["Direct Python consumers auto-PR<br/>gateway · identity · billing · storage · soundverse-py"]
    pyDirect --> spylock[soundverse-py re-locks + publishes]
    spylock --> spydisp["soundverse_updated → tool workers"]
    spydisp --> workers["Tool workers auto-PR<br/>agent · sansaarm · stitch · media · gpu"]

    disp -.commented out.-> goManual["Go services: core-database · core-mcp<br/>MANUAL ./update-proto.sh"]

    class dev,pr,ci,merge frontend
    class rel,pub,disp gateway
    class pyDirect,spylock,spydisp,workers worker
    class goManual external
    classDef frontend fill:#6366f1,color:#fff,stroke:#4338ca
    classDef gateway fill:#0ea5e9,color:#fff,stroke:#0369a1
    classDef worker fill:#10b981,color:#fff,stroke:#047857
    classDef external fill:#f59e0b,color:#111,stroke:#b45309
  1. Edit the proto on a feature branch and open a PR. ci.yml runs on the PR: buf format check, buf lint, a full-generation smoke, and per-language package smokes (Go / Python / web / Swift / Kotlin).

  2. Merge to staging. This triggers staging-release.yml, which regenerates and publishes soundverse-proto-{go,python,web,swift,kotlin}@staging, then fans out a repository_dispatch (event_type=proto_updated) to every repo matching ^core or soundverse-py.

  3. Direct Python consumers auto-PR. On proto_updated, soundverse-py, core-gateway-consumer, core-identity, core-billing, and core-storage open update-private-deps PRs. Review and merge.

  4. Tool workers bump on a second hop. easy to miss The tool workers (core-tool-agent / sansaarm / stitch / media / gpu) do not listen for proto_updated. Their update-private-deps.yml triggers on soundverse_updated, which soundverse-py fires after it re-locks and publishes. So soundverse-py must land first — then the workers get their PRs.

  5. Go services are fully manual. core-database and core-mcp have no update-private-deps workflow, and their repository_dispatch: [proto_updated] deploy trigger is commented out — the dispatch is a no-op for Go. Run ./update-proto.sh (go get …@staging && go mod tidy), commit, and push staging. Deploy core-database first when the change adds a new handler, so it is mounted before consumers call it.