使用密钥库在 Travis CI 上签署 Android 应用程序的发布版本的最佳做法是什么?

What is the best practice to use keystores to sign release version of an Android app on Travis CI?

我一直在使用 Travis CI 构建我的 Android app. I am signing it in the debug builds with a debug.keystore which I pushed to public repository

但我想使用此 gradle plugin.

构建发布版本并将它们上传到 Google Play 商店

此过程需要一个 keystore 和一个 p12 证书文件。

虽然我可以将加密的环境变量添加到 Travis CI,但我不知道存储这些文件的最佳方式。

问题 1:执行此操作的最佳做​​法是什么?有人可以提供开源实现吗? (我找不到)

一种可能的实现方式:将用户名和密码安全地存储为环境变量。将文件存储在启用 SSL 的环境中,并使用这些用户名和密码以及简单的 HTTP 身份验证来保护它们。在构建过程开始之前使用它们使用 curl 下载。

问题 2 这个实现是否有意义?安全吗?

额外: 这两篇博文是与此相关的重要资源,但不幸的是,其中 none 回答了这个问题。

http://stablekernel.com/blog/deploying-google-play-continuous-delivery-android-part-4/ https://www.bignerdranch.com/blog/continuous-delivery-for-android/

  • 当您的应用程序完成后导出它。
  • 届时自动生成key-store,SHA1 和MD5 密钥,用于play store 或公开使用。
  • 现在为 Play 商店创建最终的 APK 文件并完美地公开使用。

更新 (5/28/15):

我已经开始在这里实施我的解决方案(开源):https://github.com/NonameDev/MathApp

  • 使用 System.getenv("TRAVIS") 检测您的构建 运行ning on Travis。
  • storeFile rootProject.file('release.keystore') - 将发布密钥保存在你自己的存储库中 - travis 将隐藏密码
  • storePassword System.getenv("KEYSTORE_PASS") - 在 travis 上存储环境变量 - travis 将隐藏输出
  • keyAlias System.getenv("ALIAS_NAME") - 在 travis 上存储环境变量 - travis 将隐藏输出
  • keyPassword System.getenv("ALIAS_PASS") - 在 travis 上存储环境变量 - travis 将隐藏输出
  • System.getenv("SERVICE_EMAIL") - 在 travis 上存储环境变量 - travis 将隐藏输出
  • rootProject.file('play.p12') - 在本地存储证书 - travis 将存储电子邮件服务帐户

顶部build.gradle:

buildscript {
    repositories {
        mavenCentral()
        jcenter()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:1.2.3'
        classpath 'com.github.triplet.gradle:play-publisher:1.1.0'
    }
}

应用build.gradle:

apply plugin: 'com.android.application'
apply plugin: 'com.github.triplet.play'

android {
    compileSdkVersion 22
    buildToolsVersion '22.0.1'

    defaultConfig {
        applicationId 'burrows.apps.mathapp'
        minSdkVersion 9
        targetSdkVersion 22
        versionCode 1
        versionName '1.0'
    }

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }

    signingConfigs {
        debug {
            storeFile rootProject.file('debug.keystore')
            storePassword 'android'
            keyAlias 'androiddebugkey'
            keyPassword 'android'
        }

        if (System.getenv("TRAVIS")) {
            release {
                storeFile rootProject.file('release.keystore')
                storePassword System.getenv("KEYSTORE_PASS")
                keyAlias System.getenv("ALIAS_NAME")
                keyPassword System.getenv("ALIAS_PASS")
            }
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    lintOptions {
        abortOnError false
    }
}

if (System.getenv("TRAVIS")) {
    play {
        serviceAccountEmail = System.getenv("SERVICE_EMAIL")
        pk12File = rootProject.file('play.p12')
        track = 'production' // or 'alpha' or 'beta' or 'production'
    }
}

原答案:

你见过这个answer吗?他将 link 发布到他的 TravisCI 构建 "before" 并 "after" 更正他的构建。

这是他的回答:

Compare build #162 and #163.

基本上他不得不运行sudo pip install google-api-python-client

话虽如此,我检查了 github 存储库 here

这是他的 .travis.yml:

language: android
android:
  components:
    - build-tools-21.1.2
    - extra-android-m2repository

env:
  global:
    - secure: <removed>
    - secure: <removed>
before_install:
  - ci/decrypt_files
  - ci/start_emulator

install:
  - ./gradlew build

before_script:
  - ci/wait_for_emulator

script:
  - ./gradlew connectedAndroidTestMockDebug

after_success:
  - ci/deploy_all

notifications:
  email:
    - <removed>

来源: https://github.com/mg6maciej/VielenGamesAndroidClient/blob/develop/.travis.yml

构建前:

这是过程的 secure 部分,其中使用密钥并使用来自 TravisCI 的密码(安全地存储在 TravisCI 上)。

before_install:
  - ci/decrypt_files
  - ci/start_emulator

ci/decrypt_files的来源:

#!/bin/bash
openssl aes-256-cbc -d -k "$file_password" -in app/gradle.properties.enc -out app/gradle.properties
openssl aes-256-cbc -d -k "$file_password" -in app/crashlytics.properties.enc -out app/crashlytics.properties
openssl aes-256-cbc -d -k "$file_password" -in ci/vielengames.keystore.enc -out ci/vielengames.keystore
openssl aes-256-cbc -d -k "$file_password" -in ci/key.p12.enc -out key.p12

来源: https://github.com/mg6maciej/VielenGamesAndroidClient/blob/develop/ci/decrypt_files

构建后:

这是下载 python 和其他 Google 库并将应用程序部署到 Google Play 的地方。

after_success:
  - ci/deploy_all

ci/deploy_all的来源:

#!/bin/bash
test "$TRAVIS_BRANCH" == "master" && ci/deploy_google_play
ci/deploy_testfairy
ci/deploy_crashlytics_beta

ci/deploy_google_play的来源:

#!/bin/bash
DIR=$(dirname [=17=])

sudo apt-get install python-openssl
sudo pip install google-api-python-client

python $DIR/basic_upload_apks.py com.vielengames $DIR/../app/build/outputs/apk/app-production-release.apk
python $DIR/basic_upload_apks.py com.vielengames.staging $DIR/../app/build/outputs/apk/app-staging-release.apk

安全性:

您的问题 1:

我相信您必须同时拥有应用程序的 keystorep12,但您可以 安全地 使用 TravisCI 存储您的密码(请参阅"$file_password"), 就像上面的例子。

你的问题2:

即使您拥有 keystorep12 证书,您仍然需要密码(请参阅 "$file_password")才能工作并用于发布到商店。

为了额外的安全,您想要添加另一个登录名,其权限比主登录名。这是回购协议的作者所做的 here:

...

TRACK = 'beta'  # Can be 'alpha', beta', 'production' or 'rollout'

SERVICE_ACCOUNT_EMAIL = (
    '148768954062-sp89pjb1blr7cu2f73f4fpd6dqloc047@developer.gserviceaccount.com')

# Declare command-line flags.
argparser = argparse.ArgumentParser(add_help=False)
argparser.add_argument('package_name',
                       help='The package name. Example: com.android.sample')
argparser.add_argument('apk_file',
                       nargs='?',
                       default='test.apk',
                       help='The path to the APK file to upload.')

...

来源: https://github.com/mg6maciej/VielenGamesAndroidClient/blob/develop/ci/basic_upload_apks.py