In a CI server I would like to get rid of the signingConfigs the developers have set in the file build.gradle for an Android project:
build.gradle
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
}
}
apply plugin: 'com.android.application'
dependencies {
compile fileTree(include: '*.jar', dir: 'libs')
}
android {
signingConfigs {
releaseConfig {
keyAlias 'fake_key_alias'
keyPassword 'fake_key_pass'
storeFile file('C:/fake')
storePassword 'fake_store_pass'
}
}
compileSdkVersion 25
buildToolsVersion "25.0.0"
defaultConfig {
minSdkVersion 20
targetSdkVersion 25
}
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
resources.srcDirs = ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
}
// Move the tests to tests/java, tests/res, etc...
instrumentTest.setRoot('tests')
// Move the build types to build-types/<type>
// For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
// This moves them out of them default location under src/<type>/... which would
// conflict with src/ being used by the main source set.
// Adding new build types or product flavors should be accompanied
// by a similar customization.
debug.setRoot('build-types/debug')
release.setRoot('build-types/release')
}
buildTypes {
release {
zipAlignEnabled true
signingConfig signingConfigs.releaseConfig
}
}
}
Then, I would like to replace them with a signingConfig written in an init.gradle init script placed in the CI server. I would like to use the same technique showed here (Gradle Init script plugins) to replace the repositories but I'm not able to reference the signingConfigs.
init.gradle
apply plugin:EnterpriseSigningConfigPlugin
class EnterpriseSigningConfigPlugin implements Plugin<Gradle> {
void apply(Gradle gradle) {
gradle.allprojects{ project ->
project.android.signingConfigs {
// Remove all signingConfigs
all {SigningConfig cfg ->
remove cfg
}
// add the signingConfig
signingConfigs {
releaseConfig {
keyAlias 'CI_key_alias'
keyPassword 'CI_key_pass'
storeFile file('/CI_storeFile')
storePassword 'CI_store_pass'
}
}
}
}
}
}
When I execute the command gradle -I init.gradle clean assembleRelease, I get the following error:
FAILURE: Build failed with an exception.
* Where:
Initialization script 'C:\Users\it056548\.init\init.gradle' line: 11
* What went wrong:
Could not compile initialization script 'C:\Users\it056548\.init\init.gradle'.
> startup failed:
initialization script 'C:\Users\it056548\.init\init.gradle': 11: unable to resolve class SigningConfig
@ line 11, column 21.
all {SigningConfig cfg ->
^
1 error
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED
Total time: 3.721 secs
How should I reference the signingConfigs? Is it feasible? Is this a valid approach to address my need? Thanks in advance for the help!
To solve this problem I had to take into account that the Gradle build lifecycle happens in three phases: initialization, configuration, and execution. Overriding the signingConfig assigned to the release buildType must occur at the end of the configuration phase, meaning after the build has evaluated all the project(s) properties and tasks and they're still available for modification.
Gradle offers the project hook project.afterEvaluate() that allows executing a block of code at the end of the configuration phase, where all the project(s) properties and tasks have already been set and they are still available for modification before the execution phase starts.
The use of this hook comes at handy in an initialization script, such as the following:
init.gradle
// Enter the scope of the root project
rootProject{
println ""
println "Project name: ${project.name}"
println ""
// Apply the subsequent code after the configuration phase has finished
afterEvaluate{
//Check if it exixts the properties file for the signing configuration specified in gradle.properties by the property helloWorldAppSigningProperties.
//Then read the signing configuration properties
//If something goes wrong an exception is thrown and the build execution is terminated
if (new File(helloWorldAppSigningProperties).exists()){
println ""
println "Found properties file: ${helloWorldAppSigningProperties}!"
def signingProps = new Properties()
file(helloWorldAppSigningProperties).withInputStream{signingProps.load(it)}
ext{
ka = signingProps.getProperty("keyAlias")
kp = signingProps.getProperty("keyPassword")
sf = signingProps.getProperty("storeFile")
sp = signingProps.getProperty("storePassword")
}
if (ka == null){
throw new GradleException("Property keyAlias not found in file: ${helloWorldAppSigningProperties}")
} else if (kp == null) {
throw new GradleException("Property keyPassword not found in file: ${helloWorldAppSigningProperties}")
} else if (sf == null) {
throw new GradleException("Property storeFile not found in file: ${helloWorldAppSigningProperties}")
} else if (sp == null) {
throw new GradleException("Property storePassword not found in file: ${helloWorldAppSigningProperties}")
}
} else {
throw new GradleException("Properties file: ${helloWorldAppSigningProperties} not found!")
}
//Add a signing configuration named "helloWorldApp_release" to the android build
//Signing configuration properties that were loaded from an external properties file are here assigned
println ""
println "Adding new signingConfig helloWorldApp_release"
android.signingConfigs{
helloWorldApp_release{
keyAlias ka
keyPassword kp
storeFile file(sf)
storePassword sp
}
}
//Display the list of the available signigConfigs
println ""
println "Available signingConfigs:"
android.signingConfigs.all { sc ->
println "------------------"
println sc.name
}
println "------------------"
//Display the list of the available buildTypes
println ""
println "Available buildTypes:"
android.buildTypes.all { bt ->
println "------------------"
println bt.name
}
println "------------------"
println ""
println "SigningConfig assigned to the release buildType BEFORE overriding: ${android.buildTypes.release.signingConfig.name}"
//Set the helloWorldApp_release signingConfig to the release buildType
android.buildTypes.release.signingConfig android.signingConfigs.helloWorldApp_release
println ""
println "SigningConfig assigned to the release buildType AFTER overriding: ${android.buildTypes.release.signingConfig.name}"
println ""
}
}
I externalized the desired signingConfig properties to a file, whose location I referenced in the gradle.properties file:
gradle.properties
org.gradle.jvmargs=-Xmx1536M
....
....
....
//Signing config properties files
helloWorldAppSigningProperties=C:\\Users\\it056548\\.signing\\HelloWorldApp.properties
It resulted in a successful android build that addressed my needs when executing the command gradle -I init.gradle clean assembleRelease:
Project name: native
NDK is missing a "platforms" directory.
If you are using NDK, verify the ndk.dir is set to a valid NDK directory. It is currently set to C:\android-sdks\ndk-bundle.
If you are not using NDK, unset the NDK variable from ANDROID_NDK_HOME or local.properties to remove this warning.
Found properties file: C:\Users\it056548\.signing\HelloWorldApp.properties!
Adding new signingConfig helloWorldApp_release
Available signingConfigs:
------------------
debug
------------------
helloWorldApp_release
------------------
releaseConfig
------------------
Available buildTypes:
------------------
debug
------------------
release
------------------
SigningConfig assigned to the release buildType BEFORE overriding: releaseConfig
SigningConfig assigned to the release buildType AFTER overriding: helloWorldApp_release
:clean
:preBuild UP-TO-DATE
:preReleaseBuild UP-TO-DATE
:checkReleaseManifest
:prepareReleaseDependencies
:compileReleaseAidl
:compileReleaseRenderscript
:generateReleaseBuildConfig
:generateReleaseResValues
:generateReleaseResources
:mergeReleaseResources
:processReleaseManifest
:processReleaseResources
:generateReleaseSources
:incrementalReleaseJavaCompilationSafeguard
:javaPreCompileRelease
:compileReleaseJavaWithJavac
:compileReleaseJavaWithJavac - is not incremental (e.g. outputs have changed, no previous execution, etc.).
:compileReleaseNdk NO-SOURCE
:compileReleaseSources
:lintVitalRelease
:mergeReleaseShaders
:compileReleaseShaders
:generateReleaseAssets
:mergeReleaseAssets
:transformClassesWithDexForRelease
:mergeReleaseJniLibFolders
:transformNativeLibsWithMergeJniLibsForRelease
:processReleaseJavaRes NO-SOURCE
:transformResourcesWithMergeJavaResForRelease
:validateSigningRelease
:packageRelease
:assembleRelease
BUILD SUCCESSFUL
Total time: 8.692 secs
Hope this can help!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With