문제

우리는 T4 파일을 사용하여 어셈블리 버전 관리를 관리하고 있습니다. 기본적으로 우리는 따르고 있습니다 이 절차 각 빌드에서 어셈블리 버전을 재생성합니다. 이것은 .csproj가 사용하도록함으로써 이루어집니다 VS 2013의 SDK 모델링 ~하기 위해 MSBuild로 T4 재생 구성을 사용자 정의합니다.

이것은 훌륭합니다! 불행히도 Team Foundation Service 용 Team-Build는 빌드 서버의 vs 12 인스턴스에 TextTemplating.targets가 기본 설치 위치에 있지 않기 때문에 빌드 시간에 T4 코드 생성을 지원하는 것으로 보이지 않습니다. Modeling/vs SDK가 빌드 서버에 설치되지 않았다고 가정합니다 (TFService 빌드 실패 로그에서) :

가져온 프로젝트 "C : Program Files (x86) MSBuild 12.0 Microsoft VisualStudio V12.0 TextTemplating Microsoft.textTemplating.targets"는 찾을 수 없었습니다. 선언의 경로가 정확하고 파일이 디스크에 존재하는지 확인하십시오.

Microsoft-Released vs 2013 Addons (vs SDK, Modeling SDK 등)를 빌드 서버 이미지에 설치할 계획이 있습니까?

GIT를 통해 코드를 팀 재단 서비스에 커밋 할 때 빌드가 깨지지 않도록 구현할 수있는 작업이 있습니까?

빌드 중에 T4 파일을 변환하기 위해 TFService의 호스팅 된 빌드 컨트롤러를 구성하려면 어떻게해야합니까?

도움이 되었습니까?

해결책

결국 빌드 서버가 어셈블리를 자동 버전하는 작업에 대한 다른 솔루션을 만들었습니다. T4를 사용하여 솔루션 내의 다른 프로젝트에 대한 항목 링크를 통해 공유 할 AssemblyInfo.cs 파일을 동적으로 생성하는 대신,이 목적을 위해 파일의 재생을 최신 상태로 유지하는 방법을 알아내는 성가심을 처리해야합니다. T4를 완전히 피했습니다. T4 조작 등을 허용하는 Addons 및 SDK를 관리하는 타사 원격 빌드 머신과 통합하는 작업이 너무 많았습니다. MSBuild 커뮤니티 작업 내가 찾은 것 이렇게 질문. 솔루션은 T4에 비해 우아하게 간단합니다! 흔들리는 방법은 다음과 같습니다.

이 프로젝트마다 Application.versioning.csproj가 구축 될 때마다 3 자, Nuget Installed 'MSBuildCommunity Tasks'라이브러리에 정의 된 MSBuild 작업이 동적으로 생성됩니다. AssemblyFileVersion, AssemblyInformationalVersion, 조립 전환 현재 UTC 날짜 시간을 기준 으로이 프로젝트의 'Properties'디렉토리 (AssemblyInfo.cs 파일과 함께)에 상주하는 새 파일 인 Autoversion.cs에 입력합니다. AssemblyInfo.cs에는 곱하기 정의 된 어셈블리 속성의 빌드 오류를 피하기 위해 이러한 어셈블리 속성이 영원히 고정되어 있습니다). Autoversion.cs의 생성 후 (빌드 직전에 발생), 컴파일러는 위에서 언급 한 어셈블리 버전화 속성을 빌드 어셈블리에 통합합니다. 이 버전 작성은 그들이 구축 된 UTC 시간을 반영합니다 (아래 참조).

.sln의 다른 .csproj는 생성 된 자동화 된 autoversion.cs 파일에 대한 파일 링크를 작성하는이 동적 빌드 타임 어셈블리 버전을 구독합니다. 이 어셈블리에는 또한 어셈블리 인포 (AssemblyInfo.cs) 가지가 잘 어울려야합니다. .sln에서 모든 가입 .csprojs에 대한 어셈블리 버전은 myApplication.versioning.csproj가 구축 (또는 재건) 될 때마다 수행됩니다. 버전 관리 프로젝트의 .csproj는 다음과 같습니다.

  <!-- START DYNAMIC ASSEMBLY VERSIONING WORK-->
  <!--MSBuild Community Tasks path as installed via the nuget package 'Install-Package MSBuildTasks'-->

 <PropertyGroup>
    <MSBuildCommunityTasksPath>$(MSBuildThisFileDirectory)..\.build</MSBuildCommunityTasksPath>
    <My-PropertiesDir>Properties</My-PropertiesDir>
  </PropertyGroup>
  <PropertyGroup>

   <!--this should only be incremented (starting at zero) for MAJOR application releases this should never be reset only incremented!--> 
    <ManualMajorVersion>0</ManualMajorVersion>

   <!--3 digits maximum should only be manually incremented (starting at zero) for feature releases-->
   <!--!this should be reset to '0' at the start of each caldenar Year-->  
    <ManualMinorVersion>0</ManualMinorVersion>
  </PropertyGroup>

   <!--Import MSBuild Community Tasks library installed from Nuget -->
   <!--This library contains defined MSBUILD tasks useful for dynamically generating Assembly information via MSBUILD https://github.com/loresoft/msbuildtasks--> 
  <Import Project="$(MSBuildCommunityTasksPath)\MSBuild.Community.Tasks.Targets" />
  <Target Name="BeforeBuild">
    <Time Format="yy.MM.dd.HHmm" Kind="Utc">
      <Output TaskParameter="FormattedTime" PropertyName="My-VersionNumber" />
    </Time>
    <Message Text="Auto versioning from UTC time: $(My-VersionNumber) ...">
    </Message>
    <Time Format="yy" Kind="Utc">
      <Output TaskParameter="FormattedTime" PropertyName="Year" />
    </Time>
    <Time Format="MM" Kind="Utc">
      <Output TaskParameter="FormattedTime" PropertyName="Month" />
    </Time>
    <Time Format="dd" Kind="Utc">
      <Output TaskParameter="FormattedTime" PropertyName="Day" />
    </Time>
    <Time Format="HH" Kind="Utc">
      <Output TaskParameter="FormattedTime" PropertyName="Hour" />
    </Time>
    <Time Format="mm" Kind="Utc">
      <Output TaskParameter="FormattedTime" PropertyName="Minute" />
    </Time>
    <ItemGroup>
      <My-AssemblyInfo Include="$(My-PropertiesDir)\AutoVersion.cs" />
      <Compile Include="@(My-AssemblyInfo)" />
    </ItemGroup>
    <MakeDir Directories="$(My-PropertiesDir)" />
    <PropertyGroup>
      <GeneratedAssemblyVersion>$(ManualMajorVersion).$(Year)$(ManualMinorVersion).$(Month)$(Day).$(Hour)$(Minute)</GeneratedAssemblyVersion>
    </PropertyGroup>
    <AssemblyInfo OutputFile="@(My-AssemblyInfo)" CodeLanguage="CS" AssemblyFileVersion="$(GeneratedAssemblyVersion)" AssemblyInformationalVersion="$(GeneratedAssemblyVersion)" AssemblyVersion="$(GeneratedAssemblyVersion)" Condition="$(GeneratedAssemblyVersion) != '' " />
  </Target>
  <!-- END DYNAMIC ASSEMBLY VERSIONING WORK-->

직접 확인하기위한 단위 테스트뿐만 아니라 :

/// <summary> A test to validate the configured, auto-generated assembly versioning is working as expected </summary>
[Test]
public void AssemblyVersioningTest()
{
    DirectoryInfo currentDirectory = new DirectoryInfo(Directory.GetCurrentDirectory());
    DirectoryInfo versioningDir = new DirectoryInfo(currentDirectory.FullName + "\\" + VERSIONING_DYNAMIC_FILE_DIRECTORY);

    // verify versioning directory located/loaded/exists
    Assert.IsTrue(versioningDir.Exists);

    // locate the VERSIONING_DYNAMIC_FILE file within the VERSIONING_DYNAMIC_FILE_DIRECTORY directory
    string dynamicFilePath = versioningDir.FullName + "\\" + VERSIONING_DYNAMIC_FILE;

    // get the FileInfo for the file that is used to dynamically generate assembly versioning
    FileInfo dynamicVersioningFileInfo = new FileInfo(dynamicFilePath);
    Assert.IsTrue(dynamicVersioningFileInfo.Exists);

    // get the two digit creation Dates/Times for the assembly's file as strings
    // since that's what the versioning reflects
    DateTime dynamicVersioningFileLastWriteTime = dynamicVersioningFileInfo.LastWriteTime;

    #region    Created VERSIONING_DYNAMIC_FILE
    string dynamicVersioningFileLastWriteTimeYear = dynamicVersioningFileLastWriteTime.ToUniversalTime().ToString("yy");

    string dynamicVersioningFileLastWriteTimeMonth = dynamicVersioningFileLastWriteTime.ToUniversalTime().ToString("MM");
    string dynamicVersioningFileLastWriteTimeDay = dynamicVersioningFileLastWriteTime.ToUniversalTime().ToString("dd");

    string dynamicVersioningFileLastWriteTimeHour = dynamicVersioningFileLastWriteTime.ToUniversalTime().ToString("HH");
    string dynamicVersioningFileLastWriteTimeMinute = dynamicVersioningFileLastWriteTime.ToUniversalTime().ToString("mm");
    #endregion Created VERSIONING_DYNAMIC_FILE

    // get *this* assembly from the .sln using reflection since this assembly consumes/is dependent upon the versioning functionality we
    // are testing
    Assembly theAssemblyExecutingThisTest = Assembly.GetExecutingAssembly();

    // get this assembly's version
    // we will investigate this to compare it to a reverse-engineering of what we would
    // expect it to be based 
    AssemblyName testingAssemblyName = theAssemblyExecutingThisTest.GetName();
    Version testingAssemblyVersion = testingAssemblyName.Version;

    #region    Generated Assembly Versioning
    // get the first two digits of the assemblyVersion.MinorVersion - these represent the year
    string testingAssemblyVersionMinorYear = testingAssemblyVersion.Minor.ToString().Substring(0, 2);
    // the rest of the digits represent the manually-configured version and can be 1-3 chars long
    string testingAssemblyVersionMinorManual = GetMinorManualFromVersionString(testingAssemblyVersion.Minor.ToString());

    string testingAssemblyVersionBuildMonth = testingAssemblyVersion.Build.ToString("D4").Substring(0, 2);
    string testingAssemblyVersionBuildDay = testingAssemblyVersion.Build.ToString("D4").Substring(2, 2);

    string testingAssemblyVersionRevisionHour = testingAssemblyVersion.Revision.ToString("D4").Substring(0, 2);
    string testingAssemblyVersionRevisionMinute = testingAssemblyVersion.Revision.ToString("D4").Substring(2, 2);
    #endregion Generated Assembly Versioning

    // verify the assembly's minor version: last two digits match of assembly file creation year
    // (pad minorversion 4 spaces in case released minor version is empty)
    Assert.AreEqual(dynamicVersioningFileLastWriteTimeYear,
        testingAssemblyVersionMinorYear,
        "Assembly's minor version: last two digits do not match assembly file last write time year");

    // verify the assembly's minor version is comprised of two digit 'released minor version' + two digit year of assembly file creation date
    Assert.AreEqual(dynamicVersioningFileLastWriteTimeYear + testingAssemblyVersionMinorManual,
        testingAssemblyVersionMinorYear + testingAssemblyVersionMinorManual,
        "Assembly's minor version: not comprised of two digit year of assembly file last write time date + dynamically-sized 'minor manual version' + ");

    // verify the Assembly's build version is comprised of two digit month + two digit day of assembly file creation date
    Assert.AreEqual(dynamicVersioningFileLastWriteTimeMonth + dynamicVersioningFileLastWriteTimeDay,
        testingAssemblyVersionBuildMonth + testingAssemblyVersionBuildDay,
        "Assembly's build version: not comprised of two digit month + two digit day of assembly file last write time date");

    // verify the Assembly's revision version is comprised two digit hour + two digit minute of assembly file creation date
    Assert.AreEqual(dynamicVersioningFileLastWriteTimeHour + dynamicVersioningFileLastWriteTimeMinute,
        testingAssemblyVersionRevisionHour + testingAssemblyVersionRevisionMinute,
        "Assembly's revision version: comprised two digit hour + two digit minute of assembly file last write time date");
}

다른 팁

V & M SDK 파일 (Microsoft.textTemplating.build.tasks.dll, Microsoft.textTemplating.targets, Visualstudio.textTemplating.sdk.host.1x.0.dll)을 포함하여 유사한 문제를 해결했습니다. 제어.

IMO 이것은 대규모 프로젝트에서 제 3 자 SDK를 관리하는 한 가지 방법입니다. 모든 개별 개발자 기계 및 빌드 서버에 설치하는 것이 너무 부서지기에는 실용적이지 않습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top