Skip to content

Commit

Permalink
feat(maven): improve experience for multimodule project (#96)
Browse files Browse the repository at this point in the history
Signed-off-by: tison <[email protected]>
  • Loading branch information
tisonkun authored Sep 1, 2023
1 parent e4ad0ff commit 4605d93
Show file tree
Hide file tree
Showing 14 changed files with 233 additions and 136 deletions.
37 changes: 1 addition & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,42 +62,7 @@ docker run -it --rm -v $(pwd):/github/workspace ghcr.io/korandoru/hawkeye check

> :warning: `hawkeye-maven-plugin` is available since 3.3.0, but it's still Alpha which means that the API is subject to change before stable. Mainly, the configuration options may change.
You can integrate HawkEye's functionality with Maven Plugin:

```xml
<plugin>
<groupId>io.korandoru.hawkeye</groupId>
<artifactId>hawkeye-maven-plugin</artifactId>
<version>${hawkeye.version}</version>
</plugin>
```

The plugin provides three goals:

* `check`: Check license headers.
* `format`: Format license headers (auto-fix all files that failed the check).
* `remove`: Remove license headers.

With the plugin properly configured, you can run a specific goal as (take `check` as an example):

```shell
mvn hawkeye:check
```

You can configure a customized location of the `licenserc.toml` file as:

```xml
<plugin>
<groupId>io.korandoru.hawkeye</groupId>
<artifactId>hawkeye-maven-plugin</artifactId>
<version>${hawkeye.version}</version>
<configuration>
<config>${...}</config>
</configuration>
</plugin>
```

... the default location is `${project.basedir}/licenserc.toml`.
Read the [dedicated README](hawkeye-maven-plugin/README.md) for HawkEye Maven Plugin.

### Executable JAR

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import io.korandoru.hawkeye.core.mapping.Mapping;
import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
Expand Down Expand Up @@ -73,6 +74,12 @@ private Builder() {
// always use #of methods
}

public HawkEyeConfig.Builder addExcludes(List<String> excludes) {
this.excludes = new ArrayList<>(this.excludes);
this.excludes.addAll(excludes);
return this;
}

public HawkEyeConfig build() {
return new HawkEyeConfig(
baseDir,
Expand Down
104 changes: 104 additions & 0 deletions hawkeye-maven-plugin/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# HawkEye Maven Plugin

## Usage

You can integrate HawkEye's functionality with Maven Plugin:

```xml
<plugin>
<groupId>io.korandoru.hawkeye</groupId>
<artifactId>hawkeye-maven-plugin</artifactId>
<version>${hawkeye.version}</version>
</plugin>
```

The plugin provides three goals:

* `check`: Check license headers.
* `format`: Format license headers (auto-fix all files that failed the check).
* `remove`: Remove license headers.

With the plugin properly configured, you can run a specific goal as (take `check` as an example):

```shell
mvn hawkeye:check
```

You can configure a customized location of the `licenserc.toml` file as:

```xml
<plugin>
<groupId>io.korandoru.hawkeye</groupId>
<artifactId>hawkeye-maven-plugin</artifactId>
<version>${hawkeye.version}</version>
<configuration>
<configLocation>${...}</configLocation>
</configuration>
</plugin>
```

... the default location is `${project.basedir}/licenserc.toml`.

## Verify

The `check` goal is bind to the `verify` phase by default. If you'd like to do all verifications with a single `mvn verify`, you can add the HawkEye checks as:

```xml
<plugin>
<groupId>io.korandoru.hawkeye</groupId>
<artifactId>hawkeye-maven-plugin</artifactId>
<version>${hawkeye.version}</version>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
```

## Multimodule

HawkEye is designed to run against a whole project but Maven plugin is configured to each module.

That said, the default location of configuration file (`${project.basedir}/licenserc.toml`) will be resolved to different place due to each module has its own `${project.basedir}`. This is the same to the basedir of the execution.

Below are two recommendations for configuring multimodule project.

### Aggregator

The HawkEye plugin provides an option named `aggregate` with which you can check the headers for all modules of your project.

You can configure the plugin with `aggregate` for your parent `pom.xml`:

```xml
<plugin>
<groupId>io.korandoru.hawkeye</groupId>
<artifactId>hawkeye-maven-plugin</artifactId>
<version>${hawkeye.version}</version>
<configuration>
<aggregate>true</aggregate>
</configuration>
</plugin>
```

... and properly skip all the submodules.

You can also run as aggregator from the commandline:

```shell
mvn hawkeye:check -pl . -Daggregate=true
```

### Each module

You can still configure the plugin executions for each module, but pay attention to the resolved value of `configLocation` and `baseDir`.

> This means `aggregate=false` and the plugin will exclude submodules when running against a parent module.
The default `configLocation` is `${project.basedir}/licenserc.toml` which requires a `licenserc.toml` per module. If you use one config file for all modules, you should change the config value to a fixed location. [directory-maven-plugin](https://github.com/jdcasey/directory-maven-plugin), `${maven.multiModuleProjectDirectory}`, or [MNG-7038](https://issues.apache.org/jira/browse/MNG-7038) can help.

The default `basedir` is overwritten by `${project.basedir}`, which means the one configured in `licenserc.toml` is not used. This should often be the value you want, but you can still change the directory for each module.

Be aware that this basedir is also the one for resolving `includes` and `excludes`. If a file is not properly included or excluded, think of the resolved value of `includes` and `excludes` pattens.
12 changes: 9 additions & 3 deletions hawkeye-maven-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,22 @@
<artifactId>hawkeye-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>${maven-core.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>${maven-plugin-api.version}</version>
<version>${maven-core.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>${maven-plugin-annotation.version}</version>
<version>${maven-plugin-tools.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
Expand All @@ -53,7 +59,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>${maven-plugin-plugin.version}</version>
<version>${maven-plugin-tools.version}</version>
</plugin>
</plugins>
</build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,53 @@

package io.korandoru.hawkeye.maven.plugin;

import io.korandoru.hawkeye.core.config.HawkEyeConfig;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;

abstract class AbstractMojo extends org.apache.maven.plugin.AbstractMojo {
@Parameter(name = "config", alias = "cfg", defaultValue = "${project.basedir}/licenserc.toml")
public File config;
/**
* The base directory, in which to search for project files.
*/
@Parameter(property = "hawkeye.basedir", defaultValue = "${project.basedir}", required = true)
public File basedir;

@Parameter(name = "dryRun", defaultValue = "false")
/**
* Location of the `licenserc.toml` file.
*/
@Parameter(property = "hawkeye.configLocation", defaultValue = "${project.basedir}/licenserc.toml", required = true)
public File configLocation;

/**
* Whether to do the real formatting or removal.
*/
@Parameter(property = "hawkeye.dryRun", defaultValue = "false")
public boolean dryRun;

/**
* You can set this flag to true if you want to check the headers for all
* modules of your project. Only used for multi-modules projects, to check
* for example the header licenses from the parent module for all submodules.
*/
@Parameter(property = "hawkeye.aggregate", defaultValue = "false")
public boolean aggregate = false;

@Parameter(defaultValue = "${project}", readonly = true, required = true)
public MavenProject project;

protected HawkEyeConfig.Builder configBuilder() {
final List<String> submodulesExcludes = new ArrayList<>();
if (project != null && project.getModules() != null && !aggregate) {
for (String module : project.getModules()) {
submodulesExcludes.add(module + "/**");
}
}
return HawkEyeConfig.of(configLocation)
.dryRun(dryRun)
.addExcludes(submodulesExcludes)
.baseDir(basedir.toPath());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
package io.korandoru.hawkeye.maven.plugin;

import io.korandoru.hawkeye.core.LicenseChecker;
import io.korandoru.hawkeye.core.config.HawkEyeConfig;
import io.korandoru.hawkeye.core.report.Report;
import io.korandoru.hawkeye.core.report.ReportConstants;
import java.util.List;
Expand All @@ -32,32 +31,31 @@ public class CheckMojo extends AbstractMojo {
@Override
public void execute() throws MojoFailureException {
final Log log = getLog();
log.info("Checking license headers... with cfg: %s".formatted(config));
final HawkEyeConfig heConfig = HawkEyeConfig.of(config).build();
final LicenseChecker checker = new LicenseChecker(heConfig);
log.info("Checking license headers... with config: %s".formatted(configLocation));

final LicenseChecker checker = new LicenseChecker(configBuilder().build());
final Report report = checker.call();

final List<String> unknownHeaderFiles = report.getResults().entrySet().stream()
.filter(e -> ReportConstants.RESULT_UNKNOWN.equals(e.getValue()))
.map(Map.Entry::getKey)
.toList();

for (String unknownHeaderFile : unknownHeaderFiles) {
log.warn("Processing unknown file: %s".formatted(unknownHeaderFile));
}

final List<String> missingHeaderFiles = report.getResults().entrySet().stream()
.filter(e -> ReportConstants.RESULT_MISSING.equals(e.getValue()))
.map(Map.Entry::getKey)
.toList();

if (!unknownHeaderFiles.isEmpty()) {
log.warn("Processing unknown files: %s".formatted(unknownHeaderFiles));
}

if (missingHeaderFiles.isEmpty()) {
log.info("No missing header file has been found.");
return;
}
for (String missingHeaderFile : missingHeaderFiles) {
log.error("Found missing header file: %s".formatted(missingHeaderFile));
for (String filename : missingHeaderFiles) {
log.error("Found missing header files: %s".formatted(filename));
}
throw new MojoFailureException("Missing header files found");
throw new MojoFailureException("Found missing header files.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
package io.korandoru.hawkeye.maven.plugin;

import io.korandoru.hawkeye.core.LicenseFormatter;
import io.korandoru.hawkeye.core.config.HawkEyeConfig;
import io.korandoru.hawkeye.core.report.Report;
import io.korandoru.hawkeye.core.report.ReportConstants;
import java.util.List;
Expand All @@ -30,35 +29,29 @@ public class FormatMojo extends AbstractMojo {
@Override
public void execute() {
final Log log = getLog();
log.info("Formatting license headers... with cfg: %s, dryRun: %s".formatted(config, dryRun));
log.info("Formatting license headers... with config: %s, dryRun: %s".formatted(configLocation, dryRun));

final HawkEyeConfig heConfig = HawkEyeConfig.of(config).dryRun(dryRun).build();
final LicenseFormatter checker = new LicenseFormatter(heConfig);
final Report report = checker.call();
final LicenseFormatter formatter = new LicenseFormatter(configBuilder().build());
final Report report = formatter.call();

final List<String> unknownHeaderFiles = report.getResults().entrySet().stream()
.filter(e -> ReportConstants.RESULT_UNKNOWN.equals(e.getValue()))
.map(Map.Entry::getKey)
.toList();

for (String unknownHeaderFile : unknownHeaderFiles) {
log.warn("Processing unknown file: %s".formatted(unknownHeaderFile));
}

final List<Map.Entry<String, String>> updatedHeaderFiles = report.getResults().entrySet().stream()
.filter(e -> !ReportConstants.RESULT_UNKNOWN.equals(e.getValue()))
.filter(e -> !ReportConstants.RESULT_NOOP.equals(e.getValue()))
.toList();

if (updatedHeaderFiles.isEmpty()) {
log.info("All files have proper header.");
return;
if (!unknownHeaderFiles.isEmpty()) {
log.warn("Processing unknown files: %s".formatted(unknownHeaderFiles));
}

if (!dryRun) {
for (Map.Entry<String, String> updatedHeaderFile : updatedHeaderFiles) {
log.info("Updated header for file: %s".formatted(updatedHeaderFile.getKey()));
}
if (updatedHeaderFiles.isEmpty()) {
log.info("All files have proper header.");
} else if (!dryRun) {
log.info("Updated header for files: %s".formatted(updatedHeaderFiles));
}
}
}
Loading

0 comments on commit 4605d93

Please sign in to comment.