Where to store Android KeyStore file for CirlceCi build?

Viewed 7724

I am trying to configure continuous integration build for my Android app. I use CircleCi platform for it. Now I store my apps Keystore.jks file locally, but CircleCi needs it to sign my app. How can I achieve that without storing the file on my git repository? Or maybe I shouldn't be concerned about that while the repository is private?

My gradle signing configs:

signingConfigs {
    if (System.getenv("CIRCLECI")) {
        release {
            keyAlias '****'
            keyPassword '****'
            storeFile file(System.getenv("******"))
            storePassword '****'
        }
    }else{
        release {
             ...
        }
    }
}

My circle.yml :

general:
    artifacts:
        - /home/ubuntu/my-app/app/build/outputs/apk/
machine:
  environment:
    ANDROID_HOME: /usr/local/android-sdk-linux
dependencies:
  override:
     - chmod +x gradlew
test:
  override:
    - ./gradlew assemble

I tried to save the keystore file on CircleCi as environmental variable but it isn't working, my build fails with exception:

> Execution failed for task ':app:validateSigningDemoRelease'.
> > Keystore file /home/ubuntu/my-app/app/  HERE_IS_THE_KEYSTORE not found for signing config 'release'.

Unsigned and debug builds finish with success.

I'm also open to use any different ci platform if you suggest something else.

Thanks in advance for every advice!

4 Answers

I struggled with this problem recently and decided that the easiest solution was to encode the keystore file to base64 and put it into an environment variable at CircleCI.

This will encode the file and you can copy and paste the value across:

openssl base64 -A -in .signing/release.jks 

Then, in your config.yml file at CircleCI, decode it back:

echo $RELEASE_KEYSTORE_BASE64 | base64 -d > .signing/release.jks

if statement does not work in signingConfigs. If you want to sign apk with different keystore for different flavors, you need to create signingConfigs and put signingconfigs into buildTypes section. I did some research about where to store android keystore file in CI/CD Cycle and I come up with three approaches:

  1. Encode keystore file as an environment variable

    As @grepx's answer, convert keystore file to base-64 encoded string and save it as an environment variable in CI tools.

  2. Store encrypted keystore file in version control system

    Encrypt keystore file and store it in version control system. You can encrypt file with:

    openssl aes-256-cbc -e -in keystore.jks -out keystore.jks.encrypted -k SECRET_KEY

    You need to decrypt that encrypted keystore file in build step in CI tools:

    openssl aes-256-cbc -d -in keystore.jks.encrypted -k $ENCRYPT_SECRET_KEY >> keystore.jks

    SECRET_KEY is stored as an environment variable in CI with this key: $ENCRYPT_SECRET_KEY

  3. Download keystore from external source like AWS S3, Google Drive

I've published an article about this topic in medium and you can reach complete example in github to understand better.

According to this link you have to encrypt the file like this:

openssl aes-256-cbc -a -salt -in secrets.txt -out secrets.txt.enc

and for the decryption:

    openssl aes-256-cbc -a -salt -in secrets.txt.enc -out secrets.txt.new
Related