如何停止 Maven 的验证阶段重建工件?

想象一下我有一个使用 Maven 构建的 Java 项目:

Imagine a Java project built using Maven for which I have:

  • 一些快速运行的单元测试:
    • 开发人员应在提交前运行
    • 我的 CI 服务器(Hudson,FWIW)应在检测到新提交时运行,并在出现故障时提供几乎即时的反馈
    • 开发者可以选择运行,例如重现和修复故障
    • 我的 CI 服务器应该在成功运行单元测试后运行

    这似乎是一个典型的场景.目前,我正在跑步:

    This seems like a typical scenario. Currently, I'm running:

    • 测试"阶段的单元测试
    • 验证"阶段的验收测试

    配置了两个CI作业,都指向项目的VCS分支:

    There are two CI jobs configured, both pointing to the project's VCS branch:

    1. 提交阶段",运行mvn package"(编译和单元测试代码,构建工件),如果成功,触发:
    2. Automated Acceptance Tests",运行mvn verify"(设置、运行和拆除验收测试)

    问题在于作业 2 单元测试并重新构建被测工件(因为验证阶段会自动调用包阶段).出于以下几个原因(重要性降低),这是不可取的:

    The problem is that job 2 unit tests and builds the artifact-under-test all over again (because the verify phase automatically invokes the package phase). This is undesirable for several reasons (in decreasing importance):

    • 作业 2 创建的工件可能与作业 1 创建的工件不同(例如,如果同时有新的提交)
    • 延长了对提交的开发人员的反馈循环(即他们需要更长的时间才能发现他们破坏了构建)
    • 浪费 CI 服务器上的资源

    所以我的问题是,如何配置作业 2 以使用作业 1 创建的工件?

    So my question is, how can I configure job 2 to use the artifact created by job 1?

    我意识到我可以只拥有一个运行mvn verify"的 CI 作业,它只会创建一次工件,但我希望拥有上述单独的 CI 作业以实现 Farley 风格的部署管道.

    如果它对任何人有帮助,这是已接受答案中项目 2"的完整 Maven 2 POM:

    In case it helps anyone, here's the full Maven 2 POM of "project 2" in the accepted answer:

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.example.cake</groupId>
        <artifactId>cake-acceptance</artifactId>
        <version>1.0</version>
        <packaging>jar</packaging>
        <name>Cake Shop Acceptance Tests</name>
        <description>
            Runs the automated acceptance tests for the Cake Shop web application.
        </description>
        <build>
            <plugins>
                <!-- Compiler -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>2.3.1</version>
                    <configuration>
                        <source>${java.version}</source>
                        <target>${java.version}</target>
                    </configuration>
                </plugin>
                <!-- Suppress the normal "test" phase; there's no unit tests -->
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.5</version>
                    <configuration>
                        <skipTests>true</skipTests>
                    </configuration>
                </plugin>
                <!-- Cargo (starts and stops the web container) -->
                <plugin>
                    <groupId>org.codehaus.cargo</groupId>
                    <artifactId>cargo-maven2-plugin</artifactId>
                    <version>1.0.5</version>
                    <executions>
                        <execution>
                            <id>start-container</id>
                            <phase>pre-integration-test</phase>
                            <goals>
                                <goal>start</goal>
                            </goals>
                        </execution>
                        <execution>
                            <id>stop-container</id>
                            <phase>post-integration-test</phase>
                            <goals>
                                <goal>stop</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <!-- Don't wait for CTRL-C after starting the container -->
                        <wait>false</wait>
    
                        <container>
                            <containerId>jetty7x</containerId>
                            <type>embedded</type>
                            <timeout>20000</timeout>
                        </container>
    
                        <configuration>
                            <properties>
                                <cargo.servlet.port>${http.port}</cargo.servlet.port>
                            </properties>
                            <deployables>
                                <deployable>
                                    <groupId>${project.groupId}</groupId>
                                    <artifactId>${target.artifactId}</artifactId>
                                    <type>war</type>
                                    <properties>
                                        <context>${context.path}</context>
                                    </properties>
                                </deployable>
                            </deployables>
                        </configuration>
                    </configuration>
                </plugin>
                <!-- Failsafe (runs the acceptance tests) -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-failsafe-plugin</artifactId>
                    <version>2.6</version>
                    <executions>
                        <execution>
                            <id>integration-test</id>
                            <goals>
                                <goal>integration-test</goal>
                            </goals>
                        </execution>
                        <execution>
                            <id>verify</id>
                            <goals>
                                <goal>verify</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <includes>
                            <include>**/*Test.java</include>
                        </includes>
                        <skipTests>false</skipTests>
                    </configuration>
                </plugin>
            </plugins>
        </build>
        <dependencies>
                <!-- Add your tests' dependencies here, e.g. Selenium or Sahi,
                    with "test" scope -->
            <dependency>
                <!-- The artifact under test -->
                <groupId>${project.groupId}</groupId>
                <artifactId>${target.artifactId}</artifactId>
                <version>${target.version}</version>
                <type>war</type>
            </dependency>
        </dependencies>
        <properties>
            <!-- The artifact under test -->
            <target.artifactId>cake</target.artifactId>
            <target.version>0.1.0-SNAPSHOT</target.version>
            <context.path>${target.artifactId}</context.path>
            <http.port>8081</http.port>
            <java.version>1.6</java.version>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        </properties>
    </project>
    

    请注意,即使这个测试"项目没有创建工件,它也必须使用某种包装(我在这里使用了jar"),否则在验证阶段不会运行任何测试.

    Note that even though this "tests" project doesn't create an artifact, it has to use some kind of packaging (I used "jar" here), otherwise no tests are run in the verify phase.

    推荐答案

    尝试两个maven项目.第一个包含构建和单元测试.您将工件安装在本地存储库中.第二个作业运行第二个 maven 项目,它将第一个项目的工件声明为依赖项并运行功能测试.

    Try two maven projects. The first one contains the build and unit tests. You install the artifacts in your local repository. The second job runs the second maven project which declares the artifacts of the first project as dependencies and runs the functional tests.

    不确定我刚才描述的场景是否可能,但我认为是的.

    Not sure if the scenario I just described is possible, but I think it is.

    为了快速改进,您可以使用 -Dmaven.test.skip=true 绕过单元测试.如果您将 scm 中代码的修订号传递给第二个作业,您应该能够签出相同的源代码.

    For a quick improvement you can bypass the unit test with -Dmaven.test.skip=true. If you pass the revision number of your code in your scm to the second job, you should be able to checkout the same source code.

    您还可以查看 Clone Workspace SCM 插件.这可能会为您提供一些额外的选择.

    You can also check into the Clone Workspace SCM plugin. This might offer you some additional options.

相关文章