Skip to content

Instantly share code, notes, and snippets.

@JoshCheek
Last active December 3, 2019 17:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JoshCheek/91133b3703c10b135cd42c331f89e700 to your computer and use it in GitHub Desktop.
Save JoshCheek/91133b3703c10b135cd42c331f89e700 to your computer and use it in GitHub Desktop.
Trunk Based Development
Trunk Based Development
=======================
Disclaimer:
I've never done this on a deployed flagship app at a job.
Words:
Continuous integration: all code is merged frequently (perhaps several times per day to once every few days)
Continuous delivery: the integrated code is delivered (tested and deployable)
Continuous deployment: the deliverable code is deployed (shipped)
Release: feature is available to users
What:
* Avoid long-lived branches
* Merge into trunk/master extremely frequently (ideally multiple times a day)
Why: Continuous integration
* Code doesn't diverge
* Risk is lower because everything works together always, rather than figuring out how to integrate some big branch
* Few/no merge conflicts
* Faster pace of iteration
* Not waiting on some viable code languishing in an unmerged branch
* Not scrambling to merge everything at the end of a sprint
* Implies ZDD because everything must always work (vs creating the new code and then trying to figure out how to deploy it later, once you begin thinking about integrating)
* Each logical piece of code is smaller (eg there shouldn't be 20 parallel lines of ancestry as you scroll through history)
* Avoid large languishing branches
How:
* Develop new behaviour side-by-side with the old behaviour
* Use feature flags to toggle between old and new behaviour
* Once the new behaviour is trusted and ready, flip the flag over
* Then remove the old behaviour and the flag
Constraints:
* Trust test suite
* Trust your colleagues
* Understand risks around your code and take appropriate precautions
* Keep tests green (avoid breaking the build, as that will halt deployment)
* Always be release ready (you can commit unfinished code as long as it can be released)
* Deploy either continuously or from tags on trunk/master or from branches off of master (https://trunkbaseddevelopment.com/branch-for-release/atscale.png)
* QA is about flipping the feature on (releasability, not deployability)
* Deployment needs to be inexpensive (ie automated, stable, and quick)
Implication:
* The branching exists in the code via the feature flags instead of in the branches
* Features being developed work together with preexisting code
* Shipped code does not need to be perfect until the flag's default is flipped to "on"
* Decouple database changes from the code that depends on them (basically the ZDD stuff)
Issues addressed:
* Commits that depend on commits that aren't merged
* Juggling branches
* Difficulty switching branches
* Fewer open tickets (less overhead)
* Smaller chunks of work (less risk, easier to code review)
* Feature flagging is useful in general (eg a/b testing, bandit testing, flipping problematic features off)
* Less need for everything to be perfect before merging (because cost of merging is lower)
* Decouples releasing a feature from deploying it (ie you can flip the feature on by changing the flag instead of by deploying)
* Can deploy old functionality and new functionality in tandem
* Turn features on on a specific date, or for subsets of users, or for QA
* Turn features back off if they go awry
* Batched deployments (GitHub's trains)
* Lack of discoverability (due to shipping the entire feature at the end, rather than allowing incremental exploration / experimentation throughout the development process)
Why branch at all?
* To facilitate code review
* Some companies choose pairing over code review and then directly merge into master (though broken builds become more costly)
* You could try to spike something destructive on a branch, but you would presumably not merge that back in
* Some changes may need to be large and atomic (eg a Rails upgrade may require many changes)
Examples:
* Google does trunk based development (with a monorepo) and ~35,000 devs
Monitor:
* Lead time (https://www.youtube.com/watch?v=aNgWjSAjjtg ~23:00) for each deploy, how long ago were the deployed commits made?
Talks:
* Https://www.youtube.com/watch?v=aNgWjSAjjtg
Proposal:
* Try it on an epic first and once it stabilizes, then expand it to everything
* Some tooling will likely need to be created or added (eg if feature flags are toggled on a per-user or per-request basis, then that context needs to be passed around, potentially to other services, potentially to a background job)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment