Question

Nous utilisons un fichier T4 pour gérer notre versioning d'assembly; Fondamentalement, nous suivons ces procédures pour régénérer nos versions d'assemblage sur chaque version. Cela se fait en faisant utiliser le .csproj Modélisation SDK pour vs 2013 pour Personnaliser la configuration de régénération T4 avec msbuild.

Cela fonctionne très bien! Malheureusement, l'équipe-construction pour Team Foundation Service ne semble pas prendre en charge la génération de code T4 au moment de la construction, car les instances de vs 12 sur le serveur de construction n'ont pas le textemplating.targets dans l'emplacement d'installation par défaut; Les sdks de modélisation / vs ne sont pas installés sur le serveur de construction (à partir des journaux de défaillance de construction TFService):

Le projet importé "C: Program Files (x86) msbuild 12.0 Microsoft VisualStudio V12.0 TextTemplating Microsoft.TextTemplating.Targets" n'a pas été trouvé. Confirmez que le chemin dans la déclaration est correct et que le fichier existe sur le disque.

Est-il prévu d'installer les addons VS 2013 publiés par Microsoft (VS SDK, modélisation SDK, etc.) sur l'image du serveur de construction?

Y a-t-il un travail que je peux implémenter pour que lorsque je commette mon code à l'équipe de fondation par équipe via Git, la construction ne se cassera pas?

Comment puis-je configurer le contrôleur de construction hébergé de TFService pour transformer mes fichiers T4 pendant ses versions?

Était-ce utile?

La solution

J'ai fini par créer une solution différente à la tâche de faire en sorte que le serveur Build Server Version soit nos assemblages. Au lieu d'utiliser T4 pour créer dynamiquement un fichier assemblyinfo.cs à partager via un lien d'élément vers d'autres projets dans la solution (et donc à gérer la gêne de déterminer comment maintenir la régénération du courant à cette fin), i évité T4. C'était trop de travail à s'intégrer à la machine de construction à distance tierce, gérant les addons et les SDK qui permettent la manipulation T4, etc. Il existe une solution beaucoup plus simple impliquant Tâches communautaires MSBuild que j'ai trouvé de cette question tellement. La solution est élégamment simple par rapport à T4! Voici comment ça secoue:

Chaque fois que ce projet, application.versioning.csproj, est construit, tâches msbuild définies dans la bibliothèque «MSBuildCommunity» de Nuget, générée dynamique `` MsBuildCommunity Tasks ' AssemblyFileVieversion, AssemblyInformationSVersion, Version d'assemblage Basé sur l'heure actuelle de la date UTC et les saisir dans un nouveau fichier, Autoversion.cs, qui réside dans le répertoire des propriétés de ce projet (à côté du fichier assemblyinfo.cs). L'AssemblyInfo.CS a ces attributs d'assemblage à jamais abattus pour éviter les erreurs de construction d'attributs d'assemblage multipliés). Après la génération de Autoversion.CS (qui se produit juste avant la construction), le compilateur intègre les attributs de versioning d'assemblage susmentionné dans l'assemblage construit. Ce versioning reflète le temps UTC auquel ils ont été construits (voir ci-dessous).

Tous les autres .csproj dans le .SLN s'abonne à ce version d'assemblage dynamique de build-temps créant un lien de fichier vers le fichier autoversion.cs généré. Ces assemblées doivent également avoir leur assemblée en élagée. Le versioning d'assemblage pour tous les .csprojs souscript dans le .sln est effectué chaque fois que MyApplication.versioning.csproj est construit (ou reconstruit). Voici le .csproj pour le projet de versioning:

  <!-- 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-->

ainsi que le test unitaire à vérifier par vous-même:

/// <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");
}

Autres conseils

Nous avons résolu un problème similaire en incluant les fichiers V&M SDK (Microsoft.TextTemplating.Build.Tasks.Dll, Microsoft.TextTemplating.Targets, Microsoft.VisualStudio.TextTemplating.Sdk.Host.1x.0.Dll) dans un dossier externe_libraires dans Source contrôler.

IMO C'est la seule véritable façon de gérer les SDK tiers dans de grands projets: l'installation sur chaque machine de développement et serveur de construction individuelles est trop fragile pour être pratique.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top