在Android项目中读取Jenkins环境变量?为自动构建

时间:2016-09-07 09:35:26

标签: android jenkins environment-variables fastlane

以为我会通过搜索找到答案,但没有运气。我计划在我的Jenkins服务器上通过Crashlytics Beta自动化我的构建过程并将构建内容上传到fastlaneCrashlytics beta需要签名的APK,但我当然不想将keystore和密码直接添加到我的build.gradle文件中,然后再添加到版本控制中。

我被指向Jenkins env变量的方向。这就是我在Android项目中所拥有的:

signingConfigs {
   release {
        storeFile file(ANDROID_KEYSTORE)
        storePassword ANDROID_STORE_PASSWORD
        keyAlias ANDROID_KEY_ALIAS
        keyPassword ANDROID_STORE_PASSWORD
   }
}

然后在我的gradle.properties文件中,我有以下内容:

ANDROID_KEYSTORE=$ANDROID_KEYSTORE
ANDROID_STORE_PASSWORD=$ANDROID_STORE_PASSWORD
ANDROID_KEY_ALIAS=$ANDROID_KEY_ALIAS

当我尝试通过jenkinsfastlane上构建项目时,出现以下错误:

* What went wrong:
Execution failed for task ':app:validateReleaseSigning'.
> Keystore file /Users/macmini/.jenkins/workspace/AndroidProject/app/$ANDROID_KEYSTORE not found for signing config 'release'.

另外一件事,我在终端中有env并且它向我显示了所有系统env变量,我定义的那些变量并不存在,所以我不完全确定Jenkins放置它们的位置。我需要直接路径吗?那会是什么?

感谢任何帮助,谢谢!

2 个答案:

答案 0 :(得分:1)

来自Fabric和Fastlane的Mike来自这里。

我不相信这个:

ANDROID_KEYSTORE=$ANDROID_KEYSTORE
ANDROID_STORE_PASSWORD=$ANDROID_STORE_PASSWORD
ANDROID_KEY_ALIAS=$ANDROID_KEY_ALIAS

将以您希望的方式工作。如果您已经使用所需的值设置了环境变量,则可以在String.valueOf(System.env.ANDROID_KEYSTORE)中使用build.gradle等,并在gradle.properties中跳过其他任何内容。

答案 1 :(得分:1)

假设您的问题是:“我是否需要直接(或绝对)路径(到密钥库)”和“那将是什么(路径)”。

我会回答“否”,“它可能是您日志最后一行显示的路径,但包括变量$ ANDROID_KEYSTORE的扩展”!

事实上,我遇到了一个想要在Jenkins GNU / Linux奴隶上实现几乎相同的问题。

首先,我认为您面临的问题是那些环境变量不会从gradle.properties文件中扩展出来! Groovy有点神奇,所以我检查确定:它没有这样做,这解释了为什么你的密钥库有一个错误的路径(包含字符串“$ ANDROID_KEYSTORE”而不是变量的值)。

要解决此问题,我会看到两个选项:

  1. 您可以尝试配置Jenkins作业(可能需要预先步骤)来生成带有扩展值的gradle.properties文件:

    echo“ANDROID_KEYSTORE = $ {ANDROID_KEYSTORE}”>> gradle.properties

  2. 您甚至可以考虑使用建议here的特定属性文件。

    1. 我认为一个非常灵活的选项是添加一些代码来尝试从环境中读取这些变量,然后使用上面描述的属性文件来定义默认值(如果某些开发人员拥有密钥的副本,则非常有用)并允许手动发布版本。
    2. 我已经在app / build.gradle中成功测试了类似的内容:

      // Load a specific properties file to access the keystore if exists
      def keystoreProperties = new Properties()
      def keystorePropertiesFile = rootProject.file("keystore.properties")
      
      if (keystorePropertiesFile.exists() ) {
          // Load keystore properties from file
          keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
      } else {
          // Load keystore properties from environment or set their default values
          def env = System.getenv()
          if (env['ANDROID_KEYALIAS']) keystoreProperties.put('keyAlias', env['ANDROID_KEYALIAS'])
          else keystoreProperties.put('keyAlias', "myDefaultAlias")
          if (env['ANDROID_KEYPASSWORD']) keystoreProperties.put('keyPassword', env['ANDROID_KEYPASSWORD'])
          else keystoreProperties.put('keyPassword', "myDefaultKeyPass")
          if (env['ANDROID_STOREFILE']) keystoreProperties.put('storeFile', env['ANDROID_STOREFILE'])
          else keystoreProperties.put('storeFile', "./keystore.jks")
          if (env['ANDROID_STOREPASSWORD']) keystoreProperties.put('storePassword', env['ANDROID_STOREPASSWORD'])
          else keystoreProperties.put('storePassword', "myDefaultStorePass")
      }
      
      ...
      
      android {
          signingConfigs {
              release {
                  keyAlias keystoreProperties['keyAlias']
                  keyPassword keystoreProperties['keyPassword']
                  storeFile file(keystoreProperties['storeFile'])
                  storePassword keystoreProperties['storePassword']
              }
          }
      

      我确信这可以改进并且很多,并且可能转向用环境变量覆盖属性(如果存在)。但它今天对我有用。

      正如您所提到的,如果您在env命令的输出中没有看到这些变量,那么您最好先查找它们。我建议你使用env命令开始构建步骤。当然,在单独的终端中输入此命令不会显示Jenkins正在为该特定构建做什么。