使用AppVeyor CI 和PowerShell部署应用

开头语

\

关于如何为单一的ASP.NET web应用程序设置持续集成,你可以找到很多文章。这些文章都写到如何通过Web Deploy来构建完美的环境来部署简单、只需稍作修改VS.NET模板的web应用程序。任何东西在这一完美环境下都能顺利进行。

\

但是,真正部署应用程序的话却并非易事。总是有问题不断出现在以下情况中:当需要在注册表(Registry)或自定义文件夹中配置设置,或者你需要部署到Web集群时。

\

本文中,我们通过使用PowerShell远程处理(PowerShell remoting)和AppVeyor CI为带有ASP.NET web应用程序和Windows Service的解决方案在其暂存(staging)和产品环境中配置持续集成。

\

解决方案概述

\

我们的示例中包含4个项目:

\
  • DemoApp.Web -ASP.NET应用程序,前端\
  • DemoApp.Web.Tests -使用VisualStudio测试框架的web应用程序单元测试\
  • DemoApp.Service -承载WCF服务的Windows service,后端\
  • DemoApp.Service.Tests -使用NUnit框架的Windows service单元测试\

0200337e98078896224fb83e5ca08aa6.png

\

该示例应用程序的代码库托管于BitBucket

\

我们到底将如何部署?

\

我们遇到的第一个问题就是如何部署Windows service?我们没有针对Windows service的“发布”菜单,也没有相应的配置转换。根本没法用Web Deploy。为了自动化项目的部署,我们将使用PowerShell部署框架 - AppRolla。

\

AppRolla利用PowerShell远程处理在目标机器上执行部署任务。部署任务将下载应用程序包,解包,更新配置设置,然后创建或更新应用程序网站及pool。该应用程序包仅仅是带有应用程序文件夹的压缩包,通过HTTP上传到外部存储。其内部并没有任何特别之处 - 模块写在PowerShell内,很容易查看和修改。

\

为了让你对PowerShell部署一睹为快,我们现在就建立一个简单web应用程序,并将其部署到服务器上。

\

整个流程中最具挑战性的部分可能就是设置带有SSL认证的PowerShell远程处理了。我们强烈建议使用HTTPS与远程服务器进行通信,因为所有的数据流量都是加密的。

\

当你在Windows Azure 上创建新的虚拟机时,PowerShell远程会自动被激活和配置。防火墙将允许PowerShell远程HTTPS端点端口5986,另外我们也将HTTP端点添加到示例服务器上:

\

5fe300a9cbae074e7a6a2b8f87748e4e.png

\

如果你需设置其它服务,可以参照该链接里的具体细节:guide on how to configure PowerShell remoting。

\

为了在实例机器上快速安装IIS7.5,我们使用以下PowerShell命令:

\

Add-WindowsFeature -Name Web-Default-Doc,Web-Dir-Browsing,Web-Http-Errors,Web-Static-Content,Web-Http-Logging,Web-Stat-Compression,Web-Filtering,Web-Net-Ext,Web-Net-Ext45,Web-Asp-Net,Web-Asp-Net45,Web-ISAPI-Ext,Web-Mgmt-Console

\

我们创建带有“Hello world”的简单Web应用程序,然后将其部署到示例服务器。

\

924cfd878d8bcd5e8c12b21b714a8324.png

\

创建一个新的SimpleWebApp-1.0.zip压缩包,将带有第一版本的default.aspx存档起来。

\

现在,我们需要将该应用程序压缩包上传到外部存储,这样目标服务器就能通过HTTP来对其访问。该服务器可以是启用了FTP的web服务器,Amazon S3或Azure blob存储。对于该示例,我们使用DropBox。它为DropBox文件夹下所有项目提供公共的下载链接。

\

将该SimpleWebApp-1.0.zip拷贝到你的DropBox文件夹中,然后右击文件夹,选择“Share DropBox link”。在浏览器中打开该链接,然后拷贝“Download”键的URL。

\

fb5c3b3760a8589d133de614eda433f5.png

\

打开PowerShell的控制台“As administrator”,将执行政策(execution policy)改成为允许远程PowerShell脚本:

\
\Set-ExecutionPolicy RemoteSigned
\

安装AppRolla.psl模块(将被安装到用户配置文件中):

\
\(new-object Net.WebClient).DownloadString(\"https://raw.github.com/AppVeyor/AppRolla/master/install.ps1\") | iex
\

将AppRolla模块导入到当前会话中:

\
\Import-Module AppRolla
\

AppRolla有两组cmdlets:配置和部署。通过配置cmdlets定义应用程序和环境。

\

紧接着,添加新的“SimpleWebApp”应用程序,该应用程序只带有单一的“website”角色:

\
\New-Application SimpleWebApp
\

Add-WebsiteRole SimpleWebApp Web -PackageURL \"\u0026lt;your-dropbox-download-link\u0026gt;\"

\

在服务器上定义“示例”环境(在提示出现后,输入示例服务器的管理员证明 - 后面将有详细讲解):

\
\New-Environment demo
\

Add-EnvironmentServer demo \"appveyor-demo.cloudapp.net\" -Credential (Get-Credential)

\

将“SimpleWebApp”应用程序作为版本1.0部署到“示例”环境上:

\
\New-Deployment SimpleWebApp 1.0 -to demo
\

56bc2df0b2c41357acb278390b68b202.jpg

\\

(点击图片放大)

\\

就这样!你已经通过PowerShell将你的Web应用程序发布到示例服务器上了:

\

d157ca8e64bec5fc9eda2380652cf58d.png

\

现在,我们修改一下页面内容,然后部署一个新的示例应用程序版本。我们将“Hello,World!”改成“Hello, world2.0!”。随后,创建新的SimpleWebApp-1.1.zip文件将修改好的default.aspx文件存档,再次上传到DropBox。

\

更新“website”角色,将其压缩包的URL修改为新的值:

\
\Set-WebsiteRole SimpleWebApp Web -PackageUrl \u0026lt;public-URL-of-SimpleWebApp-1.1\u0026gt;
\

然后部署新版本1.1:

\
\New-Deployment SimpleWebApp 1.1 -to demo
\

df815788fa35edf591cb52dbd575ca42.png

\

从日志可以看出,每次部署都会在本地:\\applications\\\u0026lt;application-name\u0026gt;\\\u0026lt;role-name\u0026gt;\\\u0026lt;version\u0026gt;中生成新的文件夹。默认情况下,目标服务器上可以保留5个部署版本,因此应用程序可以很容易地回滚到上一版本:

\
\Restore-Deployment SimpleWebApp -on demo
\

从示例环境中删除所有应用程序部署:

\
\Remove-Deployment SimpleWebApp -from demo
\

整个过程,我们都使用简单且简洁的命令来完成所有工作!

\

使用AppVeyor CI持续构建

\\\

AppVeyor CI是为Windows开发人员设计的基于云的持续集成和部署平台。它有自己的服务器,因此不需要安装或配置。就算需要,配置起来也非常简单。另外,AppVeyor CI对开源项目是免费的。

\

为了在AppVeyor CI中设置工程,其代码源必须托管于在线源代码控制库上,比如:GitHub、BitBucket或Kiln。它支持Git和Mercurial。

\

在我们示例中,我们使用托管于BitBucket的Mercurial库。对商业项目来说,BitBucket相当实用,它免费地提供无限制的私有库。

\

启用NuGet存储

\

如果你的解决方案依赖于NuGet管理包,不要忘了启用NuGet restore来自动下载构建服务器上的各种程序包。可以使用如何启用NuGe包存储这一指导来确保在.Nuget文件夹中的NuGet.exe已经添加到库里了。

\

添加新项目

\

我们可以先从创建新项目开始:

\

f14ac8660cd2c278a9c246f0ad52ea11.png

\

一旦新项目建成,新的web hook就会自动添加到项目库中,为新构建拉开序幕。

\

构建配置和配置交换

\

当通过Web Deploy部署时,配置交换在应用程序配置过程中是一个关键。对于每个需要部署的环境,都需定义新的VS.NET解决方案配置,然后使用配置转换生成web.config,它带有数据库链接字符及其它应用程序针对每个环境特定的设置。该方法看起来可行,却有一系列问题:

\

• 类似数据库链接字符这样的敏感数据存储于源代码控制中。

\

• 配置转换应用于构建过程,每当项目部署到新环境中,都需要重新构建配置转换。

\

当用AppVeyor部署时,配置转换非常有用,但并非是必需的。默认情况下,VS会产生两种配置:Debug和Release,大多数情况下,这种形式完全OK。Debug配置用于本地开发,而Release配置则用于CI流程生成可以部署到任何环境的包。配置转换应该“真正地”用于转换配置文件结构,比如:禁用“Debug”标识;启用自定义错误;或启用Autofac更换模式等适用于所有环境的常见设置。

\

我们现在就可以开始改变Release设置页面中的项目构建配置:

\

a01342abb3405ca15193af1bb2c64b53.png

\

AppVeyor提供三种构建方案:

\
  • Visual Studio方案 - 运行MSBuild于VS.NET解决方案或工程文件(如果没有指定,首先查找第一个.sln或.*proj文件),还有将所有项目构建结果以工件形式打包。\
  • MSBuild - 根据自己的规定运行MSBuild,允许在“Packaging”页面上定义自定义的构建工件。\
  • Script - 运行特定PowerShell脚本或批文件。为管理构建流程及其结果提供最大化的自由。\

组件版本

\

每个新项目构建都会收到新的版本号,该版本号的格式规定于“General”页面下。

\

AppVeyor默认提供Windows style versioning(major.minor.{build}.revision),但是你也可以运用其它任意版本风格,比如:SemVer(major.minor.patch.{build})。

\

当启用“Update assembly version attributes”时,AppVeyor会将解决方案目录下的所有AssemblyInfo.*文件设置成当前版本。

\

执行测试

\

AppVeyor能通过以下这些测试框架,在assembly中发现和运行测试:

\
  • MSTest\
  • NUnit\
  • xUnit\

当“测试”步骤被启动时,AppVeyor会分析“out”文档中所有的assembly,来确认它们对所支持的测试框架是否含有相应的引用。如果有,那么所有assembly内的测试将会在相应的测试执行器中运行一遍。所有assembly的测试结果也会集合显示在UI上。

\

(点击图片放大)

\

92fc59d4f3ac94cf91360f80846b3599.jpg

\

构建.测试.打包!

\

我们现在开始创建新构建,可以对项目库进行修改或点击“New Build”。

\

该模拟项目的构建流程会生产两个构建工件:web application和Windows service。将它们下载下来,你会发现其内容就是带有应用文件的常规压缩文档。

\

由于Windows service包基本上就是其“Bin”文件夹下用于生成web应用包的内容中还需包含的一些步骤:

\
  1. Web应用应是解决方案的一部分。\
  2. 创建应用了“file system”发布方法的新发布配置文件,并发布了使用MSBuild的WAP项目,该配置文件用来确保web.config修改以及其它发布设置的执行。\
  3. 将发布的web应用打包为一压缩文件。\

构建工件将存储于Geo-redundant云存储中,能通过其独有的专属链接下载。如果想有自己专有的构建工件命名结构,以及允许公共访问的话,可以配置专有存储空间。

\

成功部署到预生产环境

\

我们现在开始往staging上配置自动化部署,作为该构建流程的一部分。

\

该部署应脚本的形式来完成,可以是PowerShell或批处理文件。在项目库的根部创建“部署”文件夹以放置部署脚本。

\

打开PowerShell命令行,跳转到“部署”文件夹,并执行以下命令下载模板脚本到现有目录:

\
\(new-object Net.WebClient).DownloadString(\"https://raw.github.com/AppVeyor/Deployment/master/install.ps1\") | iex
\

会有三个脚本被添加:configure.ps1、 project.ps1 和deploy.ps1。

\

总的说来,我们只需要编辑一个文件就能配置部署:project.psl。该文件定义了我们将要部署的环境。将删除紧接着新staging环境那一行的备注,然后添加模拟服务器:

\
\New-Environment Staging \Add-EnvironmentServer Staging “appveyor-demo.cloudapp.net”
\

返回到AppVeyor CI,打开项目设置的“Deployment”页面。

\

选择“Run deployment script”,并指定脚本路径:

\
\deployment\\deploy.ps1
\

设置以下部署变量:

\
\Environment: Staging   \ServerUsername:    \ServerPassword:    \ApiAccessKey:   \ApiSecretKey: 
\

d215bd9b6c2796d24fcf963d4273ebd2.png

\

ServerUsername和Password用来创建Credential对象以验证PowerShell的远程调用。以下两种情况要求到API关键字:a)阅读项目工件获取项目包的URL;b)验证目标服务器下载工件包。AppVeyor API关键字可以在用户配置的“API Keys”页面下找到。

\

就这样。接着只要提交“deployment”文件夹,将其推送到项目库就可以开始该部署的新构建了。

\

如何更新web.config的链接字符?

\

部署变量通过$variables参数以哈希表形式传递到脚本中。对于项目或角色,如果想启用附加的配置变量,可以在Set-Application, Set-WebsiteRole或Set-ServiceRole cmdlets中使用“Configuration”参数。打开project.ps1,并添加以下语句:

\
\Set-WebsiteRole $projectName DemoApp.Web -Configuration @{   \    “ConnectionStrings.DefaultConnection” = $variables.DefaultConnection   \}
\

}

\

然后在部署设置页面上定义“DefaultConnection”变量,用于web应用的链接字符的传递。部署脚本通过web.config为web应用程序应用了角色配置,对Windows应用程序,则通过app.config,运用了以下这些规则:

\
  • Setting with name “ConnectionStrings.\u0026lt;name\u0026gt;” updates connection string with \u0026lt;name\u0026gt; name in “connectionStrings”section.\
  • Setting with name “AppSettings.\u0026lt;name\u0026gt;” updates “AppSettings” value with \u0026lt;name\u0026gt; name.\

总结

\

本文中,我并非试图去低估或淡化其它的Web部署工具,它们可能在你的web应用中得到了很好的应用。但是,如果你的项目已经超出模板化的web应用,而必须部署到集群环境中或你需要更复杂,或对部署流程更多控制的话,那么绝对值得考虑像PowerShell remoting这样替代的解决方案。这对于具有PowerShell技能或使用PSake的开发人员来说,将会特别具有吸引力。

\

关于作者

\

Feodor Fitsner是个具有创业精神的.NET开发人员,他接触Windows Web平台已超过10年。Feodor最新项目就是Appveyor CI:专为.NET开发人员设计的主机型持续集成解决方案。在AppVeyor之前,Feodor针对Windows主机开发了DotNetPanel控制面板,之后就职于Microsoft的Azure 部门。

\

参考英文原文:Deploying it right with AppVeyor CI and PowerShell

\

感谢陈菲对本文的审校。

\

给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ)或者腾讯微博(@InfoQ)关注我们,并与我们的编辑和其他读者朋友交流。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值