Skip to content
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

add a BOM to our generated pom.xml files #2956

Merged
merged 18 commits into from
Mar 23, 2018
Merged

add a BOM to our generated pom.xml files #2956

merged 18 commits into from
Mar 23, 2018

Conversation

elharo
Copy link
Contributor

@elharo elharo commented Mar 20, 2018

@chanseokoh fix #2923 for Maven projects

@elharo elharo changed the title add a pom to our generated pom.xml files add a BOM to our generated pom.xml files Mar 20, 2018
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud</artifactId>
<version>${googleCloudJavaVersion}</version>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

googleCloudJavaBomVersion?

scopePresent = true;
}
}
Assert.assertTrue(scopePresent);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be simplified using XPath as in PomXmlValidator?

@@ -208,7 +214,7 @@ private static void createPomXml(IProject project, AppEngineProjectConfig config
String sdkVersion = getCurrentVersion(
"com.google.appengine", //$NON-NLS-1$
"appengine-api-1.0-sdk", //$NON-NLS-1$
"1.9.62"); //$NON-NLS-1$
"1.9.63"); //$NON-NLS-1$
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's worth pulling these artifact constants (including the BOM artifact too) out into explicit constants rather than have them scattered in the code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. Can you file an issue for that?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Elliotte Harold added 2 commits March 21, 2018 09:53
@codecov
Copy link

codecov bot commented Mar 21, 2018

Codecov Report

Merging #2956 into master will decrease coverage by 0.01%.
The diff coverage is 74.71%.

Impacted file tree graph

@@             Coverage Diff              @@
##             master    #2956      +/-   ##
============================================
- Coverage      69.2%   69.18%   -0.02%     
- Complexity     2648     2657       +9     
============================================
  Files           356      358       +2     
  Lines         12428    12482      +54     
  Branches       1474     1483       +9     
============================================
+ Hits           8601     8636      +35     
- Misses         3220     3233      +13     
- Partials        607      613       +6
Impacted Files Coverage Δ Complexity Δ
...oogle/cloud/tools/eclipse/util/CloudToolsInfo.java 85.71% <ø> (ø) 7 <0> (ø) ⬇️
...d/tools/eclipse/appengine/libraries/BuildPath.java 71.79% <0%> (ø) 22 <0> (ø) ⬇️
...ls/eclipse/appengine/newproject/CodeTemplates.java 93.26% <100%> (+0.13%) 21 <1> (ø) ⬇️
...se/appengine/libraries/Maven4NamespaceContext.java 50% <50%> (ø) 2 <2> (?)
...e/cloud/tools/eclipse/appengine/libraries/Bom.java 70% <70%> (ø) 6 <6> (?)
...e/cloud/tools/eclipse/appengine/libraries/Pom.java 86% <79.59%> (-4.16%) 35 <15> (+1)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 86bd279...ac9cb01. Read the comment docs.

* Maps all prefixes to http://maven.apache.org/POM/4.0.0 and
* all namespace URIs to "m". Not suitable for general use.
*/
class Maven4NamespaceContext implements NamespaceContext {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can reuse com.google.cloud.tools.eclipse.appengine.validation.MavenContext

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd forgotten about that class. Looking at it now, it has the same issues this class does. That is, it works only for very limited code and is actively broken for all other uses. Given that, I don't feels safe exposing it as part of the public API. We could look for or build a more correct namespace context that fully satisfies the interface's contract.

@chanseokoh
Copy link
Contributor

Trying to understand the direction of this BOM stuff. So, with a BOM, I believe eventually we will get rid of the <version> element of Cloud libraries we add to pom.xml through the library page, right? Just checking, as this isn't happening in this PR.

@elharo
Copy link
Contributor Author

elharo commented Mar 21, 2018

With the BOM we can remove explicit versions from the google-cloud-java dependencies. However this may require splitting our library addition code into two: one for google-cloud-java dependencies and one for everything else.

@elharo
Copy link
Contributor Author

elharo commented Mar 22, 2018

There's a bug where our code is expecting there to be only one dependencies element but gets confused when there's more than one in the document:

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>com.google.cloud</groupId>
        <artifactId>google-cloud</artifactId>
        <version>0.40.0-alpha</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    <dependency>
<groupId>com.google.endpoints</groupId>
<artifactId>endpoints-framework</artifactId>
<version>2.0.13</version>
</dependency>
<dependency>
<groupId>com.googlecode.objectify</groupId>
<artifactId>objectify</artifactId>
<version>5.1.22</version>
</dependency>
</dependencies>
  </dependencyManagement>

I'm surprised tests didn't catch this.

Copy link
Contributor Author

@elharo elharo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, this PR now fixes bugs that occur when adding libraries to any existing pom.xml files that have a dependencyManagement element.
It's not only about adding bom support.

Copy link
Contributor Author

@elharo elharo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ping. This is now ready for review.

@@ -0,0 +1,89 @@
/*
* Copyright 2018 Google LLC.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No period after "LLC".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -1,5 +1,5 @@
/*
* Copyright 2017 Google Inc.
* Copyright 2017 Google LLC. All Rights Reserved.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should end with "LLC" with no period.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


Node rootElement = doc.getDocumentElement();

dependencyManager =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this dependencyManager or dependencyManagement? (I'm confused.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

management, done

@@ -13,6 +13,18 @@
<artifactId>com.google.cloud.tools.eclipse.appengine.libraries.test</artifactId>
<version>0.1.0-SNAPSHOT</version>
<packaging>eclipse-test-plugin</packaging>

<dependencyManagement>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this dependencyManager or dependencyManagement? (I'm confused.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dependencyManagement


/**
*
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


private final static XPathFactory factory = XPathFactory.newInstance();

private static Set<String> artifacts;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about artifactIds?

"http://maven.apache.org/POM/4.0.0", "dependencies");
}
} catch (XPathExpressionException ex) {
IStatus status = StatusUtil.error(Pom.class, ex.getMessage(), ex);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem it will happen. RuntimeException?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since we can return a status here, that's safer. But your'e right, it shouldn't happen.

String bomArtifactId = (String) xpath.evaluate(
"string(./m:dependencies/m:dependency/m:artifactId)",
dependencyManager,
XPathConstants.STRING);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's say users include another 3rd-party BOM in addition to ours. I guess this code may not work, since it could return the group ID and artifact ID of the other 3rd-party POM?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Let me think about that.
FYI, right now in prod the code is broken with any dependencyManagement section including ours.

static {
try {
List<CloudLibrary> cloudLibraries =
com.google.cloud.tools.libraries.CloudLibraries.getCloudLibraries();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To confirm: so we simply assume here our Cloud BOM includes all the libraries that appengine-plugins-core returns, and a future work is to read the actual content of the BOM?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

@@ -1,5 +1,5 @@
/*
* Copyright 2017 Google Inc.
* Copyright 2017 Google LLC. All Rights Reserved.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No All Rights Reserved, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right

NodeList dependencies = actual.getElementsByTagName("dependencies");
NodeList children = ((Element) dependencies.item(0)).getElementsByTagName("dependency");

Assert.assertEquals(2, children.getLength());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's worth keeping asserting length == 2

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -286,7 +297,7 @@ public void testResolveLibraries() throws CoreException {
Library library2 = newLibrary("id2", file1, file2);

pom.updateDependencies(Arrays.asList(library1), Arrays.asList(library1, library2));

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove the introduced space

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Google style is officially not to worry about trailing whitespace

Element dependencies = (Element) dependenciesList.item(0);
Assert.assertEquals(2, dependenciesList.getLength());

Element dependencies = (Element) dependenciesList.item(1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think it's worth a comment here saying item 0 is from the <dependencyManagement> section? (Or would it be clearer to rewrite this section using XPath too to ensure the depMgmt section is never seen?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added comment

import org.w3c.dom.Element;

/**
*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Class comment? This class might be better named to indicate that it's specific to the Google Cloud BOM. (Need to remember that users may use other BOMs, like the Spring BOM, and the bom project defines BOMs for all sorts of projects.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expect it's going to become more generic. For now it's package private.

static {
try {
List<CloudLibrary> cloudLibraries =
com.google.cloud.tools.libraries.CloudLibraries.getCloudLibraries();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason for the FQCN?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have a same-name class, so I think it's good to signify that this is from appengine-plugins-core.


try {
String bomGroupId = (String) xpath.evaluate(
"string(./m:dependencies/m:dependency/m:groupId)",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't you want to get with type=pom and scope=import?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not necessary

XPathConstants.NODESET);
Assert.assertEquals(1, dependencyManagementNodes.getLength());

String bomGroupId = (String) xpath.evaluate(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth checking that there is a single <dependencies> element?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, we're not. We're getting the first top-level dependencies element.

@chanseokoh
Copy link
Contributor

Things seem to work fine. Only one minor problem:

selection_008

"Duplicating managed version 4.12 for junit" in pom.xml. BOM seems to pull in the JUnit version too. Removing the <version> element clears the warning. Not sure why the BOM exposes a test dependency version. Will there be a way to exclude it?

@elharo
Copy link
Contributor Author

elharo commented Mar 23, 2018

The ultimate fix to the JUnit warning is to expand the dependency checking code to actually query the BOM. For now, though, it's just a low priority warning with no actual effect on the user's code.

@elharo elharo merged commit 0ce011e into master Mar 23, 2018
@elharo elharo deleted the bom branch March 23, 2018 22:53
@patflynn
Copy link

patflynn commented Mar 26, 2018 via email

@elharo
Copy link
Contributor Author

elharo commented Mar 26, 2018

The BOM pulls in transitive dependencies, not just the immediate declarations. It's a lot broader and deeper than it looks.

@chanseokoh
Copy link
Contributor

Yeah, it pulls in guava too. The <version> element is not needed when importing the BOM.

@patflynn
Copy link

patflynn commented Mar 26, 2018 via email

Element springDependency =
configureBom(doc, "org.springframework.boot", "spring-boot-dependencies", "2.0.0.RELEASE");
dependencies.appendChild(springDependency);
Element cloudDependency = configureBom(doc, "com.google.cloud", "google-cloud", "0.40.0-alpha");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aha. This should be google-cloud-bom.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you guys trace which dep is pulling in junit? We should file a bug.

@patflynn turns out we were not pulling in a BOM.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

BOM support
5 participants