-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make custom tasks compatible with configuration cache
Gradle is forcing a move away from using 'project' during task excution and because of some interactions there, this is easiest by making them real classes. That makes them start looking quite strange in the build file, so they are now moved to buildSrc/. We could have continued using Groovy, but it is weird in some ways that are more apparent when making classes and not just scripting. Instead, they were converted to Java. They are compatible with delayed configuration resolution as well.
- Loading branch information
Showing
6 changed files
with
349 additions
and
121 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
tasks.withType(JavaCompile).configureEach { | ||
it.options.compilerArgs += [ | ||
"-Xlint:all", | ||
] | ||
} |
131 changes: 131 additions & 0 deletions
131
buildSrc/src/main/java/io/grpc/gradle/CheckForUpdatesTask.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
/* | ||
* Copyright 2023 The gRPC Authors | ||
* | ||
* 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 io.grpc.gradle; | ||
|
||
import java.util.Collections; | ||
import java.util.HashMap; | ||
import java.util.LinkedHashSet; | ||
import java.util.Map; | ||
import java.util.Set; | ||
import javax.inject.Inject; | ||
import org.gradle.api.DefaultTask; | ||
import org.gradle.api.artifacts.Configuration; | ||
import org.gradle.api.artifacts.Dependency; | ||
import org.gradle.api.artifacts.ModuleVersionIdentifier; | ||
import org.gradle.api.artifacts.VersionCatalog; | ||
import org.gradle.api.artifacts.VersionCatalogsExtension; | ||
import org.gradle.api.artifacts.result.ResolvedComponentResult; | ||
import org.gradle.api.artifacts.result.ResolvedDependencyResult; | ||
import org.gradle.api.provider.Provider; | ||
import org.gradle.api.tasks.Input; | ||
import org.gradle.api.tasks.Nested; | ||
import org.gradle.api.tasks.TaskAction; | ||
|
||
/** | ||
* Checks every dependency in the version catalog to see if there is a newer version available. The | ||
* passed configuration restricts the versions considered. | ||
*/ | ||
public abstract class CheckForUpdatesTask extends DefaultTask { | ||
private final Set<Library> libraries; | ||
|
||
@Inject | ||
public CheckForUpdatesTask(Configuration updateConf, String catalog) { | ||
updateConf.setVisible(false); | ||
updateConf.setTransitive(false); | ||
VersionCatalog versionCatalog = getProject().getExtensions().getByType(VersionCatalogsExtension.class).named(catalog); | ||
Set<Library> libraries = new LinkedHashSet<Library>(); | ||
for (String name : versionCatalog.getLibraryAliases()) { | ||
org.gradle.api.artifacts.MinimalExternalModuleDependency dep = versionCatalog.findLibrary(name).get().get(); | ||
|
||
Configuration oldConf = updateConf.copy(); | ||
Dependency oldDep = getProject().getDependencies().create( | ||
depMap(dep.getGroup(), dep.getName(), dep.getVersionConstraint().toString(), "pom")); | ||
oldConf.getDependencies().add(oldDep); | ||
|
||
Configuration newConf = updateConf.copy(); | ||
Dependency newDep = getProject().getDependencies().create( | ||
depMap(dep.getGroup(), dep.getName(), "+", "pom")); | ||
newConf.getDependencies().add(newDep); | ||
|
||
libraries.add(new Library( | ||
name, | ||
oldConf.getIncoming().getResolutionResult().getRootComponent(), | ||
newConf.getIncoming().getResolutionResult().getRootComponent())); | ||
} | ||
this.libraries = Collections.unmodifiableSet(libraries); | ||
} | ||
|
||
private static Map<String, String> depMap( | ||
String group, String name, String version, String classifier) { | ||
Map<String, String> map = new HashMap<>(); | ||
map.put("group", group); | ||
map.put("name", name); | ||
map.put("version", version); | ||
map.put("classifier", classifier); | ||
return map; | ||
} | ||
|
||
@Nested | ||
protected Set<Library> getLibraries() { | ||
return libraries; | ||
} | ||
|
||
@TaskAction | ||
public void checkForUpdates() { | ||
for (Library lib : libraries) { | ||
String name = lib.getName(); | ||
ModuleVersionIdentifier oldId = ((ResolvedDependencyResult) lib.getOldResult().get() | ||
.getDependencies().iterator().next()).getSelected().getModuleVersion(); | ||
ModuleVersionIdentifier newId = ((ResolvedDependencyResult) lib.getNewResult().get() | ||
.getDependencies().iterator().next()).getSelected().getModuleVersion(); | ||
if (oldId != newId) { | ||
System.out.println(String.format( | ||
"libs.%s = %s:%s %s -> %s", | ||
name, newId.getGroup(), newId.getModule(), oldId.getVersion(), newId.getVersion())); | ||
} | ||
} | ||
} | ||
|
||
public static final class Library { | ||
private final String name; | ||
private final Provider<ResolvedComponentResult> oldResult; | ||
private final Provider<ResolvedComponentResult> newResult; | ||
|
||
public Library( | ||
String name, Provider<ResolvedComponentResult> oldResult, | ||
Provider<ResolvedComponentResult> newResult) { | ||
this.name = name; | ||
this.oldResult = oldResult; | ||
this.newResult = newResult; | ||
} | ||
|
||
@Input | ||
public String getName() { | ||
return name; | ||
} | ||
|
||
@Input | ||
public Provider<ResolvedComponentResult> getOldResult() { | ||
return oldResult; | ||
} | ||
|
||
@Input | ||
public Provider<ResolvedComponentResult> getNewResult() { | ||
return newResult; | ||
} | ||
} | ||
} |
66 changes: 66 additions & 0 deletions
66
buildSrc/src/main/java/io/grpc/gradle/CheckPackageLeakageTask.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/* | ||
* Copyright 2023 The gRPC Authors | ||
* | ||
* 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 io.grpc.gradle; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.util.Enumeration; | ||
import java.util.jar.JarEntry; | ||
import java.util.jar.JarFile; | ||
import org.gradle.api.DefaultTask; | ||
import org.gradle.api.file.ConfigurableFileCollection; | ||
import org.gradle.api.provider.Property; | ||
import org.gradle.api.tasks.Classpath; | ||
import org.gradle.api.tasks.Input; | ||
import org.gradle.api.tasks.TaskAction; | ||
import org.gradle.api.tasks.TaskExecutionException; | ||
|
||
/** Verifies all class files within jar files are in a specified Java package. */ | ||
public abstract class CheckPackageLeakageTask extends DefaultTask { | ||
public CheckPackageLeakageTask() { | ||
// Fake output for UP-TO-DATE checking | ||
getOutputs().file(getProject().getLayout().getBuildDirectory().file("tmp/" + getName())); | ||
} | ||
|
||
@Classpath | ||
abstract ConfigurableFileCollection getFiles(); | ||
|
||
@Input | ||
abstract Property<String> getPrefix(); | ||
|
||
@TaskAction | ||
public void checkLeakage() throws IOException { | ||
String jarEntryPrefixName = getPrefix().get().replace('.', '/'); | ||
boolean packageLeakDetected = false; | ||
for (File jar : getFiles()) { | ||
try (JarFile jf = new JarFile(jar)) { | ||
for (Enumeration<JarEntry> e = jf.entries(); e.hasMoreElements(); ) { | ||
JarEntry entry = e.nextElement(); | ||
if (entry.getName().endsWith(".class") | ||
&& !entry.getName().startsWith(jarEntryPrefixName)) { | ||
packageLeakDetected = true; | ||
System.out.println("WARNING: package leaked, may need relocation: " + entry.getName()); | ||
} | ||
} | ||
} | ||
} | ||
if (packageLeakDetected) { | ||
throw new TaskExecutionException(this, | ||
new IllegalStateException("Resource leakage detected!")); | ||
} | ||
} | ||
} |
Oops, something went wrong.