github.com/GoogleContainerTools/skaffold@v1.39.18/pkg/skaffold/build/jib/gradle.go (about)

     1  /*
     2  Copyright 2019 The Skaffold Authors
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package jib
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"io"
    23  	"os/exec"
    24  
    25  	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/docker"
    26  	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/output"
    27  	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/output/log"
    28  	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/platform"
    29  	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest"
    30  	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/util"
    31  )
    32  
    33  // For testing
    34  var (
    35  	gradleArgsFunc      = gradleArgs
    36  	gradleBuildArgsFunc = gradleBuildArgs
    37  )
    38  
    39  // Skaffold-Jib depends on functionality introduced with Jib-Gradle 1.4.0
    40  const MinimumJibGradleVersion = "1.4.0"
    41  const MinimumJibGradleVersionForSync = "2.0.0"
    42  const MinimumJibGradleVersionForCrossPlatform = "3.2.0"
    43  
    44  // GradleCommand stores Gradle executable and wrapper name
    45  var GradleCommand = util.CommandWrapper{Executable: "gradle", Wrapper: "gradlew"}
    46  
    47  func (b *Builder) buildJibGradleToDocker(ctx context.Context, out io.Writer, workspace string, artifact *latest.JibArtifact, deps []*latest.ArtifactDependency, tag string, platforms platform.Matcher) (string, error) {
    48  	args := GenerateGradleBuildArgs("jibDockerBuild", tag, artifact, platforms, b.skipTests, b.pushImages, deps, b.artifacts, b.cfg.GetInsecureRegistries(), output.IsColorable(out))
    49  	if err := b.runGradleCommand(ctx, out, workspace, args); err != nil {
    50  		return "", jibToolErr(err)
    51  	}
    52  
    53  	return b.localDocker.ImageID(ctx, tag)
    54  }
    55  
    56  func (b *Builder) buildJibGradleToRegistry(ctx context.Context, out io.Writer, workspace string, artifact *latest.JibArtifact, deps []*latest.ArtifactDependency, tag string, platforms platform.Matcher) (string, error) {
    57  	args := GenerateGradleBuildArgs("jib", tag, artifact, platforms, b.skipTests, b.pushImages, deps, b.artifacts, b.cfg.GetInsecureRegistries(), output.IsColorable(out))
    58  	if err := b.runGradleCommand(ctx, out, workspace, args); err != nil {
    59  		return "", jibToolErr(err)
    60  	}
    61  
    62  	return docker.RemoteDigest(tag, b.cfg, nil)
    63  }
    64  
    65  func (b *Builder) runGradleCommand(ctx context.Context, out io.Writer, workspace string, args []string) error {
    66  	cmd := GradleCommand.CreateCommand(ctx, workspace, args)
    67  	cmd.Env = append(util.OSEnviron(), b.localDocker.ExtraEnv()...)
    68  	cmd.Stdout = out
    69  	cmd.Stderr = out
    70  
    71  	log.Entry(ctx).Infof("Building %s: %s, %v", workspace, cmd.Path, cmd.Args)
    72  	if err := util.RunCmd(ctx, &cmd); err != nil {
    73  		return fmt.Errorf("gradle build failed: %w", err)
    74  	}
    75  
    76  	return nil
    77  }
    78  
    79  // getDependenciesGradle finds the source dependencies for the given jib-gradle artifact.
    80  // All paths are absolute.
    81  func getDependenciesGradle(ctx context.Context, workspace string, a *latest.JibArtifact) ([]string, error) {
    82  	cmd := getCommandGradle(ctx, workspace, a)
    83  	deps, err := getDependencies(ctx, workspace, cmd, a)
    84  	if err != nil {
    85  		return nil, dependencyErr(JibGradle, workspace, err)
    86  	}
    87  	log.Entry(ctx).Debugf("Found dependencies for jib-gradle artifact: %v", deps)
    88  	return deps, nil
    89  }
    90  
    91  func getCommandGradle(ctx context.Context, workspace string, a *latest.JibArtifact) exec.Cmd {
    92  	args := append(gradleArgsFunc(a, "_jibSkaffoldFilesV2", MinimumJibGradleVersion), "-q", "--console=plain")
    93  	return GradleCommand.CreateCommand(ctx, workspace, args)
    94  }
    95  
    96  func getSyncMapCommandGradle(ctx context.Context, workspace string, a *latest.JibArtifact) *exec.Cmd {
    97  	cmd := GradleCommand.CreateCommand(ctx, workspace, gradleBuildArgsFunc("_jibSkaffoldSyncMap", a, true, false, MinimumJibMavenVersionForSync))
    98  	return &cmd
    99  }
   100  
   101  // GenerateGradleBuildArgs generates the arguments to Gradle for building the project as an image.
   102  func GenerateGradleBuildArgs(task, imageName string, a *latest.JibArtifact, platforms platform.Matcher, skipTests, pushImages bool, deps []*latest.ArtifactDependency, r ArtifactResolver, insecureRegistries map[string]bool, showColors bool) []string {
   103  	minVersion := MinimumJibGradleVersion
   104  	if platforms.IsCrossPlatform() {
   105  		minVersion = MinimumJibGradleVersionForCrossPlatform
   106  	}
   107  	args := gradleBuildArgsFunc(task, a, skipTests, showColors, minVersion)
   108  	if insecure, err := isOnInsecureRegistry(imageName, insecureRegistries); err == nil && insecure {
   109  		// jib doesn't support marking specific registries as insecure
   110  		args = append(args, "-Djib.allowInsecureRegistries=true")
   111  	}
   112  	if baseImg, found := baseImageArg(a, r, deps, pushImages); found {
   113  		args = append(args, baseImg)
   114  	}
   115  	if platforms.IsNotEmpty() {
   116  		args = append(args, fmt.Sprintf("-Djib.from.platforms=%s", platforms.String()))
   117  	}
   118  	args = append(args, "--image="+imageName)
   119  	return args
   120  }
   121  
   122  // Do not use directly, use gradleBuildArgsFunc
   123  func gradleBuildArgs(task string, a *latest.JibArtifact, skipTests, showColors bool, minimumVersion string) []string {
   124  	// Disable jib's rich progress footer on builds. Show colors on normal builds for clearer information,
   125  	// but use --console=plain for internal goals to avoid formatting issues
   126  	var args []string
   127  	if showColors {
   128  		args = []string{"-Djib.console=plain"}
   129  	} else {
   130  		args = []string{"--console=plain"}
   131  	}
   132  	args = append(args, gradleArgsFunc(a, task, minimumVersion)...)
   133  
   134  	if skipTests {
   135  		args = append(args, "-x", "test")
   136  	}
   137  	args = append(args, a.Flags...)
   138  	return args
   139  }
   140  
   141  // Do not use directly, use gradleArgsFunc
   142  func gradleArgs(a *latest.JibArtifact, task string, minimumVersion string) []string {
   143  	args := []string{"_skaffoldFailIfJibOutOfDate", "-Djib.requiredVersion=" + minimumVersion}
   144  	if a.Project == "" {
   145  		return append(args, ":"+task)
   146  	}
   147  
   148  	// multi-module
   149  	return append(args, fmt.Sprintf(":%s:%s", a.Project, task))
   150  }