以编程方式(.NET)获取SVN修订号



我知道这个问题已经出现过好几次了,比如这里:将subversion存储库编号放入代码中。

但要么它太复杂了,我无法理解,要么对我的项目来说太复杂了。简而言之,这是我的设置:几个开发人员使用visualstudio2012和ankhsvn连接到我们的subversion存储库,开发了一个.net web应用程序。开发服务器将存储库中的最新文件与cruisecontrol.net同步。一个测试服务器,其中一个特定的修订版被手动复制用于QA。

请求是在网站上显示最新版本,以便测试人员知道他们正在查看的版本

最简单的方法是什么?是否有某种方法可以直接从代码中获取它(最佳场景)?cruisecontrol.net能为我做这件事吗(但这就把手动部署的测试服务器排除在外了)。我找了又找,很多解决方案似乎都很麻烦,我只想知道在我开始建造一个精致的装置之前,是否有更简单的方法。

接受答案的第二点非常简单,并提供了所需的结果:在应用程序UI中的某个位置输出修订号:

在构建过程中使用SubWCRev.exe和一些自定义代码(脚本)将值插入到文件中。

1)考虑使用什么Assembly属性,并在项目的一个AssemblyInfo文件中注释/删除其行(我选择了一个"通用"项目和AssemblyFileVersion属性)。某些限制可能适用于基于msbuild版本的各种程序集属性,如下所示。

2)创建一个模板用于生成整个版本。例如:SolutionInfo.cs.tmpl

using System.Reflection;
// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version 
//      Build Number
//      Revision 
//
// You can specify all the values or you can default the Revision and Build Numbers 
// by using the '*' as shown below:
[assembly: AssemblyFileVersion("1.0.0.$WCREV$")] 
// [assembly: AssemblyVersion("1.0.0.$WCREV$")]

3)创建实际文件以用于存储生成的版本。例如:SolutionInfo.cs。这可以是空的,因为它将在生成时自动生成。构建后,它应该是这样的:

using System.Reflection;
// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version 
//      Build Number
//      Revision 
//
// You can specify all the values or you can default the Revision and Build Numbers 
// by using the '*' as shown below:
[assembly: AssemblyFileVersion("1.0.0.16788")] 
// [assembly: AssemblyVersion("1.0.0.16788")]

请确保从源代码管理中忽略/排除此文件。

4) 创建预生成事件以获取修订号并从其模板创建文件:

"C:Program FilesTortoiseSVNbinsubwcrev" "$(ProjectDir)..." "$(ProjectDir)PropertiesSolutionInfo.cs.tmpl" "$(ProjectDir)PropertiesSolutionInfo.cs"

注意:此生成事件假定subwcrev由TortoiseSVN安装在其默认路径中。生成服务器必须具有相同的配置,以便生成不会崩溃。如果在PATH中注册了subwcrev,则不再需要完整路径。

5)版本获取

public static class VersionExtensions
{
public static string GetFileVersion(this Assembly assembly)
{
var value = assembly.GetCustomAttributes(typeof(AssemblyFileVersionAttribute), false)
.OfType<AssemblyFileVersionAttribute>()
.SingleOrDefault();
return value != null ? value.Version : "?.?.?.?";
}
public static string GetCommonFileVersion()
{
var assembly = Assembly.GetAssembly(typeof(Common.Web.VersionExtensions));
var value = assembly.GetCustomAttributes(typeof(AssemblyFileVersionAttribute), false)
.OfType<AssemblyFileVersionAttribute>()
.SingleOrDefault();
return value != null ? value.Version : "?.?.?.?";
}

除非你自己放在那里,否则无法"直接从代码中"获得修订号(我认为你的意思是你的代码)。

有多种方法可以做到这一点(下面的列表并不详尽),这取决于你的构建过程是什么样子的以及你想做多少工作

  1. 使用$Revision$关键字&让CCNet正在调用的Subversion客户端自动展开它
  2. 在生成过程中使用SubWCRev.exe和一些自定义代码(脚本)将值插入到文件中
  3. 在构建过程中使用SharpSVN和一些自定义代码(脚本或EXE)将值插入文件中

你的问题还不够具体,无法深入了解更多细节。你还没有描述你找到的未指明的解决方案的"麻烦"之处,而"最简单"是一个非常主观的衡量标准。

我们团队为将代码部署到QA/QC和生产环境提供了相同的环境。在我看来,按照我们的做法,这可以通过简单的dos脚本和svn命令行客户端来实现。

除此之外,我们还提供了当前版本相对于生产部署所做的所有更改的列表。这样,开发人员就可以清楚地了解从登台到现场将释放哪些差异。

如下所示:

我们的CCnet部署为每个开发应用程序配置了3个相关项目。

  1. 暂存
    • 使用每个参与该项目的开发人员提交的每个svn自动构建
    • 生成生成的版本号
    • 根据生产代码生成svn差异列表
  2. QA
    • 手动构建
    • MS是否使用Live设置(连接字符串和其他环境配置)构建
    • 将其与暂存环境分离
    • 携带版本和更改历史
  3. 直播
    • 仅从QA区域推送
    • 手动构建
    • 将版本号和更改列表邮寄给所有利益相关者

CCnet模板:

版本文件创建者模板

这将在web根文件夹中创建版本

<cb:define name="versionFileCreator">
<exec description="Creating the version info file to path [$(appRootFolder)Version.txt].">
<executable>$(command_line_program_path)</executable>
<buildArgs />
<dynamicValues>
<replacementValue>
<format>/C  echo  {0} > "$(appRootFolder)Version.txt" </format>
<parameters>
<namedValue>
<name>$CCNetLabel</name>
</namedValue>
</parameters>
<property>buildArgs</property>
</replacementValue>
</dynamicValues>
<buildTimeoutSeconds>900</buildTimeoutSeconds>
<successExitCodes>0</successExitCodes>
</exec> 
</cb:define>

在当前版本w.r.t Production中发布更改

这个模板使用了一个dos脚本来完成工作,这在本节后面有解释

<cb:define name="publishChangesFromSvn">
<exec description="Consolidating and publishing changes from path [$(svnPathForProductionVersion)] ">
<executable>versionHistoryPublisher.bat</executable>
<buildArgs>"$(svnPathForProductionVersion)" "$(appDirectory)" "$(svnSrcCodeRootPath)" $(svn_password)</buildArgs>
</exec>
</cb:define>

从SVN提取更改历史的DOS脚本

@echo off
set currentProductionVersionFileSvnUrl=%1
set workingDirectory=%2
set sourceCodeSvnPath=%3
set svnPassword=%4
REM **** Creating the file with last production version ***
svn export "%currentProductionVersionFileSvnUrl%//Version.txt" "%workingDirectory%lastProductionVersion.txt" --username %svnusername% --password %svnPassword% --force --non-interactive --quiet
set /p lastCcnetBuildNumber=< %workingDirectory%lastProductionVersion.txt
set /p currentCcnetBuildNumber=< %workingDirectory%Version.txt
for /f "tokens=4 delims=." %%a in ("%lastCcnetBuildNumber%") do set lastSvnRevisionNumber=%%a
for /f "tokens=4 delims=." %%a in ("%currentCcnetBuildNumber%") do set headRevisionNumber=%%a
for /f "tokens=1 delims= " %%a in ("%headRevisionNumber%") do set headRevisionNumber=%%a
echo %lastVersion%
echo Changes in current deployment w.r.t production. > %workingDirectory%currentChangeList.txt
echo =============================================== >> %workingDirectory%currentChangeList.txt
echo Current revison : %headRevisionNumber% >> %workingDirectory%currentChangeList.txt
echo Compared to production version : %lastSvnRevisionNumber% >> %workingDirectory%currentChangeList.txt
echo =============================================== >> %workingDirectory%currentChangeList.txt
svn log %sourceCodeSvnPath% -r %headRevisionNumber%:%lastSvnRevisionNumber% --verbose --username %svnusername% --password %svnPassword% >> %workingDirectory%currentChangeList.txt

示例CCNET暂存项目定义

<project queue="Staging" queuePriority="1">
...your project configurations....

<cb:svn_settings svn_src_code_path="$(svnSrcCodeRootPath)" />
<tasks>
<artifactcleanup cleanUpMethod="KeepLastXBuilds" cleanUpValue="10" />
<modificationHistory onlyLogWhenChangesFound="true" />
<sequential>
<tasks>
<!-- Build the web-->
<msbuild description="Building [$(msbuildWorkingDirectory)$(solutionFileName)] using MsBuild.">
.. your ms build configuration...
</msbuild>
<!-- create the version file -->
<cb:versionFileCreator />
<cb:publishChangesFromSvn   svnPathForProductionVersion="$(productionCheckedInVersion)"
appDirectory="$(appRootFolder)" />
</tasks>
</sequential>
</tasks>
<publishers>
<!-- default XML logger of CCNET -->
<xmllogger />
</publishers>
<triggers>
<intervalTrigger name="continuous" seconds="15" buildCondition="IfModificationExists" initialSeconds="30" />
</triggers>
</project>

版本信息在version.txt文件中,代码更改历史记录在currentChangeList.txt文件中。由于这两个文件都在web根目录中,因此可以通过URL 轻松访问

此外,如果你想在网站上显示版本号,你可以很容易地从version.txt中读取一行,并在app_start期间将其显示在任何你想显示的地方。

SharpSVN允许您执行此操作,如果您知道存储库路径:

using SharpSvn;
private static long GetRevision() 
{
using (SvnClient client = new SvnClient())
{
SvnInfoEventArgs info;
return client.GetInfo(SvnPathTarget.FromString(REPO_PATH), out info) ? info.Revision : 0;
}
}

subversion使用的数据库是sqlite,在项目的.svn文件夹中称为wc.db。您所需要做的就是使用sqlitedb提供程序(Install-Package System.Data.Sqlite),并使用wc.db的完整路径作为连接字符串中的数据源来运行Select max(revision) from NODE

请求在网站上显示最新版本,以便测试人员知道他们在看什么版本。

以下是我的计划:测试人员需要构建u put的信息。为什么不创建调用svnversionsvn info并将输出写入文本文件的批处理文件?您可以使用项目/解决方案文件的构建后事件来调用它,甚至可以在部署新构建时使用cruisecontrol。如果文件是在您的网站中生成的,您可以使用asp.net读取并在页脚中包含信息,或者只需让测试人员访问此文本文件。

不是一个直接的解决方案。但肯定会奏效。

最新更新