将 Jenkins 凭证传递给 Maven Surefire 插件

Pass Jenkins Credentials to Maven Surefire Plugin

背景

我正在开发一个模板化的管道解决方案,这样团队就可以在 Jenkins 中对每个作业 运行 进行一致的构建、测试和扫描他们的项目。其中一个项目使用 Maven 进行依赖管理,并需要传递 Jenkins 凭证,以便集成测试 运行.

什么有效?

通过命令行参数传递凭据效果很好。例如...

withCredentials([
    [
        $class: 'UsernamePasswordMultiBinding', 
        credentialsId: 'TEST', 
        usernameVariable: 'TEST_USERNAME', 
        passwordVariable: 'TEST_PASSWORD'
    ]
]) {
    sh 'mvn clean install -D test_username=$TEST_USERNAME -D test_password=$TEST_PASSWORD'
}

想要的方法和结果是什么?

我强烈希望通过每个插件的配置(即 Maven Surefire 插件)将这些变量传递给底层插件。这种首选方法的理由是利用结构化方法来管理系统属性。我已经尝试了很多方法,包括通过设置 Surefire 配置的 <argLines> 元素和设置 <systemPropertyValues> 元素来传递参数,但是这两种方法都不起作用。此外,最好通过 YAML 文件引用这些属性以实现外部化配置,但我不反对其他访问此信息的方法如果无法在配置文件中引用凭证变量 .

pom.xml

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.22.2</version>
    <configuration>
        <!-- Tacking 'env.' to the beginning of each variable name does not make a difference; tests still fail. -->
        <argLines>-D test_username=${TEST_USERNAME} -D test_password=${TEST_PASSWORD}</argLines>
        <systemPropertyVariables>
            <test_username>${TEST_USERNAME}</test_username>
            <test_username>${TEST_PASSWORD}</test_username>
        </systemPropertyVariables>
    </configuration>
</plugin>

bootstrap-test.yaml

datasource:
    jdbc_url: *omitted*
    username: ${test_username}
    password: ${test_password}

不工作是什么意思?

如果我尝试通过在配置部分指定系统属性来 运行 在 Jenkins 环境中进行测试,那么测试会失败。顺便说一句,我将这些凭据传递给 Spring Boot,但是 entityManagerFactory (org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder) 无法初始化。

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [com/acme/Config.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: Unable to resolve persistence unit root URL

我担心这个问题可能是由于 Spring Boot 无法访问混淆的凭据,或者在 Maven 的生命周期中太晚尝试访问配置文件中的系统属性。

我也不完全反对通过命令行传递系统属性,但模板化解决方案需要包括一种有效(安全)的方式来收集不同的凭据类型以传递给 Maven 调用。

更新 1:

运行 这个项目在本地(顺便说一句,在 Windows 机器上)导出变量后确实有效,但 无效 在詹金斯。在本地工作的方法涉及在 Surefire 插件配置部分设置环境或系统 属性 变量。我用 env..

对 Jenkins 创建的环境变量做了前缀引用

更新 2:

使用 Maven ant运行 插件,我能够回应 Jenkins 导出的屏蔽秘密。

我尝试了一个新的 jenkins,它按预期工作。如果 plugin(java class) 能够读取环境变量并且 jenkins 注入环境变量,一切都应该工作。

我认为你的错误是环境变量语法。根据 this,您应该使用 ${env.VARIABLE_NAME} 在 pom.xml 中使用 环境变量 。所以在你的情况下,你的 pom.xml 应该是这样的:

<test_username>${env.TEST_USERNAME}</test_username>
<test_username>${env.TEST_PASSWORD}</test_username>

然后用

注入需要的变量
withCredentials([
    [
        $class: 'UsernamePasswordMultiBinding', 
        credentialsId: 'TEST', 
        usernameVariable: 'TEST_USERNAME', 
        passwordVariable: 'TEST_PASSWORD'
    ]
]) {
    sh 'mvn clean install'
}

Java 系统属性和环境变量

当您在任何 java 实现上使用 -Dmykey = value 时,您设置的是系统 属性, 而不是环境变量 。检查这个:

  • Java system properties and environment variables

这非常奇怪,但是如何指定 POM 位置似乎有所不同。本来我是给Maven提供-f ./pom.xml,环境变量解析不了。一时兴起,我提供了f pom.xml(没有'./')和成功解析的环境变量。

不幸的是,我不知道为什么这会有所不同,但如果我设法在路上发现更多细节,我会更新我的答案...