Para resolver isso, criei três projetos do Firebase, cada um com o mesmo projeto Android (ou seja, o mesmo applicationId
sem usar o applicationIdSuffix
sugerido por outros). Isso resultou em três arquivos google-services.json que eu armazenei no servidor de Integração Contínua (CI) como variáveis de ambiente personalizadas . Para cada estágio da construção (dev / staging / prod), usei o arquivo google-services.json correspondente.
Para o projeto Firebase associado ao dev, em seu projeto Android, adicionei a impressão digital do certificado SHA de depuração. Mas, para preparação e produção, basta que o CI assine o APK.
Aqui está um despojado .gitlab-ci.yml
que funcionou para esta configuração:
# This is a Gitlab Continuous Integration (CI) Pipeline definition
# Environment variables:
# - variables prefixed CI_ are Gitlab predefined environment variables (https://docs.gitlab.com/ee/ci/variables/predefined_variables.html)
# - variables prefixed GNDR_CI are Gitlab custom environment variables (https://docs.gitlab.com/ee/ci/variables/#creating-a-custom-environment-variable)
#
# We have three Firebase projects (dev, staging, prod) where the same package name is used across all of them but the
# debug signing certificate is only provided for the dev one (later if there are other developers, they can have their
# own Firebase project that's equivalent to the dev one). The staging and prod Firebase projects use real certificate
# signing so we don't need to enter a Debug signing certificate for them. We don't check the google-services.json into
# the repository. Instead it's provided at build time either on the developer's machine or by the Gitlab CI server
# which injects it via custom environment variables. That way the google-services.json can reside in the default
# location, the projects's app directory. The .gitlab-ci.yml is configured to copy the dev, staging, and prod equivalents
# of the google-servies.json file into that default location.
#
# References:
# https://firebase.googleblog.com/2016/08/organizing-your-firebase-enabled-android-app-builds.html
# /programming/57129588/how-to-setup-firebase-for-multi-stage-release
stages:
- stg_build_dev
- stg_build_staging
- stg_build_prod
jb_build_dev:
stage: stg_build_dev
image: jangrewe/gitlab-ci-android
cache:
key: ${CI_PROJECT_ID}-android
paths:
- .gradle/
script:
- cp ${GNDR_CI_GOOGLE_SERVICES_JSON_DEV_FILE} app/google-services.json
- ./gradlew :app:assembleDebug
artifacts:
paths:
- app/build/outputs/apk/
jb_build_staging:
stage: stg_build_staging
image: jangrewe/gitlab-ci-android
cache:
key: ${CI_PROJECT_ID}-android
paths:
- .gradle/
dependencies: []
script:
- cp ${GNDR_CI_GOOGLE_SERVICES_JSON_STAGING_FILE} app/google-services.json
- ./gradlew :app:assembleDebug
artifacts:
paths:
- app/build/outputs/apk/
jb_build_prod:
stage: stg_build_prod
image: jangrewe/gitlab-ci-android
cache:
key: ${CI_PROJECT_ID}-android
paths:
- .gradle/
dependencies: []
script:
- cp ${GNDR_CI_GOOGLE_SERVICES_JSON_PROD_FILE} app/google-services.json
# GNDR_CI_KEYSTORE_FILE_BASE64_ENCODED created on Mac via:
# base64 --input ~/Desktop/gendr.keystore --output ~/Desktop/keystore_base64_encoded.txt
# Then the contents of keystore_base64_encoded.txt were copied and pasted as a Gitlab custom environment variable
# For more info see http://android.jlelse.eu/android-gitlab-ci-cd-sign-deploy-3ad66a8f24bf
- cat ${GNDR_CI_KEYSTORE_FILE_BASE64_ENCODED} | base64 --decode > gendr.keystore
- ./gradlew :app:assembleRelease
-Pandroid.injected.signing.store.file=$(pwd)/gendr.keystore
-Pandroid.injected.signing.store.password=${GNDR_CI_KEYSTORE_PASSWORD}
-Pandroid.injected.signing.key.alias=${GNDR_CI_KEY_ALIAS}
-Pandroid.injected.signing.key.password=${GNDR_CI_KEY_PASSWORD}
artifacts:
paths:
- app/build/outputs/apk/
Estou feliz com esta solução porque ela não se baseia nos truques de build.gradle que, acredito, são muito opacos e, portanto, difíceis de manter. Por exemplo, quando tentei as abordagens usando s applicationIdSuffix
diferentes buildType
, descobri que não conseguia executar testes instrumentados nem mesmo compilar quando tentei alternar tipos de compilação usando testBuildType
. O Android parecia dar propriedades especiais às debug
buildType
quais eu não conseguia inspecionar para entender.
Virtualmente, os scripts de CI são bastante transparentes e fáceis de manter, na minha experiência. De fato, a abordagem que descrevi funcionou: quando executei cada um dos APKs gerados pelo CI em um emulador, a etapa "Execute seu aplicativo para verificar a instalação" do console do Firebase passou de
Verificando se o aplicativo se comunicou com nossos servidores. Pode ser necessário desinstalar e reinstalar o aplicativo.
para:
Parabéns, você adicionou o Firebase com sucesso ao seu aplicativo!
para todos os três aplicativos, como eu os iniciei um a um em um emulador.