Skip to content

Latest commit

 

History

History
1729 lines (1368 loc) · 43.7 KB

File metadata and controls

1729 lines (1368 loc) · 43.7 KB

Inugami Project analysis maven plugin

Inugami project analysis maven plugin have for target to generate a release note on your project. Detect hidden dependencies on microservices is not easy. This plugin use Neo4J to resolve them. You can find a generated release note example here : release-note

Last Release:

<dependency>
    <groupId>io.inugami.maven.plugin.analysis</groupId>
    <artifactId>inugami-project-analysis-maven-plugin</artifactId>
    <version>1.5.2</version>
    <executions>
        <execution>
            <id>check</id>
            <phase>analyze</phase>
            <goals>
                <goal>check</goal>
            </goals>
        </execution>
        <execution>
            <id>info</id>
            <phase>info</phase>
            <goals>
                <goal>retrieveInformation</goal>
            </goals>
        </execution>
    </executions>
</dependency>

Quick start :

This maven plugin use Neo4J database to store information and resolve them. If you don’t have Neo4J you can test on your local environment or run a Neo4J with docker.

docker-compose.yml
version: "3"
services:
  neo4j:
    image: neo4j:4.1.1
    ports:
      - "7474:7474"
      - "7473:7473"
      - "7687:7687"
    expose:
      - 7474
      - 7473
      - 7687
    environment:
      - NEO4J_AUTH=neo4j/password
      - EXTENSION_SCRIPT=/var/lib/neo4j/import/neo4j-bootstrap.sh
      - NEO4J_dbms_unmanaged__extension__classes=semantics.extension=/rdf
      - NEO4J_dbms_security_procedures_whitelist=apoc.coll.*,apoc.load.*,semantics.*
      - NEO4J_dbms_security_procedures_unrestricted=apoc.*,semantics.*
      - NEO4J_apoc_export_file_enabled=true
      - NEO4J_apoc_import_file_enabled=true
      - NEO4J_apoc_import_file_use__neo4j__config=true
    volumes:
      - ./import:/var/lib/neo4j/import
      - ./conf:/var/lib/neo4j/conf
      - ./logs:/var/lib/neo4j/logs
      - ./plugins:/var/lib/neo4j/plugins
    networks:
      - neo4j-network
networks:
  neo4j-network:
    driver: bridge

In your project pom.xml (or settings) we need to add some properties :

<properties>
    <inugami.maven.plugin.analysis.project.base.name>your.base.package</inugami.maven.plugin.analysis.project.base.name>
    <inugami.maven.plugin.analysis.writer.neo4j.url>bolt://localhost:7687</inugami.maven.plugin.analysis.writer.neo4j.url>
    <inugami.maven.plugin.analysis.writer.neo4j.user>neo4j</inugami.maven.plugin.analysis.writer.neo4j.user>
    <inugami.maven.plugin.analysis.writer.neo4j.password>password</inugami.maven.plugin.analysis.writer.neo4j.password>
</properties>

You can also define Neo4J configuration into your maven settings :

<servers>
    <servers>
        <id>neo4j</id>
        <username>neo4j</username>
        <password>{Yt5nGluOZ0sHzEiL7Le2IHFjtuTonkfx4yVEG3CYzZ8=}</password>
        <configuration>
            <url>bolt://localhost:7687</url>
        </configuration>
    </servers>
</servers>

In this case, your maven settings will override your pom.xml properties.

In your project build definition :

<plugin>
    <groupId>io.inugami.maven.plugin.analysis</groupId>
    <artifactId>inugami-project-analysis-maven-plugin</artifactId>
    <version>1.4.2</version>
    <extensions>true</extensions>
    <executions>
        <execution>
            <id>check</id>
            <phase>analyze</phase>
            <goals>
                <goal>check</goal>
            </goals>
        </execution>
        <execution>
            <id>info</id>
            <phase>info</phase>
            <goals>
                <goal>retrieveInformation</goal>
            </goals>
        </execution>
    </executions>
</plugin>

First you need to analyse your project to send data into NEO4J:

mvn analyze
analyze 01
analyze 02

After this analyse you can see in Neo4j your project information or just execute maven phase info

mvn info
info

This phase requires to specify an action to display information

Neo4j data structure :

nodes
CALL db.schema.visualization

Retrieve information :

After analyze, all information is present into Neo4J. We can now query Neo4J to retrieve information. Attention : in some commons use cases it’s easier to invoke the plugin to display result.

All additional properties can be defined in properties section of pom.xml or via command line invocation (with -D prefix).

restServices

One of common problems in microservice architecture is to known interconnections between services. What’s happen if I change my service ? Who consume a service and which version is currently in use ? To address this issue, the inugami analysis plugin will analyze all Springboot Rest endpoint and feign clients to detect interdependencies between projects.

REST endpoints can be defined in current project or as a transitive dependency. The plugin retrieve transitive dependencies over 10 sub levels.

mvn info -Daction=restServices

The color code is the same as Swagger, all GET endpoints are blue, green for POST, and red for DELETE.

restServices 01

In case where some projects consume an endpoint these will be described in the result :

restServices 02

queryDisplay

Query display allows the generation of a Neo4J cypher query from the current projet.

mvn info -Daction=queryDisplay
queryDisplay 01

Different queries are available, so it’s required to specify the one in use.

mvn info -Daction=queryDisplay -Dquery=search_services_rest
mvn info -Daction=queryDisplay -Dquery=search_error_codes
queryDisplay 02

properties

Properties action displays project properties. This action retrieves also dependencies properties. At this moment these properties are extracted from Spring properties (@Value, bean properties, conditionals beans, properties usages on JMS or RabbitMQ listeners)

If a property has no default value, it will be displayed in red. In yellow, we have properties who enable some beans. If a property have bean validator constraints, these will be displayed too.

mvn info -Daction=properties
properties

queueInfo

Queue information have the same approach as restServices but for JMS and RabbitMQ. It’s able to detect producers and listeners, tracing event payload and all information on queue binding.

Like restServices, the queueInfo retrieves information over 10 levels of transitive dependencies.

mvn info -Daction=queueInfo
queue

To track all JMS senders and RabbitMQ sender it’s required to add annotations in your source code.

For JMS :

@JmsSender(destination = "${my.activeMq.onUserCreated.queue}", id = "create.user.queue")
public void sendCreateUser(final String someParameter, @JmsEvent final User user) {
    // process sending event
}

For RabbitMQ :

@RabbitMqSender(echangeName = "${events.exchangeName}",
                queue = "${events.method.user.queueName}",
                routingKey = "${events.user.method.created.routingKey}"
)
public void fireEvent(@RabbitMqEvent  final UserCreatedEvent event) {
    // process sending event
}

If you use multi-handler on RabbitLister you need to add an annotation specifying which routing key is in use :

@RabbitMqHandlerInfo(routingKey = "${events.user.authenticated.routingKey}",
typeId = "${events.user.authenticated.typeId}")
@RabbitHandler
public void onAuthenticated(final UserAuthenticatedEvent event) {
    // process listen
}

All specific annotations are contained into an inugami artifact :

<dependency>
    <groupId>io.inugami.maven.plugin.analysis</groupId>
    <artifactId>inugami-project-analysis-maven-plugin-annotations</artifactId>
    <version>${io.inugami.maven.plugin.analysis.version}</version>
</dependency>

This artifact contains only annotations, nothing else.

errorDisplay

Error management is essential to make better applications. Interteam communication is a must. Writing wiki is not our way, it’s time-consuming and quickly outdate. Inugami generates errors directly from code.

mvn info -Daction=errorDisplay

Per default Inugami plugin use the Inugami error interface to detect error code :

package io.inugami.api.exceptions;
import java.util.function.BiConsumer;

public interface ErrorCode {
    public ErrorCode getCurrentErrorCode();

    default int getStatusCode() {
        return getCurrentErrorCode() == null ? 500 : getCurrentErrorCode().getStatusCode();
    }

    default String getErrorCode() {
        return getCurrentErrorCode() == null ? "undefine" : getCurrentErrorCode().getErrorCode();
    }

    default String getMessage() {
        return getCurrentErrorCode() == null ? "error" : getCurrentErrorCode().getMessage();
    }

    default String getMessageDetail() {
        return getCurrentErrorCode() == null ? null : getCurrentErrorCode().getMessageDetail();
    }

    default String getErrorType() {
        return getCurrentErrorCode() == null ? "technical" : getCurrentErrorCode().getErrorType();
    }

    default String getPayload() {
        return getCurrentErrorCode() == null ? null : getCurrentErrorCode().getPayload();
    }

    default BiConsumer<String, Exception> getErrorHandler() {
        return getCurrentErrorCode() == null ? null : getCurrentErrorCode().getErrorHandler();
    }
}

This interface is present in inugami_api artifact :

<dependencies>
    <groupId>io.inugami</groupId>
    <artifactId>inugami_api</artifactId>
    <version>2.0.0</version>
</dependencies>

This interface can be used over enum types or on static class fields.

public enum IssuesError implements ErrorCode {

    ISSUES_1(newBuilder()
            .setStatusCode(400)
            .setMessage("issues request invalid")
            .setErrorType("input")),

    ISSUES_1_1(newBuilder()
            .setStatusCode(400)
            .setMessage("issue uid is mandatory")
            .setFonctionnalError());

    private final ErrorCode errorCode;

    private IssuesError(final ErrorCodeBuilder errorBuilder) {
        errorCode = errorBuilder.setErrorCode(this.name()).build();
    }

    @Override
    public ErrorCode getCurrentErrorCode() {
        return errorCode;
    }
}

You can define your error code interface, to do so just add a property in your pom.xml

<properties>
   <inugami.maven.plugin.analysis.analyzer.errorCode.interface>io.inugami.demo.spring.boot.training.api.exceptions.ErrorCode</inugami.maven.plugin.analysis.analyzer.errorCode.interface>
</properties>

In this case the plugin will retrieve all values defined in your interface.

errorCode
Table 1. Additional configuration
Property type default value description

-Dinugami.maven.plugin.analysis.analyzer.errorCode.interface

String

io.inugami.api.exceptions.ErrorCode

The error code interface to use

-Dexport

boolean

false

allow exporting results as CSV files

specificsQuery

The plugin is able to retrieve information from Neo4J and display them. If you need to execute a specific cypher query is possible to use this plugin to do that.

mvn info -Daction=specificsQuery -Dexport=true
specificQuery
Table 2. Additional configuration
Property type default value description

-Dinugami.query.path

String

null

Path to cypher query, if isn’t define the plugin will ask for this one in prompt.

-Dinugami.skip.properties

String (Regex Pattern)

null

for not display some nodes properties

-Dexport

boolean

false

Allow to export result as CSV file

importData

To import some data into Neo4J it’s possible to call the importData action. This action is able to execute a cypher query or to import a JSON model.

For both it’s required to specify the property inugami.query.path to define the import script path

mvn info -Daction=importData

For cypher query is just a basic .cql script. This one must juste have for extension .cql. Neo4j has great documentation on cypher language : https://neo4j.com/docs/cypher-manual/current/

For the JSON model, is the internal plugin model as JSON :

{
  "nodes": [
    {
      "type": "String",
      "uid": "String",
      "name": "String",
      "properties": {
        "<String>": "Serializable",
        "<String>": 42
      }
    }
  ],
  "nodesToDeletes": ["String"],
  "createScripts" : ["String(Cypher)"],
  "relationships": [
    {
      "from": "String",
      "to": "String",
      "type": "String",
      "properties": {
        "<String>": "Serializable"
      }
    }
  ],
  "relationshipsToDeletes": [
    {
      "from": "String",
      "to": "String",
      "type": "String",
      "properties": {
        "<String>": "Serializable"
      }
    }
  ],
  "deleteScripts": ["String(Cypher)"]
}
Table 3. Additional configuration
Property type default value description

-Dinugami.query.path

String

null

Path to cypher or JSON import script query, if it’s not defined the plugin will prompt for a value.

Deployment management

Microservices complicate the deployment process. It’s very important to know which microservice is on which environment.

publish

You need to pass some additional information to Neo4J to detect which artifact is on wich environment. The easiest way is to use the "publish action".

mvn info -Daction=publish
publish 01
publish 02

On DEPLOY we can see that the plugin has added the deployment date (on ISO date and timestamp, both are on system time zone and on UTC) .Additional configuration

Property type default value description

-DuseMavenProject

Boolean

null

Allow using current project GAV, if null the plugin will prompt for a value.

-Denv

String

null

Destination environment, if null the plugin will prompt for a value.

-DenvLevel

int

0

To sort environments it’s necessary to add weight, if null the plugin will prompt for a value.

-DenvType

String

null

The environment type (like DEV, INT, PREP, PROD..), if null the plugin will prompt for a value.

-DautoUnpublish

boolean

false

Allow remove relationship between an artifact and an environment node

-DjustThisVersion

boolean

false

If you want to clean all version relationship between an artifact and an environment node

-DpreviousEnv

boolean

false

For cleaning previous staging environment, this value will be prompted if not defined on an enabled autoPublish.

unpublish

It’s very closer than publish but in this action we will remove deployments relationship on a specific version and an environment.

mvn info -Daction=unpublish
Table 4. Additional configuration
Property type default value description

-DuseMavenProject

boolean

false

Allow using current project GAV and not ask for this information

-Denv

String

null

Destination environment, if null the plugin will prompt for a value.

-DenvLevel

int

0

To sort environments it’s necessary to add weight, if null the plugin will prompt for a value.

-DenvType

String

null

The environment type (like DEV, INT, PREP, PROD..), if null the plugin will prompt for a value.

-DjustThisVersion

boolean

false

If you want to clean all version relationship between an artifact and an environment node

versionEnv

The action versionEnv is able to verify if your project have all dependencies available on all environments.

mvn info -Daction=versionEnv

In this example, the project project-consumer is using a REST endpoint produced by spring-boot-training-lifecycle. PREP_2 is not deployed. The service project project-consumer can’t work correctly on this environment.

Also, this project use a REST endpoint [GET]/comments/comments but no producer have been detected

versionEnv
Table 5. Additional configuration
Property type default value description

-Dexport

boolean

false

Allow exporting result as CSV file

-DuseMavenProject

boolean

false

Allow using current project GAV and not ask for this information

envInfo

This action is a quick representation of an environment deployment status. It’s able to retrieve which artifacts are present on which environments.

mvn info -Daction=envInfo
envInfo
Table 6. Additional configuration
Property type default value description

-Dexport

boolean

false

Allow to export result as CSV file

encodePassword

This action is just a small tool to encode a password or sensible value in AES.

mvn info -Daction=encodePassword
password
Table 7. Additional configuration
Property type default value description

-Dinugami.maven.plugin.analysis.secret

String (16 chars)

null

AES passphrase

Analyzers :

Feign clients

Feign clients analyzer scan all feign client interface to resolve project consuming REST endpoints;

Table 8. Properties
Property type default value description

inugami.maven.plugin.analysis.analyzer.feign.enable

boolean

true

Allow to disable feign client analyzer

inugami.maven.plugin.analysis.analyzer.restControllers.strict

boolean

true

if this mode isn’t enable, only mandatory fields in models have been used for identify REST endpoint

SpringBoot RestControllers

To resolve project REST endpoint exposition, this analyzer scan all SpringBoot RestController.

Table 9. Properties
Property type default value description

inugami.maven.plugin.analysis.analyzer.restControllers.enable

boolean

true

Allow disabling feign client analyzer

inugami.maven.plugin.analysis.analyzer.restControllers.strict

boolean

true

if this mode isn’t enable, only mandatory fields in models have been used for identify REST endpoint

Spring properties

Bad properties configuration is the source of most problems on a spring project. This analyzer scan all properties injected by @Value annotation or Bean configuration definition.

Table 10. Properties
Property type default value description

inugami.maven.plugin.analysis.analyzer.properties.enable

boolean

true

Allow disabling feign client analyzer

ActiveMQ

To resolve activeMQ consumers and listeners, this analyzer is scanning all Spring @JmsListener annotation.

Table 11. Properties
Property type default value description

inugami.maven.plugin.analysis.analyzer.jms.enable

boolean

true

Allow disabling feign client analyzer

Error code

To resolve activeMQ consumers and listeners, this analyzer is scanning all Spring @JmsListener annotation.

Table 12. Properties
Property type default value description

inugami.maven.plugin.analysis.analyzer.errorCode.enable

boolean

true

Allow disabling error code analyzer

inugami.maven.plugin.analysis.analyzer.errorCode.interface

String

io.inugami.api.exceptions.ErrorCode

Allow to specify the error code interface, configured by default with inugami error code interface

inugami.maven.plugin.analysis.analyzer.errorCode.fieldName

String

errorCode

Allow to override the default error code "field". The method defined in error code interface resolves this field. Accessor prefix is ignored

Flyway

this analyze allow to reference all flyway script. In release note you will see all them as differential.

Table 13. Properties
Property type default value description

inugami.maven.plugin.analysis.analyzer.flyway.enabled

boolean

false

Allow to enable or disable flyway analyzer

inugami.maven.plugin.analysis.analyzer.flyway.paths

String (path)

null

To define all root folders who contains flyway scripts. Semicolon is use for split each path

inugami.maven.plugin.analysis.analyzer.flyway.defaultDb

String

{{folder name}}

Allow force default Database name

inugami.maven.plugin.analysis.analyzer.flyway.scriptTypes

String

sql

Allow to define scripts type

Git SCM

Git scm analyzer allow to extract all commit since last project tag. If your project haven’t tag yet, this analyzer retrieve all commit since repository creation.

After analyze, new nodes types appear :

  • Scm, who contains all commit details

  • MergeRequest, to retrace all merges requests on version. If you use feature branch, the specified issue will be retrieve too (for example with branch name feature/123_my_feature, issue 123 will be extracted).

  • Issue

  • Issue label

git scm
github issues
github merge request

To display the release note you can invoke task mvn info -Daction=releaseNote -PpreviousVersion={previousVersion}

release note light

You can see on this example generated release-note as asciidoc : release-note

Issue Management

the Git scm analyzer will extract issues and merge request from commit message. On each it will call your issue management to retrieve more information on tickets.

To enable this behavior it’s require to add issueManagement with link to SCM API in your pom.xml :

For GitLab :

<issueManagement>
    <system>gitlab</system>
    <url>https://gitlab.com/api/v4/projects/123457890</url>
</issueManagement>

For GitHub :

<issueManagement>
    <system>github</system>
    <url>https://api.github.com/repos/inugamiio/inugami-project-analysis-maven-plugin-parent</url>
</issueManagement>

For Jira :

<issueManagement>
    <system>jira</system>
    <url>https://jira.url</url>
</issueManagement>

All issue management need credentials to grant access on REST API. To configure these you will add server tag in your maven settings.xml :

<servers>
    <server>
      <id>gitlab</id>
      <privateKey>{MIAuTFbZUxsHC0aBub3Frxr1d/kik/yafcVYW6KDzqU=}</privateKey>
    </server>

    <server>
      <id>github</id>
      <privateKey>{s5Ydy14rYAwHekKyJxAYAFnFO6igA9/lykiQCT+ct8U=}</privateKey>
    </server>

    <server>
      <id>jira</id>
      <username>{1Jur5y14rYAwHekKyJxAYAFnFO6igA9/lyki+ct8U=}</username>
      <password>{s5Ydy14rYAwHekKyJxAYAFnFO6igA9/lykiQCT+ct8U=}</password>
    </server>
</servers>

It’s possible to encrypt your password with maven standard encryption mechanism (https://maven.apache.org/guides/mini/guide-encryption.html)

Table 14. Properties
Property type default value description

inugami.maven.plugin.analysis.git

boolean

false

Allow to enable git scanning and retrieve information from issues manager

inugami.maven.plugin.analysis.issue.tracker.pr.url

String

${issueManagement.url}

If you use another repository to manage your project backlog, issueManagement.url must be configure on it. But to trace merge request you should define inugami.maven.plugin.analysis.issue.tracker.pr.url with the issue management of your source code repository

Jira custom fields

Jira allow to define custom fields on your issues. To extract these you can create a SPI implementation of interface i.inugami.maven.plugin.analysis.api.scan.issue.tracker.JiraCustomFieldsAppender

public interface JiraCustomFieldsAppender {
    void append(String issueId,
                JsonNode json,
                LinkedHashMap<String, Serializable> issueProperties,
                ScanNeo4jResult neo4jResult);
}
Table 15. Parameters
Property type description

issueId

String

Current issue uid

json

com.fasterxml.jackson.databind.JsonNode

Tree representation of current Json response. For more information on Jira Rest API see https://docs.atlassian.com/software/jira/docs/api/REST/8.13.2/#api/2/issue-getIssue

issueProperties

LinkedHashMap<String, Serializable>

Current properties

neo4jResult

io.inugami.maven.plugin.analysis.api.models.ScanNeo4jResult

Allow to create another nodes or relationships

Your implementation can be in classpath or linked on plugin dependencies. All implementation must be declare into src/resources/META-INF/services/io.inugami.maven.plugin.analysis.api.scan.issue.tracker.JiraCustomFieldsAppender

Example :

src/resources/META-INF/services/io.inugami.maven.plugin.analysis.api.scan.issue.tracker.JiraCustomFieldsAppender :

io.app.JiraCustomFieldExtractor
package io.app;

public class JiraCustomFieldExtractor implements JiraCustomFieldsAppender {
    public void append(String issueId,
                JsonNode json,
                LinkedHashMap<String, Serializable> issueProperties,
                ScanNeo4jResult neo4jResult){
        // implementation
    }
}

ReleaseNote

Plugin main target is to generate a release note from current project. By default this release note will be generate as Json file.

An ASCIIDOC implementation is present to generate a documentation more human friendly.

To display the release note you can invoke task mvn info -Daction=releaseNote -PpreviousVersion={previousVersion}

Table 16. Properties
Property type default value description

inugami.maven.plugin.analysis.display.release.note.full

boolean

false

Allow to append more information on your release note

previousVersion

String

null

To be able to compute the difference between two version; it’s require to specify previous version.

interactive

boolean

true

If you doesn’t need JSON release note; you can disable this feature with this parameter.

inugami.maven.plugin.analysis.display.release.note.asciidoc

boolean

false

Allow to generate release note as ASCIIDOC

inugami.maven.plugin.analysis.display.release.note.asciidoc.baseDir

String (path)

{builddir}/src/doc/releases

Allow to specify target folder

inugami.maven.plugin.analysis.display.release.note.asciidoc.splitFile

boolean

false

Allow to generate the release note with one document or multi document parts

ReleaseNote UI

Since version 1.6.0 a spring boot module allow to display current project release notes. To include this ui you should add this dependency :

<dependency>
    <groupId>io.inugami.maven.plugin.analysis.front</groupId>
    <artifactId>inugami-project-analysis-front-springboot</artifactId>
    <version>1.6.2</version>
</dependency>

By default the ui is accessible on URL : http://localhost:8080/release-note-app/

Table 17. Properties
Property type default value Require description

inugami.release.note.artifactName

String

null

true

Release note list json file name. This property is mandatory

After the release note building, two file will be created in your project : - src/main/resources/META-INF/releases/{{inugami.release.note.artifactName}}.releases.json : this files contains the releases note list - src/main/resources/META-INF/releases/{{inugami.release.note.artifactName}}.{{version}}.json : the release note as json

ui global
ui detail
Update & ban dependencies

The inugami front ui is able to display information about dependencies baned or deprecated. The scan process doesn’t check this information at this moment.

But you can create new DependenciesCheckService implementation:

public interface DependenciesCheckService {
    DependenciesCheck getDependenciesCheckData();
}

To implement this one you need to create a newer service and define it into a configuration bean :

public class MyDependenciesCheckService {
    public DependenciesCheck getDependenciesCheckData(){
        return DependenciesCheck.builder()
                        .deprecated(resolveDeprecatedArtifacts())
                        .ban(resolveBanedArtifacts())
                        .ban(resolveSecurityIssues())
        .build();
    }
}
@Configuration
public class MyProjectConfiguration {

    @Primary
    @Bean
    public DependenciesCheck buildDependenciesCheck(){
        return new MyDependenciesCheckService();
    }
}

This interface requires to return a DependenciesCheck object. This object is a basic DTO :

@ToString
@Builder(toBuilder = true)
@Setter
@Getter
public class DependenciesCheck {
    private List<DependencyRule> deprecated;
    private List<DependencyRule> ban;
    private List<DependencyRule> securityIssue;
}

Each list contains a DependencyRule object like :

@ToString
@Builder(toBuilder = true)
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@Setter
@Getter
public class DependencyRule {
    @EqualsAndHashCode.Include
    private String       groupId;
    @EqualsAndHashCode.Include
    private String       artifactId;
    @EqualsAndHashCode.Include
    private VersionRules rules;
    private String       comment;
    private String       link;
    private Level        level;
}

Others goals :

mkdirs

This goal allow to create basic folders

<plugin>
    <groupId>io.inugami.maven.plugin.analysis</groupId>
    <artifactId>inugami-project-analysis-maven-plugin</artifactId>
    <version>1.6.3</version>

    <executions>
        <execution>
            <id>mkdirs</id>
            <phase>validate</phase>
            <goals>
                <goal>mkdirs</goal>
            </goals>
            <configuration>
                <paths>
                    <path>${basedir}/target/test</path>
                    <path>${basedir}/target/test2</path>
                </paths>
            </configuration>
        </execution>
    </executions>
</plugin>

delete

This goal allow to delete folder or files

<plugin>
    <groupId>io.inugami.maven.plugin.analysis</groupId>
    <artifactId>inugami-project-analysis-maven-plugin</artifactId>
    <version>1.6.3</version>

    <executions>
        <execution>
            <id>mkdirs</id>
            <phase>validate</phase>
            <goals>
                <goal>delete</goal>
            </goals>
            <configuration>
                <paths>
                    <path>${basedir}/target/test.*</path>
                    <path>${basedir}/target/generate/.*log</path>
                </paths>
            </configuration>
        </execution>
    </executions>
</plugin>

loadProperties

This goal allow to load maven properties. All loaded properties will be accessible in nextmaven phase.

Global properties

The goal loadProperties can have global properties. All of them will added in maven properties context.

<plugin>
    <groupId>io.inugami.maven.plugin.analysis</groupId>
    <artifactId>inugami-project-analysis-maven-plugin</artifactId>
    <version>1.6.3</version>

    <executions>
        <execution>
            <id>loadProperties</id>
            <phase>validate</phase>
            <goals>
                <goal>loadProperties</goal>
            </goals>
            <configuration>
                <properties>
                    <simple.properties>joe</simple.properties>
                </properties>
            </configuration>
        </execution>
    </executions>
</plugin>

Local file properties

In most of time, we need to add properties from local file. This files can be properties file or json file (another file will be supported in next release). To do that you can specify resources. Each one need to specify the path (this path can have maven properties to templatize this one). Also it’s require to specify the file type (properties or json)

application.name=demo-app
application.title=My application
<plugin>
    <groupId>io.inugami.maven.plugin.analysis</groupId>
    <artifactId>inugami-project-analysis-maven-plugin</artifactId>
    <version>1.6.3</version>

    <executions>
        <execution>
            <id>loadProperties</id>
            <phase>validate</phase>
            <goals>
                <goal>loadProperties</goal>
            </goals>
            <configuration>
                <properties>
                    <simple.properties>joe</simple.properties>
                </properties>
                <resources>
                    <resource>
                        <type>properties</type>
                        <propertiesPath>${basedir}/src/test/resources/simple.properties</propertiesPath>
                        <properties>
                            <specific.file.properties>specific value</specific.file.properties>
                        </properties>
                    </resource>
                </resources>
            </configuration>
        </execution>
    </executions>
</plugin>

After properties loaded, you can use properties in maven context.

In case of JSON file, all properties will be render as flat value. For example :

{
  "version": "0.0.1-SNAPSHOT",
  "app": {
    "name": "my application"
  },
  "rules": [
    {
      "type": "json",
      "enabled": "true"
    },
    {
      "type": "yaml",
      "enabled": "false"
    }
  ],
  "authors": [
    "john",
    "smith"
  ]
}

Will be rendered in maven context as :

{
  "version" : "0.0.1-SNAPSHOT",
  "app.name" : "my application",
  "rules.0.type" : "json",
  "rules.0.enabled" : "true",
  "rules.1.type" : "yaml",
  "rules.1.enabled" : "false",
  "authors.0" : "john",
  "authors.1" : "smith"
}

Properties convertors

All properties convertors are SPI implementation. You can create easly one and enable its by including your jar dependency in inugami plugin. Inugami use a strategy partner to resolve right implementation. All of them need to implement the PropertiesConvertorSPI interface.

public interface PropertiesConvertorSpi {
    boolean accept(final String type);

    Map<String, String> convert(final String content);
}

As all SPI implementation you need to declare its in the specific file /META-INF/services/io.inugami.maven.plugin.analysis.api.convertors.PropertiesConvertorSpi

io.inugami.maven.plugin.analysis.plugin.services.build.convertors.MyConvertor

After that you can create your implementation :

@SpiPriority(10)
public class MyConvertor implements PropertiesConvertorSpi {

    public static final String PROPERTIES = "properties";


    @Override
    public boolean accept(final String type) {
        return PROPERTIES.equalsIgnoreCase(type);
    }

    @Override
    public Map<String, String> convert(final String content) {
        // implementation
    }
}

Inugami order all implementation by higher SpiPriority. You can use this annotation if you need to override existing implementation.

External URL properties

If you need to retrieve properties from external source, like springboot cloud config, you can specify corresponding url to load this resource.

<plugin>
    <groupId>io.inugami.maven.plugin.analysis</groupId>
    <artifactId>inugami-project-analysis-maven-plugin</artifactId>
    <version>1.6.3</version>

    <executions>
        <execution>
            <id>loadProperties</id>
            <phase>validate</phase>
            <goals>
                <goal>loadProperties</goal>
            </goals>
            <configuration>
                <resources>
                    <resource>
                        <propertiesUrl>http://localhost:8888/demo.json</propertiesUrl>
                        <propertiesUrlAuthorization>Basic YWRtaW46cGFzc3dvcmQ=</propertiesUrlAuthorization>
                    </resource>
                </resources>
            </configuration>
        </execution>
    </executions>
</plugin>

In this example, the endpoint will give us a response like :

{
    "external": {
        "applicationName": "externalJson"
    }
}

It will be accessible in maven context by flatten value :

{
  "external.applicationName" : "externalJson"
}

writeFile

WriteFile goal allw to write file by using mustache template. By default, maven properties will be transform to mustache values.

For example :

<plugin>
    <groupId>io.inugami.maven.plugin.analysis</groupId>
    <artifactId>inugami-project-analysis-maven-plugin</artifactId>
    <version>1.6.3</version>

    <executions>
        <execution>
            <id>loadProperties</id>
            <phase>generate-resources</phase>
            <goals>
                <goal>writeFile</goal>
            </goals>
            <configuration>
                <mavenFiltering>true</mavenFiltering>
                <fileResources>
                    <fileResource>
                        <target>${basedir}/target/file.from.innerTemplate.html</target>
                        <template><![CDATA[
<h1>${project.artifactId}</h1>
<h2>{{subtitle}}</h2>
]]>
                        </template>
                        <properties>
                            <subtitle>Simple inner template rendering</subtitle>
                        </properties>
                    </fileResource>
                </fileResources>
            </configuration>
        </execution>
    </executions>
</plugin>

Will write in ${basedir}/target/file.from.innerTemplate.html this content :

<h1>demo</h1>
<h2>Simple inner template rendering</h2>

You can also create external template file :

<plugin>
    <groupId>io.inugami.maven.plugin.analysis</groupId>
    <artifactId>inugami-project-analysis-maven-plugin</artifactId>
    <version>1.6.3</version>

    <executions>
        <execution>
            <id>loadProperties</id>
            <phase>generate-resources</phase>
            <goals>
                <goal>writeFile</goal>
            </goals>
            <configuration>
                <mavenFiltering>true</mavenFiltering>
                <fileResources>
                    <fileResource>
                        <target>${basedir}/target/file.from.externalTemplate.html</target>
                        <templatePath>${basedir}/src/test/resources/simple.template.html</templatePath>
                        <properties>
                            <subtitle>Simple external template rendering</subtitle>
                            <description>With external template, you can create more complex file without
                                pollute your maven pom.xml
                            </description>
                        </properties>
                    </fileResource>
                </fileResources>
            </configuration>
        </execution>
    </executions>
</plugin>

with template like :

<h1>demo</h1>
<h2>Simple external template rendering</h2>

<p>
With external template, you can create more complex file without
                                pollute your maven pom.xml
</p>

Will generate this file :

<h1>${project.artifactId}</h1>
<h2>{{subtitle}}</h2>

<p>
    {{description}}
</p>

copy

This goal allow to copy file. It’s also allow to filtering resource. This goal will inject properties only on text file, binary file will only be copy to target file.

copy simple file

In this example we have a simple file in ${basedir}/src/test/resources/simple.template.html

<h1>${project.artifactId}</h1>
<h2>{{subtitle}}</h2>

<p>
    {{description}}
</p>

This file will be copy to ${basedir}/src/test/resources/simple.template.html and all maven context properties will be injected :

<plugin>
    <groupId>io.inugami.maven.plugin.analysis</groupId>
    <artifactId>inugami-project-analysis-maven-plugin</artifactId>
    <version>1.6.3</version>

    <executions>
        <execution>
            <id>loadProperties</id>
            <phase>generate-resources</phase>
            <goals>
                <goal>copy</goal>
            </goals>
            <configuration>
                <mavenFiltering>true</mavenFiltering>
                <resources>
                    <resource>
                        <target>${basedir}/target/generated/file.from.externalTemplate.html</target>
                        <path>${basedir}/src/test/resources/simple.template.html</path>
                        <properties>
                            <subtitle>Simple copy</subtitle>
                            <description>Lorem ipsum</description>
                        </properties>
                    </resource>
                </resources>
            </configuration>
        </execution>
    </executions>
</plugin>

The file result will be :

<h1>demo</h1>
<h2>Simple copy</h2>

<p>
    Lorem ipsum
</p>

copy folder

The copy goal can also copy folder. To do that you need only to specify folder path and target as directories:

<plugin>
    <groupId>io.inugami.maven.plugin.analysis</groupId>
    <artifactId>inugami-project-analysis-maven-plugin</artifactId>
    <version>1.6.3</version>

    <executions>
        <execution>
            <id>loadProperties</id>
            <phase>generate-resources</phase>
            <goals>
                <goal>copy</goal>
            </goals>
            <configuration>
                <mavenFiltering>true</mavenFiltering>
                <resources>
                    <resource>
                        <target>${basedir}/target/generated/template</target>
                        <path>${basedir}/src/test/resources/template</path>
                        <properties>
                            <subtitle>Simple copy</subtitle>
                            <description>Lorem ipsum</description>
                        </properties>
                    </resource>
                </resources>
            </configuration>
        </execution>
    </executions>
</plugin>

maven dependencies

The copy goal can copy maven dependencies. In this case you need to specify the artifact GAV to copy in target destination :

<plugin>
    <groupId>io.inugami.maven.plugin.analysis</groupId>
    <artifactId>inugami-project-analysis-maven-plugin</artifactId>
    <version>1.6.3</version>

    <executions>
        <execution>
            <id>loadProperties</id>
            <phase>generate-resources</phase>
            <goals>
                <goal>copy</goal>
            </goals>
            <configuration>
                <mavenFiltering>true</mavenFiltering>
                <resources>
                    <resource>
                        <target>${basedir}/target/maven/io.inugami.maven.plugin.analysis.front.jar</target>
                        <gav>io.inugami.maven.plugin.analysis.front:inugami-project-analysis-front-plugins:1.6.2-SNAPSHOT</gav>
                    </resource>
                </resources>
            </configuration>
        </execution>
    </executions>
</plugin>

unpack

Unpack goal can unzip resources into folder. When resources are write on filesystem, if it’s text resources, the filtering is apply. This behavior can be disabled by configuration.

<plugin>
    <groupId>io.inugami.maven.plugin.analysis</groupId>
    <artifactId>inugami-project-analysis-maven-plugin</artifactId>
    <version>1.6.3</version>

    <executions>
        <execution>
            <id>loadProperties</id>
            <phase>generate-resources</phase>
            <goals>
                <goal>unpack</goal>
            </goals>
            <configuration>
                <filtering>true</filtering>
                <mavenFiltering>true</mavenFiltering>
                <resources>
                    <resource>
                        <target>${basedir}/target/unpack</target>
                        <gav>
                            io.inugami.maven.plugin.analysis.front:inugami-project-analysis-front-plugins:1.6.2-SNAPSHOT
                        </gav>
                    </resource>
                </resources>
            </configuration>
        </execution>
    </executions>
</plugin>