首先,将所有配置选项移动到一个(或多个)配置文件中。使用与语言无关的格式,例如 JSON 或 YAML。
将配置文件/目录放在源代码树的顶部,便于查找。
范围是维护单个存储库并为不同的实例提供不同的分支。
单一的回购是好的。不同的分支不是。管理许多长期存在的分支机构迅速变得复杂。
取而代之的是一个长寿的分支,可能是master
. 使用功能分支来隔离开发并在允许它们合并到master
. 这条路master
随时可以走。直接从 部署master
。
这就是它的样子。每个字母都是一个提交。每个[branch]
都是一个分支头。
I - J L - M - N [feature1]
/ \ /
A - B - C ----- F - G ----- K [master]
\ / \
D - E O - P [feature2]
这显示了两个已完成的功能,D - E
并且I - J
已经通过了 QA 并被合并到master
. 由于 QA 已经在功能分支上完成,因此master
已部署到生产环境中。有两个开放的功能分支,每个分支都会定期运行git rebase master
,因此它们是最新的、经过全面测试的代码。
请注意,没有直接提交master
,它仅通过功能分支合并进行更改。这意味着master
始终经过测试、可靠且随时可以部署。正在进行中的各个功能不会相互干扰,并且可以依赖于稳定的master
分支;如果出现问题,他们知道这是因为他们的工作,而不是因为有人破坏了开发分支。
但是不同的配置呢?
对于每个分支,该文件显然会有所不同,并且该文件不会在分支中更改。
相同的配置文件在不同的分支中不同是一种很好的方式来产生冲突,人们会不小心用测试和开发信息覆盖配置。
拥有一组配置文件更简单,其中包含所有不同上下文的配置,以及它们共享的默认值。
例如,您的数据库配置在YAML中可能如下所示。
default: &default
adapter: postgresql
encoding: unicode
username: postgres
development:
<<: *default
database: myapp_development
host: localhost
test:
<<: *default
database: myapp_test
host: localhost
production: &production
<<: *default
host: our.production.server
username: production_db_user
client1:
<<: *production
database: client1
client2:
<<: *production
database: client2
这使用YAML 锚点和别名来进行覆盖,<<: *default
表示包含标记为 的节点&default
。这消除了各种上下文之间的大量冗余。
让您的应用从环境变量中选择环境,或从上下文中猜测。
这就是 Rails 的做法,多个配置文件,每个文件都有每个上下文的配置部分。
下一步是从源代码中取出生产机密并将它们放入环境变量中。秘密是诸如密码和 API 密钥之类的东西。然后,当您的生产系统启动时,它们会以设置的环境变量启动。这就是 Heroku 等云托管网站的做法。
或者,您可以在配置文件中硬编码生产机密,但要加密。然后通过环境变量提供解密密钥。这意味着您只需要一个用于生产的环境变量,如果您要迁移旧系统,这可能会更简单。这就是 TravisCI 的做法。
这可能是一堆工作,具体取决于您现有的系统和工作流程当前的设置方式,但这是一个非常成功的模式。