-
Notifications
You must be signed in to change notification settings - Fork 72
feat: unmanaged dependency check #2223
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
3b7a7a9
0cc007d
3b151d3
49574ec
cbd15e3
420e8ec
b97b883
7c4ae40
09f3a0e
10c4243
e42a382
e8a6412
2290942
74f69b2
39c5e87
73d79f3
ae9b747
ec17df1
22f99ff
df34a0e
8b1e836
ff4a502
5ba8ce8
8cacf76
abd704e
a952d7a
e404f90
f15ecd9
f72ad9f
df445ba
3feb3e9
d3537f9
5df6a31
1170018
79530e8
6590740
81c23f0
c230765
6a1e3e5
3dd389e
4300d70
a17d693
cd64141
b28ac5e
a526ab0
99baeaa
4c0b1c6
c92525d
0723511
11bb40e
8c39284
20fcebe
9b6d3ae
b01b0f0
67310bd
ae72da2
0f35e6a
3b276df
f47bb73
3f182fa
6c59374
abfe946
ac23cf1
cce1d69
d06099b
38b3ee4
5060033
37a5837
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| name: "Unmanaged dependency check" | ||
| description: "Checks whether there's a dependency that is not managed by java shared dependencies." | ||
| inputs: | ||
| bom-path: | ||
| description: "The relative path from the repository root to the pom.xml file" | ||
| required: true | ||
| runs: | ||
| using: "composite" | ||
| steps: | ||
| - uses: actions/setup-java@v3 | ||
| with: | ||
| distribution: temurin | ||
| java-version: 11 | ||
| cache: maven | ||
| - name: Set up Maven | ||
| uses: stCarolas/setup-maven@v4.5 | ||
| with: | ||
| maven-version: 3.8.2 | ||
| - name: Install latest Java shared dependencies | ||
| shell: bash | ||
| run: | | ||
| cd ${{ github.action_path }}/.. | ||
| echo "Install Java shared dependencies" | ||
| mvn clean install -V --batch-mode --no-transfer-progress -DskipTests | ||
| - name: Install check | ||
| shell: bash | ||
| run: | | ||
| cd ${{ github.action_path }} | ||
| echo "Install Unmanaged Dependency Check in $(pwd)" | ||
| mvn clean install -V --batch-mode --no-transfer-progress -DskipTests | ||
| - name: Run unmanaged dependency check | ||
| shell: bash | ||
| run: | | ||
| bom_absolute_path=$(realpath "${{ inputs.bom-path }}") | ||
| cd ${{ github.action_path }} | ||
| echo "Running Unmanaged Dependency Check against ${bom_absolute_path}" | ||
| unmanaged_dependencies=$(mvn exec:java -Dexec.args="../pom.xml ${bom_absolute_path}" -q) | ||
| if [[ "${unmanaged_dependencies}" != "[]" ]]; then | ||
| echo "This pull request seems to add new third-party dependency, ${unmanaged_dependencies}, among the artifacts listed in ${{ inputs.bom-path }}." | ||
| echo "Please see go/cloud-sdk-java-dependency-governance." | ||
| exit 1 | ||
| fi | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| <?xml version="1.0" encoding="UTF-8"?> | ||
| <project xmlns="http://maven.apache.org/POM/4.0.0" | ||
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
| xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
| <modelVersion>4.0.0</modelVersion> | ||
| <groupId>com.google.cloud</groupId> | ||
| <artifactId>unmanaged-dependency-check</artifactId> | ||
| <version>0.0.1-SNAPSHOT</version> | ||
| <name>Unmanaged dependency check</name> | ||
| <description> | ||
|
|
||
| </description> | ||
|
|
||
| <properties> | ||
| <maven.compiler.source>1.8</maven.compiler.source> | ||
| <maven.compiler.target>1.8</maven.compiler.target> | ||
| <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
| </properties> | ||
|
|
||
| <build> | ||
| <plugins> | ||
| <plugin> | ||
| <groupId>org.codehaus.mojo</groupId> | ||
| <artifactId>exec-maven-plugin</artifactId> | ||
| <version>3.1.1</version> | ||
| <executions> | ||
| <execution> | ||
| <goals> | ||
| <goal>java</goal> | ||
| </goals> | ||
| </execution> | ||
| <execution> | ||
| <!-- run the shell script to install test poms so the tests can be executed --> | ||
| <id>install-test-poms</id> | ||
| <phase>test-compile</phase> | ||
| <goals> | ||
| <goal>exec</goal> | ||
| </goals> | ||
| <configuration> | ||
| <executable>bash</executable> | ||
| <arguments> | ||
| <argument>local-install.sh</argument> | ||
| </arguments> | ||
| <workingDirectory>src/test/resources</workingDirectory> | ||
| </configuration> | ||
| </execution> | ||
| </executions> | ||
| <configuration> | ||
| <mainClass>com.google.cloud.UnmanagedDependencyCheck</mainClass> | ||
| </configuration> | ||
| </plugin> | ||
| </plugins> | ||
| </build> | ||
|
|
||
| <dependencies> | ||
| <dependency> | ||
| <groupId>com.google.cloud.tools</groupId> | ||
| <artifactId>dependencies</artifactId> | ||
| <version>1.5.13</version> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>junit</groupId> | ||
| <artifactId>junit</artifactId> | ||
| <version>4.13.2</version> | ||
| <scope>test</scope> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>com.google.truth</groupId> | ||
| <artifactId>truth</artifactId> | ||
| <version>1.1.5</version> | ||
| <scope>test</scope> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.slf4j</groupId> | ||
| <artifactId>slf4j-api</artifactId> | ||
| <version>2.0.9</version> | ||
| </dependency> | ||
| <dependency> | ||
| <groupId>org.slf4j</groupId> | ||
| <artifactId>slf4j-simple</artifactId> | ||
| <version>2.0.9</version> | ||
| </dependency> | ||
| </dependencies> | ||
|
|
||
| </project> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| package com.google.cloud; | ||
|
|
||
| import static com.google.common.base.Preconditions.checkArgument; | ||
|
|
||
| import com.google.cloud.tools.opensource.classpath.ClassPathBuilder; | ||
| import com.google.cloud.tools.opensource.classpath.DependencyMediation; | ||
| import com.google.cloud.tools.opensource.dependencies.Bom; | ||
| import com.google.cloud.tools.opensource.dependencies.MavenRepositoryException; | ||
| import java.nio.file.Paths; | ||
| import java.util.HashSet; | ||
| import java.util.List; | ||
| import java.util.Set; | ||
| import java.util.stream.Collectors; | ||
| import org.eclipse.aether.artifact.Artifact; | ||
| import org.eclipse.aether.version.InvalidVersionSpecificationException; | ||
|
|
||
| /** | ||
| * A utility class to check unmanaged dependencies in BOM. | ||
| */ | ||
| public class UnmanagedDependencyCheck { | ||
| // regex of handwritten artifacts | ||
| private final static String downstreamArtifact = "(com.google.cloud:google-cloud-.*)|(com.google.api.grpc:(grpc|proto)-google-cloud-.*)"; | ||
|
|
||
|
|
||
| /** | ||
| * @param args An array with two elements.<p> The first string is the path of Java shared | ||
| * dependencies BOM. <p> The second string is the path of a pom.xml contains BOM. | ||
| */ | ||
| public static void main(String[] args) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would you add Javadoc for the arguments?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think passing the version of Java shared dependencies will be come inconvenient.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Users of unmanaged dependency check don't need to pass this parameter. The version of shared dependencies needs update every two weeks so I think it's fine to set a parameter.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As talked yesterday |
||
| throws MavenRepositoryException, InvalidVersionSpecificationException { | ||
| checkArgument(args.length == 2, "The length of the inputs should be 2"); | ||
| System.out.println(getUnmanagedDependencies(args[0], args[1])); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What are good error message for library developers?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Idea. "This pull request seems to be adding a new third-party dependency com.h2.xxx:h2 among the artifacts listed in BOM com.google.cloud:bigtable-bom. Please see go/cloud-sdk-java-dependency-governance. " |
||
| } | ||
|
|
||
| /** | ||
| * Returns dependency coordinates that are not managed by shared dependency BOM. | ||
| * | ||
| * @param sharedDependenciesBomPath the path of shared dependency BOM | ||
| * @param projectBomPath the path of current project BOM | ||
| * @return a list of unmanaged dependencies by the given version of shared dependency BOM | ||
| * @throws MavenRepositoryException thrown if the artifacts in Bom can't be reached in remote or | ||
| * local Maven repository | ||
| * @throws InvalidVersionSpecificationException thrown if the shared dependency version can't be | ||
| * parsed | ||
| */ | ||
| public static List<String> getUnmanagedDependencies( | ||
| String sharedDependenciesBomPath, String projectBomPath) | ||
| throws MavenRepositoryException, InvalidVersionSpecificationException { | ||
| Set<String> sharedDependencies = getManagedDependencies(sharedDependenciesBomPath); | ||
| Set<String> managedDependencies = getManagedDependencies(projectBomPath); | ||
|
|
||
| return managedDependencies.stream() | ||
| .filter(dependency -> !sharedDependencies.contains(dependency)) | ||
| // handwritten artifacts, e.g., com.google.cloud:google-cloud-bigtable, should be excluded. | ||
| .filter(dependency -> !dependency.matches(downstreamArtifact)) | ||
| .collect(Collectors.toList()); | ||
| } | ||
|
|
||
| private static Set<String> getManagedDependencies(String projectBomPath) | ||
| throws MavenRepositoryException, InvalidVersionSpecificationException { | ||
| return getManagedDependenciesFromBom(Bom.readBom(Paths.get(projectBomPath))); | ||
| } | ||
|
|
||
| private static Set<String> getManagedDependenciesFromBom(Bom bom) | ||
| throws InvalidVersionSpecificationException { | ||
| Set<String> res = new HashSet<>(); | ||
| new ClassPathBuilder() | ||
| .resolve(bom.getManagedDependencies(), true, DependencyMediation.MAVEN) | ||
suztomo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| .getClassPath() | ||
| .forEach( | ||
| classPath -> { | ||
| Artifact artifact = classPath.getArtifact(); | ||
| res.add(String.format("%s:%s", artifact.getGroupId(), artifact.getArtifactId())); | ||
| }); | ||
|
|
||
| return res; | ||
| } | ||
|
|
||
| private UnmanagedDependencyCheck() { | ||
| throw new IllegalStateException("Utility class"); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| package com.google.cloud; | ||
|
|
||
| import static com.google.common.truth.Truth.assertThat; | ||
| import static org.junit.Assert.assertTrue; | ||
|
|
||
| import com.google.cloud.tools.opensource.dependencies.MavenRepositoryException; | ||
| import com.google.common.collect.ImmutableList; | ||
| import java.util.List; | ||
| import org.eclipse.aether.version.InvalidVersionSpecificationException; | ||
| import org.junit.Test; | ||
|
|
||
| public class UnmanagedDependencyCheckTest { | ||
suztomo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| @Test | ||
| public void getUnmanagedDependencyFromSamePomTest() | ||
| throws MavenRepositoryException, InvalidVersionSpecificationException { | ||
| String sharedDependenciesBom = "src/test/resources/shared-dependency-3.18.0-pom.xml"; | ||
| List<String> unManagedDependencies = | ||
| UnmanagedDependencyCheck.getUnmanagedDependencies(sharedDependenciesBom, sharedDependenciesBom); | ||
| assertTrue(unManagedDependencies.isEmpty()); | ||
| } | ||
|
|
||
| @Test | ||
| public void getUnmanagedDependencyFromHWBomTest() | ||
| throws MavenRepositoryException, InvalidVersionSpecificationException { | ||
| List<String> unManagedDependencies = | ||
| UnmanagedDependencyCheck.getUnmanagedDependencies( | ||
| "src/test/resources/shared-dependency-3.18.0-pom.xml", "src/test/resources/bigtable-pom.xml"); | ||
| assertTrue(unManagedDependencies.isEmpty()); | ||
| } | ||
|
|
||
| @Test | ||
| public void getUnmanagedDependencyFromNestedPomTest() | ||
suztomo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| throws MavenRepositoryException, InvalidVersionSpecificationException { | ||
| List<String> unManagedDependencies = | ||
| UnmanagedDependencyCheck.getUnmanagedDependencies( | ||
| "src/test/resources/shared-dependency-3.18.0-pom.xml", "src/test/resources/transitive-dependency-pom.xml"); | ||
| assertThat(unManagedDependencies) | ||
| .containsAtLeastElementsIn(ImmutableList.of("com.h2database:h2")); | ||
| // test dependency should be ignored. | ||
| assertThat(unManagedDependencies) | ||
| .doesNotContain(ImmutableList.of("com.mysql:mysql-connector-j")); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.