Setting up Jenkins for Embedded the right way (or not at all)

Embracing continuous integration (CI) practices and tools makes embedded development smoother. Jenkins isn’t always the best choice for Embedded CI, but if you follow the 3 CI principles laid out in this article, you’ll start off well!
Continuous Integration. Improves your embedded life.
Is your embedded product releasable right now? How long would it take for all the software changes to be merged, release candidate (RC) binaries to be created, and the RC to be tested?
Continuous Integration is a practice that challenges you to keep your product releasable continuously. To achieve this lofty goal, you need
- code merged across the team frequently (think daily!)
- rapid, automated feedback from your automated build, test, and release steps
In web development, this can be as extreme as teams that practice trunk-based development and continuous deployment (passing CI causes at least a partial rollout of the changes directly to production). Your embedded environment will have unique challenges vs. web (execution environment controlled by end-users, testing challenges, history of manual testing, tooling support). Still, the concepts of CI are being adopted by modern embedded teams. Embedded CI practices and tools provide improvements in feedback that lead to less stressful software development.
CI tool principles
While the practices of CI are critical, many people immediately jump to Jenkins when they think CI. Jenkins is “The leading open source automation server“, but before I try to convince you to not use Jenkins, let’s review why you want an “automation server” (called CI server from now on).
You want feedback from your build and tests when you check in code changes. A CI server is a web application that integrates with your version control (typically git) tool. The CI server detects the code changes, runs your automated processes on connected computers, notifies you of the results, and provides you logs and saved artifacts.
Principle: CI servers are commodities
Jenkins is one of many available CI servers that fulfill all or at least most of the functions described above. In addition, with the intentional design of your automated processes, you will be able to move between CI servers with low risk and low effort – more on this later.
Principle: Automated scripts should be runnable locally and on your CI server
Nothing is more frustrating than your CI build failing and either not being able to replicate it locally or, even worse, not being able to execute it locally. The exception to this principle is for things like creating release packages that are signed or uploaded to protected areas – you still want to be able to exercise this code locally, but without all the keys 😉
Principle: Leverage off-the-shelf tooling for your automation system
Embedded does not require innovation from your chosen CI server. Embedded developers typically do not enjoy the challenge of operating delivery critical web applications – installation, updates, security, etc. Engineering management even less likes the idea of embedded developers operating a delivery critical web application. On your CI journey, embedded developers’ skills can be leveraged much better by developing solid build scripts, or unit tests.
Don’t use Jenkins
Ok, so I’ve jabbed some at Jenkins already and provided 3 CI tool principles. Let’s dig into some more detail on Jenkins.
Jenkins, the good
Jenkins is fast and free to set up for piloting on your local computer. You can run both the web application and the build-runner on your local computer (although you shouldn’t: “Builds should not be executed on the built-in node“). Since you’re running everything on your computer, your IT person or department might not care or at least notice the web server you’ve set up.
Jenkins, the bad (or what’s a better choice)
Operating an up-to-date (Jenkins application & plugins), backed up, and secure Jenkins server requires time and expertise that a typical embedded developer doesn’t have. However, SaaS alternatives like Github, Bitbucket, and Gitlab all provide best-in-class CI capabilities at a reasonable per-developer cost.
Additionally, these SaaS services are evolving and competing by providing “batteries included” features like version control hosting (git), issue management, container-based build execution capacity, code review workflows, etc.
If you insist on Jenkins
If you still choose to start your Embedded CI journey with Jenkins here are 3 tips that will minimize the pain (and set you up to migrate later ;-))
Keep your CI pipelines simple and in source control.
Your CI pipeline defines the scripts to run when you make code changes. Jenkins has many options on how to set this up, but just use a Jenkinsfile stored alongside your code in version control (see Using a Jenkinsfile). Keeping the pipeline file in version control gives visibility locally to what will run on the CI system.
Also, keep that Jenkinsfile simple! Any logic or processing you need to do should be outside the Jenkinsfile in a platform-independent script (python, makefile, etc.).
Do not use plugins.
Jenkins plugins seem great – there’s one for anything you want, so you install anything that sounds interesting and turn it on for your project. Unfortunately, the next time you upgrade Jenkins and/or the plugins (you’re doing that at least monthly for security updates, right?), at least one plugin will likely have a breaking config change or is deprecated/orphaned.
Also, the more valuable the plugin is, the more you violate the principle of builds providing the same feedback in both CI and local environments.
Minimize the manual setup of your build runner.
While SaaS CI servers use containerized environments for job execution, Jenkins allows you to build directly on your local computer. This is a speedup, but your build environment is not fully managed and defined.
Do not set up Jenkins on your personal development computer. Instead, start with a new computer and completely automate or document everything you need to have installed or configured (environment variables) to for your build. This process will also help your new developer setup time and repeatability.
As you consider automation related to build dependencies, keep in mind how you can leverage container-based builds in the future.
Final Thoughts
Improving your development flow with Continuous Integration practices and tools is a journey that can be incrementally advanced. While Jenkins is a helpful tool, consider SaaS alternatives and use the CI principles when choosing your next move.