From 9e5f82c87e2ee23320fb7210be4928b6caebe591 Mon Sep 17 00:00:00 2001 From: Alex Landau Date: Wed, 10 Nov 2021 15:27:25 -0800 Subject: [PATCH] Add a marker task for writing just product dependencies locks (#1178) * Add a marker task for writing just product dependencies locks In some circumstances, it is useful to do just one type of lock writing at a time, without running everything that keys off of --write-locks. This is less common for product-dependencies.lock updates, which are now usually slower than other types, but this still comes in useful in certain situations. Adds a marker task named `writeProductDependenciesLocks`, matching the convention of `writeVersionsLocks` in gradle-consistent-versions. This modifies the behavior of the existing createManifest tasks. Co-authored-by: Alex Landau Co-authored-by: svc-changelog Co-authored-by: Eric Sword --- changelog/@unreleased/pr-1178.v2.yml | 7 ++++ .../gradle/dist/tasks/CreateManifestTask.java | 21 +++++++++-- ...iteProductDependenciesLocksMarkerTask.java | 37 +++++++++++++++++++ .../JavaServiceDistributionPluginTests.groovy | 10 ++++- .../CreateManifestTaskIntegrationSpec.groovy | 23 ++++++++++++ readme.md | 2 +- 6 files changed, 94 insertions(+), 6 deletions(-) create mode 100644 changelog/@unreleased/pr-1178.v2.yml create mode 100644 gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/tasks/WriteProductDependenciesLocksMarkerTask.java diff --git a/changelog/@unreleased/pr-1178.v2.yml b/changelog/@unreleased/pr-1178.v2.yml new file mode 100644 index 000000000..25db978f1 --- /dev/null +++ b/changelog/@unreleased/pr-1178.v2.yml @@ -0,0 +1,7 @@ +type: improvement +improvement: + description: Add a new `writeProductDependenciesLocks` task that allows writing + out the `product-dependencies.lock` files without running `--write-locks` and + possibly triggering undesirable code paths from other gradle plugins. + links: + - https://github.com/palantir/sls-packaging/pull/1178 diff --git a/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/tasks/CreateManifestTask.java b/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/tasks/CreateManifestTask.java index 7b0666847..064a367be 100644 --- a/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/tasks/CreateManifestTask.java +++ b/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/tasks/CreateManifestTask.java @@ -48,6 +48,7 @@ import org.gradle.api.Project; import org.gradle.api.Task; import org.gradle.api.file.RegularFileProperty; +import org.gradle.api.invocation.Gradle; import org.gradle.api.provider.MapProperty; import org.gradle.api.provider.Property; import org.gradle.api.provider.SetProperty; @@ -139,7 +140,7 @@ private void requireAbsentLockfile() { return; } - if (getProject().getGradle().getStartParameter().isWriteDependencyLocks()) { + if (shouldWriteLocks(getProject())) { lockfile.delete(); getLogger().lifecycle("Deleted {}", relativePath); } else { @@ -153,6 +154,15 @@ private File getLockfile() { return getProject().file(ProductDependencyLockFile.LOCK_FILE); } + public static boolean shouldWriteLocks(Project project) { + String taskName = project.getPath().equals(":") + ? ":writeProductDependenciesLocks" + : project.getPath() + ":writeProductDependenciesLocks"; + Gradle gradle = project.getGradle(); + return gradle.getStartParameter().isWriteDependencyLocks() + || gradle.getTaskGraph().hasTask(taskName); + } + private void ensureLockfileIsUpToDate(List productDeps) throws IOException { File lockfile = getLockfile(); Path relativePath = getProject().getRootDir().toPath().relativize(lockfile.toPath()); @@ -160,7 +170,7 @@ private void ensureLockfileIsUpToDate(List productDeps) throw productDeps, getInRepoProductIds().get()); boolean lockfileExists = lockfile.exists(); - if (getProject().getGradle().getStartParameter().isWriteDependencyLocks()) { + if (shouldWriteLocks(getProject())) { Files.writeString(lockfile.toPath(), upToDateContents); if (!lockfileExists) { @@ -244,7 +254,7 @@ public static TaskProvider createManifestTask(Project projec task.getOutputs().upToDateWhen(new Spec() { @Override public boolean isSatisfiedBy(Task _task) { - return !project.getGradle().getStartParameter().isWriteDependencyLocks(); + return !shouldWriteLocks(project); } }); @@ -257,6 +267,11 @@ public boolean isSatisfiedBy(Task _task) { .configure(task -> task.dependsOn(createManifest)); }); + project.getTasks() + .register("writeProductDependenciesLocks", WriteProductDependenciesLocksMarkerTask.class, task -> { + task.dependsOn(createManifest); + }); + // We want `./gradlew --write-locks` to magically fix up the product-dependencies.lock file // We can't do this at configuration time because it would mess up gradle-consistent-versions. StartParameter startParam = project.getGradle().getStartParameter(); diff --git a/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/tasks/WriteProductDependenciesLocksMarkerTask.java b/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/tasks/WriteProductDependenciesLocksMarkerTask.java new file mode 100644 index 000000000..657217c39 --- /dev/null +++ b/gradle-sls-packaging/src/main/java/com/palantir/gradle/dist/tasks/WriteProductDependenciesLocksMarkerTask.java @@ -0,0 +1,37 @@ +/* + * (c) Copyright 2021 Palantir Technologies Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.palantir.gradle.dist.tasks; + +import org.gradle.api.DefaultTask; +import org.gradle.api.GradleException; +import org.gradle.api.tasks.TaskAction; + +public class WriteProductDependenciesLocksMarkerTask extends DefaultTask { + @TaskAction + public final void checkWriteLocksShouldBeRunning() { + // Check that our task name matcher for writeProductDependenciesLocks is actually matching up the Gradle one; + // if this task is running but we didn't actually write locks, error out. + if (!CreateManifestTask.shouldWriteLocks(getProject())) { + throw new GradleException("This `writeProductDependenciesLocks` marker task has been run, but the " + + "product-dependencies.lock files did not actually get written out at configuration time. Either " + + "there is another task dependency on this task, which is not supported " + + "(`writeProductDependenciesLocks` must be run as a gradle task from the command line - not as a " + + "dependent task), or this is a bug and should be reported to the owners of the " + + "gradle-sls-packaging plugin."); + } + } +} diff --git a/gradle-sls-packaging/src/test/groovy/com/palantir/gradle/dist/service/JavaServiceDistributionPluginTests.groovy b/gradle-sls-packaging/src/test/groovy/com/palantir/gradle/dist/service/JavaServiceDistributionPluginTests.groovy index 6efc50bdc..890549f96 100644 --- a/gradle-sls-packaging/src/test/groovy/com/palantir/gradle/dist/service/JavaServiceDistributionPluginTests.groovy +++ b/gradle-sls-packaging/src/test/groovy/com/palantir/gradle/dist/service/JavaServiceDistributionPluginTests.groovy @@ -27,6 +27,8 @@ import org.gradle.testkit.runner.BuildResult import java.util.jar.Attributes import java.util.jar.JarOutputStream import java.util.jar.Manifest +import spock.lang.Unroll + import java.util.zip.ZipFile import org.gradle.testkit.runner.TaskOutcome import org.junit.Assert @@ -847,7 +849,8 @@ class JavaServiceDistributionPluginTests extends GradleIntegrationSpec { launcherStatic.classpath.any { it.contains('/lib/mockito-core-2.7.22.jar') } } - def 'docker can resolve inter-project product dependencies'() { + @Unroll + def 'docker can resolve inter-project product dependencies (#writeLocksTask)'() { buildFile << """ buildscript { repositories { @@ -889,7 +892,7 @@ class JavaServiceDistributionPluginTests extends GradleIntegrationSpec { } """.stripIndent()) - runTasks("--write-locks") + runTasks(writeLocksTask) // We're just using generateDockerCompose as it conveniently resolves the 'docker' configuration for us // Which in turn, conveniently depends on all subprojects' `productDependencies` configurations @@ -897,6 +900,9 @@ class JavaServiceDistributionPluginTests extends GradleIntegrationSpec { expect: runTasks("generateDockerCompose") + + where: + writeLocksTask << ['--write-locks', 'writeProductDependenciesLocks'] } def 'uses the runtimeClasspath in manifest jar'() { diff --git a/gradle-sls-packaging/src/test/groovy/com/palantir/gradle/dist/tasks/CreateManifestTaskIntegrationSpec.groovy b/gradle-sls-packaging/src/test/groovy/com/palantir/gradle/dist/tasks/CreateManifestTaskIntegrationSpec.groovy index 2d70cbd27..fb207abbf 100644 --- a/gradle-sls-packaging/src/test/groovy/com/palantir/gradle/dist/tasks/CreateManifestTaskIntegrationSpec.groovy +++ b/gradle-sls-packaging/src/test/groovy/com/palantir/gradle/dist/tasks/CreateManifestTaskIntegrationSpec.groovy @@ -19,6 +19,7 @@ package com.palantir.gradle.dist.tasks import com.palantir.gradle.dist.ObjectMappers import com.palantir.gradle.dist.pdeps.ResolveProductDependenciesIntegrationSpec import nebula.test.IntegrationSpec +import spock.lang.Unroll class CreateManifestTaskIntegrationSpec extends IntegrationSpec { @@ -179,6 +180,28 @@ class CreateManifestTaskIntegrationSpec extends IntegrationSpec { ] } + @Unroll + def 'writes locks when #writeLocksTask is on the command line'() { + buildFile << """ + distribution { + ${ResolveProductDependenciesIntegrationSpec.PDEP} + } + """.stripIndent() + + when: + def buildResult = runTasksSuccessfully(writeLocksTask) + + then: + buildResult.wasExecuted(':createManifest') + file('product-dependencies.lock').text == """\ + # Run ./gradlew --write-locks to regenerate this file + group1:name1 (1.0.0, 1.3.x) + """.stripIndent() + + where: + writeLocksTask << ['--write-locks', 'writeProductDependenciesLocks', 'wPDL'] + } + def "check depends on createManifest"() { when: def result = runTasks(':check') diff --git a/readme.md b/readme.md index a511c8e1d..f9912292a 100644 --- a/readme.md +++ b/readme.md @@ -77,7 +77,7 @@ distribution { } ``` -sls-packaging also maintains a lockfile, `product-dependencies.lock`, which should be checked in to Git. This file is an accurate reflection of all the inferred and explicitly defined product dependencies. Run **`./gradlew --write-locks`** to update it. e.g. +sls-packaging also maintains a lockfile, `product-dependencies.lock`, which should be checked in to Git. This file is an accurate reflection of all the inferred and explicitly defined product dependencies. Run **`./gradlew --write-locks`** or **`./gradlew writeProductDependenciesLocks`** to update it. e.g. ``` # Run ./gradlew --write-locks to regenerate this file