commit 2926da400764ecd1ce2cf1967c7578e686b5d88d
parent 14d93104bcbfa623e8b2772b983022fdb4e94a15
Author: Andreas Gruhler <agruhl@gmx.ch>
Date: Thu, 19 Mar 2026 20:52:07 +0100
feat: add BuildahParallelBuild
Diffstat:
1 file changed, 111 insertions(+), 0 deletions(-)
diff --git a/src/BuildahParallelBuild.groovy b/src/BuildahParallelBuild.groovy
@@ -0,0 +1,111 @@
+import BuildahBud
+import BuildahPush
+import BuildahManifest
+
+// Matrix build for scripted pipelines:
+// https://www.jenkins.io/blog/2019/12/02/matrix-building-with-scripted-pipeline/#full-pipeline-example-with-dynamic-choices
+
+// A class to perform parallel builds with buildah
+class BuildahParallelBuild implements Serializable {
+ private final Script script
+
+ private BuildahBud buildahbud
+ private BuildahPush buildahpush
+ private BuildahManifest buildahmanifest
+
+ // responses of dynamic choice
+ private Map response = [:]
+
+ // possible build dimensions
+ private Map matrix_axes = [
+ PLATFORM: ['podman'],
+ ARCH: ['arm64', 'amd64'],
+ ]
+
+ // parallel task map
+ private Map tasks = [failFast: false]
+
+ BuildahParallelBuild(Script script) {
+ this.script = script
+ buildahbud = new BuildahBud(script)
+ buildahpush = new BuildahPush(script)
+ buildahmanifest = new BuildahManifest(script)
+ }
+
+ @NonCPS
+ private List getMatrixAxes(Map matrix_axes) {
+ List axes = []
+ matrix_axes.each { axis, values ->
+ List axisList = []
+ values.each { value ->
+ axisList << [(axis): value]
+ }
+ axes << axisList
+ }
+ // calculate cartesian product
+ axes.combinations()*.sum()
+ }
+
+ void build(String imgName,
+ String imgTag,
+ String imgContext,
+ Map imgBuildArgs = [:],
+ String dockerFile = "Dockerfile",
+ String imgRegistry = "haproxy.lan:5000") {
+
+ script.stage("Choose combinations") {
+ response = script.input(
+ id: 'Platform',
+ message: 'Customize your matrix build.',
+ parameters: this.matrix_axes.collect { key, options ->
+ script.choice(
+ choices: ['all'] + options.sort(),
+ description: "Choose a single ${key.toLowerCase()} or all to run tests.",
+ name: key)
+ })
+ }
+
+ List axes = this.getMatrixAxes(this.matrix_axes)
+
+ for(int i = 0; i < axes.size(); i++) {
+ // convert the Axis into valid values for withEnv step
+ Map axis = axes[i]
+ List axisEnv = axis.collect { k, v ->
+ "${k}=${v}"
+ }
+
+ String nodeLabel = "${axis['PLATFORM']} && ${axis['ARCH']}"
+ this.tasks[axisEnv.join(', ')] = { ->
+ script.node(nodeLabel) {
+ script.withEnv(axisEnv) {
+ script.stage("Buildah Bud") {
+ buildahbud.execute(imgBuildArgs, imgContext, imgName,
+ "${imgTag}-${axis['ARCH']}", dockerFile, axis['ARCH'])
+ }
+ script.stage("Buildah Push") {
+ buildahpush.execute(imgName, "${imgTag}-${axis['ARCH']}")
+ }
+ }
+ }
+ }
+ }
+
+ script.stage("Matrix builds") {
+ script.parallel(this.tasks)
+ }
+
+ script.stage("Manifest creation") {
+ script.node('podman&&arm64') {
+ script.stage("Buildah Manifest Create") {
+ buildahmanifest.create("${imgRegistry}/${imgName}:${imgTag}", [
+ "${imgRegistry}/${imgName}:${imgTag}-arm64",
+ "${imgRegistry}/${imgName}:${imgTag}-amd64"
+ ])
+ }
+ script.stage("Buildah Manifest Push") {
+ buildahmanifest.push("${imgRegistry}/${imgName}:${imgTag}")
+ }
+ }
+ }
+ }
+}