源代码管理 (使用 Azure) 生成 Real-World 云应用
作者 :Rick Anderson, Tom Dykstra
使用 Azure 构建真实世界云应用 电子书基于 Scott Guthrie 开发的演示文稿。 本文介绍了 13 种模式和做法,可帮助你成功开发适用于云的 Web 应用。 有关电子书的信息,请参阅 第一章。
源代码管理对于所有云开发项目至关重要,而不仅仅是团队环境。 你不会考虑在没有撤消函数和自动备份的情况下编辑源代码甚至Word文档,而源代码管理在项目级别提供这些功能,当出现问题时,它们可以节省更多时间。 使用云源代码管理服务,你再也不必担心复杂的设置,最多 5 个用户可以使用Azure Repos源代码管理。
本章的第一部分介绍了要记住的三个关键最佳做法:
- 将自动化脚本视为源代码 ,并将其与应用程序代码一起进行版本控制。
- 切勿将机密 (敏感数据(例如凭据)检查) 源代码存储库。
- 设置源分支 以启用 DevOps 工作流。
本章的其余部分提供了 Visual Studio、Azure 和 Azure Repos 中这些模式的一些示例实现:
将自动化脚本视为源代码
处理云项目时,会频繁更改内容,并希望能够快速响应客户报告的问题。 快速响应涉及使用自动化脚本,如 自动化一切 一章中所述。 用于创建环境、部署到环境、缩放环境等的所有脚本都需要与应用程序源代码同步。
若要使脚本与代码保持同步,请将它们存储在源代码管理系统中。 然后,如果需要回滚更改或快速修复与开发代码不同的生产代码,则不必浪费时间尝试跟踪哪些设置已更改或哪些团队成员拥有所需版本的副本。 可以放心,所需的脚本与所需的代码库同步,并保证所有团队成员都在使用相同的脚本。 然后,无论你是需要自动测试和部署生产还是新功能开发的热修补程序,你都将为需要更新的代码创建正确的脚本。
请勿在机密中检查
源代码存储库通常可供太多人访问,因此它不能成为敏感数据(如密码)的适当安全位置。 如果脚本依赖于密码等机密,请参数化这些设置,以便它们不会保存在源代码中,并将机密存储在其他位置。
例如,Azure 允许下载包含发布设置的文件,以便自动创建发布配置文件。 这些文件包括有权管理 Azure 服务的用户名和密码。 如果使用此方法创建发布配置文件,并且检查这些文件进行源代码管理,则有权访问存储库的任何人都可以看到这些用户名和密码。 你可以安全地将密码存储在发布配置文件本身中,因为它已加密,并且它位于默认情况下未包含在源代码管理中的 .pubxml.user 文件中。
构建源分支以简化 DevOps 工作流
在存储库中实现分支的方式会影响开发新功能和修复生产中问题的能力。 下面是许多中型团队使用的模式:
main分支始终与生产中的代码匹配。 main下的分支对应于开发生命周期中的不同阶段。 可在开发分支中实现新功能。 对于小型团队,你可能只有main和开发,但我们通常建议人们在开发和main之间具有过渡分支。 在将更新移动到生产环境之前,可以使用过渡进行最终集成测试。
对于大型团队,每个新功能可能都有单独的分支:对于较小的团队,你可能让每个人都签入开发分支。
如果每个功能都有一个分支,则当功能 A 准备就绪时,将其源代码更改合并到开发分支中,向下合并到其他功能分支。 此源代码合并过程可能非常耗时,为了避免在功能保持独立的同时工作,一些团队实现了一种称为 功能切换 (也称为 功能标志) 的替代方法。 这意味着所有功能的所有代码都位于同一分支中,但你可以使用代码中的开关启用或禁用每个功能。 例如,假设功能 A 是修复 It 应用任务的新字段,而功能 B 添加了缓存功能。 这两个功能的代码都可以在开发分支中,但仅当变量设置为 true 时,应用才会显示新字段,并且仅当其他变量设置为 true 时才使用缓存。 如果功能 A 尚未准备好升级,但功能 B 已准备就绪,则可以在关闭功能 A 并打开功能 B 的情况下,将所有代码提升到生产环境。 然后,你可以完成功能 A 并在以后升级它,而无需合并源代码。
无论是否对功能使用分支或切换,此类分支结构都使你能够以敏捷且可重复的方式将代码从开发流向生产环境。
此结构还使你能够快速响应客户反馈。 如果需要对生产进行快速修复,还可以以敏捷的方式高效执行此操作。 可以在main或暂存中创建分支,并在它准备就绪时将其合并到main向下合并到开发和功能分支中。
如果没有这样的分支结构以及生产和开发分支的分离,生产问题可能会使你不得不在生产修复的同时推广新功能代码。 新功能代码可能尚未经过全面测试,尚未准备好投入生产,可能需要执行大量工作来备份尚未准备好的更改。 或者,为了测试更改并准备好部署更改,可能需要延迟修复程序。
接下来,你将看到如何在 Visual Studio、Azure 和 Azure Repos 中实现这三种模式的示例。 这些是示例,而不是详细的分步操作说明;有关提供所有必要上下文的详细说明,请参阅本章末尾的 “资源” 部分。
在 Visual Studio 中将脚本添加到源代码管理
可以将脚本添加到 Visual Studio 中的源代码管理,方法是将其包含在 Visual Studio 解决方案文件夹中, (假设项目位于源代码管理) 中。 下面是执行此操作的一种方法。
在解决方案文件夹中为脚本创建一个文件夹, () .sln 文件的同一文件夹。
将脚本文件复制到 文件夹中。
在 Visual Studio 中,向项目添加解决方案文件夹。
并将脚本文件添加到解决方案文件夹。
脚本文件现在包含在项目中,源代码管理将跟踪其版本更改以及相应的源代码更改。
在 Azure 中存储敏感数据
如果在 Azure 网站中运行应用程序,避免在源代码管理中存储凭据的一种方法是将凭据存储在 Azure 中。
例如,Fix It 应用程序在其Web.config文件中存储两个连接字符串,这些连接字符串在生产环境中具有密码,以及一个允许访问 Azure 存储帐户的密钥。
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\MyFixItMembership.mdf;Initial Catalog=MyFixItMembership;Integrated Security=True" providerName="System.Data.SqlClient" />
<add name="appdb" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\MyFixItTasks.mdf;Initial Catalog=aspnet-MyFixItTasks;Integrated Security=True" providerName="System.Data.SqlClient" />
</connectionStrings>
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
<add key="StorageAccountName" value="fixitdemostorage" />
<add key="StorageAccountAccessKey" value="[accesskeyvalue]" />
</appSettings>
如果将这些设置的实际生产值放入 Web.config 文件中,或者将其放入 Web.Release.config 文件中以配置Web.config转换以在部署期间插入这些值,则它们将存储在源存储库中。 如果在生产发布配置文件中输入数据库连接字符串,密码将位于 .pubxml 文件中。 (可以从源代码管理中排除 .pubxml 文件,但随后将失去共享所有其他部署设置的好处。)
Azure 为 Web.config 文件的 appSettings 和连接字符串部分提供了替代项。 下面是 Azure 管理门户中网站的 “配置 ”选项卡的相关部分:
将项目部署到此网站并运行应用程序时,在 Azure 中存储的任何值都会覆盖 Web.config 文件中的任何值。
可以使用管理门户或脚本在 Azure 中设置这些值。 在“自动化一切”一章中看到的环境创建自动化脚本创建Azure SQL数据库、获取存储和SQL 数据库连接字符串,并将这些机密存储在网站的设置中。
# Configure app settings for storage account and New Relic
$appSettings = @{ `
"StorageAccountName" = $storageAccountName; `
"StorageAccountAccessKey" = $storage.AccessKey; `
"COR_ENABLE_PROFILING" = "1"; `
"COR_PROFILER" = "{71DA0A04-7777-4EC6-9643-7D28B46A8A41}"; `
"COR_PROFILER_PATH" = "C:\Home\site\wwwroot\newrelic\NewRelic.Profiler.dll"; `
"NEWRELIC_HOME" = "C:\Home\site\wwwroot\newrelic" `
}
# Configure connection strings for appdb and ASP.NET member db
$connectionStrings = ( `
@{Name = $sqlAppDatabaseName; Type = "SQLAzure"; ConnectionString = $sql.AppDatabase.ConnectionString}, `
@{Name = "DefaultConnection"; Type = "SQLAzure"; ConnectionString = $sql.MemberDatabase.ConnectionString}
)
请注意,脚本已参数化,因此不会将实际值保存到源存储库。
在开发环境中本地运行时,应用会读取本地Web.config文件,并且连接字符串指向 Web 项目的 App_Data 文件夹中的 LocalDB SQL Server 数据库。 在 Azure 中运行应用并且应用尝试从 Web.config 文件中读取这些值时,它返回和使用的值是网站存储的值,而不是Web.config文件中实际存储的值。
在 Visual Studio 和 Azure DevOps 中使用 Git
可以使用任何源代码管理环境来实现前面介绍的 DevOps 分支结构。 对于分布式团队, 分布式版本控制系统 (DVCS) 可能效果最好:对于其他团队, 集中式系统 可能效果更好。
Git 是一种常用的分布式版本控制系统。 使用 Git 进行源代码管理时,你在本地计算机上拥有存储库的完整副本及其所有历史记录。 许多人更喜欢这样做,因为当你未连接到网络时,可以更轻松地继续工作-你可以继续执行提交和回滚,创建和切换分支,等等。 即使已连接到网络,在一切为本地时,创建分支和切换分支也更容易、更快速。 还可以执行本地提交和回滚,而不会对其他开发人员产生影响。 可以在将提交内容发送到服务器之前进行批处理提交。
Azure Repos提供 Git 和 Team Foundation 版本控制 (TFVC;集中式源代码管理) 。 在此处开始使用 Azure DevOps。
Visual Studio 2017 包括内置的一流 Git 支持。 下面是其工作原理的快速演示。
在 Visual Studio 中打开项目后,在 解决方案资源管理器 中右键单击该解决方案,然后选择“将解决方案添加到源代码管理”。
Visual Studio 询问是否要使用 TFVC (集中式版本控制) 还是 Git。
选择“Git”并单击“ 确定”时,Visual Studio 会在解决方案文件夹中创建新的本地 Git 存储库。 新存储库尚未包含任何文件;必须通过执行 Git 提交将它们添加到存储库。 右键单击解决方案资源管理器中的解决方案,然后单击“提交”。
Visual Studio 自动暂存提交的所有项目文件,并在“包含的更改”窗格的团队资源管理器中列出这些文件。 (如果提交中不希望包含某些内容,则可以选择它们,右键单击,然后单击“ 排除”。)
输入提交注释并单击“提交”,Visual Studio 将执行提交并显示提交 ID。
现在,如果更改某些代码,使其与存储库中的代码不同,可以轻松查看差异。 右键单击已更改的文件,选择“ 与未修改的比较”,然后会显示显示未提交的更改的比较显示。
可以轻松查看正在进行的更改并检查。
假设需要创建分支 - 你也可以在 Visual Studio 中执行此操作。 在 “团队资源管理器”中,单击“ 新建分支”。
输入分支名称,单击“ 创建分支”,如果选择了 “签出分支”,Visual Studio 会自动签出新分支。
现在可以对文件进行更改,并将其检查到此分支。 并且可以轻松地在分支之间切换,Visual Studio 会自动将文件同步到已签出的分支。在此示例中, _Layout.cshtml 中的网页标题已更改为 HotFix1 分支中的“热修复 1”。
如果切换回 main 分支,_Layout.cshtml 文件的内容将自动还原到它们在 main 分支中的内容。
这是一个简单的示例,说明如何快速创建分支并在分支之间来回翻转。 此功能使用自动化 一切一章 中介绍的分支结构和自动化脚本实现高度敏捷的工作流。 例如,可以在开发分支中工作,从main创建热修复分支,切换到新分支,在那里进行更改并提交,然后切换回开发分支并继续执行操作。
你在此处看到的是在 Visual Studio 中使用本地 Git 存储库的方式。 在团队环境中,通常还会将更改推送到通用存储库。 Visual Studio 工具还允许你指向远程 Git 存储库。 可以使用 GitHub.com 实现此目的,也可以使用 Git 和Azure Repos与所有其他 Azure DevOps 功能(如工作项和 bug 跟踪)集成。
当然,这不是实现敏捷分支策略的唯一方法。 可以使用集中式源代码管理存储库启用相同的敏捷工作流。
总结
根据做出更改并使其以安全且可预测的方式运行的速度来衡量源代码管理系统的成功程度。 如果你发现自己害怕进行更改,因为必须对其进行一两天的手动测试,你可能会问自己,你必须在过程或测试方面执行哪些操作,以便在几分钟内或最坏的情况下不超过一小时。 这样做的一个策略是实现持续集成和持续交付,我们将在 下一章中介绍。
资源
有关分支策略的详细信息,请参阅以下资源:
- 使用 Team Foundation Server 2012 生成发布管道。 Microsoft 模式和做法文档。 有关分支策略的讨论,请参阅第 6 章。 支持功能分支上的功能切换,如果使用功能的分支,则主张在最多) (小时或天数保持短生存期。
- 版本控制指南。 ALM Rangers 分支策略指南。 请参阅“下载”选项卡上的“分支Strategies.pdf”。
- 使用功能切换进行软件开发。 MSDN 杂志文章。
- 功能切换。 Martin Fowler 博客上的功能切换/功能标志简介。
- 功能切换与功能分支。 另一篇关于功能切换的博客文章,作者:Dylan Smith。
有关如何处理不应保留在源代码管理存储库中的敏感信息的详细信息,请参阅以下资源:
- 将密码和其他敏感数据部署到 ASP.NET 和Azure 应用服务的最佳做法。
- Azure 网站:应用程序字符串和连接字符串的工作原理。 介绍替代
appSettings
connectionStrings
Web.config 文件中数据的 Azure 功能。 - Azure 网站中的自定义配置和应用程序设置 - 使用 Stefan Schackow。
有关将敏感信息排除在源代码管理之外的其他方法的信息,请参阅 ASP.NET MVC:使专用设置远离源代码管理。