【问题标题】:Retrieve assembly version for use in Jenkins build检索程序集版本以在 Jenkins 构建中使用
【发布时间】:2018-03-21 10:24:27
【问题描述】:

工具

  • MSBuild v14

  • Visual Studio 2013

  • 在 Windows Server 2012 上运行的 Jenkins v2.111

  • Git(本地文件服务器上的裸仓库)

  • Windows 批处理

我的目标

使用 MSBuild 构建一个 c# Visual Studio 项目,该项目从项目 AssemblyInfo.cs 中提取主要和次要版本号以在构建期间使用。构建将产生类似 1.2.$BUILD_NUMBER 的内容,从而产生类似 1.2.121、1.2.122、1.2.123 等的内容。一旦用户选择“发布”构建,文件夹名称中具有正确版本的 clickonce 部署将被复制到其目标位置,并将标签应用于 Git 存储库。

管道示例

下面是我正在做的“正在进行的工作”。欢迎任何改进建议。对于那些想知道为什么我将代码库放到一个临时文件夹中的人。我在 Jenkins 中使用多分支作业,自动生成的文件夹非常长!这给了我错误,即我的文件名、项目名称或两者都太长(因为整个路径超过 255 个字符长度)。因此,解决此问题的唯一方法是复制内容,以便构建和发布能够正常工作。

pipeline {
agent none
stages {
    stage ('Checkout'){
    agent any
        steps 
        {
            checkout scm
        }
    }

    stage ('Nuget Restore'){
    agent any
    steps
    {
        bat 'nuget restore "%WORKSPACE%\\src\\Test\\MyTestSolution.sln"'
    }
    }

    stage('Build Debug') {
    agent any
        steps 
        {
            bat "xcopy %WORKSPACE%\\src\\* /ey d:\\temp\\"
            bat "\"${tool 'MSBuild'}\" d:\\temp\\Test\\MyTestSolution.sln /p:Configuration=Debug /target:publish /property:PublishUrl=d:\\temp\\ /p:OutputPath=d:\\temp\\build\\ /p:GenerateBootstrapperSdkPath=\"C:\\Program Files (x86)\\Microsoft SDKs\\Windows\\v8.1A\\Bootstrapper\" /p:VersionAssembly=1.0.$BUILD_NUMBER /p:ApplicationVersion=1.0.$BUILD_NUMBER"         
        }
    }


     stage('Deploy to Dev'){
     agent none
       steps {
            script {
                env.DEPLOY_TO_DEV = input message: 'Deploy to dev?',
                parameters: [choice(name: 'Deploy to dev staging area?', choices: 'no\nyes', description: 'Choose "yes" if you want to deploy this build')]
            }
        }
     }

     stage ('Deploying to Dev')
     {
     agent any
        when {
            environment name: 'DEPLOY_TO_DEV', value: 'yes'
        }
        steps {
            echo 'Deploying debug build...'

       }

     }

     stage ('Git tagging')
     {
     agent any
        steps 
        {
        bat 'd:\\BuildTargets\\TagGit.bat %WORKSPACE% master v1.0.%BUILD_NUMBER%.0(DEV) "DEV: Build deployed."'
        }
     }
}
}

目前我已经在上面的脚本中硬编码了主要和次要版本。我想从 AssemblyInfo.cs 中提取这些值,以便开发人员可以从那里控制它,而无需编辑 Jenkinsfile。有什么建议/最佳实践来实现这一目标?

因为我正在为 winforms 应用程序执行 clickonce 部署,所以我不得不使用 MSBuild 的 VersionAssembly 和 ApplicationVersion 开关来传递版本。这似乎有助于在 MSBuild 发布文件时正确标记文件夹。我是否在我的设置中遗漏了一些可以否定这些开关并使生活更简单的东西?

我的管道中的最后一个操作是触发 .bat 文件以将标签添加回存储库的主分支。这是我需要使管道脚本可以访问主要和次要版本的另一个原因。

用于编辑 AssemblyInfo.cs 的 MSBuild 目标

此代码取自这里:http://www.lionhack.com/2014/02/13/msbuild-override-assembly-version/

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <PropertyGroup>
    <CompileDependsOn>
        CommonBuildDefineModifiedAssemblyVersion;
        $(CompileDependsOn);
    </CompileDependsOn>
</PropertyGroup>
<Target Name="CommonBuildDefineModifiedAssemblyVersion" Condition="'$(VersionAssembly)' != ''">
    <!-- Find AssemblyInfo.cs or AssemblyInfo.vb in the "Compile" Items. Remove it from "Compile" Items because we will use a modified version instead. -->
    <ItemGroup>
        <OriginalAssemblyInfo Include="@(Compile)" Condition="%(Filename) == 'AssemblyInfo' And (%(Extension) == '.vb' Or %(Extension) == '.cs')" />
        <Compile Remove="**/AssemblyInfo.vb" />
        <Compile Remove="**/AssemblyInfo.cs" />
    </ItemGroup>
    <!-- Copy the original AssemblyInfo.cs/.vb to obj\ folder, i.e. $(IntermediateOutputPath). The copied filepath is saved into @(ModifiedAssemblyInfo) Item. -->
    <Copy SourceFiles="@(OriginalAssemblyInfo)"
          DestinationFiles="@(OriginalAssemblyInfo->'$(IntermediateOutputPath)%(Identity)')">
        <Output TaskParameter="DestinationFiles" ItemName="ModifiedAssemblyInfo"/>
    </Copy>
    <!-- Replace the version bit (in AssemblyVersion and AssemblyFileVersion attributes) using regular expression. Use the defined property: $(VersionAssembly). -->
    <Message Text="Setting AssemblyVersion to $(VersionAssembly)" />
    <RegexUpdateFile Files="@(ModifiedAssemblyInfo)"
                Regex="Version\(&quot;(\d+)\.(\d+)(\.(\d+)\.(\d+)|\.*)&quot;\)"
                ReplacementText="Version(&quot;$(VersionAssembly)&quot;)"
                />
    <!-- Include the modified AssemblyInfo.cs/.vb file in "Compile" items (instead of the original). -->
    <ItemGroup>
        <Compile Include="@(ModifiedAssemblyInfo)" />
    </ItemGroup>
</Target>
<UsingTask TaskName="RegexUpdateFile" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
    <ParameterGroup>
        <Files ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
        <Regex ParameterType="System.String" Required="true" />
        <ReplacementText ParameterType="System.String" Required="true" />
    </ParameterGroup>
    <Task>
        <Reference Include="System.Core" />
        <Using Namespace="System" />
        <Using Namespace="System.IO" />
        <Using Namespace="System.Text.RegularExpressions" />
        <Using Namespace="Microsoft.Build.Framework" />
        <Using Namespace="Microsoft.Build.Utilities" />
        <Code Type="Fragment" Language="cs">
            <![CDATA[
            try {
                var rx = new System.Text.RegularExpressions.Regex(this.Regex);
                for (int i = 0; i < Files.Length; ++i)
                {
                    var path = Files[i].GetMetadata("FullPath");
                    if (!File.Exists(path)) continue;

                    var txt = File.ReadAllText(path);
                    txt = rx.Replace(txt, this.ReplacementText);
                    File.WriteAllText(path, txt);
                }
                return true;
            }
            catch (Exception ex) {
                Log.LogErrorFromException(ex);
                return false;
            }
        ]]>
        </Code>
    </Task>
</UsingTask>

</Project>

Git 标记

此 bat 文件被启动并传递用于创建标签并将标签推送到定义的存储库的值。

echo off
set gitPath=%1
set gitBranchName=%2
set gitTag=%3
set gitMessage=%4
@echo on
@echo Adding tag to %gitBranchName% branch.
@echo Working at path %gitPath%
@echo Tagging with %gitTag%
@echo Using commit message: %gitMessage%

d:
cd %gitPath%
git checkout %gitBranchName%
git pull
git tag -a %gitTag% -m %gitMessage%
git push origin %gitBranchName% %gitTag% 

如果有任何其他有助于简化或改进整个工作流程的金块,我也会欢迎!

【问题讨论】:

    标签: c# git visual-studio jenkins msbuild


    【解决方案1】:

    我最近遇到了同样的问题,我通过创建 Windows 脚本解决了这个问题。

    for /f delims^=^"^ tokens^=2 %%i in ('findstr "AssemblyFileVersion" %1\\AssemblyFile.cs') DO SET VERSION=%%i
    

    此脚本从 AssemblyInfo.cs 中提取版本号并将其放入一个变量中,以便稍后使用它来标记提交(尽管在同一步骤中):

    CALL FindAssemblyVersion .\Properties
    
    git tag %VERSION% 
    git push http://%gitCredentials%@url:port/repo.git %VERSION%
    

    【讨论】:

      【解决方案2】:

      不完全来自程序集文件,而是一个非常方便的解决方法,可以在使用 Jenkins 并使用批处理(或 powershell)命令时从 DLL 获取文件版本:

      转到您的 DLL 所在的目录 [CD Foo/Bar ]

      FOR /F "USEBACKQ" %F IN (`powershell -NoLogo -NoProfile -Command (Get-Item "myApi.dll").VersionInfo.FileVersion`) DO (SET fileVersion=%F )
      
      echo File version: %fileVersion%
      

      【讨论】:

        猜你喜欢
        • 2017-11-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-26
        • 1970-01-01
        • 1970-01-01
        • 2011-07-16
        • 2012-09-05
        相关资源
        最近更新 更多