求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
  
 
 
     
   
分享到
使用AppVeyor CI 和PowerShell部署应用
 
作者 Feodor Fitsner,火龙果软件    发布于 2014-04-01
 

关于如何为单一的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单元测试

 

我们到底将如何部署?

我们遇到的第一个问题就是如何部署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端点添加到示例服务器上:

 

如果你需设置其它服务,可以参照该链接里的具体细节: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应用程序,然后将其部署到示例服务器。

 

创建一个新的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。

 

打开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

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

New-Environment demo

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

New-Deployment SimpleWebApp 1.0 -to demo

 

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

 

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

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

Set-WebsiteRole SimpleWebApp Web -PackageUrl <public-URL-of-SimpleWebApp-1.1>

然后部署新版本1.1:

New-Deployment SimpleWebApp 1.1 -to demo

 

从日志可以看出,每次部署都会在本地:\applications\<application-name>\<role-name>\<version>中生成新的文件夹。默认情况下,目标服务器上可以保留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已经添加到库里了。

添加新项目

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

 

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

构建配置和配置交换

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

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

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

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

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

 

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上。

 

构建.测试.打包!

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

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

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

Web应用应是解决方案的一部分。

创建应用了“file system”发布方法的新发布配置文件,并发布了使用MSBuild的WAP项目,该配置文件用来确保web.config修改以及其它发布设置的执行。

将发布的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:

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.<name>” updates connection string with <name> name in “connectionStrings”section.
Setting with name “AppSettings.<name>” updates “AppSettings” value with <name> name.

总结

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

 
相关文章

云计算的架构
对云计算服务模型
云计算核心技术剖析
了解云计算的漏洞
 
相关文档

云计算简介
云计算简介与云安全
下一代网络计算--云计算
软浅析云计算
 
相关课程

云计算原理与应用
云计算应用与开发
CMMI体系与实践
基于CMMI标准的软件质量保证
 
分享到
 
 


专家视角看IT与架构
软件架构设计
面向服务体系架构和业务组件的思考
人人网移动开发架构
架构腐化之谜
谈平台即服务PaaS
更多...   
相关培训课程

云计算原理与应用
Windows Azure 云计算应用

摩托罗拉 云平台的构建与应用
通用公司GE Docker原理与实践
某研发中心 Openstack实践
知名电子公司 云平台架构与应用
某电力行业 基于云平台构建云服务
云计算与Windows Azure培训
北京 云计算原理与应用