In a larger organization I recently observed several teams migrating automated build infrastructure to CI/CD pipelines using Jenkins 2. But for reasons I might not fully understand, the pipeline code turned out to be complicated, non-reusable, and was tested manually. In short, it reminded me of software development practices of the past.
Certainly, one of the reasons is the growing complexity of CI/CD infrastructure requiring ever more skills. That’s why it might make sense to delegate complexity to specialists. But perhaps another cause is sloppy engineering. As if software engineers still treat pipelines like trivial build scripts, not fully acknowledging the consequences of infrastructure as code.
So if you opt to maintain your own CI/CD infrastructure I’m arguing to treat pipelines not just as code, but as production code. This means:
-
Design pipelines instead of making them up ad-hoc. Example: cleanly separate different configuration scopes component-specific[1] (like installing component-specific build dependencies), team-specific (like where to publish build artifacts), and shared (e.g. if the entire organization uses the same static code analysis infrastructure).
-
If useful, share common functionality in modules and building blocks.
-
Keep pipelines simple e.g. by following the paradigm convention over configuration.
-
Cover essential complexity by tests.
Simplicity might feel like a challenge. A sketch of an elegant pipeline design was posted on reddit. A more tangible solution for modular Jenkins pipelines is MPL. It supports reuse of pipelines and building blocks, overriding general building blocks by specialized ones, and it demonstrates how to test pipelines based on JenkinsPipelineUnit.