2025-02-07 07:18:40 +00:00
package com . freeleaps . devops
import com.freeleaps.devops.enums.ImageBuilderTypes
class ImageBuilder {
def steps
def workspace
def contextRoot
def dockerfile
def builderType
2025-02-09 18:56:27 +00:00
// customized parameters
def name
def registry
def repository
def architectures
def version
def registryCredentialsId
def buildxBuilderName
2025-02-09 19:03:18 +00:00
ImageBuilder ( steps , workspace , contextRoot , dockerfile , builderType ) {
2025-02-07 07:18:40 +00:00
this . steps = steps
this . workspace = workspace
this . contextRoot = contextRoot
this . dockerfile = dockerfile
this . builderType = builderType
}
2025-02-09 18:56:27 +00:00
def setManifestsOfImage ( registry , repository , name , version ) {
if ( registry = = null | | registry . isEmpty ( ) ) {
steps . error ( "registry is empty" )
}
this . registry = registry
if ( repository = = null | | repository . isEmpty ( ) ) {
steps . error ( "repository is empty" )
}
this . repository = repository
if ( name = = null | | name . isEmpty ( ) ) {
steps . error ( "name is empty" )
}
this . name = name
if ( version = = null | | version . isEmpty ( ) ) {
steps . error ( "version is empty" )
}
this . version = version
}
def setArchitectures ( architectures ) {
if ( architectures = = null | | architectures . isEmpty ( ) ) {
steps . error ( "architectures is empty" )
}
this . architectures = architectures
if ( builderType = = ImageBuilderTypes . DOCKER_IN_DOCKER & & architectures . size ( ) > 1 ) {
steps . log . warn ( "ImageBuilder" , "If you want to build multi-arch images and using Docker in Docker (DIND) as builder, system will using buildx to replace build command." )
steps . log . info ( "ImageBuilder" , "Creating buildx builder with name: multiarch-builder-${name}" )
steps . sh "docker buildx create --use --name multiarch-builder-${name}"
steps . log . info ( "ImageBuilder" , "Inspecting buildx builder with name: multiarch-builder-${name}" )
steps . sh "docker buildx inspect --bootstrap"
steps . log . info ( "ImageBuilder" , "Register clean up hook for buildx builder deletion for builder named: multiarch-builder-${name}" )
steps . post {
always {
steps . sh "docker buildx rm multiarch-builder-${name} || true"
}
}
this . buildxBuilderName = "multiarch-builder-${name}"
}
}
def useCredentials ( registryCredentialsId ) {
if ( registryCredentialsId = = null | | registryCredentialsId . isEmpty ( ) ) {
steps . error ( "registryCredentialsId is empty" )
}
this . registryCredentialsId = registryCredentialsId
}
def build ( ) {
2025-02-07 07:18:40 +00:00
steps . log . info ( "ImageBuilder" , "Building image with ${builderType.builder}" )
steps . log . info ( "ImageBuilder" , "Workspace sets to: ${workspace}" )
steps . log . info ( "ImageBuilder" , "Using dockerfile at: ${dockerfile}, context root sets to: ${contextRoot}" )
if ( architectures = = null | | architectures . isEmpty ( ) ) {
steps . log . warn ( "ImageBuilder" , "No architectures specified, using default amd64" )
architectures = [ 'linux/amd64' ]
}
2025-02-09 17:26:11 +00:00
steps . withCredentials ( [ steps . usernamePassword ( credentialsId: registryCredentialsId , passwordVariable: 'DOCKER_PASSWORD' , usernameVariable: 'DOCKER_USERNAME' ) ] ) {
2025-02-08 04:07:41 +00:00
steps . log . info ( "ImageBuilder" , "Authentication to ${registry}" )
switch ( builderType ) {
case ImageBuilderTypes . DOCKER_IN_DOCKER :
2025-02-09 17:33:26 +00:00
steps . sh "docker login -u ${steps.env.DOCKER_USERNAME} -p ${steps.env.DOCKER_PASSWORD} ${registry}"
2025-02-08 04:07:41 +00:00
break
case ImageBuilderTypes . KANIKO :
2025-02-09 17:33:26 +00:00
def auth = "${steps.env.DOCKER_USERNAME}:${steps.env.DOCKER_PASSWORD}" . bytes . encodeBase64 ( ) . toString ( )
2025-02-08 04:07:41 +00:00
steps . writeFile file: '/kaniko/.docker/config.json' , text: "" " {
"auths" : {
"${registry}" : {
"auth" : "${auth}"
}
}
} "" "
break
default :
steps . error ( "Unsupported builder type: ${builderType.builder}" )
}
}
2025-02-07 07:18:40 +00:00
switch ( builderType ) {
case ImageBuilderTypes . DOCKER_IN_DOCKER :
steps . dir ( workspace ) {
2025-02-09 18:56:27 +00:00
if ( buildxBuilderName ! = null & & ! buildxBuilderName . isEmpty ( ) & & architectures . size ( ) > 1 ) {
steps . log . info ( "ImageBuilder" , "Building image ${registry}/${repository}/${name} with architectures: ${architectures} using buildx builder: ${buildxBuilderName}, tag sets to ${version}" )
steps . sh "docker buildx build --builder ${buildxBuilderName} --platform ${architectures.join(" , ")} -t ${registry}/${repository}/${name}:${version} -f ${dockerfile} --push ${contextRoot}"
} else {
architectures . each { architecture - >
def archTag = architecture . split ( "/" ) [ 1 ]
steps . log . info ( "ImageBuilder" , "Building image ${registry}/${repository}/${name} with architectures: ${architectures}, tag sets to ${version}" )
steps . sh "docker build -t ${registry}/${repository}/${name}:${version}-${archTag} --platform ${architecture} -f ${dockerfile} ${contextRoot}"
steps . sh "docker push ${registry}/${repository}/${name}:${version}-${archTag}"
}
2025-02-07 07:18:40 +00:00
}
}
break
case ImageBuilderTypes . KANIKO :
steps . dir ( workspace ) {
architectures . each { architecture - >
def archTag = architecture . split ( "/" ) [ 1 ]
steps . log . info ( "ImageBuilder" , "Building image ${registry}/${repository}/${name} with architectures: ${architectures}, tag sets to ${version}-${archTag}" )
steps . sh "/kaniko/executor --log-format text --context ${contextRoot} --dockerfile ${dockerfile} --destination ${registry}/${repository}/${name}:${version}-${archTag} --custom-platform ${architecture}"
}
}
break
default :
steps . error ( "Unsupported builder type: ${builderType.builder}" )
}
}
}