我们如何强制在构建结束时仅将一次maven MOJO执行一次?

时间:2020-03-06 14:43:02  来源:igfitidea点击:

我有一个MOJO,我想执行一次,并且只在反应堆中最后一个项目的测试阶段运行之后执行一次。

使用:

if (!getProject().isExecutionRoot()) {
        return ;
}

在execute()方法的开始意味着我的mojo被执行了一次,但是在构建的开始就比其他所有子模块先执行了。

解决方案

通常,这是配置问题。我们可能必须仅为mojo设置一个项目,并使它依赖于所有其他项目。或者,我们可以通过使子项目之一依赖于所有其他子项目来强制其最后一个。

我认为,如果使用@aggregator标记并将mojo绑定到以下生命周期阶段之一,则可能会满足需要:

  • 准备包装
  • 包裹
  • 整合前测试
  • 整合测试
  • 整合后测试
  • 核实
  • 安装
  • 部署

我为此找到的最佳解决方案是:

/**
 * The projects in the reactor.
 *
 * @parameter expression="${reactorProjects}"
 * @readonly
 */
private List reactorProjects;

public void execute() throws MojoExecutionException {

    // only execute this mojo once, on the very last project in the reactor
    final int size = reactorProjects.size();
    MavenProject lastProject = (MavenProject) reactorProjects.get(size - 1);
    if (lastProject != getProject()) {
        return;
    }
   // do work
   ...
}

这似乎适用于我测试过的小型构建层次结构。

有一个Sonatype博客条目,描述了如何执行此操作。最后一个要运行的项目将是根项目,因为它将包含对其余项目的模块引用。因此,我们需要在mojo中进行测试以检查当前项目的目录是否与启动Maven的目录相同:

boolean result = mavenSession.getExecutionRootDirectory().equalsIgnoreCase(basedir.toString());

在引用的条目中,有一个非常全面的示例,说明如何在mojo中使用它。

查看Maven-Monitor API

我们可以将EventMonitor添加到调度程序中,然后捕获" reactor-execute"事件的END:在完成所有操作后即在看到BUILD SUCCESSFUL / FAILED输出后即进行调度。

这是我最近使用它在结尾处立即打印摘要的方式:

/**
 * The Maven Project Object
 *
 * @parameter expression="${project}"
 * @required
 * @readonly
 */
protected MavenProject project;

/**
 * The Maven Session.
 *
 * @parameter expression="${session}"
 * @required
 * @readonly
 */
protected MavenSession session;

...

@Override
public void execute() throws MojoExecutionException, MojoFailureException
{
    //Register the event handler right at the start only
    if (project.isExecutionRoot())
        registerEventMonitor();
    ...
}

/**
 * Register an {@link EventMonitor} with Maven so that we can respond to certain lifecycle events
 */
protected void registerEventMonitor()
{
    session.getEventDispatcher().addEventMonitor(
            new EventMonitor() {

                @Override
                public void endEvent(String eventName, String target, long arg2) {
                    if (eventName.equals("reactor-execute"))
                        printSummary();
                }

                @Override
                public void startEvent(String eventName, String target, long arg2) {}

                @Override
                public void errorEvent(String eventName, String target, long arg2, Throwable arg3) {}

            }
    );
}

/**
 * Print summary at end
 */
protected void printSummary()
{
    ...
}