Securing a hyper-scaling CI/CD: ManoMano's story
When ManoMano hyper-grew, security challenges became crucial. Fabien shares with us how he shaped a culture within their company that leads the way on security challenges.
All competitive technology organizations use continuous integration and delivery (CI/CD) to establish a fast and predictable software release cycle. A CI/CD pipeline uses automation to mobilize all the processes required to build, test, and release or deploy your software at a speed that is not possible with any other method.
We teamed up with Semaphore—a CI/CD solution for high-performance engineering teams—to write this article, where we’ll learn the basics of CI/CD and how to make the most out of pipelines.
Continuous integration (CI) is the industry standard for software development as it allows developers to release features at a predictable and sustainable rate. When following CI practices, developers merge their changes into the main branch several times per day—hence the "continuous" in continuous integration.
Each code push initiates an automatic build and test stage that:
The CI process can be extended with CD:
The CI/CD process is frequently depicted as a pipeline, with code entering on one side and an artifact or deployment emerging from the other. A pipeline is a series of jobs—performed by a dedicated CI machine—that accomplishes all the steps required to achieve the organization’s goals.
A pipeline can be separated into many stages:
As you might imagine, tending to the pipeline is essential to any software development project. The pipeline is a runnable specification that describes how an application will be built and released. So, you'll need to keep a few things in mind to make the most of your CI/CD pipeline.
The platform you choose for running your CI/CD pipelines will be around for a long time, so it’s essential to consider all the alternatives and how they fit with your particular requirements. At a minimum, a CI/CD platform should provide:
The CI/CD pipeline is the vital sign monitor for your project: it will tell you if the build is broken and if your application is ready to be released. Consequently, a pipeline failure must not be ignored:
Trunk-based development is a programming methodology that focuses on keeping branches as short as possible. With this practice, developers collaborate on a single main (or master) branch called the trunk. Branches can be created as long as they do not last for more than a few minutes or a couple of hours—never longer than a day. They must be merged into the trunk (or rejected) as fast as possible to keep the codebase in a constant releasable state.
Long-lived branches, e.g. feature branches, complicate development in many ways. The most problematic issues they cause are:
Keeping the branches as short as possible gives us two benefits. First, we are spared from the problems long branches cause. Second, short branches naturally lead to working in small and safe increments.
Every CI pipeline begins with a build stage in which the artifact is produced. In the build stage we:
The important thing is that the build process takes place only once. The resulting artifact is saved and is used in all later tests. Running all tests on the same artifact ensures results are consistent and accurate. Then, when all tests pass, the artifact is packaged for release.
Where should you store the artifact once it has been built? The answer depends on its nature. Compiled binaries and executables can be stored in an artifact store and published when ready, while container images typically go into registries like Docker Hub.
The bulk of your testing should be completely automated—human intervention should not be not required. Ideally, tests should run each time you save a file on your development machine. Every language has many testing frameworks to choose from. Most will allow you to track file changes and re-run the tests when needed. This establishes a rapid feedback loop that adds consistency and will likely save hours of developers’ time every week.
Another instance in which tests must run is when you commit changes to the repository. Without automation, continuous integration is simply impossible.
While it can take some practice and may feel unnatural at first, an effective way to develop software is to write tests first and then the code. This is called Test-Driven Development, and, together with Behavior-Driven Development, are a powerful combo for writing code with fewer errors.
In TDD, we write the test first, set the objectives the code must meet a priori, and then write the minimal code needed for the test to pass. Finally, we refactor and improve the code until we have a modular and clean commit to push.
If it takes more than 10 minutes to see results after pushing new code, your CI/CD pipeline is holding you back. When results take a long time to arrive, they are less relevant and useful because developers must stop what they are doing to fix the problem. A rapid iteration cycle is what keeps engineers in a productive state.
Keeping a CI/CD pipeline fast involves optimizing the speed of your tests. Optimizing the testing suite can be done in many ways:
If you have a large and slow test suite, you will need to formulate a plan to improve it:
The entire DevOps philosophy can be summed up in these seven words: “if you build it, you run it”. The custom of having separate development and operations silos does not work in a fast-paced, customer-oriented market. A DevOps culture means dev and ops are not separated in silos. The important thing is that developers' responsibility does not end when the test pass. They must be involved in the deployment and day-to-day maintenance in production.
Engaging developers in daily operations results in a better product. But developers are not operations experts, so how do we bridge the gap? By automating every step needed to release and deploy with CI/CD. To that end, a continuous deployment pipeline is responsible for:
For example, the following pipeline builds a Docker image and deploys it to Kubernetes:
A CI/CD pipeline at work. In this instance, the pipeline builds, tests, and deploys the application to production automatically. This is awesome because it makes deployment routine and allows developers to release as soon as a new feature is ready.
A pipeline may sound like overhead, but once it’s set up and running, it is an enabler for higher productivity, better developer experience, shorter development cycles, and more satisfied users. Without CI/CD, we are in the dark about the state of our project—we can neither maintain momentum nor produce software at a predictable rate.
We hope these tips will help you set up your first CI/CD pipeline and make the most of it. Happy building!
When ManoMano hyper-grew, security challenges became crucial. Fabien shares with us how he shaped a culture within their company that leads the way on security challenges.
We built a whole system on top of Redis to facilitate the setup of a secure cache. The result? A lighter load for your primary database and a secure and smooth automated caching service.