To close out our second-ever launch week, we’re excited to start solving one of the most painful problems every rapidly-scaling company faces: growing CI costs.
As we’ve seen Graphite usage swell in the largest, fastest-growing companies, we’ve heard from them how much faster their engineers are able to ship now that they’re stacking pull requests (see Ramp, Asana)— and also how it means they’re running more CI.
When developers learn to stack their pull requests, they start writing smaller PRs and shipping more code. This means that they’re going to be running more CI — so teams adopting stacking need to have a strategy in place to avoid ballooning costs and wait times.
One side effect of stacking PRs is the constant rebasing required to keep your PRs up to date — which Graphite now handles for you. However, updating one PR in a stack changes the SHAs of everything upstack — which can trigger CI systems to do full rebuilds when logically no code changed.
Introducing Graphite CI optimizer
Our customers of all sizes have asked us for a better approach to running CI on stacked PRs, and we’ve felt this pain ourselves as we’ve scaled Graphite.
Today we’re excited to announce first-class integrations with Buildkite and GitHub Actions that let you optimize your CI pipelines for stacking, so your releases stay reliable while your costs stay in control. Here’s how it works:
Run CI on selective PRs in a stack
CI admins, devops teams, and dev tools teams can now configure Graphite to only run CI on part of a stack of PRs, i.e. just on the bottom PRs of the stack (or top + bottom).
You merge stacked PRs from the bottom of the stack into your main trunk branch—so you should always know your CI status at the base of the stack. If you want to see the CI status of your whole feature at once, configure the optimizer to run CI on the top of the stack automatically (or trigger a build manually). Both options ensure you can ensure you don’t automatically run unnecessary CI as you work on the stack.
Selectively running fast and slow CI on your stacked PRs
Taking it a step further, you may have a fast suite of tests you always want to run on any update to the stack, and another set of slower tests you want to run less often. You can now configure the Graphite CI optimizer to do exactly this, i.e. “run linters on all PRs all the time, and only run end-to-end tests before merging a PR.”
Reducing CI runs when merging with the Graphite merge queue
As a part of this launch week, we also announced batch merges for the Graphite merge queue. Today’s announcement adds to batch merging to give you the biggest possible reduction in unnecessary CI runs.
Both are useful in tandem because you commonly run CI when you push a PR for the first time, then again for any updates to it, and at least once more when you go to merge it into your trunk branch via the merge queue.
We’re also going to add the ability to run different suites of tests against PRs when you create them versus when you queue them for merging — so you’re in control when you need to run slower tests.
How CI optimizer works
Our CI optimization works similarly for both Buildkite and GitHub Actions. First, add a new CI optimizer to the desired repo in the Graphite CI optimization settings. Then, add the Buildkite plugin or GitHub Action step to your pipelines.
For Buildkite specifically, you can create a new Graphite optimizer pipeline that then triggers your own pipeline(s) if it determines they should run. Or, you can add a job to the beginning of your pipeline that your other jobs wait
on before kicking off.
For GitHub Actions, add an optimize_ci
job to the start of your pipeline and have your other jobs wait on the results of this one before running automatically.
Start optimizing your CI
We’re actively rolling out CI optimizer to Graphite customers using both Buildkite and GitHub Actions. It’s currently in private beta with a few enterprise customers, and we plan to open it for public beta in the coming weeks.
Request early access and check out the docs for more information.