写点什么

使用 AppVeyor CI 和 PowerShell 部署应用

  • 2014-03-24
  • 本文字数:5279 字

    阅读完需:约 17 分钟

开头语

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

该示例应用程序的代码库托管于 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 端点添加到示例服务器上:

如果你需设置其它服务,可以参照该链接里的具体细节: 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

Add-WebsiteRole SimpleWebApp Web -PackageURL “

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

复制代码
New-Environment demo

Add-EnvironmentServer demo “appveyor-demo.cloudapp.net” -Credential (Get-Credential)

将“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\\\中生成新的文件夹。默认情况下,目标服务器上可以保留 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,它带有数据库链接字符及其它应用程序针对每个环境特定的设置。该方法看起来可行,却有一系列问题:

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

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

当用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 应用包的内容中还需包含的一些步骤:

  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 Stagingappveyor-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.” updates connection string with name in “connectionStrings”section.
  • Setting with name “AppSettings.” updates “AppSettings” value with 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 )关注我们,并与我们的编辑和其他读者朋友交流。

2014-03-24 03:167162
用户头像

发布了 39 篇内容, 共 13.4 次阅读, 收获喜欢 2 次。

关注

评论

发布
暂无评论
发现更多内容

问题代码定位神器: Git Bisect

俞凡

git

【Redis技术专区】「优化案例」谈谈使用Redis慢查询日志以及Redis慢查询分析指南

洛神灬殇

redis 性能调优 慢查询

会声会影2023和谐版本补丁包下载

茶色酒

会声会影 会声会影2023

我总结了写出高质量代码的12条建议

JAVA旭阳

Java

GLM国产大模型训练加速:性能最高提升3倍,显存节省1/3,低成本上手

OneFlow

人工智能 深度学习

精华推荐 | 【深入浅出 RocketMQ原理及实战】「底层源码挖掘系列」透彻剖析贯穿RocketMQ的消费者端的运行核心的流程(上篇)

洛神灬殇

RocketMQ 消息队列 原理分析

影响产品开发决策的认知偏见

俞凡

认知

设计微博系统中”微博评论“的高性能高可用计算架构

悟空

架构 高可用 高性能 微博评论

如何判断候选人与岗位的匹配程度?

石云升

极客时间 1月月更 技术领导力实战笔记

【PHP】英文博客专栏PHP快速入门个人笔记

懒时小窝

php

极客时间运维进阶训练营第12周作业

独钓寒江

模块六作业

Ryan

架构

你知道这个提高 Java 单元测试效率的 IDEA 插件吗

JAVA旭阳

Java

企业架构治理指什么,如何做?

涛哥 数字产品和业务架构

架构治理 企业构架

IntelliJ中高效重构的 10 个快捷方式

JAVA旭阳

Java

关于环境变量配置的思考总结

timerring

Go 环境变量

FPGA:硬件描述语言简介

timerring

FPGA

我们需要怎样的低代码平台

agnostic

低代码

如何用Know Streaming来查询Kafka的消息

石臻臻的杂货铺

Kafk

技术管理者如何获得下属的认同?

石云升

极客时间 1月月更 技术领导力实战笔记

FPGA:逻辑功能的仿真与验证

timerring

FPGA

Verilog HDL仿真常用命令

timerring

FPGA

模块5 微博高性能计算架构设计

KING

从任务分配角度来看管理

石云升

极客时间 1月月更 技术领导力实战笔记

【腾讯云AI】用1行Python代码识别增值税发票,YYDS

程序员晚枫

Python 人工智能 发票 OCR

CleanMyMac X2024版本值不值得买?

茶色酒

CleanMyMac X CleanMyMac X2023

复习前端:浏览器渲染机制

devpoint

DOM CSSOM 渲染树 重绘 重排

复习前端:前端应掌握的网络知识

devpoint

OSI七层协议 http2 HTTPS协议加密

OneFlow v0.9.0正式发布

OneFlow

人工智能 深度学习

FPGA:Verilog HDL程序的基本结构

timerring

FPGA

如何妥善且优雅地做好解聘工作?

石云升

极客时间 1月月更 技术领导力实战笔记

使用AppVeyor CI 和PowerShell部署应用_DevOps & 平台工程_Feodor Fitsner_InfoQ精选文章