diff --git a/deprecation-policy.md b/deprecation-policy.md index 35cd3b90f85..bfdaa093e55 100644 --- a/deprecation-policy.md +++ b/deprecation-policy.md @@ -54,8 +54,7 @@ However the **behavior** of individual component might suffer breaking changes d - Artifact types: - Dockerfile: beta - Bazel: beta - - jibMaven: alpha - - jibGradle: alpha + - Jib: beta - Filesync: alpha - Port-forwarding: alpha - Taggers: beta diff --git a/docs/content/en/docs/how-tos/builders/_index.md b/docs/content/en/docs/how-tos/builders/_index.md index f28b3df121b..2dfc1ca956f 100755 --- a/docs/content/en/docs/how-tos/builders/_index.md +++ b/docs/content/en/docs/how-tos/builders/_index.md @@ -161,7 +161,7 @@ Skaffold requires using Jib v1.4.0 or later. ### Configuration -To use Jib, add a `jibMaven` or `jibGradle` field to each artifact you specify in the +To use Jib, add a `jib` field to each artifact you specify in the `artifacts` part of the `build` section. `context` should be a path to your Maven or Gradle project. @@ -169,13 +169,18 @@ your Maven or Gradle project. Your project must be configured to use Jib already. {{< /alert >}} -The `jibMaven` type offers the following options: +The `jib` type offers the following options: -{{< schema root="JibMavenArtifact" >}} +{{< schema root="JibArtifact" >}} -The `jibGradle` type offers the following options: +Skaffold's jib support chooses the underlying builder (Maven or Gradle) +based on the presence of standard build files in the `artifact`'s +`context` directory: -{{< schema root="JibGradleArtifact" >}} + - _Maven_: `pom.xml`, or `.mvn` directory. + - _Gradle_: `build.gradle`, `gradle.properties`, `settings.gradle`, + or the Gradle wrapper script (`gradlew`, `gradlew.bat`, or + `gradlew.cmd`). ### Example @@ -190,13 +195,13 @@ each produce a separate container image. #### Maven -To build a Maven multi-module project, first identify the modules that should -produce a container image. Then for each such module: +To build a Maven multi-module project, first identify the sub-projects (also called _modules_ +in Maven) that should produce a container image. Then for each such sub-project: - - Create a Skaffold `artifact` in the `skaffold.yaml`: + - Create a Skaffold `artifact` in the `skaffold.yaml`. - Set the `artifact`'s `context` field to the root project location. - - Add a `jibMaven` element and set its `module` field to the module's - `:artifactId`, `groupId:artifactId`, or the relative path to the module + - Add a `jib` element and set its `project` field to the sub-project's + `:artifactId`, `groupId:artifactId`, or the relative path to the sub-project _within the project_. {{% alert title="Updating from earlier versions" %}} @@ -207,10 +212,12 @@ no longer required with Jib 1.4.0 and should be removed. #### Gradle -To build a multi-module project with Gradle, specify each sub-project as a separate -Skaffold artifact. For each artifact, add a `jibGradle` field with a `project` field -containing the sub-project's name (the directory, by default). Each artifact's `context` field -should point to the root project location. +To build a multi-module project with Gradle, first identify the sub-projects that should produce +a container image. Then for each such sub-project: + + - Create a Skaffold `artifact` in the `skaffold.yaml`. + - Set the `artifact`'s `context` field to the root project location. + - Add a `jib` element and set its `project` field to the sub-project's name (the directory, by default). ## Jib Maven and Gradle remotely with Google Cloud Build diff --git a/docs/content/en/schemas/v1beta14.json b/docs/content/en/schemas/v1beta14.json index d0fe01a2594..b67cc7d7943 100755 --- a/docs/content/en/schemas/v1beta14.json +++ b/docs/content/en/schemas/v1beta14.json @@ -163,10 +163,10 @@ "gcr.io/k8s-skaffold/example" ] }, - "jibMaven": { - "$ref": "#/definitions/JibMavenArtifact", - "description": "*alpha* builds images using the [Jib plugin for Maven](https://github.com/GoogleContainerTools/jib/tree/master/jib-maven-plugin).", - "x-intellij-html-description": "alpha builds images using the Jib plugin for Maven." + "jib": { + "$ref": "#/definitions/JibArtifact", + "description": "*alpha* builds images using the [Jib plugins for Maven or Gradle](https://github.com/GoogleContainerTools/jib/).", + "x-intellij-html-description": "alpha builds images using the Jib plugins for Maven or Gradle." }, "sync": { "$ref": "#/definitions/Sync", @@ -178,42 +178,7 @@ "image", "context", "sync", - "jibMaven" - ], - "additionalProperties": false - }, - { - "properties": { - "context": { - "type": "string", - "description": "directory containing the artifact's sources.", - "x-intellij-html-description": "directory containing the artifact's sources.", - "default": "." - }, - "image": { - "type": "string", - "description": "name of the image to be built.", - "x-intellij-html-description": "name of the image to be built.", - "examples": [ - "gcr.io/k8s-skaffold/example" - ] - }, - "jibGradle": { - "$ref": "#/definitions/JibGradleArtifact", - "description": "*alpha* builds images using the [Jib plugin for Gradle](https://github.com/GoogleContainerTools/jib/tree/master/jib-gradle-plugin).", - "x-intellij-html-description": "alpha builds images using the Jib plugin for Gradle." - }, - "sync": { - "$ref": "#/definitions/Sync", - "description": "*alpha* local files synced to pods instead of triggering an image build when modified.", - "x-intellij-html-description": "alpha local files synced to pods instead of triggering an image build when modified." - } - }, - "preferredOrder": [ - "image", - "context", - "sync", - "jibGradle" + "jib" ], "additionalProperties": false }, @@ -1236,15 +1201,15 @@ "description": "patch to be applied by a profile.", "x-intellij-html-description": "patch to be applied by a profile." }, - "JibGradleArtifact": { + "JibArtifact": { "properties": { "args": { "items": { "type": "string" }, "type": "array", - "description": "additional build flags passed to Gradle.", - "x-intellij-html-description": "additional build flags passed to Gradle.", + "description": "additional build flags passed to the builder.", + "x-intellij-html-description": "additional build flags passed to the builder.", "default": "[]", "examples": [ "[\"--no-build-cache\"]" @@ -1252,8 +1217,8 @@ }, "project": { "type": "string", - "description": "selects which Gradle project to build.", - "x-intellij-html-description": "selects which Gradle project to build." + "description": "selects which sub-project to build for multi-module builds.", + "x-intellij-html-description": "selects which sub-project to build for multi-module builds." } }, "preferredOrder": [ @@ -1261,42 +1226,8 @@ "args" ], "additionalProperties": false, - "description": "*alpha* builds images using the [Jib plugin for Gradle](https://github.com/GoogleContainerTools/jib/tree/master/jib-gradle-plugin).", - "x-intellij-html-description": "alpha builds images using the Jib plugin for Gradle." - }, - "JibMavenArtifact": { - "properties": { - "args": { - "items": { - "type": "string" - }, - "type": "array", - "description": "additional build flags passed to Maven.", - "x-intellij-html-description": "additional build flags passed to Maven.", - "default": "[]", - "examples": [ - "[\"-x\", \"-DskipTests\"]" - ] - }, - "module": { - "type": "string", - "description": "selects which Maven module to build, for a multi module project.", - "x-intellij-html-description": "selects which Maven module to build, for a multi module project." - }, - "profile": { - "type": "string", - "description": "selects which Maven profile to activate.", - "x-intellij-html-description": "selects which Maven profile to activate." - } - }, - "preferredOrder": [ - "module", - "profile", - "args" - ], - "additionalProperties": false, - "description": "*alpha* builds images using the [Jib plugin for Maven](https://github.com/GoogleContainerTools/jib/tree/master/jib-maven-plugin).", - "x-intellij-html-description": "alpha builds images using the Jib plugin for Maven." + "description": "*alpha* builds images using the [Jib plugins for Maven and Gradle](https://github.com/GoogleContainerTools/jib/).", + "x-intellij-html-description": "alpha builds images using the Jib plugins for Maven and Gradle." }, "KanikoArtifact": { "properties": { diff --git a/integration/examples/jib-gradle/skaffold.yaml b/integration/examples/jib-gradle/skaffold.yaml index 51253318cd1..f5e6c290020 100644 --- a/integration/examples/jib-gradle/skaffold.yaml +++ b/integration/examples/jib-gradle/skaffold.yaml @@ -3,7 +3,7 @@ kind: Config build: artifacts: - image: gcr.io/k8s-skaffold/skaffold-jib-gradle - jibGradle: {} + jib: {} # optional profile to run the jib build on Google Cloud Build profiles: diff --git a/integration/examples/jib-multimodule/README.adoc b/integration/examples/jib-multimodule/README.adoc index f1ea1431d23..7dfdcbd5b45 100644 --- a/integration/examples/jib-multimodule/README.adoc +++ b/integration/examples/jib-multimodule/README.adoc @@ -2,10 +2,10 @@ :icons: font Jib is one of the supported builders in Skaffold. -[Jib](https://github.com/GoogleContainerTools/jib) builds Docker and OCI images +https://github.com/GoogleContainerTools/jib[Jib] builds Docker and OCI images for your Java applications and is available as plugins for Maven and Gradle. -Sometimes a project is configured to have multiple modules to create several +Sometimes a project is configured to have multiple _modules_ to create several container images. Skaffold can work with Jib to build these containers as required. @@ -18,14 +18,17 @@ build: - image: gcr.io/k8s-skaffold/skaffold-jib-1 # context is the root of the multi-module project context: . - jibMaven: - # module is either the relative location within the project (i.e., - # relative to `context`) or :artifactId or groupId:artifactId - module: moduleLocation + jib: + # project is the location relative to the artifact `context` + # For Maven, this is either the path relative to the artifact's + # `context`, or `:artifactId` or `groupId:artifactId`. + # For Gradle, this is the project name (defaults to the + # directory name). + project: moduleLocation - image: gcr.io/k8s-skaffold/skaffold-jib-2 context: . - jibMaven: - module: :artifactId + jib: + project: :artifactId ---- There are a few caveats: diff --git a/integration/examples/jib-multimodule/skaffold.yaml b/integration/examples/jib-multimodule/skaffold.yaml index de437207070..1119cb6d3e1 100644 --- a/integration/examples/jib-multimodule/skaffold.yaml +++ b/integration/examples/jib-multimodule/skaffold.yaml @@ -3,13 +3,13 @@ kind: Config build: artifacts: - image: gcr.io/k8s-skaffold/skaffold-jib-1 - jibMaven: - # module can be the relative directory - module: project1 + jib: + # project can be the relative directory + project: project1 - image: gcr.io/k8s-skaffold/skaffold-jib-2 - jibMaven: - # module can be [groupId]:artifactId - module: :skaffold-project-2 + jib: + # project can be [groupId]:artifactId + project: :skaffold-project-2 # optional profile to run the jib build on Google Cloud Build profiles: diff --git a/integration/examples/jib/README.adoc b/integration/examples/jib/README.adoc index af6473958a7..1c49e6c847a 100644 --- a/integration/examples/jib/README.adoc +++ b/integration/examples/jib/README.adoc @@ -13,7 +13,7 @@ build: artifacts: - image: gcr.io/k8s-skaffold/skaffold-example context: . - jibMaven: {} + jib: {} ---- Please note that this example is for a standalone Maven project, where diff --git a/integration/examples/jib/skaffold.yaml b/integration/examples/jib/skaffold.yaml index 82f603cee09..3307be5511d 100644 --- a/integration/examples/jib/skaffold.yaml +++ b/integration/examples/jib/skaffold.yaml @@ -3,7 +3,7 @@ kind: Config build: artifacts: - image: gcr.io/k8s-skaffold/skaffold-jib - jibMaven: {} + jib: {} # optional profile to run the jib build on Google Cloud Build profiles: diff --git a/integration/testdata/debug/skaffold.yaml b/integration/testdata/debug/skaffold.yaml index 5aa6dff199d..c1b0bbdd907 100644 --- a/integration/testdata/debug/skaffold.yaml +++ b/integration/testdata/debug/skaffold.yaml @@ -1,10 +1,10 @@ -apiVersion: skaffold/v1beta10 +apiVersion: skaffold/v1beta14 kind: Config build: artifacts: - image: gcr.io/k8s-skaffold/skaffold-debug-jib context: jib - jibMaven: + jib: args: - --no-transfer-progress - image: gcr.io/k8s-skaffold/skaffold-debug-npm diff --git a/integration/testdata/jib-gradle/skaffold.yaml b/integration/testdata/jib-gradle/skaffold.yaml index 034798a8091..7aa749fea4a 100644 --- a/integration/testdata/jib-gradle/skaffold.yaml +++ b/integration/testdata/jib-gradle/skaffold.yaml @@ -3,7 +3,7 @@ kind: Config build: artifacts: - image: gcr.io/k8s-skaffold/skaffold-jib - jibGradle: {} + jib: {} profiles: - name: gcb diff --git a/integration/testdata/jib/skaffold.yaml b/integration/testdata/jib/skaffold.yaml index b2ac251cdda..5069f1cccef 100644 --- a/integration/testdata/jib/skaffold.yaml +++ b/integration/testdata/jib/skaffold.yaml @@ -3,7 +3,7 @@ kind: Config build: artifacts: - image: gcr.io/k8s-skaffold/skaffold-jib - jibMaven: + jib: args: - --no-transfer-progress @@ -16,5 +16,5 @@ profiles: - name: old-jib patches: - op: add - path: /build/artifacts/0/jibMaven/args + path: /build/artifacts/0/jib/args value: ['-Djib.maven-plugin-version=1.3.0'] diff --git a/pkg/skaffold/build/gcb/jib.go b/pkg/skaffold/build/gcb/jib.go index 3f90509c370..466c8089b58 100644 --- a/pkg/skaffold/build/gcb/jib.go +++ b/pkg/skaffold/build/gcb/jib.go @@ -21,26 +21,35 @@ import ( "github.com/GoogleContainerTools/skaffold/pkg/skaffold/jib" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" + "github.com/pkg/errors" cloudbuild "google.golang.org/api/cloudbuild/v1" ) -func (b *Builder) jibMavenBuildSpec(artifact *latest.JibMavenArtifact, tag string) cloudbuild.Build { - return cloudbuild.Build{ - Steps: []*cloudbuild.BuildStep{{ - Name: b.MavenImage, - Entrypoint: "sh", - Args: fixHome("mvn", jib.GenerateMavenArgs("build", tag, artifact, b.skipTests, b.insecureRegistries)), - }}, +func (b *Builder) jibBuildSpec(artifact *latest.Artifact, tag string) (cloudbuild.Build, error) { + t, err := jib.DeterminePluginType(artifact.Workspace, artifact.JibArtifact) + if err != nil { + return cloudbuild.Build{}, err } -} -func (b *Builder) jibGradleBuildSpec(artifact *latest.JibGradleArtifact, tag string) cloudbuild.Build { - return cloudbuild.Build{ - Steps: []*cloudbuild.BuildStep{{ - Name: b.GradleImage, - Entrypoint: "sh", - Args: fixHome("gradle", jib.GenerateGradleArgs("jib", tag, artifact, b.skipTests, b.insecureRegistries)), - }}, + switch t { + case jib.JibMaven: + return cloudbuild.Build{ + Steps: []*cloudbuild.BuildStep{{ + Name: b.MavenImage, + Entrypoint: "sh", + Args: fixHome("mvn", jib.GenerateMavenArgs("build", tag, artifact.JibArtifact, b.skipTests, b.insecureRegistries)), + }}, + }, nil + case jib.JibGradle: + return cloudbuild.Build{ + Steps: []*cloudbuild.BuildStep{{ + Name: b.GradleImage, + Entrypoint: "sh", + Args: fixHome("gradle", jib.GenerateGradleArgs("jib", tag, artifact.JibArtifact, b.skipTests, b.insecureRegistries)), + }}, + }, nil + default: + return cloudbuild.Build{}, errors.New("skaffold can't determine Jib artifact type for Google Cloud Build") } } diff --git a/pkg/skaffold/build/gcb/jib_test.go b/pkg/skaffold/build/gcb/jib_test.go index fb273625aef..a7ba2c021d9 100644 --- a/pkg/skaffold/build/gcb/jib_test.go +++ b/pkg/skaffold/build/gcb/jib_test.go @@ -46,7 +46,7 @@ func TestJibMavenBuildSpec(t *testing.T) { testutil.Run(t, test.description, func(t *testutil.T) { artifact := &latest.Artifact{ ArtifactType: latest.ArtifactType{ - JibMavenArtifact: &latest.JibMavenArtifact{}, + JibArtifact: &latest.JibArtifact{Type: int(jib.JibMaven)}, }, } @@ -91,7 +91,7 @@ func TestJibGradleBuildSpec(t *testing.T) { testutil.Run(t, test.description, func(t *testutil.T) { artifact := &latest.Artifact{ ArtifactType: latest.ArtifactType{ - JibGradleArtifact: &latest.JibGradleArtifact{}, + JibArtifact: &latest.JibArtifact{Type: int(jib.JibGradle)}, }, } diff --git a/pkg/skaffold/build/gcb/spec.go b/pkg/skaffold/build/gcb/spec.go index 4e9411dd31f..17545e2f793 100644 --- a/pkg/skaffold/build/gcb/spec.go +++ b/pkg/skaffold/build/gcb/spec.go @@ -56,11 +56,8 @@ func (b *Builder) buildSpecForArtifact(artifact *latest.Artifact, tag string) (c case artifact.DockerArtifact != nil: return b.dockerBuildSpec(artifact.DockerArtifact, tag) - case artifact.JibMavenArtifact != nil: - return b.jibMavenBuildSpec(artifact.JibMavenArtifact, tag), nil - - case artifact.JibGradleArtifact != nil: - return b.jibGradleBuildSpec(artifact.JibGradleArtifact, tag), nil + case artifact.JibArtifact != nil: + return b.jibBuildSpec(artifact, tag) case artifact.BazelArtifact != nil: return cloudbuild.Build{}, errors.New("skaffold can't build a bazel artifact with Google Cloud Build") diff --git a/pkg/skaffold/build/gcb/types.go b/pkg/skaffold/build/gcb/types.go index 53a207302de..b3bd8f9f046 100644 --- a/pkg/skaffold/build/gcb/types.go +++ b/pkg/skaffold/build/gcb/types.go @@ -118,14 +118,8 @@ func (b *Builder) DependenciesForArtifact(ctx context.Context, a *latest.Artifac return nil, errors.Wrapf(err, "getting dependencies for %s", a.ImageName) } } - if a.JibMavenArtifact != nil { - paths, err = jib.GetDependenciesMaven(ctx, a.Workspace, a.JibMavenArtifact) - if err != nil { - return nil, errors.Wrapf(err, "getting dependencies for %s", a.ImageName) - } - } - if a.JibGradleArtifact != nil { - paths, err = jib.GetDependenciesGradle(ctx, a.Workspace, a.JibGradleArtifact) + if a.JibArtifact != nil { + paths, err = jib.GetDependencies(ctx, a.Workspace, a.JibArtifact) if err != nil { return nil, errors.Wrapf(err, "getting dependencies for %s", a.ImageName) } diff --git a/pkg/skaffold/build/local/jib_gradle.go b/pkg/skaffold/build/local/jib_gradle.go index 2578baf3607..292763eb809 100644 --- a/pkg/skaffold/build/local/jib_gradle.go +++ b/pkg/skaffold/build/local/jib_gradle.go @@ -28,14 +28,14 @@ import ( "github.com/sirupsen/logrus" ) -func (b *Builder) buildJibGradle(ctx context.Context, out io.Writer, workspace string, artifact *latest.JibGradleArtifact, tag string) (string, error) { +func (b *Builder) buildJibGradle(ctx context.Context, out io.Writer, workspace string, artifact *latest.JibArtifact, tag string) (string, error) { if b.pushImages { return b.buildJibGradleToRegistry(ctx, out, workspace, artifact, tag) } return b.buildJibGradleToDocker(ctx, out, workspace, artifact, tag) } -func (b *Builder) buildJibGradleToDocker(ctx context.Context, out io.Writer, workspace string, artifact *latest.JibGradleArtifact, tag string) (string, error) { +func (b *Builder) buildJibGradleToDocker(ctx context.Context, out io.Writer, workspace string, artifact *latest.JibArtifact, tag string) (string, error) { args := jib.GenerateGradleArgs("jibDockerBuild", tag, artifact, b.skipTests, b.insecureRegistries) if err := b.runGradleCommand(ctx, out, workspace, args); err != nil { return "", err @@ -44,7 +44,7 @@ func (b *Builder) buildJibGradleToDocker(ctx context.Context, out io.Writer, wor return b.localDocker.ImageID(ctx, tag) } -func (b *Builder) buildJibGradleToRegistry(ctx context.Context, out io.Writer, workspace string, artifact *latest.JibGradleArtifact, tag string) (string, error) { +func (b *Builder) buildJibGradleToRegistry(ctx context.Context, out io.Writer, workspace string, artifact *latest.JibArtifact, tag string) (string, error) { args := jib.GenerateGradleArgs("jib", tag, artifact, b.skipTests, b.insecureRegistries) if err := b.runGradleCommand(ctx, out, workspace, args); err != nil { return "", err diff --git a/pkg/skaffold/build/local/jib_gradle_test.go b/pkg/skaffold/build/local/jib_gradle_test.go index 15dc55850d8..aa5d92bcb95 100644 --- a/pkg/skaffold/build/local/jib_gradle_test.go +++ b/pkg/skaffold/build/local/jib_gradle_test.go @@ -33,35 +33,35 @@ import ( func TestBuildJibGradleToDocker(t *testing.T) { tests := []struct { description string - artifact *latest.JibGradleArtifact + artifact *latest.JibArtifact commands util.Command shouldErr bool expectedError string }{ { description: "build", - artifact: &latest.JibGradleArtifact{}, + artifact: &latest.JibArtifact{}, commands: testutil.CmdRun( "gradle -Djib.console=plain _skaffoldFailIfJibOutOfDate -Djib.requiredVersion=" + jib.MinimumJibGradleVersion + " :jibDockerBuild --image=img:tag", ), }, { description: "build with additional flags", - artifact: &latest.JibGradleArtifact{Flags: []string{"--flag1", "--flag2"}}, + artifact: &latest.JibArtifact{Flags: []string{"--flag1", "--flag2"}}, commands: testutil.CmdRun( "gradle -Djib.console=plain _skaffoldFailIfJibOutOfDate -Djib.requiredVersion=" + jib.MinimumJibGradleVersion + " :jibDockerBuild --image=img:tag --flag1 --flag2", ), }, { description: "build with project", - artifact: &latest.JibGradleArtifact{Project: "project"}, + artifact: &latest.JibArtifact{Project: "project"}, commands: testutil.CmdRun( "gradle -Djib.console=plain _skaffoldFailIfJibOutOfDate -Djib.requiredVersion=" + jib.MinimumJibGradleVersion + " :project:jibDockerBuild --image=img:tag", ), }, { description: "fail build", - artifact: &latest.JibGradleArtifact{}, + artifact: &latest.JibArtifact{}, commands: testutil.CmdRunErr( "gradle -Djib.console=plain _skaffoldFailIfJibOutOfDate -Djib.requiredVersion="+jib.MinimumJibGradleVersion+" :jibDockerBuild --image=img:tag", errors.New("BUG"), @@ -100,35 +100,35 @@ func TestBuildJibGradleToDocker(t *testing.T) { func TestBuildJibGradleToRegistry(t *testing.T) { tests := []struct { description string - artifact *latest.JibGradleArtifact + artifact *latest.JibArtifact commands util.Command shouldErr bool expectedError string }{ { description: "remote build", - artifact: &latest.JibGradleArtifact{}, + artifact: &latest.JibArtifact{}, commands: testutil.CmdRun( "gradle -Djib.console=plain _skaffoldFailIfJibOutOfDate -Djib.requiredVersion=" + jib.MinimumJibGradleVersion + " :jib --image=img:tag", ), }, { description: "build with additional flags", - artifact: &latest.JibGradleArtifact{Flags: []string{"--flag1", "--flag2"}}, + artifact: &latest.JibArtifact{Flags: []string{"--flag1", "--flag2"}}, commands: testutil.CmdRun( "gradle -Djib.console=plain _skaffoldFailIfJibOutOfDate -Djib.requiredVersion=" + jib.MinimumJibGradleVersion + " :jib --image=img:tag --flag1 --flag2", ), }, { description: "build with project", - artifact: &latest.JibGradleArtifact{Project: "project"}, + artifact: &latest.JibArtifact{Project: "project"}, commands: testutil.CmdRun( "gradle -Djib.console=plain _skaffoldFailIfJibOutOfDate -Djib.requiredVersion=" + jib.MinimumJibGradleVersion + " :project:jib --image=img:tag", ), }, { description: "fail build", - artifact: &latest.JibGradleArtifact{}, + artifact: &latest.JibArtifact{}, commands: testutil.CmdRunErr( "gradle -Djib.console=plain _skaffoldFailIfJibOutOfDate -Djib.requiredVersion="+jib.MinimumJibGradleVersion+" :jib --image=img:tag", errors.New("BUG"), diff --git a/pkg/skaffold/build/local/jib_maven.go b/pkg/skaffold/build/local/jib_maven.go index e35309cd260..93de77ab0ca 100644 --- a/pkg/skaffold/build/local/jib_maven.go +++ b/pkg/skaffold/build/local/jib_maven.go @@ -28,14 +28,14 @@ import ( "github.com/sirupsen/logrus" ) -func (b *Builder) buildJibMaven(ctx context.Context, out io.Writer, workspace string, artifact *latest.JibMavenArtifact, tag string) (string, error) { +func (b *Builder) buildJibMaven(ctx context.Context, out io.Writer, workspace string, artifact *latest.JibArtifact, tag string) (string, error) { if b.pushImages { return b.buildJibMavenToRegistry(ctx, out, workspace, artifact, tag) } return b.buildJibMavenToDocker(ctx, out, workspace, artifact, tag) } -func (b *Builder) buildJibMavenToDocker(ctx context.Context, out io.Writer, workspace string, artifact *latest.JibMavenArtifact, tag string) (string, error) { +func (b *Builder) buildJibMavenToDocker(ctx context.Context, out io.Writer, workspace string, artifact *latest.JibArtifact, tag string) (string, error) { args := jib.GenerateMavenArgs("dockerBuild", tag, artifact, b.skipTests, b.insecureRegistries) if err := b.runMavenCommand(ctx, out, workspace, args); err != nil { return "", err @@ -44,7 +44,7 @@ func (b *Builder) buildJibMavenToDocker(ctx context.Context, out io.Writer, work return b.localDocker.ImageID(ctx, tag) } -func (b *Builder) buildJibMavenToRegistry(ctx context.Context, out io.Writer, workspace string, artifact *latest.JibMavenArtifact, tag string) (string, error) { +func (b *Builder) buildJibMavenToRegistry(ctx context.Context, out io.Writer, workspace string, artifact *latest.JibArtifact, tag string) (string, error) { args := jib.GenerateMavenArgs("build", tag, artifact, b.skipTests, b.insecureRegistries) if err := b.runMavenCommand(ctx, out, workspace, args); err != nil { return "", err diff --git a/pkg/skaffold/build/local/jib_maven_test.go b/pkg/skaffold/build/local/jib_maven_test.go index 670328057fd..078e3617418 100644 --- a/pkg/skaffold/build/local/jib_maven_test.go +++ b/pkg/skaffold/build/local/jib_maven_test.go @@ -33,42 +33,35 @@ import ( func TestBuildJibMavenToDocker(t *testing.T) { tests := []struct { description string - artifact *latest.JibMavenArtifact + artifact *latest.JibArtifact commands util.Command shouldErr bool expectedError string }{ { description: "build", - artifact: &latest.JibMavenArtifact{}, + artifact: &latest.JibArtifact{}, commands: testutil.CmdRun( "mvn -Djib.console=plain jib:_skaffold-fail-if-jib-out-of-date -Djib.requiredVersion=" + jib.MinimumJibMavenVersion + " --non-recursive prepare-package jib:dockerBuild -Dimage=img:tag", ), }, { description: "build with additional flags", - artifact: &latest.JibMavenArtifact{Flags: []string{"--flag1", "--flag2"}}, + artifact: &latest.JibArtifact{Flags: []string{"--flag1", "--flag2"}}, commands: testutil.CmdRun( "mvn -Djib.console=plain jib:_skaffold-fail-if-jib-out-of-date -Djib.requiredVersion=" + jib.MinimumJibMavenVersion + " --flag1 --flag2 --non-recursive prepare-package jib:dockerBuild -Dimage=img:tag", ), }, { description: "build with module", - artifact: &latest.JibMavenArtifact{Module: "module"}, + artifact: &latest.JibArtifact{Project: "module"}, commands: testutil.CmdRun( "mvn -Djib.console=plain jib:_skaffold-fail-if-jib-out-of-date -Djib.requiredVersion=" + jib.MinimumJibMavenVersion + " --projects module --also-make package jib:dockerBuild -Djib.containerize=module -Dimage=img:tag", ), }, - { - description: "build with module and profile", - artifact: &latest.JibMavenArtifact{Module: "module", Profile: "profile"}, - commands: testutil.CmdRun( - "mvn -Djib.console=plain jib:_skaffold-fail-if-jib-out-of-date -Djib.requiredVersion=" + jib.MinimumJibMavenVersion + " --activate-profiles profile --projects module --also-make package jib:dockerBuild -Djib.containerize=module -Dimage=img:tag", - ), - }, { description: "fail build", - artifact: &latest.JibMavenArtifact{}, + artifact: &latest.JibArtifact{}, commands: testutil.CmdRunErr( "mvn -Djib.console=plain jib:_skaffold-fail-if-jib-out-of-date -Djib.requiredVersion="+jib.MinimumJibMavenVersion+" --non-recursive prepare-package jib:dockerBuild -Dimage=img:tag", errors.New("BUG"), @@ -106,42 +99,35 @@ func TestBuildJibMavenToDocker(t *testing.T) { func TestBuildJibMavenToRegistry(t *testing.T) { tests := []struct { description string - artifact *latest.JibMavenArtifact + artifact *latest.JibArtifact commands util.Command shouldErr bool expectedError string }{ { description: "build", - artifact: &latest.JibMavenArtifact{}, + artifact: &latest.JibArtifact{}, commands: testutil.CmdRun( "mvn -Djib.console=plain jib:_skaffold-fail-if-jib-out-of-date -Djib.requiredVersion=" + jib.MinimumJibMavenVersion + " --non-recursive prepare-package jib:build -Dimage=img:tag", ), }, { description: "build with additional flags", - artifact: &latest.JibMavenArtifact{Flags: []string{"--flag1", "--flag2"}}, + artifact: &latest.JibArtifact{Flags: []string{"--flag1", "--flag2"}}, commands: testutil.CmdRun( "mvn -Djib.console=plain jib:_skaffold-fail-if-jib-out-of-date -Djib.requiredVersion=" + jib.MinimumJibMavenVersion + " --flag1 --flag2 --non-recursive prepare-package jib:build -Dimage=img:tag", ), }, { description: "build with module", - artifact: &latest.JibMavenArtifact{Module: "module"}, + artifact: &latest.JibArtifact{Project: "module"}, commands: testutil.CmdRun( "mvn -Djib.console=plain jib:_skaffold-fail-if-jib-out-of-date -Djib.requiredVersion=" + jib.MinimumJibMavenVersion + " --projects module --also-make package jib:build -Djib.containerize=module -Dimage=img:tag", ), }, - { - description: "build with module and profile", - artifact: &latest.JibMavenArtifact{Module: "module", Profile: "profile"}, - commands: testutil.CmdRun( - "mvn -Djib.console=plain jib:_skaffold-fail-if-jib-out-of-date -Djib.requiredVersion=" + jib.MinimumJibMavenVersion + " --activate-profiles profile --projects module --also-make package jib:build -Djib.containerize=module -Dimage=img:tag", - ), - }, { description: "fail build", - artifact: &latest.JibMavenArtifact{}, + artifact: &latest.JibArtifact{}, commands: testutil.CmdRunErr( "mvn -Djib.console=plain jib:_skaffold-fail-if-jib-out-of-date -Djib.requiredVersion="+jib.MinimumJibMavenVersion+" --non-recursive prepare-package jib:build -Dimage=img:tag", errors.New("BUG"), diff --git a/pkg/skaffold/build/local/local.go b/pkg/skaffold/build/local/local.go index e0cafa292c5..fe49dd7b476 100644 --- a/pkg/skaffold/build/local/local.go +++ b/pkg/skaffold/build/local/local.go @@ -81,11 +81,8 @@ func (b *Builder) runBuildForArtifact(ctx context.Context, out io.Writer, artifa case artifact.BazelArtifact != nil: return b.buildBazel(ctx, out, artifact, tag) - case artifact.JibMavenArtifact != nil: - return b.buildJibMaven(ctx, out, artifact.Workspace, artifact.JibMavenArtifact, tag) - - case artifact.JibGradleArtifact != nil: - return b.buildJibGradle(ctx, out, artifact.Workspace, artifact.JibGradleArtifact, tag) + case artifact.JibArtifact != nil: + return b.buildJib(ctx, out, artifact, tag) case artifact.CustomArtifact != nil: return b.buildCustom(ctx, out, artifact, tag) @@ -94,6 +91,23 @@ func (b *Builder) runBuildForArtifact(ctx context.Context, out io.Writer, artifa } } +func (b *Builder) buildJib(ctx context.Context, out io.Writer, artifact *latest.Artifact, tag string) (string, error) { + t, err := jib.DeterminePluginType(artifact.Workspace, artifact.JibArtifact) + if err != nil { + return "", err + } + + switch t { + case jib.JibMaven: + return b.buildJibMaven(ctx, out, artifact.Workspace, artifact.JibArtifact, tag) + case jib.JibGradle: + return b.buildJibGradle(ctx, out, artifact.Workspace, artifact.JibArtifact, tag) + default: + return "", errors.Errorf("Unable to determine Jib builder type for %s", artifact.Workspace) + } + +} + func (b *Builder) DependenciesForArtifact(ctx context.Context, a *latest.Artifact) ([]string, error) { var ( paths []string @@ -107,11 +121,8 @@ func (b *Builder) DependenciesForArtifact(ctx context.Context, a *latest.Artifac case a.BazelArtifact != nil: paths, err = bazel.GetDependencies(ctx, a.Workspace, a.BazelArtifact) - case a.JibMavenArtifact != nil: - paths, err = jib.GetDependenciesMaven(ctx, a.Workspace, a.JibMavenArtifact) - - case a.JibGradleArtifact != nil: - paths, err = jib.GetDependenciesGradle(ctx, a.Workspace, a.JibGradleArtifact) + case a.JibArtifact != nil: + paths, err = jib.GetDependencies(ctx, a.Workspace, a.JibArtifact) case a.CustomArtifact != nil: paths, err = custom.GetDependencies(ctx, a.Workspace, a.CustomArtifact, b.insecureRegistries) diff --git a/pkg/skaffold/deploy/resource/status_test.go b/pkg/skaffold/deploy/resource/status_test.go index 7d58a121eec..ffaf95dca96 100644 --- a/pkg/skaffold/deploy/resource/status_test.go +++ b/pkg/skaffold/deploy/resource/status_test.go @@ -24,6 +24,41 @@ import ( "github.com/GoogleContainerTools/skaffold/testutil" ) +func TestString(t *testing.T) { + var tests = []struct { + description string + details string + err error + expected string + }{ + { + description: "should return error string if error is set", + err: errors.New("some error"), + expected: "some error", + }, + { + description: "should return error details if error is not set", + details: "details", + expected: "details", + }, + { + description: "should return error if both details and error are set", + details: "error details", + err: errors.New("error happened due to something"), + expected: "error happened due to something", + }, + { + description: "should return empty string if all empty", + }, + } + for _, test := range tests { + testutil.Run(t, test.description, func(t *testutil.T) { + status := newStatus(test.details, test.err) + t.CheckDeepEqual(test.expected, status.String()) + }) + } +} + func TestEqual(t *testing.T) { var tests = []struct { description string @@ -57,6 +92,7 @@ func TestEqual(t *testing.T) { description: "status should be new if details change", old: Status{details: "same", err: nil}, new: Status{details: "error", err: nil}, + }, } for _, test := range tests { diff --git a/pkg/skaffold/generate_pipeline/profile_test.go b/pkg/skaffold/generate_pipeline/profile_test.go index 80ab2a6bdbf..018461ca39a 100644 --- a/pkg/skaffold/generate_pipeline/profile_test.go +++ b/pkg/skaffold/generate_pipeline/profile_test.go @@ -85,9 +85,8 @@ func TestGenerateProfile(t *testing.T) { { ImageName: "test", ArtifactType: latest.ArtifactType{ - JibMavenArtifact: &latest.JibMavenArtifact{ - Module: "test-module", - Profile: "test-profile", + JibArtifact: &latest.JibArtifact{ + Project: "test-module", }, DockerArtifact: nil, }, @@ -105,9 +104,8 @@ func TestGenerateProfile(t *testing.T) { { ImageName: "test-pipeline", ArtifactType: latest.ArtifactType{ - JibMavenArtifact: &latest.JibMavenArtifact{ - Module: "test-module", - Profile: "test-profile", + JibArtifact: &latest.JibArtifact{ + Project: "test-module", }, }, }, diff --git a/pkg/skaffold/initializer/init.go b/pkg/skaffold/initializer/init.go index ca8eeed448e..0686fc176db 100644 --- a/pkg/skaffold/initializer/init.go +++ b/pkg/skaffold/initializer/init.go @@ -300,7 +300,7 @@ func processCliArtifacts(artifacts []string) ([]builderImagePair, error) { pairs = append(pairs, pair) // FIXME: shouldn't use a human-readable name? - case jib.JibGradle.Name(), jib.JibMaven.Name(): + case jib.PluginName(jib.JibGradle), jib.PluginName(jib.JibMaven): parsed := struct { Payload jib.Jib `json:"payload"` }{} diff --git a/pkg/skaffold/initializer/init_test.go b/pkg/skaffold/initializer/init_test.go index 5fe38213eff..89e5a87ba3c 100644 --- a/pkg/skaffold/initializer/init_test.go +++ b/pkg/skaffold/initializer/init_test.go @@ -38,14 +38,14 @@ func TestPrintAnalyzeJSON(t *testing.T) { }{ { description: "builders and images with pairs", - pairs: []builderImagePair{{jib.Jib{BuilderName: jib.JibGradle.Name(), Image: "image1", FilePath: "build.gradle", Project: "project"}, "image1"}}, + pairs: []builderImagePair{{jib.Jib{BuilderName: jib.PluginName(jib.JibGradle), Image: "image1", FilePath: "build.gradle", Project: "project"}, "image1"}}, builders: []InitBuilder{docker.Docker{File: "Dockerfile"}}, images: []string{"image2"}, expected: `{"builders":[{"name":"Jib Gradle Plugin","payload":{"image":"image1","path":"build.gradle","project":"project"}},{"name":"Docker","payload":{"path":"Dockerfile"}}],"images":[{"name":"image1","foundMatch":true},{"name":"image2","foundMatch":false}]}`, }, { description: "builders and images with no pairs", - builders: []InitBuilder{jib.Jib{BuilderName: jib.JibGradle.Name(), FilePath: "build.gradle", Project: "project"}, docker.Docker{File: "Dockerfile"}}, + builders: []InitBuilder{jib.Jib{BuilderName: jib.PluginName(jib.JibGradle), FilePath: "build.gradle", Project: "project"}, docker.Docker{File: "Dockerfile"}}, images: []string{"image1", "image2"}, expected: `{"builders":[{"name":"Jib Gradle Plugin","payload":{"path":"build.gradle","project":"project"}},{"name":"Docker","payload":{"path":"Dockerfile"}}],"images":[{"name":"image1","foundMatch":false},{"name":"image2","foundMatch":false}]}`, }, @@ -289,10 +289,10 @@ func fakeValidateDockerfile(path string) bool { func fakeValidateJibConfig(path string) []jib.Jib { if strings.HasSuffix(path, "build.gradle") { - return []jib.Jib{{BuilderName: jib.JibGradle.Name(), FilePath: path}} + return []jib.Jib{{BuilderName: jib.PluginName(jib.JibGradle), FilePath: path}} } if strings.HasSuffix(path, "pom.xml") { - return []jib.Jib{{BuilderName: jib.JibMaven.Name(), FilePath: path}} + return []jib.Jib{{BuilderName: jib.PluginName(jib.JibMaven), FilePath: path}} } return nil } @@ -326,7 +326,7 @@ func TestResolveBuilderImages(t *testing.T) { }, { description: "prompt for multiple builders and images", - buildConfigs: []InitBuilder{docker.Docker{File: "Dockerfile1"}, jib.Jib{BuilderName: jib.JibGradle.Name(), FilePath: "build.gradle"}, jib.Jib{BuilderName: jib.JibMaven.Name(), Project: "project", FilePath: "pom.xml"}}, + buildConfigs: []InitBuilder{docker.Docker{File: "Dockerfile1"}, jib.Jib{BuilderName: jib.PluginName(jib.JibGradle), FilePath: "build.gradle"}, jib.Jib{BuilderName: jib.PluginName(jib.JibMaven), Project: "project", FilePath: "pom.xml"}}, images: []string{"image1", "image2"}, shouldMakeChoice: true, expectedPairs: []builderImagePair{ @@ -335,7 +335,7 @@ func TestResolveBuilderImages(t *testing.T) { ImageName: "image1", }, { - Builder: jib.Jib{BuilderName: jib.JibGradle.Name(), FilePath: "build.gradle"}, + Builder: jib.Jib{BuilderName: jib.PluginName(jib.JibGradle), FilePath: "build.gradle"}, ImageName: "image2", }, }, @@ -371,15 +371,15 @@ func TestAutoSelectBuilders(t *testing.T) { description: "no automatic matches", builderConfigs: []InitBuilder{ docker.Docker{File: "Dockerfile"}, - jib.Jib{BuilderName: jib.JibGradle.Name(), FilePath: "build.gradle"}, - jib.Jib{BuilderName: jib.JibMaven.Name(), FilePath: "pom.xml", Image: "not a k8s image"}, + jib.Jib{BuilderName: jib.PluginName(jib.JibGradle), FilePath: "build.gradle"}, + jib.Jib{BuilderName: jib.PluginName(jib.JibMaven), FilePath: "pom.xml", Image: "not a k8s image"}, }, images: []string{"image1", "image2"}, expectedPairs: nil, expectedBuildersLeft: []InitBuilder{ docker.Docker{File: "Dockerfile"}, - jib.Jib{BuilderName: jib.JibGradle.Name(), FilePath: "build.gradle"}, - jib.Jib{BuilderName: jib.JibMaven.Name(), FilePath: "pom.xml", Image: "not a k8s image"}, + jib.Jib{BuilderName: jib.PluginName(jib.JibGradle), FilePath: "build.gradle"}, + jib.Jib{BuilderName: jib.PluginName(jib.JibMaven), FilePath: "pom.xml", Image: "not a k8s image"}, }, expectedFilteredImages: []string{"image1", "image2"}, }, @@ -387,17 +387,17 @@ func TestAutoSelectBuilders(t *testing.T) { description: "automatic jib matches", builderConfigs: []InitBuilder{ docker.Docker{File: "Dockerfile"}, - jib.Jib{BuilderName: jib.JibGradle.Name(), FilePath: "build.gradle", Image: "image1"}, - jib.Jib{BuilderName: jib.JibMaven.Name(), FilePath: "pom.xml", Image: "image2"}, + jib.Jib{BuilderName: jib.PluginName(jib.JibGradle), FilePath: "build.gradle", Image: "image1"}, + jib.Jib{BuilderName: jib.PluginName(jib.JibMaven), FilePath: "pom.xml", Image: "image2"}, }, images: []string{"image1", "image2", "image3"}, expectedPairs: []builderImagePair{ { - jib.Jib{BuilderName: jib.JibGradle.Name(), FilePath: "build.gradle", Image: "image1"}, + jib.Jib{BuilderName: jib.PluginName(jib.JibGradle), FilePath: "build.gradle", Image: "image1"}, "image1", }, { - jib.Jib{BuilderName: jib.JibMaven.Name(), FilePath: "pom.xml", Image: "image2"}, + jib.Jib{BuilderName: jib.PluginName(jib.JibMaven), FilePath: "pom.xml", Image: "image2"}, "image2", }, }, @@ -407,14 +407,14 @@ func TestAutoSelectBuilders(t *testing.T) { { description: "multiple matches for one image", builderConfigs: []InitBuilder{ - jib.Jib{BuilderName: jib.JibGradle.Name(), FilePath: "build.gradle", Image: "image1"}, - jib.Jib{BuilderName: jib.JibMaven.Name(), FilePath: "pom.xml", Image: "image1"}, + jib.Jib{BuilderName: jib.PluginName(jib.JibGradle), FilePath: "build.gradle", Image: "image1"}, + jib.Jib{BuilderName: jib.PluginName(jib.JibMaven), FilePath: "pom.xml", Image: "image1"}, }, images: []string{"image1", "image2"}, expectedPairs: nil, expectedBuildersLeft: []InitBuilder{ - jib.Jib{BuilderName: jib.JibGradle.Name(), FilePath: "build.gradle", Image: "image1"}, - jib.Jib{BuilderName: jib.JibMaven.Name(), FilePath: "pom.xml", Image: "image1"}, + jib.Jib{BuilderName: jib.PluginName(jib.JibGradle), FilePath: "build.gradle", Image: "image1"}, + jib.Jib{BuilderName: jib.PluginName(jib.JibMaven), FilePath: "pom.xml", Image: "image1"}, }, expectedFilteredImages: []string{"image1", "image2"}, }, diff --git a/pkg/skaffold/jib/jib.go b/pkg/skaffold/jib/jib.go index 200a8c31743..7b3b6fc95c7 100644 --- a/pkg/skaffold/jib/jib.go +++ b/pkg/skaffold/jib/jib.go @@ -18,6 +18,7 @@ package jib import ( "bytes" + "context" "encoding/json" "os" "os/exec" @@ -28,6 +29,7 @@ import ( "time" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/docker" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/util" "github.com/google/go-containerregistry/pkg/name" "github.com/karrick/godirwalk" @@ -39,28 +41,26 @@ const ( dotDotSlash = ".." + string(filepath.Separator) ) -// PluginType is an enum for the different supported Jib plugins. +// PluginType defines the different supported Jib plugins. type PluginType int -// Define the different plugin types supported by Jib. const ( - JibMaven PluginType = iota + // use `iota+1` so that 0 is an invalid value + JibMaven PluginType = iota + 1 JibGradle ) -// ID returns the identifier for a Jib plugin type, suitable for external references (YAML, JSON, command-line, etc). -func (t PluginType) ID() string { +// IsKnown checks that the num value is a known value (vs 0 or an unknown value). +func (t PluginType) IsKnown() bool { switch t { - case JibMaven: - return "maven" - case JibGradle: - return "gradle" + case JibMaven, JibGradle: + return true } - panic("Unknown Jib Plugin Type: " + string(t)) + return false } // Name provides a human-oriented label for a plugin type. -func (t PluginType) Name() string { +func PluginName(t PluginType) string { switch t { case JibMaven: return "Jib Maven Plugin" @@ -88,6 +88,45 @@ type filesLists struct { // watchedFiles maps from project name to watched files var watchedFiles = map[string]filesLists{} +// GetDependencies returns a list of files to watch for changes to rebuild +func GetDependencies(ctx context.Context, workspace string, artifact *latest.JibArtifact) ([]string, error) { + t, err := DeterminePluginType(workspace, artifact) + if err != nil { + return nil, err + } + + switch t { + case JibMaven: + return getDependenciesMaven(ctx, workspace, artifact) + case JibGradle: + return getDependenciesGradle(ctx, workspace, artifact) + default: + return nil, errors.Errorf("Unable to determine Jib builder type for %s", workspace) + } +} + +// DeterminePluginType tries to determine the Jib plugin type for the given artifact. +func DeterminePluginType(workspace string, artifact *latest.JibArtifact) (PluginType, error) { + // check if explicitly specified + if artifact != nil { + if t := PluginType(artifact.Type); t.IsKnown() { + return t, nil + } + } + + // check for typical gradle files + for _, gradleFile := range []string{"build.gradle", "gradle.properties", "settings.gradle", "gradlew", "gradlew.bat", "gradlew.cmd"} { + if util.IsFile(filepath.Join(workspace, gradleFile)) { + return JibGradle, nil + } + } + // check for typical maven files; .mvn is a directory used for polyglot maven + if util.IsFile(filepath.Join(workspace, "pom.xml")) || util.IsDir(filepath.Join(workspace, ".mvn")) { + return JibMaven, nil + } + return -1, errors.Errorf("Unable to determine Jib plugin type for %s", workspace) +} + // getDependencies returns a list of files to watch for changes to rebuild func getDependencies(workspace string, cmd exec.Cmd, projectName string) ([]string, error) { var dependencyList []string diff --git a/pkg/skaffold/jib/jib_gradle.go b/pkg/skaffold/jib/jib_gradle.go index 5e5923a8c42..14d5e7f9a51 100644 --- a/pkg/skaffold/jib/jib_gradle.go +++ b/pkg/skaffold/jib/jib_gradle.go @@ -33,25 +33,25 @@ const MinimumJibGradleVersion = "1.4.0" // GradleCommand stores Gradle executable and wrapper name var GradleCommand = util.CommandWrapper{Executable: "gradle", Wrapper: "gradlew"} -// GetDependenciesGradle finds the source dependencies for the given jib-gradle artifact. +// getDependenciesGradle finds the source dependencies for the given jib-gradle artifact. // All paths are absolute. -func GetDependenciesGradle(ctx context.Context, workspace string, a *latest.JibGradleArtifact) ([]string, error) { +func getDependenciesGradle(ctx context.Context, workspace string, a *latest.JibArtifact) ([]string, error) { cmd := getCommandGradle(ctx, workspace, a) deps, err := getDependencies(workspace, cmd, a.Project) if err != nil { - return nil, errors.Wrapf(err, "getting jibGradle dependencies") + return nil, errors.Wrapf(err, "getting jib-gradle dependencies") } - logrus.Debugf("Found dependencies for jibGradle artifact: %v", deps) + logrus.Debugf("Found dependencies for jib-gradle artifact: %v", deps) return deps, nil } -func getCommandGradle(ctx context.Context, workspace string, a *latest.JibGradleArtifact) exec.Cmd { +func getCommandGradle(ctx context.Context, workspace string, a *latest.JibArtifact) exec.Cmd { args := append(gradleCommand(a, "_jibSkaffoldFilesV2"), "-q") return GradleCommand.CreateCommand(ctx, workspace, args) } // GenerateGradleArgs generates the arguments to Gradle for building the project as an image. -func GenerateGradleArgs(task string, imageName string, a *latest.JibGradleArtifact, skipTests bool, insecureRegistries map[string]bool) []string { +func GenerateGradleArgs(task string, imageName string, a *latest.JibArtifact, skipTests bool, insecureRegistries map[string]bool) []string { // disable jib's rich progress footer; we could use `--console=plain` // but it also disables colour which can be helpful args := []string{"-Djib.console=plain"} @@ -70,7 +70,7 @@ func GenerateGradleArgs(task string, imageName string, a *latest.JibGradleArtifa return args } -func gradleCommand(a *latest.JibGradleArtifact, task string) []string { +func gradleCommand(a *latest.JibArtifact, task string) []string { args := []string{"_skaffoldFailIfJibOutOfDate", "-Djib.requiredVersion=" + MinimumJibGradleVersion} if a.Project == "" { return append(args, ":"+task) diff --git a/pkg/skaffold/jib/jib_gradle_test.go b/pkg/skaffold/jib/jib_gradle_test.go index ac155420073..3582231cbb4 100644 --- a/pkg/skaffold/jib/jib_gradle_test.go +++ b/pkg/skaffold/jib/jib_gradle_test.go @@ -87,7 +87,7 @@ func TestGetDependenciesGradle(t *testing.T) { for _, test := range tests { testutil.Run(t, test.description, func(t *testutil.T) { t.Override(&util.DefaultExecCommand, testutil.CmdRunOutErr( - strings.Join(getCommandGradle(ctx, tmpDir.Root(), &latest.JibGradleArtifact{Project: "gradle-test"}).Args, " "), + strings.Join(getCommandGradle(ctx, tmpDir.Root(), &latest.JibArtifact{Project: "gradle-test"}).Args, " "), test.stdout, test.err, )) @@ -95,9 +95,9 @@ func TestGetDependenciesGradle(t *testing.T) { // Change build file mod time os.Chtimes(build, test.modTime, test.modTime) - deps, err := GetDependenciesGradle(ctx, tmpDir.Root(), &latest.JibGradleArtifact{Project: "gradle-test"}) + deps, err := getDependenciesGradle(ctx, tmpDir.Root(), &latest.JibArtifact{Project: "gradle-test"}) if test.err != nil { - t.CheckErrorAndDeepEqual(true, err, "getting jibGradle dependencies: initial Jib dependency refresh failed: failed to get Jib dependencies: "+test.err.Error(), err.Error()) + t.CheckErrorAndDeepEqual(true, err, "getting jib-gradle dependencies: initial Jib dependency refresh failed: failed to get Jib dependencies: "+test.err.Error(), err.Error()) } else { t.CheckDeepEqual(test.expected, deps) } @@ -109,39 +109,39 @@ func TestGetCommandGradle(t *testing.T) { ctx := context.Background() tests := []struct { - description string - jibGradleArtifact latest.JibGradleArtifact - filesInWorkspace []string - expectedCmd func(workspace string) exec.Cmd + description string + jibArtifact latest.JibArtifact + filesInWorkspace []string + expectedCmd func(workspace string) exec.Cmd }{ { - description: "gradle default", - jibGradleArtifact: latest.JibGradleArtifact{}, - filesInWorkspace: []string{}, + description: "gradle default", + jibArtifact: latest.JibArtifact{}, + filesInWorkspace: []string{}, expectedCmd: func(workspace string) exec.Cmd { return GradleCommand.CreateCommand(ctx, workspace, []string{"_skaffoldFailIfJibOutOfDate", "-Djib.requiredVersion=" + MinimumJibGradleVersion, ":_jibSkaffoldFilesV2", "-q"}) }, }, { - description: "gradle default with project", - jibGradleArtifact: latest.JibGradleArtifact{Project: "project"}, - filesInWorkspace: []string{}, + description: "gradle default with project", + jibArtifact: latest.JibArtifact{Project: "project"}, + filesInWorkspace: []string{}, expectedCmd: func(workspace string) exec.Cmd { return GradleCommand.CreateCommand(ctx, workspace, []string{"_skaffoldFailIfJibOutOfDate", "-Djib.requiredVersion=" + MinimumJibGradleVersion, ":project:_jibSkaffoldFilesV2", "-q"}) }, }, { - description: "gradle with wrapper", - jibGradleArtifact: latest.JibGradleArtifact{}, - filesInWorkspace: []string{"gradlew", "gradlew.cmd"}, + description: "gradle with wrapper", + jibArtifact: latest.JibArtifact{}, + filesInWorkspace: []string{"gradlew", "gradlew.cmd"}, expectedCmd: func(workspace string) exec.Cmd { return GradleCommand.CreateCommand(ctx, workspace, []string{"_skaffoldFailIfJibOutOfDate", "-Djib.requiredVersion=" + MinimumJibGradleVersion, ":_jibSkaffoldFilesV2", "-q"}) }, }, { - description: "gradle with wrapper and project", - jibGradleArtifact: latest.JibGradleArtifact{Project: "project"}, - filesInWorkspace: []string{"gradlew", "gradlew.cmd"}, + description: "gradle with wrapper and project", + jibArtifact: latest.JibArtifact{Project: "project"}, + filesInWorkspace: []string{"gradlew", "gradlew.cmd"}, expectedCmd: func(workspace string) exec.Cmd { return GradleCommand.CreateCommand(ctx, workspace, []string{"_skaffoldFailIfJibOutOfDate", "-Djib.requiredVersion=" + MinimumJibGradleVersion, ":project:_jibSkaffoldFilesV2", "-q"}) }, @@ -152,7 +152,7 @@ func TestGetCommandGradle(t *testing.T) { tmpDir := t.NewTempDir(). Touch(test.filesInWorkspace...) - cmd := getCommandGradle(ctx, tmpDir.Root(), &test.jibGradleArtifact) + cmd := getCommandGradle(ctx, tmpDir.Root(), &test.jibArtifact) expectedCmd := test.expectedCmd(tmpDir.Root()) t.CheckDeepEqual(expectedCmd.Path, cmd.Path) @@ -164,18 +164,18 @@ func TestGetCommandGradle(t *testing.T) { func TestGenerateGradleArgs(t *testing.T) { tests := []struct { - in latest.JibGradleArtifact + in latest.JibArtifact image string skipTests bool insecureRegistries map[string]bool out []string }{ - {latest.JibGradleArtifact{}, "image", false, nil, []string{"-Djib.console=plain", "_skaffoldFailIfJibOutOfDate", "-Djib.requiredVersion=" + MinimumJibGradleVersion, ":task", "--image=image"}}, - {latest.JibGradleArtifact{Flags: []string{"-extra", "args"}}, "image", false, nil, []string{"-Djib.console=plain", "_skaffoldFailIfJibOutOfDate", "-Djib.requiredVersion=" + MinimumJibGradleVersion, ":task", "--image=image", "-extra", "args"}}, - {latest.JibGradleArtifact{}, "image", true, nil, []string{"-Djib.console=plain", "_skaffoldFailIfJibOutOfDate", "-Djib.requiredVersion=" + MinimumJibGradleVersion, ":task", "--image=image", "-x", "test"}}, - {latest.JibGradleArtifact{Project: "project"}, "image", false, nil, []string{"-Djib.console=plain", "_skaffoldFailIfJibOutOfDate", "-Djib.requiredVersion=" + MinimumJibGradleVersion, ":project:task", "--image=image"}}, - {latest.JibGradleArtifact{Project: "project"}, "image", true, nil, []string{"-Djib.console=plain", "_skaffoldFailIfJibOutOfDate", "-Djib.requiredVersion=" + MinimumJibGradleVersion, ":project:task", "--image=image", "-x", "test"}}, - {latest.JibGradleArtifact{Project: "project"}, "registry.tld/image", true, map[string]bool{"registry.tld": true}, []string{"-Djib.console=plain", "_skaffoldFailIfJibOutOfDate", "-Djib.requiredVersion=" + MinimumJibGradleVersion, ":project:task", "-Djib.allowInsecureRegistries=true", "--image=registry.tld/image", "-x", "test"}}, + {latest.JibArtifact{}, "image", false, nil, []string{"-Djib.console=plain", "_skaffoldFailIfJibOutOfDate", "-Djib.requiredVersion=" + MinimumJibGradleVersion, ":task", "--image=image"}}, + {latest.JibArtifact{Flags: []string{"-extra", "args"}}, "image", false, nil, []string{"-Djib.console=plain", "_skaffoldFailIfJibOutOfDate", "-Djib.requiredVersion=" + MinimumJibGradleVersion, ":task", "--image=image", "-extra", "args"}}, + {latest.JibArtifact{}, "image", true, nil, []string{"-Djib.console=plain", "_skaffoldFailIfJibOutOfDate", "-Djib.requiredVersion=" + MinimumJibGradleVersion, ":task", "--image=image", "-x", "test"}}, + {latest.JibArtifact{Project: "project"}, "image", false, nil, []string{"-Djib.console=plain", "_skaffoldFailIfJibOutOfDate", "-Djib.requiredVersion=" + MinimumJibGradleVersion, ":project:task", "--image=image"}}, + {latest.JibArtifact{Project: "project"}, "image", true, nil, []string{"-Djib.console=plain", "_skaffoldFailIfJibOutOfDate", "-Djib.requiredVersion=" + MinimumJibGradleVersion, ":project:task", "--image=image", "-x", "test"}}, + {latest.JibArtifact{Project: "project"}, "registry.tld/image", true, map[string]bool{"registry.tld": true}, []string{"-Djib.console=plain", "_skaffoldFailIfJibOutOfDate", "-Djib.requiredVersion=" + MinimumJibGradleVersion, ":project:task", "-Djib.allowInsecureRegistries=true", "--image=registry.tld/image", "-x", "test"}}, } for _, test := range tests { command := GenerateGradleArgs("task", test.image, &test.in, test.skipTests, test.insecureRegistries) diff --git a/pkg/skaffold/jib/jib_init.go b/pkg/skaffold/jib/jib_init.go index 1c892513408..18e7ebbdeb4 100644 --- a/pkg/skaffold/jib/jib_init.go +++ b/pkg/skaffold/jib/jib_init.go @@ -66,21 +66,21 @@ func (j Jib) CreateArtifact(manifestImage string) *latest.Artifact { a.Workspace = workspace } - if j.BuilderName == JibMaven.Name() { - jibMaven := &latest.JibMavenArtifact{} + if j.BuilderName == PluginName(JibMaven) { + jibMaven := &latest.JibArtifact{Type: int(JibMaven)} if j.Project != "" { - jibMaven.Module = j.Project + jibMaven.Project = j.Project } jibMaven.Flags = []string{"-Dimage=" + manifestImage} - a.ArtifactType = latest.ArtifactType{JibMavenArtifact: jibMaven} + a.ArtifactType = latest.ArtifactType{JibArtifact: jibMaven} - } else if j.BuilderName == JibGradle.Name() { - jibGradle := &latest.JibGradleArtifact{} + } else if j.BuilderName == PluginName(JibGradle) { + jibGradle := &latest.JibArtifact{Type: int(JibGradle)} if j.Project != "" { jibGradle.Project = j.Project } jibGradle.Flags = []string{"-Dimage=" + manifestImage} - a.ArtifactType = latest.ArtifactType{JibGradleArtifact: jibGradle} + a.ArtifactType = latest.ArtifactType{JibArtifact: jibGradle} } return a @@ -149,7 +149,7 @@ func ValidateJibConfig(path string) []Jib { return nil } - results[i] = Jib{BuilderName: builderType.Name(), Image: parsedJSON.Image, FilePath: path, Project: parsedJSON.Project} + results[i] = Jib{BuilderName: PluginName(builderType), Image: parsedJSON.Image, FilePath: path, Project: parsedJSON.Project} } return results } diff --git a/pkg/skaffold/jib/jib_init_test.go b/pkg/skaffold/jib/jib_init_test.go index 3b7cebf4ffd..5f6b82d591d 100644 --- a/pkg/skaffold/jib/jib_init_test.go +++ b/pkg/skaffold/jib/jib_init_test.go @@ -53,7 +53,7 @@ func TestValidateJibConfig(t *testing.T) { {"image":"image","project":"project"} `, expectedConfig: []Jib{ - {BuilderName: JibGradle.Name(), FilePath: "path/to/build.gradle", Image: "image", Project: "project"}, + {BuilderName: PluginName(JibGradle), FilePath: "path/to/build.gradle", Image: "image", Project: "project"}, }, }, { @@ -67,8 +67,8 @@ BEGIN JIB JSON {"project":"project2"} `, expectedConfig: []Jib{ - {BuilderName: JibGradle.Name(), FilePath: "path/to/build.gradle", Image: "image", Project: "project1"}, - {BuilderName: JibGradle.Name(), FilePath: "path/to/build.gradle", Project: "project2"}, + {BuilderName: PluginName(JibGradle), FilePath: "path/to/build.gradle", Image: "image", Project: "project1"}, + {BuilderName: PluginName(JibGradle), FilePath: "path/to/build.gradle", Project: "project2"}, }, }, { @@ -78,7 +78,7 @@ BEGIN JIB JSON stdout: `BEGIN JIB JSON {"image":"image","project":"project"}`, expectedConfig: []Jib{ - {BuilderName: JibMaven.Name(), FilePath: "path/to/pom.xml", Image: "image", Project: "project"}, + {BuilderName: PluginName(JibMaven), FilePath: "path/to/pom.xml", Image: "image", Project: "project"}, }, }, { @@ -92,8 +92,8 @@ BEGIN JIB JSON {"project":"project2"} `, expectedConfig: []Jib{ - {BuilderName: JibMaven.Name(), FilePath: "path/to/pom.xml", Image: "image", Project: "project1"}, - {BuilderName: JibMaven.Name(), FilePath: "path/to/pom.xml", Project: "project2"}, + {BuilderName: PluginName(JibMaven), FilePath: "path/to/pom.xml", Image: "image", Project: "project1"}, + {BuilderName: PluginName(JibMaven), FilePath: "path/to/pom.xml", Project: "project2"}, }, }, } @@ -119,22 +119,22 @@ func TestDescribe(t *testing.T) { }{ { description: "gradle without project", - config: Jib{BuilderName: JibGradle.Name(), FilePath: "path/to/build.gradle"}, + config: Jib{BuilderName: PluginName(JibGradle), FilePath: "path/to/build.gradle"}, expectedPrompt: "Jib Gradle Plugin (path/to/build.gradle)", }, { description: "gradle with project", - config: Jib{BuilderName: JibGradle.Name(), Project: "project", FilePath: "path/to/build.gradle"}, + config: Jib{BuilderName: PluginName(JibGradle), Project: "project", FilePath: "path/to/build.gradle"}, expectedPrompt: "Jib Gradle Plugin (project, path/to/build.gradle)", }, { description: "maven without project", - config: Jib{BuilderName: JibMaven.Name(), FilePath: "path/to/pom.xml"}, + config: Jib{BuilderName: PluginName(JibMaven), FilePath: "path/to/pom.xml"}, expectedPrompt: "Jib Maven Plugin (path/to/pom.xml)", }, { description: "maven with project", - config: Jib{BuilderName: JibMaven.Name(), Project: "project", FilePath: "path/to/pom.xml"}, + config: Jib{BuilderName: PluginName(JibMaven), Project: "project", FilePath: "path/to/pom.xml"}, expectedPrompt: "Jib Maven Plugin (project, path/to/pom.xml)", }, } @@ -155,61 +155,57 @@ func TestCreateArtifact(t *testing.T) { }{ { description: "jib gradle with image and project", - config: Jib{BuilderName: JibGradle.Name(), FilePath: filepath.Join("path", "to", "build.gradle"), Image: "image", Project: "project"}, + config: Jib{BuilderName: "Jib Gradle Plugin", FilePath: filepath.Join("path", "to", "build.gradle"), Image: "image", Project: "project"}, manifestImage: "different-image", expectedArtifact: latest.Artifact{ ImageName: "different-image", Workspace: filepath.Join("path", "to"), ArtifactType: latest.ArtifactType{ - JibGradleArtifact: &latest.JibGradleArtifact{Project: "project", Flags: []string{"-Dimage=different-image"}}, + JibArtifact: &latest.JibArtifact{Project: "project", Flags: []string{"-Dimage=different-image"}, Type: int(JibGradle)}, }, }, }, { description: "jib gradle without image and project", - config: Jib{BuilderName: JibGradle.Name(), FilePath: filepath.Join("path", "to", "build.gradle")}, + config: Jib{BuilderName: "Jib Gradle Plugin", FilePath: filepath.Join("path", "to", "build.gradle")}, manifestImage: "different-image", expectedArtifact: latest.Artifact{ ImageName: "different-image", Workspace: filepath.Join("path", "to"), ArtifactType: latest.ArtifactType{ - JibGradleArtifact: &latest.JibGradleArtifact{Flags: []string{"-Dimage=different-image"}}, + JibArtifact: &latest.JibArtifact{Flags: []string{"-Dimage=different-image"}, Type: int(JibGradle)}, }, }, }, { description: "jib maven with image and project", - config: Jib{BuilderName: JibMaven.Name(), FilePath: filepath.Join("path", "to", "pom.xml"), Image: "image", Project: "project"}, + config: Jib{BuilderName: "Jib Maven Plugin", FilePath: filepath.Join("path", "to", "pom.xml"), Image: "image", Project: "project"}, manifestImage: "different-image", expectedArtifact: latest.Artifact{ - ImageName: "different-image", - Workspace: filepath.Join("path", "to"), - ArtifactType: latest.ArtifactType{ - JibMavenArtifact: &latest.JibMavenArtifact{Module: "project", Flags: []string{"-Dimage=different-image"}}, - }, + ImageName: "different-image", + Workspace: filepath.Join("path", "to"), + ArtifactType: latest.ArtifactType{JibArtifact: &latest.JibArtifact{Project: "project", Flags: []string{"-Dimage=different-image"}, Type: int(JibMaven)}}, }, }, { description: "jib maven without image and project", - config: Jib{BuilderName: JibMaven.Name(), FilePath: filepath.Join("path", "to", "pom.xml")}, + config: Jib{BuilderName: "Jib Maven Plugin", FilePath: filepath.Join("path", "to", "pom.xml")}, manifestImage: "different-image", expectedArtifact: latest.Artifact{ ImageName: "different-image", Workspace: filepath.Join("path", "to"), ArtifactType: latest.ArtifactType{ - JibMavenArtifact: &latest.JibMavenArtifact{Flags: []string{"-Dimage=different-image"}}, + JibArtifact: &latest.JibArtifact{Flags: []string{"-Dimage=different-image"}, Type: int(JibMaven)}, }, }, }, { description: "ignore workspace", - config: Jib{BuilderName: JibGradle.Name(), FilePath: "build.gradle", Image: "image"}, + config: Jib{BuilderName: "Jib Gradle Plugin", FilePath: "build.gradle", Image: "image"}, manifestImage: "different-image", expectedArtifact: latest.Artifact{ - ImageName: "different-image", - ArtifactType: latest.ArtifactType{ - JibGradleArtifact: &latest.JibGradleArtifact{Flags: []string{"-Dimage=different-image"}}, - }, + ImageName: "different-image", + ArtifactType: latest.ArtifactType{JibArtifact: &latest.JibArtifact{Flags: []string{"-Dimage=different-image"}, Type: int(JibGradle)}}, }, }, } diff --git a/pkg/skaffold/jib/jib_maven.go b/pkg/skaffold/jib/jib_maven.go index 1ac7885d993..e647a6a9301 100644 --- a/pkg/skaffold/jib/jib_maven.go +++ b/pkg/skaffold/jib/jib_maven.go @@ -32,18 +32,18 @@ const MinimumJibMavenVersion = "1.4.0" // MavenCommand stores Maven executable and wrapper name var MavenCommand = util.CommandWrapper{Executable: "mvn", Wrapper: "mvnw"} -// GetDependenciesMaven finds the source dependencies for the given jib-maven artifact. +// getDependenciesMaven finds the source dependencies for the given jib-maven artifact. // All paths are absolute. -func GetDependenciesMaven(ctx context.Context, workspace string, a *latest.JibMavenArtifact) ([]string, error) { - deps, err := getDependencies(workspace, getCommandMaven(ctx, workspace, a), a.Module) +func getDependenciesMaven(ctx context.Context, workspace string, a *latest.JibArtifact) ([]string, error) { + deps, err := getDependencies(workspace, getCommandMaven(ctx, workspace, a), a.Project) if err != nil { - return nil, errors.Wrapf(err, "getting jibMaven dependencies") + return nil, errors.Wrapf(err, "getting jib-maven dependencies") } - logrus.Debugf("Found dependencies for jibMaven artifact: %v", deps) + logrus.Debugf("Found dependencies for jib maven artifact: %v", deps) return deps, nil } -func getCommandMaven(ctx context.Context, workspace string, a *latest.JibMavenArtifact) exec.Cmd { +func getCommandMaven(ctx context.Context, workspace string, a *latest.JibArtifact) exec.Cmd { args := mavenArgs(a) args = append(args, "jib:_skaffold-files-v2", "--quiet") @@ -51,7 +51,7 @@ func getCommandMaven(ctx context.Context, workspace string, a *latest.JibMavenAr } // GenerateMavenArgs generates the arguments to Maven for building the project as an image. -func GenerateMavenArgs(goal string, imageName string, a *latest.JibMavenArtifact, skipTests bool, insecureRegistries map[string]bool) []string { +func GenerateMavenArgs(goal string, imageName string, a *latest.JibArtifact, skipTests bool, insecureRegistries map[string]bool) []string { // disable jib's rich progress footer on builds; we could use --batch-mode // but it also disables colour which can be helpful args := []string{"-Djib.console=plain"} @@ -61,12 +61,12 @@ func GenerateMavenArgs(goal string, imageName string, a *latest.JibMavenArtifact args = append(args, "-DskipTests=true") } - if a.Module == "" { + if a.Project == "" { // single-module project args = append(args, "prepare-package", "jib:"+goal) } else { // multi-module project: instruct jib to containerize only the given module - args = append(args, "package", "jib:"+goal, "-Djib.containerize="+a.Module) + args = append(args, "package", "jib:"+goal, "-Djib.containerize="+a.Project) } if insecure, err := isOnInsecureRegistry(imageName, insecureRegistries); err == nil && insecure { @@ -78,20 +78,16 @@ func GenerateMavenArgs(goal string, imageName string, a *latest.JibMavenArtifact return args } -func mavenArgs(a *latest.JibMavenArtifact) []string { +func mavenArgs(a *latest.JibArtifact) []string { args := []string{"jib:_skaffold-fail-if-jib-out-of-date", "-Djib.requiredVersion=" + MinimumJibMavenVersion} args = append(args, a.Flags...) - if a.Profile != "" { - args = append(args, "--activate-profiles", a.Profile) - } - - if a.Module == "" { + if a.Project == "" { // single-module project args = append(args, "--non-recursive") } else { // multi-module project - args = append(args, "--projects", a.Module, "--also-make") + args = append(args, "--projects", a.Project, "--also-make") } return args diff --git a/pkg/skaffold/jib/jib_maven_test.go b/pkg/skaffold/jib/jib_maven_test.go index 19a01b1f925..e837550750b 100644 --- a/pkg/skaffold/jib/jib_maven_test.go +++ b/pkg/skaffold/jib/jib_maven_test.go @@ -87,7 +87,7 @@ func TestGetDependenciesMaven(t *testing.T) { for _, test := range tests { testutil.Run(t, test.description, func(t *testutil.T) { t.Override(&util.DefaultExecCommand, testutil.CmdRunOutErr( - strings.Join(getCommandMaven(ctx, tmpDir.Root(), &latest.JibMavenArtifact{Module: "maven-test"}).Args, " "), + strings.Join(getCommandMaven(ctx, tmpDir.Root(), &latest.JibArtifact{Project: "maven-test"}).Args, " "), test.stdout, test.err, )) @@ -95,9 +95,9 @@ func TestGetDependenciesMaven(t *testing.T) { // Change build file mod time os.Chtimes(build, test.modTime, test.modTime) - deps, err := GetDependenciesMaven(ctx, tmpDir.Root(), &latest.JibMavenArtifact{Module: "maven-test"}) + deps, err := getDependenciesMaven(ctx, tmpDir.Root(), &latest.JibArtifact{Project: "maven-test"}) if test.err != nil { - t.CheckErrorAndDeepEqual(true, err, "getting jibMaven dependencies: initial Jib dependency refresh failed: failed to get Jib dependencies: "+test.err.Error(), err.Error()) + t.CheckErrorAndDeepEqual(true, err, "getting jib-maven dependencies: initial Jib dependency refresh failed: failed to get Jib dependencies: "+test.err.Error(), err.Error()) } else { t.CheckDeepEqual(test.expected, deps) } @@ -109,13 +109,13 @@ func TestGetCommandMaven(t *testing.T) { ctx := context.Background() tests := []struct { description string - jibMavenArtifact latest.JibMavenArtifact + jibArtifact latest.JibArtifact filesInWorkspace []string expectedCmd func(workspace string) exec.Cmd }{ { - description: "maven no profile", - jibMavenArtifact: latest.JibMavenArtifact{}, + description: "maven basic", + jibArtifact: latest.JibArtifact{}, filesInWorkspace: []string{}, expectedCmd: func(workspace string) exec.Cmd { return MavenCommand.CreateCommand(ctx, workspace, []string{"jib:_skaffold-fail-if-jib-out-of-date", "-Djib.requiredVersion=" + MinimumJibMavenVersion, "--non-recursive", "jib:_skaffold-files-v2", "--quiet"}) @@ -123,7 +123,7 @@ func TestGetCommandMaven(t *testing.T) { }, { description: "maven with extra flags", - jibMavenArtifact: latest.JibMavenArtifact{ + jibArtifact: latest.JibArtifact{ Flags: []string{"-DskipTests", "-x"}, }, filesInWorkspace: []string{}, @@ -132,40 +132,24 @@ func TestGetCommandMaven(t *testing.T) { }, }, { - description: "maven with profile", - jibMavenArtifact: latest.JibMavenArtifact{Profile: "profile"}, - filesInWorkspace: []string{}, - expectedCmd: func(workspace string) exec.Cmd { - return MavenCommand.CreateCommand(ctx, workspace, []string{"jib:_skaffold-fail-if-jib-out-of-date", "-Djib.requiredVersion=" + MinimumJibMavenVersion, "--activate-profiles", "profile", "--non-recursive", "jib:_skaffold-files-v2", "--quiet"}) - }, - }, - { - description: "maven with wrapper no profile", - jibMavenArtifact: latest.JibMavenArtifact{}, + description: "maven with wrapper", + jibArtifact: latest.JibArtifact{}, filesInWorkspace: []string{"mvnw", "mvnw.bat"}, expectedCmd: func(workspace string) exec.Cmd { return MavenCommand.CreateCommand(ctx, workspace, []string{"jib:_skaffold-fail-if-jib-out-of-date", "-Djib.requiredVersion=" + MinimumJibMavenVersion, "--non-recursive", "jib:_skaffold-files-v2", "--quiet"}) }, }, { - description: "maven with wrapper no profile", - jibMavenArtifact: latest.JibMavenArtifact{}, + description: "maven with wrapper", + jibArtifact: latest.JibArtifact{}, filesInWorkspace: []string{"mvnw", "mvnw.cmd"}, expectedCmd: func(workspace string) exec.Cmd { return MavenCommand.CreateCommand(ctx, workspace, []string{"jib:_skaffold-fail-if-jib-out-of-date", "-Djib.requiredVersion=" + MinimumJibMavenVersion, "--non-recursive", "jib:_skaffold-files-v2", "--quiet"}) }, }, - { - description: "maven with wrapper and profile", - jibMavenArtifact: latest.JibMavenArtifact{Profile: "profile"}, - filesInWorkspace: []string{"mvnw", "mvnw.bat"}, - expectedCmd: func(workspace string) exec.Cmd { - return MavenCommand.CreateCommand(ctx, workspace, []string{"jib:_skaffold-fail-if-jib-out-of-date", "-Djib.requiredVersion=" + MinimumJibMavenVersion, "--activate-profiles", "profile", "--non-recursive", "jib:_skaffold-files-v2", "--quiet"}) - }, - }, { description: "maven with multi-modules", - jibMavenArtifact: latest.JibMavenArtifact{Module: "module"}, + jibArtifact: latest.JibArtifact{Project: "module"}, filesInWorkspace: []string{"mvnw", "mvnw.bat"}, expectedCmd: func(workspace string) exec.Cmd { return MavenCommand.CreateCommand(ctx, workspace, []string{"jib:_skaffold-fail-if-jib-out-of-date", "-Djib.requiredVersion=" + MinimumJibMavenVersion, "--projects", "module", "--also-make", "jib:_skaffold-files-v2", "--quiet"}) @@ -177,7 +161,7 @@ func TestGetCommandMaven(t *testing.T) { tmpDir := t.NewTempDir(). Touch(test.filesInWorkspace...) - cmd := getCommandMaven(ctx, tmpDir.Root(), &test.jibMavenArtifact) + cmd := getCommandMaven(ctx, tmpDir.Root(), &test.jibArtifact) expectedCmd := test.expectedCmd(tmpDir.Root()) t.CheckDeepEqual(expectedCmd.Path, cmd.Path) @@ -189,21 +173,17 @@ func TestGetCommandMaven(t *testing.T) { func TestGenerateMavenArgs(t *testing.T) { tests := []struct { - in latest.JibMavenArtifact + in latest.JibArtifact image string skipTests bool insecureRegistries map[string]bool out []string }{ - {latest.JibMavenArtifact{}, "image", false, nil, []string{"-Djib.console=plain", "jib:_skaffold-fail-if-jib-out-of-date", "-Djib.requiredVersion=" + MinimumJibMavenVersion, "--non-recursive", "prepare-package", "jib:goal", "-Dimage=image"}}, - {latest.JibMavenArtifact{}, "image", true, nil, []string{"-Djib.console=plain", "jib:_skaffold-fail-if-jib-out-of-date", "-Djib.requiredVersion=" + MinimumJibMavenVersion, "--non-recursive", "-DskipTests=true", "prepare-package", "jib:goal", "-Dimage=image"}}, - {latest.JibMavenArtifact{Profile: "profile"}, "image", false, nil, []string{"-Djib.console=plain", "jib:_skaffold-fail-if-jib-out-of-date", "-Djib.requiredVersion=" + MinimumJibMavenVersion, "--activate-profiles", "profile", "--non-recursive", "prepare-package", "jib:goal", "-Dimage=image"}}, - {latest.JibMavenArtifact{Profile: "profile"}, "image", true, nil, []string{"-Djib.console=plain", "jib:_skaffold-fail-if-jib-out-of-date", "-Djib.requiredVersion=" + MinimumJibMavenVersion, "--activate-profiles", "profile", "--non-recursive", "-DskipTests=true", "prepare-package", "jib:goal", "-Dimage=image"}}, - {latest.JibMavenArtifact{Module: "module"}, "image", false, nil, []string{"-Djib.console=plain", "jib:_skaffold-fail-if-jib-out-of-date", "-Djib.requiredVersion=" + MinimumJibMavenVersion, "--projects", "module", "--also-make", "package", "jib:goal", "-Djib.containerize=module", "-Dimage=image"}}, - {latest.JibMavenArtifact{Module: "module"}, "image", true, nil, []string{"-Djib.console=plain", "jib:_skaffold-fail-if-jib-out-of-date", "-Djib.requiredVersion=" + MinimumJibMavenVersion, "--projects", "module", "--also-make", "-DskipTests=true", "package", "jib:goal", "-Djib.containerize=module", "-Dimage=image"}}, - {latest.JibMavenArtifact{Module: "module", Profile: "profile"}, "image", false, nil, []string{"-Djib.console=plain", "jib:_skaffold-fail-if-jib-out-of-date", "-Djib.requiredVersion=" + MinimumJibMavenVersion, "--activate-profiles", "profile", "--projects", "module", "--also-make", "package", "jib:goal", "-Djib.containerize=module", "-Dimage=image"}}, - {latest.JibMavenArtifact{Module: "module", Profile: "profile"}, "image", true, nil, []string{"-Djib.console=plain", "jib:_skaffold-fail-if-jib-out-of-date", "-Djib.requiredVersion=" + MinimumJibMavenVersion, "--activate-profiles", "profile", "--projects", "module", "--also-make", "-DskipTests=true", "package", "jib:goal", "-Djib.containerize=module", "-Dimage=image"}}, - {latest.JibMavenArtifact{Module: "module", Profile: "profile"}, "registry.tld/image", true, map[string]bool{"registry.tld": true}, []string{"-Djib.console=plain", "jib:_skaffold-fail-if-jib-out-of-date", "-Djib.requiredVersion=" + MinimumJibMavenVersion, "--activate-profiles", "profile", "--projects", "module", "--also-make", "-DskipTests=true", "package", "jib:goal", "-Djib.containerize=module", "-Djib.allowInsecureRegistries=true", "-Dimage=registry.tld/image"}}, + {latest.JibArtifact{}, "image", false, nil, []string{"-Djib.console=plain", "jib:_skaffold-fail-if-jib-out-of-date", "-Djib.requiredVersion=" + MinimumJibMavenVersion, "--non-recursive", "prepare-package", "jib:goal", "-Dimage=image"}}, + {latest.JibArtifact{}, "image", true, nil, []string{"-Djib.console=plain", "jib:_skaffold-fail-if-jib-out-of-date", "-Djib.requiredVersion=" + MinimumJibMavenVersion, "--non-recursive", "-DskipTests=true", "prepare-package", "jib:goal", "-Dimage=image"}}, + {latest.JibArtifact{Project: "module"}, "image", false, nil, []string{"-Djib.console=plain", "jib:_skaffold-fail-if-jib-out-of-date", "-Djib.requiredVersion=" + MinimumJibMavenVersion, "--projects", "module", "--also-make", "package", "jib:goal", "-Djib.containerize=module", "-Dimage=image"}}, + {latest.JibArtifact{Project: "module"}, "image", true, nil, []string{"-Djib.console=plain", "jib:_skaffold-fail-if-jib-out-of-date", "-Djib.requiredVersion=" + MinimumJibMavenVersion, "--projects", "module", "--also-make", "-DskipTests=true", "package", "jib:goal", "-Djib.containerize=module", "-Dimage=image"}}, + {latest.JibArtifact{Project: "module"}, "registry.tld/image", true, map[string]bool{"registry.tld": true}, []string{"-Djib.console=plain", "jib:_skaffold-fail-if-jib-out-of-date", "-Djib.requiredVersion=" + MinimumJibMavenVersion, "--projects", "module", "--also-make", "-DskipTests=true", "package", "jib:goal", "-Djib.containerize=module", "-Djib.allowInsecureRegistries=true", "-Dimage=registry.tld/image"}}, } for _, test := range tests { args := GenerateMavenArgs("goal", test.image, &test.in, test.skipTests, test.insecureRegistries) diff --git a/pkg/skaffold/jib/jib_test.go b/pkg/skaffold/jib/jib_test.go index b55b378e557..c42058fcb15 100644 --- a/pkg/skaffold/jib/jib_test.go +++ b/pkg/skaffold/jib/jib_test.go @@ -22,17 +22,11 @@ import ( "path/filepath" "testing" + "github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest" "github.com/GoogleContainerTools/skaffold/pkg/skaffold/util" "github.com/GoogleContainerTools/skaffold/testutil" ) -func TestPluginType(t *testing.T) { - testutil.CheckDeepEqual(t, "maven", JibMaven.ID()) - testutil.CheckDeepEqual(t, "Jib Maven Plugin", JibMaven.Name()) - testutil.CheckDeepEqual(t, "gradle", JibGradle.ID()) - testutil.CheckDeepEqual(t, "Jib Gradle Plugin", JibGradle.Name()) -} - func TestGetDependencies(t *testing.T) { tmpDir, cleanup := testutil.NewTempDir(t) defer cleanup() @@ -145,3 +139,56 @@ func TestGetUpdatedDependencies(t *testing.T) { t.CheckNoError(err) }) } + +func TestPluginName(t *testing.T) { + testutil.CheckDeepEqual(t, "Jib Maven Plugin", PluginName(JibMaven)) + testutil.CheckDeepEqual(t, "Jib Gradle Plugin", PluginName(JibGradle)) +} + +func TestPluginType_IsKnown(t *testing.T) { + tests := []struct { + value PluginType + known bool + }{ + {JibMaven, true}, + {JibGradle, true}, + {PluginType(0), false}, + {PluginType(-1), false}, + {PluginType(3), false}, + } + for _, test := range tests { + testutil.Run(t, string(test.value), func(t *testutil.T) { + t.CheckDeepEqual(test.known, test.value.IsKnown()) + }) + } +} + +func TestDeterminePluginType(t *testing.T) { + tests := []struct { + description string + files []string + artifact *latest.JibArtifact + shouldErr bool + PluginType PluginType + }{ + {"empty", []string{}, nil, true, PluginType(-1)}, + {"gradle-2", []string{"gradle.properties"}, nil, false, JibGradle}, + {"gradle-3", []string{"gradlew"}, nil, false, JibGradle}, + {"gradle-4", []string{"gradlew.bat"}, nil, false, JibGradle}, + {"gradle-5", []string{"gradlew.cmd"}, nil, false, JibGradle}, + {"gradle-6", []string{"settings.gradle"}, nil, false, JibGradle}, + {"maven-1", []string{"pom.xml"}, nil, false, JibMaven}, + {"maven-2", []string{".mvn/maven.config"}, nil, false, JibMaven}, + {"maven-2", []string{".mvn/extensions.xml"}, nil, false, JibMaven}, + {"gradle override", []string{"pom.xml"}, &latest.JibArtifact{Type: int(JibGradle)}, false, JibGradle}, + {"maven override", []string{"build.gradle"}, &latest.JibArtifact{Type: int(JibMaven)}, false, JibMaven}, + } + for _, test := range tests { + testutil.Run(t, test.description, func(t *testutil.T) { + buildDir := t.NewTempDir() + buildDir.Touch(test.files...) + PluginType, err := DeterminePluginType(buildDir.Root(), test.artifact) + t.CheckErrorAndDeepEqual(test.shouldErr, err, test.PluginType, PluginType) + }) + } +} diff --git a/pkg/skaffold/runner/diagnose.go b/pkg/skaffold/runner/diagnose.go index 482654bdcba..b58355d81c0 100644 --- a/pkg/skaffold/runner/diagnose.go +++ b/pkg/skaffold/runner/diagnose.go @@ -95,10 +95,8 @@ func typeOfArtifact(a *latest.Artifact) string { return "Docker artifact" case a.BazelArtifact != nil: return "Bazel artifact" - case a.JibGradleArtifact != nil: - return "Jib Gradle artifact" - case a.JibMavenArtifact != nil: - return "Jib Maven artifact" + case a.JibArtifact != nil: + return "Jib artifact" default: return "Unknown artifact" } diff --git a/pkg/skaffold/schema/latest/config.go b/pkg/skaffold/schema/latest/config.go index e0ea7f848d3..708b4c2181a 100644 --- a/pkg/skaffold/schema/latest/config.go +++ b/pkg/skaffold/schema/latest/config.go @@ -638,13 +638,9 @@ type ArtifactType struct { // contain [Bazel](https://bazel.build/) configuration files. BazelArtifact *BazelArtifact `yaml:"bazel,omitempty" yamltags:"oneOf=artifact"` - // JibMavenArtifact *alpha* builds images using the - // [Jib plugin for Maven](https://github.com/GoogleContainerTools/jib/tree/master/jib-maven-plugin). - JibMavenArtifact *JibMavenArtifact `yaml:"jibMaven,omitempty" yamltags:"oneOf=artifact"` - - // JibGradleArtifact *alpha* builds images using the - // [Jib plugin for Gradle](https://github.com/GoogleContainerTools/jib/tree/master/jib-gradle-plugin). - JibGradleArtifact *JibGradleArtifact `yaml:"jibGradle,omitempty" yamltags:"oneOf=artifact"` + // JibArtifact *alpha* builds images using the + // [Jib plugins for Maven or Gradle](https://github.com/GoogleContainerTools/jib/). + JibArtifact *JibArtifact `yaml:"jib,omitempty" yamltags:"oneOf=artifact"` // KanikoArtifact *alpha* builds images using [kaniko](https://github.com/GoogleContainerTools/kaniko). KanikoArtifact *KanikoArtifact `yaml:"kaniko,omitempty" yamltags:"oneOf=artifact"` @@ -763,27 +759,16 @@ type BazelArtifact struct { BuildArgs []string `yaml:"args,omitempty"` } -// JibMavenArtifact *alpha* builds images using the -// [Jib plugin for Maven](https://github.com/GoogleContainerTools/jib/tree/master/jib-maven-plugin). -type JibMavenArtifact struct { - // Module selects which Maven module to build, for a multi module project. - Module string `yaml:"module,omitempty"` - - // Profile selects which Maven profile to activate. - Profile string `yaml:"profile,omitempty"` - - // Flags are additional build flags passed to Maven. - // For example: `["-x", "-DskipTests"]`. - Flags []string `yaml:"args,omitempty"` -} - -// JibGradleArtifact *alpha* builds images using the -// [Jib plugin for Gradle](https://github.com/GoogleContainerTools/jib/tree/master/jib-gradle-plugin). -type JibGradleArtifact struct { - // Project selects which Gradle project to build. +// JibArtifact *alpha* builds images using the +// [Jib plugins for Maven and Gradle](https://github.com/GoogleContainerTools/jib/). +type JibArtifact struct { + // Project selects which sub-project to build for multi-module builds. Project string `yaml:"project,omitempty"` - // Flags are additional build flags passed to Gradle. + // Flags are additional build flags passed to the builder. // For example: `["--no-build-cache"]`. Flags []string `yaml:"args,omitempty"` + + // Type the Jib builder type (internal: see jib.PluginType) + Type int `yaml:"-"` } diff --git a/pkg/skaffold/schema/v1beta13/upgrade.go b/pkg/skaffold/schema/v1beta13/upgrade.go index 8af20dff5d6..e3fc6eb4094 100755 --- a/pkg/skaffold/schema/v1beta13/upgrade.go +++ b/pkg/skaffold/schema/v1beta13/upgrade.go @@ -24,14 +24,46 @@ import ( // Upgrade upgrades a configuration to the next version. // Config changes from v1beta13 to v1beta14 -// 1. No Additions -// 2. No removals -// 3. No Updates +// 1. Additions: +// single jib builder for local and gcb +// 2. Removals: +// jibMaven builder +// jibGradle builder +// jibMaven profile removed +// 3. No updates func (config *SkaffoldConfig) Upgrade() (util.VersionedConfig, error) { var newConfig next.SkaffoldConfig pkgutil.CloneThroughJSON(config, &newConfig) + if err := util.UpgradePipelines(config, &newConfig, upgradeOnePipeline); err != nil { + return nil, err + } newConfig.APIVersion = next.Version return &newConfig, nil } + +func upgradeOnePipeline(oldPipeline, newPipeline interface{}) error { + oldBuild := &oldPipeline.(*Pipeline).Build + newBuild := &newPipeline.(*next.Pipeline).Build + + for i, a := range oldBuild.Artifacts { + switch { + case a.JibMavenArtifact != nil: + flags := a.JibMavenArtifact.Flags + if a.JibMavenArtifact.Profile != "" { + flags = append(flags, "--activate-profiles", a.JibMavenArtifact.Profile) + } + newBuild.Artifacts[i].JibArtifact = &next.JibArtifact{ + Project: a.JibMavenArtifact.Module, + Flags: flags, + } + case a.JibGradleArtifact != nil: + newBuild.Artifacts[i].JibArtifact = &next.JibArtifact{ + Project: a.JibGradleArtifact.Project, + Flags: a.JibGradleArtifact.Flags, + } + } + } + return nil +} diff --git a/pkg/skaffold/schema/v1beta13/upgrade_test.go b/pkg/skaffold/schema/v1beta13/upgrade_test.go index 390fc9b30cd..aa74dfc8189 100755 --- a/pkg/skaffold/schema/v1beta13/upgrade_test.go +++ b/pkg/skaffold/schema/v1beta13/upgrade_test.go @@ -35,6 +35,14 @@ build: - image: gcr.io/k8s-skaffold/bazel bazel: target: //mytarget + - image: gcr.io/k8s-skaffold/jib-maven + jibMaven: + args: ['-v'] + profile: prof + module: dir + - image: gcr.io/k8s-skaffold/jib-gradle + jibGradle: + args: ['-v'] googleCloudBuild: projectId: test-project test: @@ -88,6 +96,13 @@ build: - image: gcr.io/k8s-skaffold/bazel bazel: target: //mytarget + - image: gcr.io/k8s-skaffold/jib-maven + jib: + args: ['-v', '--activate-profiles', 'prof'] + project: dir + - image: gcr.io/k8s-skaffold/jib-gradle + jib: + args: ['-v'] googleCloudBuild: projectId: test-project test: diff --git a/pkg/skaffold/util/util.go b/pkg/skaffold/util/util.go index ee96cc83374..f8c04560533 100644 --- a/pkg/skaffold/util/util.go +++ b/pkg/skaffold/util/util.go @@ -303,6 +303,18 @@ func AbsolutePaths(workspace string, paths []string) []string { return list } +func IsFile(path string) bool { + info, err := os.Stat(path) + // err could be permission-related + return (err == nil || !os.IsNotExist(err)) && info.Mode().IsRegular() +} + +func IsDir(path string) bool { + info, err := os.Stat(path) + // err could be permission-related + return (err == nil || !os.IsNotExist(err)) && info.IsDir() +} + // IsHiddenDir returns if a directory is hidden. func IsHiddenDir(filename string) bool { // Return false for current dir diff --git a/pkg/skaffold/util/util_test.go b/pkg/skaffold/util/util_test.go index eee0db9c30d..956a02631af 100644 --- a/pkg/skaffold/util/util_test.go +++ b/pkg/skaffold/util/util_test.go @@ -334,3 +334,18 @@ func TestStrSliceInsert(t *testing.T) { testutil.CheckDeepEqual(t, []string{"a", "b", "c"}, StrSliceInsert([]string{"a", "b", "c"}, 0, nil)) testutil.CheckDeepEqual(t, []string{"a", "b", "c"}, StrSliceInsert([]string{"a", "b", "c"}, 1, nil)) } + +func TestIsFileIsDir(t *testing.T) { + tmpDir, cleanup := testutil.NewTempDir(t) + defer cleanup() + tmpDir.Touch("file") + + testutil.CheckDeepEqual(t, false, IsFile(tmpDir.Root())) + testutil.CheckDeepEqual(t, true, IsDir(tmpDir.Root())) + + testutil.CheckDeepEqual(t, true, IsFile(filepath.Join(tmpDir.Root(), "file"))) + testutil.CheckDeepEqual(t, false, IsDir(filepath.Join(tmpDir.Root(), "file"))) + + testutil.CheckDeepEqual(t, false, IsFile(filepath.Join(tmpDir.Root(), "nonexistent"))) + testutil.CheckDeepEqual(t, false, IsDir(filepath.Join(tmpDir.Root(), "nonexistent"))) +}