// vim: set sw=4 sts=4 ts=4 et : def call(args) { def registry = args?.registry def project = args?.project def name = args?.name def tag = args?.tag def archlist = args?.archlist def schedule = args?.schedule def defaultBranch = args?.defaultBranch def pi = args?.pi def resources = args?.resources properties([ pipelineTriggers([cron(schedule ?: 'H H H * *')]) ]) if (registry == null) { registry = 'git.pyrocufflink.net' } if (project == null) { project = 'containerimages' } if (name == null) { name = escapeImageName(env.JOB_NAME.split('/')[1]) } if (tag == null) { tag = escapeImageName(env.BRANCH_NAME) } if (archlist == null) { archlist = ['amd64'] } if (defaultBranch == null) { defaultBranch = 'main' } def repo = "${registry}/${project}/${name}" def full_name = "${repo}:${tag}" def stages = [:] archlist.each { arch -> def stageName = "Build ${arch}" stages[stageName] = { stage(stageName) { buildStage( name: name, full_name: full_name, registry: registry, arch: arch, resources: resources, ) } } } parallel stages this.runInPod { container('buildah') { withBuildahCreds(registry) { if (archlist.size() > 1) { stage('Build Manifest') { sh "buildah manifest create '${full_name}'" archlist.each { arch -> unstash arch sh "buildah manifest add '${full_name}' oci-archive:\${PWD}/${escapeImageName(name)}-${arch}.tar:${full_name}" } } } stage('Push') { if (archlist.size() > 1) { sh "buildah manifest push --all ${full_name} docker://${full_name}-${env.BUILD_NUMBER}" sh "buildah manifest push ${full_name} docker://${full_name}" if (env.BRANCH_NAME == defaultBranch) { sh "buildah manifest push ${full_name} docker://${repo}:latest" } } else { archlist.each { arch -> unstash arch sh "buildah pull oci-archive:\${PWD}/${escapeImageName(name)}-${arch}.tar:${full_name}" } sh "buildah push ${full_name} ${full_name}-${env.BUILD_NUMBER}" sh "buildah push ${full_name}" if (env.BRANCH_NAME == defaultBranch) { sh "buildah push ${full_name} ${repo}:latest" } } } } } } } def buildStage(args) { def name = args.name def full_name = args.full_name def registry = args.registry def arch = args.arch def resources = args?.resources runInPod(arch: arch, resources: resources) { checkout scm container('buildah') { withBuildahCreds(registry) { sh "buildah build -t '${full_name}' ." sh "buildah push '${full_name}' oci-archive:\${PWD}/${escapeImageName(name)}-${arch}.tar:${full_name}" stash name: arch, includes: "${escapeImageName(name)}-*.tar" } } } } def runInPod(args, block) { def arch = args?.arch def resources = args?.resources def podTemplateYaml = libraryResource('podTemplate2.yaml') if (resources) { def tmpl = readYaml(text: podTemplateYaml) tmpl.spec.containers.each { c -> c.resources = c.resources ?: [:] c.resources.putAll([ requests: (c.resources.requests ?: [:]) + resources, limits: (c.resources.limits ?: [:]) + resources, ]) } podTemplateYaml = writeYaml(data: tmpl, returnText: true) echo podTemplateYaml } podTemplate( yaml: podTemplateYaml, nodeSelector: arch ? "kubernetes.io/arch=${arch}" : null, workspaceVolume: emptyDirWorkspaceVolume(), ) { node(POD_LABEL) { block() } } } def withBuildahCreds(registry, block) { withEnv([ "REGISTRY_AUTH_FILE=${env.WORKSPACE_TMP}/auth.json" ]) { withCredentials([usernamePassword( credentialsId: 'jenkins-packages', usernameVariable: 'BUILDAH_USERNAME', passwordVariable: 'BUILDAH_PASSWORD', )]) { sh """ buildah login \ --username \${BUILDAH_USERNAME} \ --password \${BUILDAH_PASSWORD} \ ${registry} """ } block() } } def escapeImageName(name) { return name. toLowerCase(). replaceAll('[^a-zA-z0-9._-]', '-'). replaceAll('^[.-]', '_') }