- All playbooks
- Constrain agent migrations with repeatable validation
Constrain agent migrations with repeatable validation
Give migration agents a bounded recipe and validation contract so changes can be checked and reviewed in manageable units.
How companies used this technique
Read what each company changed and follow the original sources.
Find every consumer from lineage data and open one agent pull request per repository
Translated to GitHub Actions
- What Spotify built
- Spotify used Backstage's endpoint lineage, Codesearch and Fleetshift to roll out 240 Honk migration pull requests across its BigQuery Runner and dbt pipelines.
- Your GitHub Actions version
- List every consumer from lineage data, then open one agent pull request per repository.
Spotify had to move about 1,800 downstream data pipelines off two deprecated datasets. Backstage's endpoint lineage listed each dataset's downstream consumers, and Codesearch queries marked the target repositories as in scope. Fleetshift then orchestrated the change on the BigQuery Runner and dbt pipelines, with Honk making the edit in each repository from a context file whose field mappings were written out in tables. Where a change needed a judgement call, Honk left the field unchanged and added a comment linking to the human migration guide for the reviewing team.
Spotify estimated about 10 engineering weeks of effort to migrate the pipelines manually, and rolled out 240 automated migration pull requests. Source
- Use it when
- A deprecation or upgrade touches many repositories, and a dependency or lineage graph can list who is affected.
- Before applying it
- Spell out every mapping in the context file, and have the agent hand judgement calls to the reviewing team.
- GitHub Actions adaptation
- Compare the source system with your own workflow before applying this translation.
Upgrade the JDK in bounded pull requests computed from the build graph
Translated to GitHub Actions
- What Stripe built
- Stripe's AutoJDK analyzes the live build graph and generates JDK upgrades in bounded partitions, with minions fixing mechanical CI errors.
- Your GitHub Actions version
- Compute eligible targets from the build graph and open upgrades in bounded, rerunnable pull requests.
Stripe's AutoJDK analyzes the live build graph to decide which Java and Scala targets are eligible, weighing reverse dependencies, runtime JDK compatibility caps, dependency ordering and framework-specific guards. It generates target_jdk upgrades in bounded partitions as automated pull requests that are safe to rerun, and tracks adoption and blockers over time. Minions fix mechanical CI errors from an upgrade in sandboxes with fresh git checkouts, and an agentic skill runs upgrades across all partitions, monitors and fixes CI, and cherry-picks the commits into larger pull requests.
Since going live 3 months ago, Stripe merged 160+ PRs using the automated upgrader. Source
- Use it when
- A language or toolchain upgrade touches thousands of build targets, and large upgrade waves overwhelm reviewers or produce merge conflicts.
- Before applying it
- Keep the version policy in the platform so the upgrader has one place to change, and keep CI checks that enforce dependency ordering between targets.
- GitHub Actions adaptation
- Compare the source system with your own workflow before applying this translation.
Migrate a test framework with a recipe that keeps only passing targets
Translated to GitHub Actions
- What Uber built
- Uber faced over 600,000 JUnit 4 tests and migrated over 75,000 test classes to JUnit 5 with OpenRewrite recipes applied per Bazel test target, with Shepherd generating the diffs.
- Your GitHub Actions version
- Apply a migration recipe per test target, run that target's tests, and keep the change only when they pass.
Uber faced over 600,000 JUnit 4 tests and migrated over 75,000 test classes to JUnit 5 with OpenRewrite recipes applied per Bazel test target. A precondition recipe limits each run to files whose test runners, rules and base classes the recipe supports. A script applies the patch, updates the build dependencies and runs the target's tests, and keeps the change when they pass. Shepherd then generates a diff for each migrated target, and each rollout round adds recipes for the patterns the previous round turned up.
Uber reports migrating over 75,000 test classes to JUnit 5, modifying over 1.25 million lines of code within 4 months, with over 5,000 diffs generated. Source
- Use it when
- A framework or API migration spans thousands of test targets, and a manual migration would take developer hours across many teams.
- Before applying it
- Start with the utilities used most often. Revert any target whose tests change outcome, and rerun after adding a recipe for the pattern behind it.
- GitHub Actions adaptation
- Compare the source system with your own workflow before applying this translation.
Company Playbooks
- Read Anthropic’s playbookRun only affected tests
- Read DoorDash’s playbookRun build and test in parallel, sharded across CI agents
- Read Linear’s playbookBenchmark the same job on faster hardware
- Read Mastra’s playbookStarSling runners for the slowest test workflow
- Read OpenAI’s playbookRank CI fixes by the minutes they save
- Read Ramp’s playbookMove a CPU-bound test suite to a faster CPU
- Read Shopify’s playbookLet an agent iterate against one CI metric
- Read Spotify’s playbookBuild arm64 on native arm64 runners
- Read Stripe’s playbookRun only the tests a change can reach
- Read Uber’s playbookBuild the merge-queue speculations most likely to be needed