19

我正在开发一个使用 SVN 和 TeamCity 构建服务器的 C#/VB.Net 项目。构建产生了十几个程序集。我想控制程序集版本,以便它们都匹配并匹配 TeamCity 构建标签。

我已将 TeamCity 配置为使用构建标签

Major.Minor.{Build}.{Revision}

其中 Major 和 Minor 是我手动设置的常量,{Revision} 由结帐时的 SVN 存储库版本确定,{Build} 是 TeamCity 自动递增构建计数器。所以一个示例构建标签将是

2.5.437.4423

您建议使用哪些技术来确保所有程序集版本都与 TeamCity 构建标签匹配?

4

4 回答 4

31

I'd suggest using TeamCity's AssemblyInfo patcher build feature:

http://confluence.jetbrains.net/display/TCD65/AssemblyInfo+Patcher

Just create your projects from VisualStudio, configure the build feature in the BuildSteps page (see http://confluence.jetbrains.net/display/TCD65/Adding+Build+Features), and as long as you keep the default AssemblyInfo.cs file, it will work.

This approach is working great for me.

Advantages:

  • Developers can build the solution in their machines.
  • You don't need to touch the .sln or .csproj files. It just works.
  • By using TeamCity variables you can easily make the version number match some other project's version, etc.

Disadvantages:

  • You can't easily switch to another CI server from TeamCity because you don't have a build script (but switching CI servers is like switching ORM or database: it is very unlikely and will require a lot of work anyway).
于 2011-10-19T09:13:04.463 回答
7

I'm leaving Hamish's answer as the accepted answer, but for completeness I thought it would be worth documenting the approach we finally adopted.

I maintain 2 seperate build configurations in TeamCity, one is the CI build and another is a build that runs weekly when there are any changes (or manually) and is our official release build. I went for the two-build approach because the build takes perhaps 40 minutes end-to-end and I wanted developers to get a quick feedback on any build issues when they commit changes. The CI build therefore is a subset of the full release build but it does build all of the code. The versioning also differs between the two builds:

  • The CI build has version numbers {Major.minor.BuildCounter.SvnRevision}
    • BuildCounter starts from 0
    • does not tag the svn repository
  • The Weekly/Release build has a similar versioning system, but
    • the build counter starts at (Major * 1000), so if Major is '8', the build counter starts from 8000.
    • Creates a tag called 'Build_{Version}' in the svn repository

The reason for this somewhat arbitrary choice is to allow us to clearly and simply distinguish between CI builds and Release builds.

We have a solution-wide file called AssemblyVersionInfo that is included (soft linked) in every project in the solution. The file contains (in essence) this:

using System.Reflection;
// Revision and Build both set to 9999 indicates a private build on a developer's private workstation.
[assembly: AssemblyFileVersion("6.0.9999.9999")]        // Win32 File Version (not used by .NET)

So developer builds all use the same static and readily identifiable version number, which is higher than anything produced by the build server so that in a versioning conflict, the developer's file wins.

On the build server, we us MSBuild Community Tasks to generate a new AssemblyVersionInfo file that overwrites the default content. We use the TeamCity build string as the new version. In this way, we can easily distinguish between the following 3 situations:

  • A private build performed on the developer's workstation
  • A CI build performed on the build server but which should not be released
  • An officially sanctioned release build, which is tagged in the Svn repository

In another twist, note that I am setting AssemblyFileVersion, not AssemblyVersion. We force our assembly versions to be a static, fixed version string of 'Major.Minor.0.0'. We do this so that we are able to issue bug fix releases without having to worry about versioning issues. The AssemblyFileVersion lets us figure out what build a user has installed without it being part of the assembly's identity.

于 2012-01-03T05:17:40.590 回答
5

我们使用 CruiseControl.net 和 SVN。我们以另一种方式驾驶它。我们在 MSBuild 脚本中使用MSBuildCommunityTasks Version 任务来增加 CI 构建的版本号,并使用该版本号来标记源代码。

编辑:询问有关 MSBuild 目标的更多详细信息...
我们使用单独的脚本用于 CI 构建,而不用于开发人员构建。我们尝试在 Studio 用作项目文件的 MSBuild 文件中使用不同的目标,但这让人头疼,并且需要手动编辑 Studio 生成的文件。
MSBuild 文件的结构非常简单:

  1. 导入额外的部分

    <Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets" />
    <!-- contains some variables that set project names, paths etc. -->
    <Import Project="Properties.msbuild"/>

  2. BeforeBuild:设置新版本号并重写 AssemblyInfo 文件

    <Version VersionFile="$(VersionFile)" BuildType="None" RevisionType="Increment">
    <Output TaskParameter="Major" PropertyName="Major" />
    <Output TaskParameter="Minor" PropertyName="Minor" />
    <Output TaskParameter="Build" PropertyName="Build" />
    <Output TaskParameter="Revision" PropertyName="Revision" />
    </Version>

    <!--Modify Assembly Info-->
    <AssemblyInfo CodeLanguage="CS"
    OutputFile="Properties\AssemblyInfo.cs"
    AssemblyTitle="$(TargetAssembly)"
    AssemblyDescription="$(AssemblyDescription) svn:@(SanitizedSvnUrl) revision:$(SvnRevision)"
    AssemblyCompany="Your company name"
    AssemblyProduct="Name of product"
    AssemblyCopyright="Copyright © your company 2009"
    ComVisible="false" Guid="$(WindowGuid)"
    AssemblyVersion="$(Major).$(Minor).$(Build).$(Revision)"
    AssemblyFileVersion="$(Major).$(Minor).$(Build).$(Revision)"
    Condition="$(Revision) != '0' " />

  3. Build: build the actual project file MSBuild script in release mode

  4. AfterBuild: we run our unit test projects (as a guard against creating tags for broken builds in the next steps), use the SvnInfo tasks and some RegexReplace tasks to set some variables up with paths and tag names, and use the SvnCopy task to create the tag.

<SvnCopy UserName="username"
Password="password"
SourcePath="@(SvnTrunkPath)"
DestinationPath="@(SvnTagsPath)/BUILD-$(TargetAssembly)-$(Major).$(Minor).$(Build).$(Revision)" Message="Tagging successful build" />

于 2009-08-04T22:24:06.093 回答
1

Even though this is already having an accepted answer, I would like to add an idea we have used.

For large projects there may be many assembly info files to update, and with constant re-factoring there is always the risk that the build script is not aware of new files that needs to be updated.

For this reason we have created a simple code file which defines a constant for the actual version and then all projects inherit this constant and us in the assembly info file. Then the build script need only update one file.

Another benefit here is that this is also speeding up the build process somewhat since it does not need to go through many files and change.

于 2013-08-16T09:21:44.700 回答