关闭

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

1229人阅读 评论(0) 收藏 举报

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

最近几年我主要开发基于 .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"
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:2857次
    • 积分:47
    • 等级:
    • 排名:千里之外
    • 原创:2篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章分类
    文章存档