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

Clean up CLI #448

Merged
merged 4 commits into from
Feb 14, 2023
Merged

Clean up CLI #448

merged 4 commits into from
Feb 14, 2023

Conversation

basil
Copy link
Member

@basil basil commented Feb 7, 2023

This PR cleans up the command-line interface (CLI) of this component, probably not to a final state but to a state significantly better than the status quo which allows a lot of upstream code to be deleted and allows one bug to be fixed.

As part of this PR I have swapped out JCommander for the more elegant picocli. One of the things this allows us to do is easily accumulate properties in a map with multiple -D arguments. Apart from switching to picocli's casing and dash convention, I preserved existing semantics but with one important exception: I redefined the passing of Maven properties to apply only to Maven test execution, not Maven compilation. This is an important change in semantics that allows for a lot of cleanup to be done. It results in no loss of functionality, because the existing "Maven arguments" functionality can be used to pass properties to compilation. But allowing properties to be passed solely for test execution turns out to be quite handy. This leaves us with the following Maven-related properties:

  • --mvn: Global path to the Maven executable, passed to both compilation and tests
  • --m2-settings: Global settings file, passed to both compilation and tests
  • --maven-args: Global Maven arguments, passed to both compilation and tests (currently unused)
  • -D: Passed just when running tests

With this functionality there was simply no need to allow for properties to be passed in via a file anymore, so I ripped that out. (The only reason before was to represent properties that had a colon, but that is now supported natively with the picocli -D syntax.)

With that out of the way, I went ahead and transferred the responsibility for setting overrideWar, jenkins.version, and useUpperBounds from consumers of this component to this component itself. This simplifies consumers and de-duplicates code. And of course it is only passed when running tests, so compilation takes place with as vanilla a configuration as possible to achieve the originally intended goal of testing binary compatibility.

This PR also removes any references to -DforkCount or -Dsurefire.excludesFile from this component, leaving the responsibility for setting these firmly in the hands of consumers. Both consumers already set them, and this seems like the right place to do it. So no need to set them in this component.

There is still some messiness that remains duplicated in consumers after this PR: setting -Denforcer.skip, -Dhpi-plugin.version, -Djth.jenkins-war.path, and -DoverrideWarAdditions. These can be cleaned up separately, but at least they now only apply to tests, which is a strict improvement over the status quo.

Testing done

Besides jenkinsci/bom#1735 I manually tested text-finder with both old and new versions of Jenkins core and verified that the Maven properties were set correctly in each case (for both compilation and testing).

How to adapt consumers

See jenkinsci/bom#1735 for an example.

  • Replace -war with --war
  • Replace -workDirectory with --working-dir
  • Replace -includePlugins with --include-plugins
  • Replace -excludePlugins with --exclude-plugins
  • Replace -excludeHooks with --exclude-hooks
  • Replace -fallbackGitHubOrganization with --fallback-github-organization
  • Replace -m2SettingsFile with --m2-settings
  • Replace -mavenProperties with -Dkey=value for each property. Use multiple -D arguments, one for each property. (These will only apply to test execution, not compilation, which is probably what you want anyway.)
  • Replace -mavenPropertiesFile with -Dkey=value for each property. Use multiple -D arguments, one for each property. (These will only apply to test execution, not compilation, which is probably what you want anyway.)
  • Replace -mavenArgs with --maven-args
  • Replace -hookPrefixes with --hook-prefixes
  • Replace -externalHooksJars with --external-hooks-jars
  • Replace -localCheckoutDir with --local-checkout-dir
  • Replace -failFast true with --fail-fast
  • Replace -failFast false with --no-fail-fast
  • If you were passing overrideWar as a Maven property, stop doing that. We'll now add it automatically when running tests.
  • If you were passing jenkins.version as a Maven property, stop doing that. We'll now add it automatically when running tests.
  • If you were passing useUpperBounds as a Maven property, stop doing that. We'll now add it automatically when running tests.
  • If you were passing upperBoundsExcludes as a Maven property, stop doing that. We'll now add it automatically when running tests, but only if required for older Jenkins cores.
  • Replace calls to new ExternalMavenRunner(config.getExternalMaven()) with new ExternalMavenRunner(config.getExternalMaven(), config.getM2Settings(), config.getMavenArgs())`
  • Replace the first argument to MavenRunner#run with a map of properties. Assuming your usage is calling Maven for compilation rather than testing, this should just be Map.of("maven.javadoc.skip", "true"). Finally move any properties that you might have in the old MavenRunner.Config mconfig argument into this map. For example the first argument would read Map.of("maven-hpi-plugin.disabledTestInjection", "true", "maven.javadoc.skip", "true") followed by deleting the MavenRunner.Config mconfig variable.

Comment on lines +182 to +198
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<!-- Version specified in parent POM -->
<configuration>
<annotationProcessorPaths>
<path>
<groupId>info.picocli</groupId>
<artifactId>picocli-codegen</artifactId>
<version>${picocli.version}</version>
</path>
</annotationProcessorPaths>
<compilerArgs>
<arg>-Aproject=${project.groupId}/${project.artifactId}</arg>
</compilerArgs>
</configuration>
</plugin>
Copy link
Member Author

Choose a reason for hiding this comment

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

This is optional, but including this annotation processor gives feedback faster at compile-time rather than at runtime if an invalid CLI option is present.

Comment on lines 86 to 88
runner =
new ExternalMavenRunner(
config.getExternalMaven(), config.getM2Settings(), config.getMavenArgs());
Copy link
Member Author

Choose a reason for hiding this comment

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

The new calling convention for ExternalMavenRunner sets up the path to Maven and "global" arguments (including the settings file) but not properties: these are now specific to the type of Maven run (compilation or testing) and are passed in to MavenRunner#run on a case-by-case basis.

Comment on lines -136 to -139
MavenRunner.Config mconfig = new MavenRunner.Config(config);
// TODO REMOVE
mconfig.userProperties.put("failIfNoTests", "false");

Copy link
Member Author

Choose a reason for hiding this comment

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

This was unneeded; a jenkinsci/bom run passed without it. If it turns out this is still needed, proprietary consumers can pass it in with -D when invoking PCT. But please try not to.

@@ -252,7 +249,7 @@ private void testPluginAgainst(

File pluginCheckoutDir =
new File(
config.workDirectory.getAbsolutePath()
config.getWorkingDir().getAbsolutePath()
Copy link
Member Author

Choose a reason for hiding this comment

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

For some reason this never had a getter before. When cleaning up this code I made the field private and added a getter for consistency.

Comment on lines +318 to +329
File localCheckoutDir = config.getLocalCheckoutDir();
if (localCheckoutDir == null) {
throw new AssertionError(
"Could never happen, but needed to silence SpotBugs");
}
LOGGER.log(
Level.INFO,
"Copy plugin directory from {0}",
config.getLocalCheckoutDir().getAbsolutePath());
localCheckoutDir.getAbsolutePath());
try {
org.codehaus.plexus.util.FileUtils.copyDirectoryStructure(
config.getLocalCheckoutDir(), pluginCheckoutDir);
localCheckoutDir, pluginCheckoutDir);
Copy link
Member Author

Choose a reason for hiding this comment

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

Just making SpotBugs happy.

}
for (Map.Entry<String, String> entry : config.userProperties.entrySet()) {
cmd.add("--define=" + entry);
for (Map.Entry<String, String> entry : properties.entrySet()) {
Copy link
Member Author

Choose a reason for hiding this comment

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

Notice that this is now based on the parameter rather than a global set of properties for all Maven invocations. And the properties map that we pass in during compilation is almost always just skipping Javadoc generation, while the properties map that we pass in during test execution is what the user specified with -D when invoking PCT as well as the things like -overrideWar, jenkins.version, etc.

// The megawar
private File war;
@NonNull private final File war;
Copy link
Member Author

Choose a reason for hiding this comment

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

What looks like needless churn in this file is just sorting these fields, getters, and setters in the same order as they appear in the main CLI Java source file.

"hpi:resolve-test-dependencies",
"hpi:test-hpl",
"surefire:test")));
List.of("hpi:resolve-test-dependencies", "hpi:test-hpl", "surefire:test")));
Copy link
Member Author

Choose a reason for hiding this comment

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

Adapting to the fact that we're no longer in the business of managing forkCount.

"hpi:resolve-test-dependencies",
"hpi:test-hpl",
"surefire:test")));
List.of("hpi:resolve-test-dependencies", "hpi:test-hpl", "surefire:test")));
Copy link
Member Author

Choose a reason for hiding this comment

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

Adapting to the fact that we're no longer in the business of managing forkCount.

Comment on lines -67 to -78

@Test
public void testType() {
final WarningsNGExecutionHook hook = new WarningsNGExecutionHook();

Map<String, Object> info = new HashMap<>();
info.put("types", new ArrayList<>(List.of("surefire")));
Map<String, Object> afterAction = hook.action(info);
List<String> types = (List<String>) afterAction.get("types");
assertThat(types.size(), is(2));
assertTrue(types.contains("failsafe"));
}
Copy link
Member Author

Choose a reason for hiding this comment

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

Removing a test for unused functionality that existed only for the XML report which is now ripped out.

@basil basil requested a review from jtnord February 8, 2023 02:08
@basil basil marked this pull request as ready for review February 8, 2023 02:08
@basil basil requested a review from a team as a code owner February 8, 2023 02:08
Copy link
Member

@jtnord jtnord left a comment

Choose a reason for hiding this comment

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

can no longer test all plugins in a war by ommiting --include-plugins

Comment on lines +625 to +622
File localCheckoutDir = config.getLocalCheckoutDir();
return localCheckoutDir != null && localCheckoutDir.exists();
Copy link
Member

Choose a reason for hiding this comment

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

:-o #449 filed - this is fine here.

basil and others added 3 commits February 14, 2023 11:48
@basil basil merged commit b0641fa into master Feb 14, 2023
@basil basil deleted the cli branch February 14, 2023 19:58
basil added a commit that referenced this pull request Feb 15, 2023
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.

3 participants