11

I am setting up a Circle CI build for an Android project, and am wondering how to add a gradle.properties file to my project build. I use a local gradle.properties to store my API keys and sensitive data. Other CI tools (ie, Jenkins) allow you to upload a gradle.properties file to use across all builds, but I am not able to find a way to do this in Circle CI.

It seems that environment variables are the only way Circle CI allows you to add secret credentials to your project.

Is there a way to use credentials from gradle.properties on Circle CI builds?

Kio Krofovitch
  • 2,954
  • 1
  • 21
  • 30

3 Answers3

17

Add all properties in the gradle.properties to CircleCI "Environment Variables", but prepend them with:

ORG_GRADLE_PROJECT_
Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
JeffgNpc
  • 314
  • 4
  • 11
  • This works together with the answer by @kio above. Blog: http://www.kiodev.com/circle-ci-and-gradle-properties/ – GurpreetSK95 Oct 21 '18 at 13:11
  • 1
    This is the best answer for anyone looking to add non-fabric build config fields, works perfectly with no additional config! – Jules Sep 12 '19 at 16:30
  • 1
    This should be the selected answer. – sandpat Nov 13 '19 at 09:54
  • I'm not understanding. Should I create a env variable like ORG_GRADLE_PROJECT_STORE_PASSWORD and another one ORG_GRADLE_PROJECT_KEY_PASSWORD and it’s automatically going to pull the passwords? – I'm not human Apr 27 '21 at 02:51
14

I have found a way to add credentials / API Keys to gradle.properties via Circle CI. It allows Android projects to reference gradle.properties for credentials in the same way for local and CircleCI builds.

First step, store your credentials in your Circle CI project settings as environment variables, which are guaranteed to be private. In the Circle CI GUI, go to to your project, then select "Project Settings" in the upper right hand corner. In the menu on the left side click "Environment variables" which is under the "Tweaks" header. Here you can add your credentials as a name value pair.

Next, create a bash script in your Android project which will write your Circle CI environment variables to a local gradle.properties file. I have written such a script and posted it here as gist. Here is the method which does the work:

function copyEnvVarsToGradleProperties {
    GRADLE_PROPERTIES=$HOME"/.gradle/gradle.properties"
    export GRADLE_PROPERTIES
    echo "Gradle Properties should exist at $GRADLE_PROPERTIES"

    if [ ! -f "$GRADLE_PROPERTIES" ]; then
        echo "Gradle Properties does not exist"

        echo "Creating Gradle Properties file..."
        touch $GRADLE_PROPERTIES

        echo "Writing TEST_API_KEY to gradle.properties..."
        echo "TEST_API_KEY=$TEST_API_KEY_ENV_VAR" >> $GRADLE_PROPERTIES
    fi
}

This script is only called during a Circle CI build, and not during local builds. Invoke this script as a pre-process dependency in your circle.yml file, so that your gradle.properties is written before the actual gradle build begins:

dependencies:
    pre:
        - source environmentSetup.sh && copyEnvVarsToGradleProperties

You will continue to access API keys in build.gradle just as you always have:

buildConfigField("String", "THIS_TEST_API_KEY", "\"" + TEST_API_KEY + "\"")

Kio Krofovitch
  • 2,954
  • 1
  • 21
  • 30
0

Depending on your environment(s), you could also use base64 to encode/decode gradle.properties. This worked for me on my macOS CircleCI environment:

  • From my local macOS computer, I encoded my multi-line gradle.properties file using:

    base64 < gradle.properties > encoded-gradle.properties

  • I copied the value in encoded-gradle.properties and placed it in a CircleCI environment variable (in this case, named the variable: GRADLE_PROPERTIES_DATA)

In my CircleCI config.yaml file, before building, created the gradle.properties file and decoded the encoded value and placed it in gradle.properties, using the following:

echo $GRADLE_PROPERTIES_DATA | base64 --decode > gradle.properties
h-bomb
  • 366
  • 5
  • 17