将Firebase开发环境和生产环境分离

269

我正在考虑使用Firebase作为MBaaS,但我找不到任何可靠的解决方案来解决以下问题:

我想设置两个独立的Firebase环境,一个用于开发,另一个用于生产,但我不想在开发和生产环境之间手动复制功能(例如远程配置设置、通知规则等)。

有没有工具或方法可以依赖?从头开始设置远程配置或通知规则可能是一项艰巨的任务,也太冒险了。

有什么建议吗?是否有比拥有两个独立环境更好的方法?

在你发表解释如何设置独立Firebase账户的答案之前,请再次阅读问题。问题是:如何在不同的开发和生产账户之间传输更改或其他方案优于手动复制。


14
作为一项功能,这将是很棒的! - Patrick Jackson
4
https://firebase.googleblog.com/2016/07/deploy-to-multiple-environments-with.html - Timmerz
@Timmerz 请看第一个答案:仅适用于托管和数据库,而不适用于其他功能。 - racs
1
@LOG_TAG 你创建一个全新的标签的原因是什么?这是否涉及到任何尚未被 [firebase] 覆盖的新技术? - Michael Dodd
@MichaelDodd #askfirebase 是谷歌 Firebase 开发者 QA 下更受欢迎的标签!为了获得更多问题的曝光度,我创建了这个标签,有任何反馈吗?https://twitter.com/search?q=%23askfirebase - LOG_TAG
显示剩余4条评论
12个回答

80
如果您正在使用firebase-tools,有一个命令firebase use,可以让您设置要用于firebase deploy的项目。 firebase use --add将列出您的项目列表,选择一个并询问您要使用的别名。之后,您可以使用firebase use alias命令,并且firebase deploy将推送到该项目。
在我的个人使用中,Firebase控制台中有my-app和my-app-dev作为项目。

2
据我所了解,Firebase工具对于部署托管文件和数据库非常有用,但它并不涉及数据库、分析或远程配置。或者我有什么误解吗? - racs
@racs,看起来这是最近的事情,但我将要开始尝试使用cli对我的开发实例进行数据播种/维护:https://firebase.googleblog.com/2015/11/the-firebase-cli-now-with-database_82.html - Chris
@Chris,感谢您告诉我们这件事。据我所知,这仍然是一个未解决的问题。 - racs
@Lunchbox,你是如何限制访问你的“my-app-dev”实例的呢?比如说,你是否指定哪些域名或用户可以访问你的页面? - Luke Becker
但这也意味着要付两次钱..? - ProblemsOfSumit
显示剩余5条评论

68

正如其他人所指出的一样,你需要不止一个项目/数据库。

但是回答你关于需要能够从开发环境复制设置/数据等到生产环境的问题。我也有同样的需求。在开发和测试了几个月后,我不想手动复制数据。

我的结果是将数据备份到存储桶中,然后从那里恢复到另一个数据库中。这是一种相当粗糙的方法 - 我做了整个数据库备份/还原 - 但您可能可以朝这个方向寻找更可控的方法。我没有使用过它 - 它非常新 - 但这可能是一个解决方案:NPM模块firestore-export-import

编辑:Firestore备份/导出/导入信息在这里:Cloud Firestore导出和导入数据

如果你正在使用Firebase RTDB而不是Firestore - 这份文档可能会有所帮助:Firebase自动备份

您需要正确设置权限,以允许您的生产数据库访问与开发相同的存储桶。祝好运。


3
谢谢,这是目前为止最好的答案。 - racs
8
针对拥有数千用户的任何项目,都需要将一些数据从生产数据库迁移到暂存或开发服务器。遗憾的是,Firebase并没有内置此项功能,但对于任何类型的项目来说,这都是需要完成的事情。 - user9903
我使用“在项目之间移动数据”的指南导入了数据库。但它创建的Firestore数据库是在Datastore模式下。我需要在Native模式下使用它。 - Debiprasad
2
除了“正如大家所指出的”之外,以下是有关编程的内容:https://firebase.google.com/docs/projects/dev-workflows/overview-environments和下一个站点一般最佳实践。 - Alexander Sidikov Pfeif
1
Firebase很棒,但它还有很长的路要走,它看起来像是一个测试版产品,缺少很多功能,感谢这个回答的点赞,尽管我对FB不太满意。 - guilherme victor ramalho natal

28

我目前没有使用Firebase,但像你一样正在考虑使用它。看起来最好的方法是在控制台上创建一个完全独立的项目。以前Firebase网站上有一篇博客文章建议这样做,不过现在看起来已经被删除了。https://web.archive.org/web/20160310115701/https://www.firebase.com/blog/2015-10-29-managing-development-environments.html

此外,还有这个讨论也建议同样的做法:https://groups.google.com/forum/#!msg/firebase-talk/L7ajIJoHPcA/7dsNUTDlyRYJ


3
谢谢您的回答。最可能的选择是拥有两个独立的项目。然而,在它们之间复制数据至少是一件复杂的事情。我想知道 Firebase 工具是否可以复制规则、受众设置等内容。它似乎只处理与数据库相关的操作:https://github.com/firebase/firebase-tools - racs
2
不确定你是否看过这个,但是你可以在 firebase-server 上运行你的开发:https://firebase.googleblog.com/2015/04/end-to-end-testing-with-firebase-server_16.html - krico
2
这正是我所做的,但问题是:如何在两个环境之间复制任何设置?例如远程配置、受众设置等。手动将它们添加到生产环境中容易出错。 - racs
2
我遇到的问题是使用相同的包和签名验证多个Firebase实例。控制台不允许您将相同的包sha1添加到多个项目中,因此这可能不可行。文档中说有一种通过将客户端ID列入白名单的解决方法,但我尝试过没有成功。另一个解决方法是使用不同的包名称(更准确地说是'applicationIds'),但这会带来其他复杂性。 - Patrick Jackson
3
此外,阅读以下内容: https://firebase.googleblog.com/2016/08/organizing-your-firebase-enabled-android-app-builds.html - racs
显示剩余4条评论

22

我的做法:

  1. 在Firebase上我有两个项目,一个是DEV,另一个是PROD
  2. 本地应用也有两个分支,一个名为DEV,另一个名为PROD
  3. 在DEV分支中,我始终拥有DEV Firebase项目的JSON文件,同样适用于PROD

这样我就不需要维护我的JSON文件。


2
我理解,但是根据最新的Firebase版本,没有通用的解决方案来回答这个问题。你需要尝试当前的选项并得出最佳实践。也许我的回答没有指向这一点,但我只是想从我的角度帮助提问者。 - Kunal Khaire

12

根据我刚找到的信息,我正在更新这个答案。

步骤1

在 firebase.google.com 上创建多个环境(例如:dev,staging,prod)


mysite-dev

mysite-staging

mysite-prod


步骤2

a. 移动到您想要成为默认环境的目录(例如:dev)

b. 运行 firebase deploy

c. 部署后,运行 firebase use --add

d. 将显示从当前拥有的不同项目中进行选择的选项。

滚动到要添加的项目:mysite-staging,然后选择它。

e. 然后会要求您为该项目输入别名。输入staging

再次为 prod 和 dev 运行 a-e 步骤,以便每个环境都有一个别名


了解您处于哪个环境

运行 firebase use default (mysite-dev)

* dev (mysite-dev)

staging (mysite-staging)

prod (mysite-dev)

(其中一个环境左侧将有一个星号。这是您当前所在的环境。它也将突出显示为蓝色)


在不同环境之间切换

运行 firebase use stagingfirebase use prod 以在它们之间移动。

一旦进入您想要的环境,请运行firebase deploy,您的项目将会在那里部署。

这里有几个有用的链接...

CLI参考

部署到多个环境

希望这能帮到您。


2
当你说多个环境时,你是指多个项目吗? - walidvb
我的意思是多个环境。请阅读此处的帖子以获得澄清。这就是标题。它涉及相同的项目,但在开发/质量保证和生产上。 - Millhorn
11
谢谢,我已经完整观看了这个视频。这意味着我明白他在不同的环境中使用不同的“项目”,而不是在同一个项目内使用专用的环境。 - walidvb
我不明白环境变量是如何使用的?只需一个命令切换到指定的 Firebase 应用程序是如何实现的? - undefined

12

你需要管理不同的构建类型

按照以下步骤

  1. 首先,在Firebase控制台上创建一个名为YOURAPPNAME-DEV的新项目

  2. 点击“添加Android应用程序”按钮并创建一个新的应用程序。例如,将其命名为com.yourapp.debug。新的google-services.json文件将自动下载

  3. 在您的项目src目录下创建名为“debug”的新目录,并将新的google-services.json文件复制到此处

  4. 在您的模块级build.gradle中添加以下内容

    debug {
            applicationIdSuffix ".debug"
        }
    
    现在,当您构建调试版本时,将使用“debug”文件夹中的google-services.json文件。而当您以发布模式构建时,则会考虑来自模块根目录的google-services.json文件。


1
如果有人需要官方文档,Google服务Gradle插件会在此处查找google-services.json,即在buildType的子目录下的src中,如此处所述:https://developers.google.com/android/guides/google-services-plugin#adding_the_json_file - Michael Osofsky

10

我表述不够清楚:您是否通过连接到模拟的 Firebase 主机来执行所有集成测试?那是否足够模拟真实服务? - racs
是的。除了CORS、安全和其他非功能问题外,我们看不到任何区别。 - belwood
谢谢,很高兴听到这个消息。我有机会的时候会尝试一下。听起来比设置一个单独的完整环境要好。 - racs
2
要小心假设模拟器是完全足够的测试环境。例如,模拟的Firestore不会为需要设置复合索引的查询抛出任何错误,而真实的Firestore(基于云的实例)会这样做。 - Jason Frank
1
请参阅:https://firebase.google.com/docs/emulator-suite/connect_firestore#how_the_emulator_differs_from_production - Jason Frank
显示剩余2条评论

8

这篇博客文章介绍了一种非常简单的方法来创建调试版本和发布版本。

简而言之:

  • 为每个构建类型创建一个新的Firebase应用程序,使用不同的应用程序ID后缀。
  • 将Android项目配置为使用最新的JSON文件。
  • 使用applicationIdSuffix,根据构建类型更改应用程序ID以匹配Firebase上不同的应用程序。

=>请参阅博客文章以获取详细说明。

如果您想要使用不同的构建品味,请阅读官方Firebase博客中这篇博客文章。 它包含了很多有价值的信息。

希望这可以帮到你!


谢谢你的回复。我已经能够设置不同的应用程序,但是我仍在寻找一种方法来从FB dev应用程序复制各种配置到FB prod应用程序,就像我在问题中提出的那样。(例如远程配置或受众设置。) - racs
3
请注意,这将在同一项目中创建两个应用程序,因此您将会分离某些服务(例如分析),但数据库将是共享的,因此并不是真正的环境分离,如此处所述:https://firebase.googleblog.com/2016/08/organizing-your-firebase-enabled-android-app-builds.html。 - AntPachon

6
为了解决我的问题,我创建了三个Firebase项目,每个项目都有相同的Android项目(即相同的applicationId,而不使用其他人建议的applicationIdSuffix)。这样就得到了三个google-services.json文件,我将它们存储在我的持续集成(CI)服务器上作为自定义环境变量。对于构建的每个阶段(开发/暂存/产品),我都使用相应的google-services.json文件。
对于与开发相关的Firebase项目,在其Android项目中,我添加了调试SHA证书指纹。但是对于暂存和产品,我只是让CI签署APK文件。
以下是一个简化的.gitlab-ci.yml,适用于此设置:
# 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
# https://stackoverflow.com/questions/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/

我对这种解决方案感到满意,因为它不依赖于我认为过于难以维护的build.gradle技巧。例如,当我尝试使用应用程序ID后缀和不同的构建类型时,我发现无法在切换构建类型时运行或编译插装测试。 Android似乎给予debug构建类型特殊属性,我无法进行检查以理解其含义。
相比之下,CI脚本非常透明且易于维护,根据我的经验来看。实际上,我描述的方法是可行的:当我在模拟器上运行CI生成的每个APK时,Firebase控制台中的“运行您的应用程序以验证安装”步骤从“检查应用程序是否已与我们的服务器通信。您可能需要卸载并重新安装您的应用程序。”变成了“恭喜您成功将Firebase添加到应用程序!”,当我一个接一个地启动它们时,针对所有三个应用程序都是如此。

感谢你提供的详细描述,Michael。我通过添加不同的flavor并将相应的google-services.json复制到每个flavor的文件夹下来实现了相同的结果。 然而,这并不是我的问题,请再次阅读我的问题。 - racs
我同意@racs,但不幸的是,当我写https://dev59.com/G1oU5IYBdhLWcg3wc2tW时,它被https://stackoverflow.com/users/807126/doug-stevenson标记为您的问题的重复。 - Michael Osofsky
2
道格...你干了什么!:D 我不介意你在这里的回答,我相信对于一些正在寻找分离环境解决方案的人来说,这是有帮助的。 - racs
1
是的,我们一直在寻找一个适用于我们移动应用程序的解决方案,需要使用 Firebase 服务来创建不同的环境。这绝对是我们的一个很好的起点。我们会尝试一下。 - L.T.

1
Firebase有一篇关于此的页面,介绍了如何为开发和生产环境进行设置。

https://firebase.google.com/docs/functions/config-env

Set environment configuration for your project To store environment data, you can use the firebase functions:config:set command in the Firebase CLI. Each key can be namespaced using periods to group related configuration together. Keep in mind that only lowercase characters are accepted in keys; uppercase characters are not allowed.

For instance, to store the Client ID and API key for "Some Service", you might run:

firebase functions:config:set someservice.key="THE API KEY" someservice.id="THE CLIENT ID"

Retrieve current environment configuration To inspect what's currently stored in environment config for your project, you can use firebase functions:config:get. It will output JSON something like this:

{
  "someservice": {
    "key":"THE API KEY",
    "id":"THE CLIENT ID"
  }
}

1
解析为404。下次记得同时包含内容! - CorayThan
这并没有提到如何分离开发和生产环境,它只是讲述了如何设置环境变量。是否有一种简单的方法可以在开发和生产环境之间轻松切换配置? - bze12

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接