How we ship GitHub Mobile every week
Learn how the GitHub Mobile Team automates their release process with GitHub Actions.
![](https://github.blog/wp-content/uploads/2022/01/Engineering_Product.png?resize=1200%2C630)
Every week, the GitHub Mobile team updates the GitHub Mobile apps on both iOS and Android with new features, bug fixes and improvements. Shipping a mobile app is not an easy task. Before a build goes out to our users’ hands, we must make sure the end result is properly built, all written tests are passed, and any critical issues are captured by testing. Also, we compose release notes with changes since our last update. All of these tasks can be quite time-consuming.
Since we’re a small team, repeating this release process every week would mean less time spent writing code or building new features. In order to focus on product development, we use a number of tools to automate the release process. In this post, I’ll share how we automate the build release process by using the iOS pipeline as an example.
A release candidate build is ready to go out to our beta users when these criteria are met:
- A branch is created for addressing any hot fixes needed for the release candidate
- The build is generated with a proper version number and uploaded to TestFlight
- All unit and snapshot tests have passed
- An issue is created to track the release process
- Release notes are ready
GitHub provides great tools for continuous integration and delivery. We primarily use GitHub Actions to automate most of the steps to meet our criteria, plus some additional tools like fastlane.
![Workflow visualized on GitHub.com](https://i0.wp.com/user-images.githubusercontent.com/976424/141815735-85db8cfc-6f8e-4b31-b02d-1c41d7101475.png?w=858&ssl=1)
![Steps to release a build. The icon on the top right of each step indicates if the step is executed automatically by an action or manually.](https://i0.wp.com/user-images.githubusercontent.com/976424/130087754-86ee05cb-0972-4fb4-9430-6842ee126977.png?w=858&ssl=1)
The figure above illustrates the entire process of making a build ready to ship. The gray steps are automated by GitHub Actions, while the blue steps are manually processed by our team. As you can see in the figure, most of the steps are automated. Only the final steps, like merging release-related changes or finalizing an app submission, require human interactions. We manually write release notes because humans are still better than machines at writing prose, but the materials are prepared by the automation, so the writing itself is not very time-consuming.
Let’s dive into some of the details.
Build and release
First, my team needs to generate an app binary for any given build. We define a job, which contains multiple steps for generating a build, going through the test cases, archiving, and uploading to TestFlight. We create a dedicated branch for each version we ship, so that we can go back and cherry-pick any changes we want to include. GitHub Actions has a great community support, and there are tons of open source actions we can use. For example, the peterjgrainger/action-create-branch
action makes it easy to create a new release branch.
Once the branch has been created, we run fastlane
to build, test, archive, and upload. In order to code-sign the binary and upload it to TestFlight, our action will need certificates and credentials to run these secure and authenticated commands. Those credentials are stored in GitHub Secrets, and they can be easily passed into an action without revealing them to would-be attackers.
Issue creation
Once a build is created and uploaded to TestFlight, we kick off another job. This one creates a GitHub issue to track any paperwork or manual processes needed in order to distribute the build. The issue serves as a playbook containing all steps to get the build out to our users including verification of release marketing materials, pre-launch manual tests, and even sharing the status with the team. By following this playbook, a release captain does not need to remember the steps, and any new folks can become a release captain with little training. The issue creation is easily done with GitHub CLI by adding a shell command in the GitHub Actions workflow YAML file, such as gh issue create -t {title} -b {body} -a {assignees} -l {labels}
. Also, there are a number of open source actions like JasonEtco/create-an-issue
, which makes it easy to create an issue with a template.
We manage the release engineer rotation with PagerDuty. In order to fetch the next release engineer via PagerDuty API, we also utilize open source actions, such as JamesIves/fetch-api-data-action
. The release captain is then assigned to the issue so that we all know who is responsible for the release.
![A sneak peak of a release tracking issue. Each step is described with a lot of details, so that one can just follow the instruction.](https://i0.wp.com/user-images.githubusercontent.com/976424/141815916-d81a9563-212b-4be4-9b76-311da13b3f68.png?w=858&ssl=1)
Release notes
With another parallel job, we prepare materials to compose release notes. Using fastlane
, we collect all commits that have been pushed since the last release (alternatively, you can try another automation recently added to GitHub). The change logs are raw records of all commits and pull requests, meaning that this text alone is not suitable for release notes for our users. Thus, we create a text file with those raw change logs in our repo, and open a pull request where we can compose customer-friendly release notes. Opening a pull request is pretty easy with GitHub CLI. Adding a shell command, gh pr create -t {title} -b {body} -a {assignees}, -r {reviewers} -l {labels}
, will automatically create a pull request as part of the job. An open source action such as peter-evans/create-pull-request
is also useful to open a pull request.
We retrieve the next release engineer (the same way we retrieve one when creating an issue) and assign the engineer to the pull request. Once the engineer has finished writing customer-friendly release notes and another teammate has reviewed the change logs, we merge the pull request to store it in our repository.
Version number management
We have another parallel job for managing the build version numbers. Once a release candidate is created, we bump the version number in main
so that everyone can begin with the next ship cycle. To prevent any errors, we do not push any code changes into main
directly. Instead, a pull request to increment the version number update is opened by an action. The version update is done with small Bash and Ruby scripts, and the pull request is created via the same method we use for release notes.
![Timeline for a build release. Once a build is created by the actions, it goes out to the public after a week of beta testing.](https://i0.wp.com/user-images.githubusercontent.com/976424/130087927-998b6de4-2f38-4aa7-94d7-fb7a4a6c13e2.png?w=865&ssl=1)
The figure above illustrates a timeline for a build release. The four jobs described, along with all of their steps, are defined in one single YAML file that defines a GitHub Actions workflow. The workflow is kicked off every Saturday morning so that the release engineer has all the materials when Monday rolls around. On Monday morning, the engineer ticks off all the steps described in the issue created by the workflow, sending the build out to our TestFlight beta users and then finally submitting to the build for App Store review. During the week, we monitor how beta testing is going. If we find a critical issue from the build, we fix it in main
, cherry-pick the fix into the release branch, and upload another build. We have another GitHub Actions workflow that automates this additional build process, which is triggered whenever we push a code change into the release branch.
If the beta metrics for the week look good, with no crashes or regressions, we finally release the build on the App Store, a week after it began beta testing. In this way, our customers get solid GitHub Mobile updates every week.
🎉 Conclusion
In this post, I described how we ship GitHub Mobile apps every week with build release pipelines implemented using GitHub Actions. The community support for GitHub Actions is amazing, and there are so many powerful open source actions that you can use right away. If you want to have your own custom action and workflow, it is also quite easy to create one and re-use it across repositories or projects. With our release pipeline greatly improved by the automations powered by GitHub Actions, we have more time and focus for product development and spend less time waiting for Xcode to compile. By automating our release process and running it via GitHub Actions and GitHub Issues, it’s a lot easier to get new teammates onboarded as release engineers and shipping their new features to the App Store every week.
I hope this post helps people who wants to build solid CI/CD pipelines with GitHub tools. To learn more about automating your release process with GitHub Actions, check out the following resources:
- Join the Beta program
- GitHub Actions
- GitHub CLI
- GitHub Secrets
- Automatic release notes generation on GitHub
- fastlane
peterjgrainger/action-create-branch
JasonEtco/create-an-issue
JamesIves/fetch-api-data-action
peter-evans/create-pull-request
Tags:
Written by
Related posts
![](https://github.blog/wp-content/uploads/2024/08/1200x630-Blog-Banner-Light-Mode-2.png?resize=400%2C212)
The ultimate guide to developer happiness
Five actionable tips and strategies to supercharge developer happiness—and a more innovative workplace.
![A landscape image with a simple dark background featuring two security-themed shapes in the top left and bottom right corners. The foreground text is centered and reads "Strategies for supporting your neurodivergent employees."](https://github.blog/wp-content/uploads/2024/07/neurocats-header.png?resize=400%2C212)
How GitHub supports neurodiverse employees (and how your company can, too)
Teams with neurodivergent employees can be up to 30 percent more productive. Discover tips on how best to support them in your workplace.
![](https://github.blog/wp-content/uploads/2023/12/Productivity-DarkMode-2-1.png?resize=400%2C212)
How we improved availability through iterative simplification
Solving and staying ahead of problems when scaling up a system of GitHub’s size is a delicate process. Here’s a look at some of the tools in GitHub’s toolbox, and how we’ve used them to solve problems.