读取 Android 项目中的 Jenkins 环境变量?为自动构建签署 APK
Read Jenkins environment variables in Android project? Sign APK for automated builds
以为我会通过搜索找到答案,但没有运气。我计划自动化我的构建过程并通过我的 Jenkins 服务器上的 fastlane
将构建上传到 Crashlytics Beta
。 Crashlytics beta
需要签名的 APKS,但我当然不想将我的 keystore
和密码直接添加到我的 build.gradle
文件中,然后再进入版本控制。
我被指向了 Jenkins 环境变量的方向。这是我在 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
当我尝试通过 fastlane
在 jenkins
上构建我的项目时,出现以下错误:
* 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,它向我显示了所有系统环境变量,我定义的变量不在那里,所以我不完全确定 Jenkins
把它们放在哪里。我需要直接路径吗?那会是什么?
感谢任何帮助,谢谢!
这里是来自 Fabric 和 Fastlane 的 Mike。
我不相信这个:
ANDROID_KEYSTORE=$ANDROID_KEYSTORE
ANDROID_STORE_PASSWORD=$ANDROID_STORE_PASSWORD
ANDROID_KEY_ALIAS=$ANDROID_KEY_ALIAS
将按照您希望的方式工作。如果您已经为环境变量设置了您想要的值,您可以在 build.gradle
中使用 String.valueOf(System.env.ANDROID_KEYSTORE)
等,并跳过在 gradle.properties
中放置任何其他内容。
假设您的问题是:"do I need a direct (or absolute) path (to the keystore)" 和 "what would that (path) be"。
我会回答 "no" 和 "it's likely to be the path shown in the last line of your log, but including the expansion of the variable $ANDROID_KEYSTORE"!
事实上,我遇到了你的问题,希望在 Jenkins GNU/Linux 奴隶上实现几乎相同的目标。
首先,我认为您面临的问题是那些环境变量不会从 gradle.properties 文件中展开! Groovy 有时是神奇的,所以我检查过以确保:它不会那样做,这解释了为什么你的密钥库路径错误(包含字符串“$ANDROID_KEYSTORE”而不是变量的值)。
要解决此问题,我看到两个选项:
您可以尝试配置您的 Jenkins 作业(可能需要预先执行步骤)以生成具有扩展值的 gradle.properties 文件:
echo "ANDROID_KEYSTORE=${ANDROID_KEYSTORE}" >> gradle.properties
您甚至可以考虑按照建议使用特定的属性文件 here。
- 在我看来,一个更灵活的选择是添加一些代码来尝试从环境中读取这些变量,然后使用如上所述的属性文件来定义默认值(如果某些开发人员拥有密钥并允许手动发布版本)。
我已经在 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 正在为该特定构建做什么。
以为我会通过搜索找到答案,但没有运气。我计划自动化我的构建过程并通过我的 Jenkins 服务器上的 fastlane
将构建上传到 Crashlytics Beta
。 Crashlytics beta
需要签名的 APKS,但我当然不想将我的 keystore
和密码直接添加到我的 build.gradle
文件中,然后再进入版本控制。
我被指向了 Jenkins 环境变量的方向。这是我在 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
当我尝试通过 fastlane
在 jenkins
上构建我的项目时,出现以下错误:
* 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,它向我显示了所有系统环境变量,我定义的变量不在那里,所以我不完全确定 Jenkins
把它们放在哪里。我需要直接路径吗?那会是什么?
感谢任何帮助,谢谢!
这里是来自 Fabric 和 Fastlane 的 Mike。
我不相信这个:
ANDROID_KEYSTORE=$ANDROID_KEYSTORE
ANDROID_STORE_PASSWORD=$ANDROID_STORE_PASSWORD
ANDROID_KEY_ALIAS=$ANDROID_KEY_ALIAS
将按照您希望的方式工作。如果您已经为环境变量设置了您想要的值,您可以在 build.gradle
中使用 String.valueOf(System.env.ANDROID_KEYSTORE)
等,并跳过在 gradle.properties
中放置任何其他内容。
假设您的问题是:"do I need a direct (or absolute) path (to the keystore)" 和 "what would that (path) be"。
我会回答 "no" 和 "it's likely to be the path shown in the last line of your log, but including the expansion of the variable $ANDROID_KEYSTORE"!
事实上,我遇到了你的问题,希望在 Jenkins GNU/Linux 奴隶上实现几乎相同的目标。
首先,我认为您面临的问题是那些环境变量不会从 gradle.properties 文件中展开! Groovy 有时是神奇的,所以我检查过以确保:它不会那样做,这解释了为什么你的密钥库路径错误(包含字符串“$ANDROID_KEYSTORE”而不是变量的值)。
要解决此问题,我看到两个选项:
您可以尝试配置您的 Jenkins 作业(可能需要预先执行步骤)以生成具有扩展值的 gradle.properties 文件:
echo "ANDROID_KEYSTORE=${ANDROID_KEYSTORE}" >> gradle.properties
您甚至可以考虑按照建议使用特定的属性文件 here。
- 在我看来,一个更灵活的选择是添加一些代码来尝试从环境中读取这些变量,然后使用如上所述的属性文件来定义默认值(如果某些开发人员拥有密钥并允许手动发布版本)。
我已经在 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 正在为该特定构建做什么。