Nylas published this on 22 July 2020. It is their engineering blog.
They sync email with Python services. Every change starts as a GitHub pull request. After review, a merge runs tests, a build, and a deploy. The full suite and the Debian package build run in parallel. Both have to succeed before production sees the package.
If you are on the same path, start with the Jenkins → GitHub Actions playbook. Nylas gives you the constraint, the rollout shape, and two outcome lines. They do not publish a Jenkinsfile or a workflow file.
Why Jenkins stopped fitting
Jenkins ran unit tests on every commit. Builds were faster than a laptop, and the box was closer to production than a developer machine. A merge to main could produce a deployable artifact without someone babysitting it.
The cost was the Jenkins host. Nylas says the tool predates microservices and containers, so automating it was hard, and it needed constant care. They were seeing build and test failures that came from the Jenkins environment, not from the Python change.
The aim they name is time. Less of the week spent keeping the build environment alive. Less friction between a merge and staging or production.
Why Actions was allowed
SOC 2 is the filter. They were not willing to open the code to a third-party CI vendor. The repositories already lived on GitHub, so GitHub Actions stayed inside that boundary. That is why Actions won. A speed bake-off is not the story.
YAML was the second thing they wanted. Anyone on the team could add a workflow. After the move they check code quality, type annotations, progress toward Python 3, and whether a pull request description means something. Actions also powers a Slack router that picks a channel, and a Clubhouse integration that files tickets for small pull requests such as typo fixes.
They thank David Baumgold for GitHub Actions help. The post does not say which workflows he touched.
How a deploy moves
A finished build notifies the delivery system, which pushes that version to the services that should take it.
- Lock the target servers so two deploys cannot run together.
- Roll staging out in batches. Start at 10% of that service’s staging nodes, then widen until staging is done.
- At each stage, query monitoring and logs. An error spike or a slowdown alerts the team. They continue, or they roll the whole environment back to the last known-good version.
- Promote that staging build to production with the same batches and the same checks.
- Do this on every build, and at least weekly, so deploys stay frequent.
They do not name the monitoring product that answers the anomaly check.
What they measured
The migration had been finished for a few weeks. The results section gives two figures.
Pull-request tests took 30% less time. Some weeks had zero build failures, which they read as time given back to other infrastructure work.
The title says deployment time fell by 30%. The paragraph that holds the number is about tests on each pull request. Keep both sentences. They are not the same clock.
They also say they ship more often, with less developer involvement and more confidence. There is no before-and-after deploy time in minutes, no plugin list, and no count of old environment failures.
What I would copy
If a compliance program forbids an outside CI vendor, start from the git host you already use. Nylas did not describe a CircleCI or Buildkite trial. SOC 2 removed those options.
Time a pull request on Jenkins before you leave. Their reason to move was environment failures. The 30% test figure showed up after, and only because they had a clock.
Copy the lock and the 10% staging batch if two deploys can hit the same servers. The Clubhouse ticket bot is optional.
The Jenkins → GitHub Actions playbook is the inventory of credentials, agents, and plugins. Nylas never published that list. Use their post for the SOC 2 line and the PR-test number.