利用 MSBuild 实现 Web Application 项目的每日构建(上)

原创 2007年10月06日 12:07:00

每日构建,对于这个术语,大家已是耳熟能详。不管项目有多大或有多小,我们都在潜意识的进行持续性构建,无非就是自动化和方便性的程度高低而已。

最近几年我主要开发基于 .NET 平台的应用软件,其中又以 B/S 架构为多。既然是在.NET平台上开发,我倾向于尽量使用此平台上的工具来做每日构建。经过几番查找和实验,发现以 MSBuild 为主、以基于 MSBuild 的开源软件为辅的方法,即可完成 Web Application 项目的自动化每日构建。

我要实现的每日构建,其流程如下:

  1. 从源代码库获取最新源代码;
  2. 根据需要(Debug/Release)编译项目;
  3. 备份编译的项目程序集及其所需文件;
  4. 项目发布;
  5. 每日构建结果通知;

所用软件:

MSBuild,其用法请参考微软相关文档,MSBuild Community Tasks,则可以参考其文档。

至于我为什么要用 MSBuild Community Tasks,原因在于 MSBuild 提供的 Task 不足以达到我的要求,比如版本号维护、文件(夹)压缩、在 IIS 中创建/删除虚拟目录、EMail等等。

一旦准备好环境,就可以开始每日构建的具体步骤了。

考虑到每日构建的最后一步——结果通知——依赖编译及发布的结果,以及自动化的要求,故分为以下三个文件来完成调用:

  1. 步骤2、3、4放在 Project 文件 TestProject.proj 中;
  2. 步骤1和步骤5放在 Project 文件 DailyBuild.proj 中,其间调用 TestProject.proj,在步骤5中根据编译发布结果发送不同的 EMail;
  3. 批处理文件 DailyBuild.bat,调用 Project 文件 DailyProject.proj,记录日志,用以 Windows 任务调用;

以下是各个步骤的源代码。

步骤1:从源代码库获取源代码

<!-- 忽略错误,我们需要自己控制结果。-->
<Target Name="SyncSource">
    
<Exec
        
Command="[Your command line]"
        IgnoreExitCode
="true"
        
>
        
<Output TaskParameter="ExitCode" PropertyName="ExitCode" />
    
</Exec>

    
<Error Text="Failed to Sync source code." Condition=" $(ExitCode) != 0 " />
</Target>

 步骤2:根据需要(Debug/Release)编译项目,及步骤3:备份编译的项目程序集及其所需文件

<Target Name="CoreBuild">
    
<RemoveDir Directories="$(TempDir)" Condition="Exists('$(TempDir)')" />

    
<MakeDir Directories="$(TempDir)%(Configuration.Identity)" />

    
<MSBuild Projects="$(ProjectReferences)" Targets="Build"
        Properties
="Configuration=%(Configuration.Identity);OutDir=$(TempDir)%(Configuration.Identity)"
    
/>

    
<Copy
        
SourceFiles="$(TempDir)%(Configuration.Identity)_PublishedWebsitesWebWeb.config.%(Configuration.Identity)"
        DestinationFiles
="$(TempDir)%(Configuration.Identity)_PublishedWebsitesWebWeb.config"
        SkipUnchangedFiles
="false"
    
/>

    
<Delete Files="$(TempDir)%(Configuration.Identity)_PublishedWebsitesWebWeb.config.Debug" />
    
<Delete Files="$(TempDir)%(Configuration.Identity)_PublishedWebsitesWebWeb.config.Release" />

    
<CreateItem Include="$(TempDir)%(Configuration.Identity)_PublishedWebsitesWeb***.*">
        
<Output
            
TaskParameter="Include"
            ItemName
="%(Configuration.Identity)SourceFiles"/>
    
</CreateItem>

    
<Zip
        
Files="@(%(Configuration.Identity)SourceFiles)"
        WorkingDirectory
="$(TempDir)%(Configuration.Identity)_PublishedWebsitesWeb"
        ZipFileName
="$(TempDir)%(Configuration.Identity)Web$(BuildNumber).zip" />

    
<RemoveDir
        
Directories="$(DailyBuildDir)%(Configuration.Identity)"
        Condition
="Exists('$(DailyBuildDir)%(Configuration.Identity)')"
    
/>

    
<MakeDir Directories="$(DailyBuildDir)%(Configuration.Identity)" />

    
<Copy
        
SourceFiles="$(TempDir)%(Configuration.Identity)Web$(BuildNumber).zip"
        DestinationFolder
="$(DailyBuildDir)%(Configuration.Identity)"
        SkipUnchangedFiles
="false"
    
/>
        
    
<RemoveDir
        
Directories="$(LatestBuildDir)%(Configuration.Identity)"
        Condition
="Exists('$(LatestBuildDir)%(Configuration.Identity)')"
    
/>

    
<MakeDir Directories="$(LatestBuildDir)%(Configuration.Identity)" />

    
<Copy
        
SourceFiles="$(TempDir)%(Configuration.Identity)Web$(BuildNumber).zip"
        DestinationFolder
="$(LatestBuildDir)%(Configuration.Identity)"
        SkipUnchangedFiles
="false"
    
/>
</Target>

步骤4:项目发布

<Target Name="AfterBuild">
    
<Copy
        
SourceFiles="@(PublicFiles)"
        DestinationFiles
="@(PublicFiles->'$(WWWRoot)%(RecursiveDir)%(Filename)%(Extension)')"
        SkipUnchangedFiles
="false"
    
/>

    
<ServiceController ServiceName="w3svc" Action="Restart" />

    
<WebDirectoryDelete
        
VirtualDirectoryName="$(VirtualDirectoryName)"
        Condition
="Exists('$(VirtualDirectoryPhysicalPath)')"
        ContinueOnError
="true"
    
/>

    
<RemoveDir
        
Directories="$(VirtualDirectoryPhysicalPath)"
        Condition
="Exists('$(VirtualDirectoryPhysicalPath)')"
    
/>

    
<MakeDir Directories="$(VirtualDirectoryPhysicalPath)" />

    
<Copy
        
SourceFiles="@(DebugSourceFiles)"
        DestinationFiles
="@(DebugSourceFiles->'$(VirtualDirectoryPhysicalPath)%(RecursiveDir)%(Filename)%(Extension)')"
        SkipUnchangedFiles
="false"
    
/>

    
<WebDirectoryCreate
        
VirtualDirectoryName="$(VirtualDirectoryName)"
        VirtualDirectoryPhysicalPath
="$(VirtualDirectoryPhysicalPath)"
        AuthAnonymous
="False"
        AuthBasic
="false"
        AuthNtlm
="true"
        EnableDefaultDoc
="true"
        DefaultDoc
="Index.aspx"
    
/>

    
<WebDirectoryDelete
        
VirtualDirectoryName="$(NeedsToBeDeletedVirtualDirectoryName)"
        Condition
="Exists('$(NeedsToBeDeletedVirtualDirectoryPhysicalPath)')"
        ContinueOnError
="true"
    
/>

    
<RemoveDir
        
Directories="$(NeedsToBeDeletedVirtualDirectoryPhysicalPath)"
        Condition
="Exists('$(NeedsToBeDeletedVirtualDirectoryPhysicalPath)')"
    
/>
</Target>

步骤5:每日构建结果通知

<Target Name="SendEMailOnSuccess">
    
<Mail
        
SmtpServer="smtphost"
        To
="@(ToEMailAddress)"
        Cc
="@(CcEMailAddress)"
        From
="$(FromEMailAddress)"
        Subject
="TestProject Daily Build from $(SourceBranch) source"
        IsBodyHtml
="true"
        Body
="[You email body for building success]"
        Attachments
="@(LogFile)"
    
/>
</Target>

<Target Name="SendEMailOnFail">
    
<Mail
        
SmtpServer="smtphost"
        To
="@(ToEMailAddress)"
        Cc
="@(CcEMailAddress)"
        From
="$(FromEMailAddress)"
        Subject
="TestProject Daily Build from $(SourceBranch) source"
        IsBodyHtml
="true"
        Body
="[You email body for building fail]"
        Attachments
="@(LogFile)"
    
/>
</Target>

最后就是自动化了,每日调度实现自动化。编写含有以下内容的批处理文件,然后将其放入 Windows 任务计划中即可。

rem @echo off

echo User Domain: %userdnsdomain%
echo User Name: %username%

set CurrentDate=%date=_%
set CurrentDate=%CurrentDate:/=_%
set CurrentDate=%CurrentDate:-=_%

set CurrentTime=%time=0%
set CurrentTime=%CurrentTime::=_%
set CurrentTime=%CurrentTime:.=_%

set LogFileName=%CurrentDate%.%CurrentTime%.log

%SystemRoot%/
Microsoft.NET/Framework/v2.0.50727/MSBuild.exe /nologo /noconlog /l:FileLogger,Microsoft.Build.Engine;logfile=E:/Build/Logs/DailyBuild.%LogFileName%;append=false;verbosity=normal;encoding=utf-8 /p:WWWPath=C:/Inetpub/wwwroot;SourceBranch=Development;SourcePath=D:/Source/TestProject/Web;BuildPath=E:/Build "D:Source/TestProject/Build/DailyBuild.proj"

相关文章推荐

项目管理实践【三】每日构建【Daily Build Using CruiseControl.NET and MSBuild】

在上一篇项目管理实践教程二、源代码控制【Source Control Using VisualSVN Server and TortoiseSVN】中我们已经讲解了如何使用TortoiseSVN和Vi...

在.NET环境中实现每日构建(Daily Build)--ccnet,MSBuild篇

每日构建,对我们团队来说一个全新的概念。随着项目开发的进展,在开发过程需要及时反馈一些BUG和功能要求的处理情况。而在这种情况下每天或隔一段时间Build一个版本,工作量还是比较大的,所以就特别有必要...
  • wlanye
  • wlanye
  • 2012年02月10日 10:56
  • 608

ccnet +msbuild +svn 每日构建( 一 )

今天体验了一把ccnet+svn+msbuild 每日构建环境的搭建,整个过程完整进行下来,还是遇到些小问题,不过还好顺利完工,不罗嗦了,看步骤: 1.安装CruiseControl.NET-1.8...

从零开始构建MSBuild C#项目文件

本文参考自MSDN的一篇文章,从零开始创建MSBuild C#项目文件。准备条件 一个好用的文本编辑器,例如Atom或者Sublime Text。 MSBuild命令行工具。如果已经安装了Visual...

Silverlight利用Application_Startup获取web项目中的初始化参数

一个新建的silverlight项目在解决方案中往往有两个项目,silverlight的本身项目和供其在浏览器中展现的Web项目,在web项目中有相应的web页面提供给silverlight程序承载展...

图解持续集成--纯命令行实现.Net项目每日构建(流程支持)

图解持续集成--纯命令行实现.Net项目每日构建(流程支持) 在前一博客 图解持续集成--纯命令行实现.Net项目每日构建 中介绍了通过命令行进行每日构建,在本文中将介绍支持其流程 ...

纯命令行实现.Net项目每日构建(升级版本)

解持续集成 --纯命令行实现.Net项目每日构建(升级版本) 该工具源代码下载           在《纯命令行实现.Net项目每日构建》实现了完全自动化、可重复的构建工作,但随着时间的推移...

部署项目时出现:Error configuring application listener of class org.springframework.web.context.解决方案

我的项目环境是:jdk1.8.0_131、Tomcat7.0、项目架构用的SSM,dubbo,虚拟机上搭了六个redis节点,项目在开发环境中部署到Tomcat上时出现了错误。之前确定了Tomcat启...

springmvc项目不用配置application.xml文件,web.xml不用加载contextlistener

springmvc项目不用配置application.xml文件,web.xml不用加载contextlistener
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:利用 MSBuild 实现 Web Application 项目的每日构建(上)
举报原因:
原因补充:

(最多只允许输入30个字)