feat(pipeline): enhance ImageBuilder with manifest setting and multi-architecture support
Signed-off-by: 孙振宇 <>
This commit is contained in:
parent
fd3e1545b3
commit
7af2883fcc
@ -9,7 +9,17 @@ class ImageBuilder {
|
|||||||
def dockerfile
|
def dockerfile
|
||||||
def builderType
|
def builderType
|
||||||
|
|
||||||
ImageBuilder(steps, workspace, contextRoot, dockerfile, builderType) {
|
// customized parameters
|
||||||
|
def name
|
||||||
|
def registry
|
||||||
|
def repository
|
||||||
|
def architectures
|
||||||
|
def version
|
||||||
|
def registryCredentialsId
|
||||||
|
|
||||||
|
def buildxBuilderName
|
||||||
|
|
||||||
|
ImageBuilder(buildId, steps, workspace, contextRoot, dockerfile, builderType) {
|
||||||
this.steps = steps
|
this.steps = steps
|
||||||
this.workspace = workspace
|
this.workspace = workspace
|
||||||
this.contextRoot = contextRoot
|
this.contextRoot = contextRoot
|
||||||
@ -17,7 +27,58 @@ class ImageBuilder {
|
|||||||
this.builderType = builderType
|
this.builderType = builderType
|
||||||
}
|
}
|
||||||
|
|
||||||
def build(name, repository, registry, architectures, version, registryCredentialsId) {
|
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() {
|
||||||
steps.log.info("ImageBuilder", "Building image with ${builderType.builder}")
|
steps.log.info("ImageBuilder", "Building image with ${builderType.builder}")
|
||||||
steps.log.info("ImageBuilder", "Workspace sets to: ${workspace}")
|
steps.log.info("ImageBuilder", "Workspace sets to: ${workspace}")
|
||||||
steps.log.info("ImageBuilder", "Using dockerfile at: ${dockerfile}, context root sets to: ${contextRoot}")
|
steps.log.info("ImageBuilder", "Using dockerfile at: ${dockerfile}, context root sets to: ${contextRoot}")
|
||||||
@ -51,13 +112,18 @@ class ImageBuilder {
|
|||||||
switch(builderType) {
|
switch(builderType) {
|
||||||
case ImageBuilderTypes.DOCKER_IN_DOCKER:
|
case ImageBuilderTypes.DOCKER_IN_DOCKER:
|
||||||
steps.dir(workspace) {
|
steps.dir(workspace) {
|
||||||
|
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 ->
|
architectures.each { architecture ->
|
||||||
def archTag = architecture.split("/")[1]
|
def archTag = architecture.split("/")[1]
|
||||||
steps.log.info("ImageBuilder", "Building image ${registry}/${repository}/${name} with architectures: ${architectures}, tag sets to ${version}-${archTag}")
|
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 build -t ${registry}/${repository}/${name}:${version}-${archTag} --platform ${architecture} -f ${dockerfile} ${contextRoot}"
|
||||||
steps.sh "docker push ${registry}/${repository}/${name}:${version}-${archTag}"
|
steps.sh "docker push ${registry}/${repository}/${name}:${version}-${archTag}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break
|
break
|
||||||
case ImageBuilderTypes.KANIKO:
|
case ImageBuilderTypes.KANIKO:
|
||||||
steps.dir(workspace) {
|
steps.dir(workspace) {
|
||||||
|
|||||||
4
first-class-pipeline/tests/Jenkinsfile
vendored
4
first-class-pipeline/tests/Jenkinsfile
vendored
@ -73,7 +73,7 @@ executeFreeleapsPipeline {
|
|||||||
// imageBuildRoot used to specify the image build context root
|
// imageBuildRoot used to specify the image build context root
|
||||||
imageBuildRoot: '.',
|
imageBuildRoot: '.',
|
||||||
// imageReleaseArchitectures used to specify the released image architectures
|
// imageReleaseArchitectures used to specify the released image architectures
|
||||||
imageReleaseArchitectures: ['linux/amd64', 'linux/arm64'],
|
imageReleaseArchitectures: ['linux/amd64', 'linux/arm64/v8'],
|
||||||
// registryCredentialsId used to specify the registry credential that stored in Jenkins
|
// registryCredentialsId used to specify the registry credential that stored in Jenkins
|
||||||
registryCredentialsId: 'gitops-mvp-app-dockerhub-secret',
|
registryCredentialsId: 'gitops-mvp-app-dockerhub-secret',
|
||||||
// semanticReleaseEnabled used to specify whether to enable semantic release
|
// semanticReleaseEnabled used to specify whether to enable semantic release
|
||||||
@ -120,7 +120,7 @@ executeFreeleapsPipeline {
|
|||||||
// imageBuildRoot used to specify the image build context root
|
// imageBuildRoot used to specify the image build context root
|
||||||
imageBuildRoot: '.',
|
imageBuildRoot: '.',
|
||||||
// imageReleaseArchitectures used to specify the released image architectures
|
// imageReleaseArchitectures used to specify the released image architectures
|
||||||
imageReleaseArchitectures: ['linux/amd64', 'linux/arm64'],
|
imageReleaseArchitectures: ['linux/amd64', 'linux/arm64/v8'],
|
||||||
// registryCredentialsId used to specify the registry credential that stored in Jenkins
|
// registryCredentialsId used to specify the registry credential that stored in Jenkins
|
||||||
registryCredentialsId: 'gitops-mvp-app-dockerhub-secret',
|
registryCredentialsId: 'gitops-mvp-app-dockerhub-secret',
|
||||||
// semanticReleaseEnabled used to specify whether to enable semantic release
|
// semanticReleaseEnabled used to specify whether to enable semantic release
|
||||||
|
|||||||
@ -411,7 +411,12 @@ def generateComponentStages(component, configurations) {
|
|||||||
log.error("Pipeline", "Unknown image builder for ${component.name}, skipping image building")
|
log.error("Pipeline", "Unknown image builder for ${component.name}, skipping image building")
|
||||||
}
|
}
|
||||||
|
|
||||||
def imageBuilder = new ImageBuilder(this, env.workroot + "/" + component.root + "/", component.imageBuildRoot, component.dockerfilePath, imageBuilderType)
|
def imageBuilder = new ImageBuilder(this,
|
||||||
|
env.workroot + "/" + component.root + "/",
|
||||||
|
component.imageBuildRoot,
|
||||||
|
component.dockerfilePath,
|
||||||
|
imageBuilderType
|
||||||
|
)
|
||||||
|
|
||||||
log.info("Pipeline", "Retrieve version of image from pervious stage...")
|
log.info("Pipeline", "Retrieve version of image from pervious stage...")
|
||||||
if (env.LATEST_VERSION == null || env.LATEST_VERSION.isEmpty()) {
|
if (env.LATEST_VERSION == null || env.LATEST_VERSION.isEmpty()) {
|
||||||
@ -423,7 +428,10 @@ def generateComponentStages(component, configurations) {
|
|||||||
}
|
}
|
||||||
def version
|
def version
|
||||||
|
|
||||||
imageBuilder.build(component.imageName, component.imageRepository, component.imageRegistry, component.imageReleaseArchitectures, env.LATEST_VERSION, component.registryCredentialsId)
|
imageBuilder.setManifestsOfImage(component.imageRegistry, component.imageRepository, component.imageName, env.LATEST_VERSION)
|
||||||
|
imageBuilder.useCredentials(component.registryCredentialsId)
|
||||||
|
imageBuilder.setArchitectures(component.imageReleaseArchitectures)
|
||||||
|
imageBuilder.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user