All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.gesellix.gradle.docker.tasks.DockerBuildTask.groovy Maven / Gradle / Ivy

package de.gesellix.gradle.docker.tasks

import de.gesellix.docker.client.authentication.AuthConfig
import de.gesellix.docker.client.image.BuildConfig
import de.gesellix.gradle.docker.worker.BuildcontextArchiver
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputDirectory
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.TaskAction
import org.gradle.workers.WorkerExecutor

import javax.inject.Inject

class DockerBuildTask extends GenericDockerTask {

    def buildContextDirectory

    @Input
    @Optional
    def imageName

    @Input
    @Optional
    InputStream buildContext

    @InputDirectory
    @Optional
    File getBuildContextDirectory() {
        buildContextDirectory ? project.file(this.buildContextDirectory) : null
    }

    @Input
    @Optional
    def buildParams

    @Input
    @Optional
    def buildOptions

    /**
     * A map of registry URL name to AuthConfig.
     *
     * Only the registry domain name (and port if not the default 443) are required. However, for legacy reasons, the Docker Hub registry must be specified with both a https:// prefix and a /v1/ suffix even though Docker will prefer to use the v2 registry API.
     *
     * See https://docs.docker.com/engine/api/v1.40/#operation/ImageBuild for reference.
     */
    @Input
    @Optional
    Map authConfigs = [:]

    @Input
    @Optional
    def enableBuildLog = false

    @Internal
    File targetFile

    @Internal
    def imageId

    @Internal
    WorkerExecutor workerExecutor

    @Inject
    DockerBuildTask(WorkerExecutor workerExecutor) {
        this.workerExecutor = workerExecutor

        description = "Build an image from a Dockerfile"
        group = "Docker"

//    addValidator(new TaskValidator() {
//      @Override
//      void validate(TaskInternal task, Collection messages) {
//        if (getBuildContextDirectory() && getBuildContext()) {
//          messages.add("Please provide only one of buildContext and buildContextDirectory")
//        }
//        if (!getBuildContextDirectory() && !getBuildContext()) {
//          messages.add("Please provide either buildContext or buildContextDirectory")
//        }
//      }
//    })
    }

    @TaskAction
    def build() {
        logger.info "docker build"

        if (getBuildContextDirectory()) {
            // only one of buildContext and buildContextDirectory shall be provided
            assert !getBuildContext()
            buildContext = createBuildContextFromDirectory()
        }

        // at this point we need the buildContext
        assert getBuildContext()

        // Add tag to build params
        def buildParams = getBuildParams() ?: [rm: true]
        if (getImageName()) {
            buildParams.putIfAbsent("rm", true)
            if (buildParams.t) {
                logger.warn "Overriding build parameter \"t\" with imageName as both were given"
            }
            buildParams.t = getImageName() as String
        }

        if (getAuthConfig() != '') {
            logger.info("Docker Build requires a Map of AuthConfig by registry name. The configured 'authConfig' will be ignored." +
                        " Please use the 'authConfigs' (plural form) task parameter if you need to override the DockerClient's default behaviour.")
        }
        Map buildOptions = getBuildOptions() ?: [:] as Map
        if (!buildOptions['EncodedRegistryConfig'] && getAuthConfigs() != [:]) {
            buildOptions['EncodedRegistryConfig'] = getDockerClient().encodeAuthConfigs(getAuthConfigs())
        }

        // TODO this one needs some beautification
        if (getEnableBuildLog()) {
            imageId = getDockerClient().buildWithLogs(getBuildContext(), new BuildConfig(query: buildParams, options: buildOptions)).imageId
        }
        else {
            imageId = getDockerClient().build(getBuildContext(), new BuildConfig(query: buildParams, options: buildOptions)).imageId
        }

        return imageId
    }

    @Internal
    def getNormalizedImageName() {
        if (!getImageName()) {
            return UUID.randomUUID().toString()
        }
        return getImageName().replaceAll("\\W", "_")
    }

    InputStream createBuildContextFromDirectory() {
        targetFile = new File(getTemporaryDir(), "buildContext_${getNormalizedImageName()}.tar.gz")
//            outputs.file(targetFile.absolutePath)
//            outputs.upToDateWhen { false }
        workerExecutor.noIsolation().submit(BuildcontextArchiver) { parameters ->
            parameters.sourceDirectory.set(getBuildContextDirectory())
            parameters.archivedTargetFile.set(targetFile)
        }
        workerExecutor.await()

        logger.info "temporary buildContext: ${targetFile}"
        return new FileInputStream(targetFile as File)
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy