In several of my previous posts, we’ve been looking at embedded software testing using Cpputest and build environments using Docker. Each topic is a building block in a modern software process using Continuous Integration/Continuous Deployment (CI/CD). CI/CD is a process of automating building, testing, analyzing, and deploying software to end-users. CI/CD can provide development teams with a variety of values such as:
- Improving software quality
- Decreasing the time spent debugging
- Decreasing project costs
- Enhancing the ability to meet deadlines
- Simplifying the software deployment process
In this post, we will explore CI/CD for embedded systems.
Introduction to CI/CD
There are many different tools and configurations that a team can use to set up a CI/CD process for use with embedded software development. The general pieces though remain relatively similar.
First, the team has a git repository that contains the product's source code. Developers branch the repositories source code to develop a feature or fix a bug locally on their development machine. In the local environment, the developer may use tools like Docker for a containerized build environment along with testing and debugging tools. Once the feature is ready, the developer will commit their changes to their branch in the repository.
Next, committing code will kick off a pre-defined process using the CI/CD toolchains that the development team has selected. For example, common tools for use in CI/CD processes include Jenkins and GitLab. The CI/CD process will be configured to run a series of automated steps, known as a pipeline, to ensure that the software meets preconfigured parameters.
At this point, the first step in a pipeline is usually to build the application image. Building the application image requires having all the tools necessary to successfully build. This is where Docker comes in! The CI/CD tool can use a Docker image that has the build toolchain already set up to verify that the code can build successfully. To do so, the CI/CD tool often needs a runner set up that can dispatch commands to build and run the Docker image. For small teams, the runner may exist on a single developer’s laptop, but it’s highly recommended that the runner be installed on a server either on-premises or in the cloud. This removes the dependency of the developer’s laptop being on when someone needs to commit code.
When the runner has completed the pipeline stage, it will report back the results to the CI/CD tool. The CI/CD tool may dispatch further commands if there are multiple stages in the pipelines. Once completed, the CI/CD tool will report the results of running the pipeline. If everything went well, then the status will be set to passed. If something did not complete successfully, it will be set to failed. If the pipeline failed, developers could go in and review which job in the pipeline did not complete successfully. They are then responsible for fixing it.
CI / CD Pipelines
A CI/CD pipeline is just a collection of jobs that are executed; However, these jobs specify important aspects of the software application build process that need to be verified prior to releasing the software. For example, when getting started, a team may create a simple pipeline that builds the image, lint’s the source code, performs unit tests, and then deploys the application. The pipeline would look something like Figure 2. During a first deployment, I would even recommend not concerning yourself with a deploy job. Just getting build and testing set up can provide a lot of value to the team. (Not all teams require automated deployment anyways).
Once the basics work, teams can then build on their pipeline to add additional jobs that add new capabilities. For example, a more advanced pipeline might start to look like Figure 3.
CI/CD provides a lot of value to embedded software teams. At first, the process can seem complicated, especially since embedded systems often require custom hardware. However, once the process is set up, it can help identify issues early which saves time and money in the long run. The process can help keep developers accountable for the code they write, especially the level of quality that they write. If you are just getting into CI/CD, start simple and just get a build stage up and running. After that, incrementally increase the capabilities until you have a complete and automated CI/CD process.
Jacob Beningo is an embedded software consultant who works with clients in more than a dozen countries. He has published many blogs to count embedded software architecture, processes, and development techniques. He holds three degrees, including a Master of Engineering from the University of Michigan. Feel free to contact him at [email protected], at his website www.beningo.com, and sign-up for his monthly Embedded Bytes Newsletter.