.Net and VisualStudio ALM
Article tagué TeamBuild 2010
TeamBuild 2010 : TFS Build Extensions v1.2
26/12/11

Nous venons de publier une nouvelle version stable des Community TFS Build Extensions. Je vous laisse aller voir la liste des modifications sur la page de téléchargement ici.
Vos retours et suggestions sont les bienvenus ; vous pouvez utiliser le forum sur le site pour cela
Carpe Diem.
TeamBuild 2010 : TFS Build Extensions v1.1
23/09/11

Un billet rapide pour vous indiquer que Mike vient de publier hier une nouvelle version stable des Community TFS Build Extensions. Au programme quelque corrections de bogues et nouvelles fonctionnalités.
Nous restons sur un planning de livraison tout les 2 ou 3 mois. Vos retours et suggestions sont les bienvenus ; vous pouvez utiliser le forum sur le site pour cela
Carpe Diem.
TeamBuild 2010 : TFS Build Extensions v1
5/07/11

Hier est sortie la première version stable des Community TFS Build Extensions. Il s’agit d’un ensemble d’activités pour TeamBuild 2010 afin de personnaliser vos processus de build. Voici quelques exemples d’activités proposées :
- File
- Zip
- AssemblyInfo
- CodeMetrics
- RoboCopy
- NUnit
- HyperV
- TfsSource
- …
J’en profite pour remercier Mike Fourie le coordinateur et principal contributeur sur le projet ainsi que l’ensemble des autres contributeurs (dont je fais parti
).
N’hésitez pas a nous faire part de vos retours et suggestions. Ce n’est que le début et nous espérons pouvoir partir sur un mode de release tout les 2 ou 3 mois.
Carpe Diem.
TFS 2010 : Build Customization Guide
20/06/11

Les VisualStudio ALM Rangers viennent de publier leur guide sur la personnalisation des builds !
Pour plus d’infos rendez-vous sur le blog des VisualStudio ALM Rangers ou le site codeplex du projet.
Carpe Diem.
TeamBuild 2010 : Paramètre extensible personnalisé
8/03/11
Voici un petit billet sur comment ajouter un paramètre “extensible” à un workflow de build. Ce que j’entend par paramètre extensible est un paramètre à coté duquel s’affiche un petit + permettant de l’ouvrir pour remplir des propriétés, la ligne principale affichant un résumé des valeurs :

Pour cela rien de plus simple, on commence par créer une classe qui va contenir nos données :
public class VersioningSettings
{
public string AssemblyInfoFileSpec { get; set; }
public string AssemblyVersionFormat { get; set; }
public string AssemblyFileVersionFormat { get; set; }
public string AssemblyInformationalVersionFormat { get; set; }
}
Une fois cette classe écrite on décore l’ensemble des propriétés pour personnaliser l’affichage dans la grille des propriétés (contrôle WinForms de type PropertyGrid). Voici certain des attributs que l’on peut utiliser :
- DisplayNameAttribute : le libellé a affiche à la place du nom de la propriété.
- DescriptionAttribute : un petit descriptif de la propriété qui est affiché en bas de la grille des propriétés .
- BrowsableAttribute : indique si la propriété doit être affichée dans la grille des propriétés .
- RefreshPropertiesAttribute : indique comment la grille des propriétés doit être rafraichit suite à la modification de la valeur de la propriété. La liste des valeurs possible est disponible ici.
Voici ce que cela donne appliqué à l’exemple ci-dessus :
public class VersioningSettings
{
[DisplayName(@"AssemblyInfo Filespec")]
[Description(@"Specifiy the search pattern for locating AssemblyInfo files - e.g. **\*AssemblyInfo*.cs.")]
[RefreshProperties(RefreshProperties.All)]
[Browsable(true)]
public string AssemblyInfoFileSpec { get; set; }
[DisplayName("AssemblyVersion Format")]
[Description("Specify the AssemblyVersion format. Supported tokens are: $(current), $(increment), $(date:<format>).")]
[RefreshProperties(RefreshProperties.All)]
[Browsable(true)]
public string AssemblyVersionFormat { get; set; }
[DisplayName("AssemblyFileVersion Format")]
[Description("Specify the AssemblyFileVersion format. Supported tokens are: $(current), $(increment), $(date:<format>).")]
[RefreshProperties(RefreshProperties.All)]
[Browsable(true)]
public string AssemblyFileVersionFormat { get; set; }
[DisplayName("AssemblyInformationalVersion Format")]
[Description("Specify the AssemblyInformationalVersion format. Supported tokens are: $(version), $(fileversion), $(date:<format>).")]
[RefreshProperties(RefreshProperties.All)]
[Browsable(true)]
public string AssemblyInformationalVersionFormat { get; set; }
[Browsable(false)]
public bool HasAssemblyInfoFileSpec
{
get
{
return !string.IsNullOrEmpty(this.AssemblyInfoFileSpec);
}
}
}
Dans le code suivant j’ai ajouté une propriété HasAssemblyInfoFileSpec qui n’est pas visible dans la grille de propriété mais qui me sert dans mon workflow. Il reste maintenant à ajouter des attributs sur la classe elle même :
- SerializableAttribute : pour qu’une classe puisse être utilisée comment paramètre d’un workflow elle doit être sérialisable.
- TypeConverterAttribute : spécifie le type de convertisseur à utiliser pour afficher la classe. Dans notre cas on utilisera un convertisseur de type ExpandableObjectConverter, c’est cet attribut qui va indiquer à la grille de propriété qu’il faut afficher un “+” et les propriétés de l’objet.
Cela donne :
[Serializable]
[TypeConverter(typeof(ExpandableObjectConverter))]
public class VersioningSettings
{
//...
}
Afin d’afficher sur la ligne principale un résumé, il faudrait normalement faire son propre TypeConverter héritant de ExpandableObjectConverter et renvoyant le résumé via la méthode ConvertTo. Malheureusement il y a un bogue dans TeamExplorer qui fait que notre TypeConverter n’est pas utilisé, le problème devrait être corrigé dans la prochaine version de Visual Studio mais en attendant il va falloir contourner ce bogue
Pour cela on va tout simplement surcharger la méthode ToString de notre classe :
//...
public class VersioningSettings
{
//...
public override string ToString()
{
if (this.HasAssemblyInfoFileSpec)
{
var args = new List<string>();
if (!string.IsNullOrEmpty(this.AssemblyVersionFormat))
{
args.Add(
string.Format("'{0}' for version", this.AssemblyVersionFormat)
);
}
if (!string.IsNullOrEmpty(this.AssemblyFileVersionFormat))
{
args.Add(
string.Format("'{0}' for file version", this.AssemblyFileVersionFormat)
);
}
if (!string.IsNullOrEmpty(this.AssemblyInformationalVersionFormat))
{
args.Add(
string.Format("'{0}' for informational version", this.AssemblyInformationalVersionFormat)
);
}
if (args.Count != 0)
{
return string.Format(
"Update AssemblyInfo files matching '{0}' using {1}",
this.AssemblyInfoFileSpec,
args.Aggregate((a1, a2) => a1 + ", " + a2)
);
}
else
{
return string.Format("Update AssemblyInfo files matching '{0}'", this.AssemblyInfoFileSpec);
}
}
return string.Empty;
}
}
Voila notre classe est prête à être utilisée, il ne reste plus qu’a éditer le workflow de build, ajouter une référence à l’assembly contenant le type du paramètre et ajouter le paramètre. Pour le déploiement, il faut mettre l’assembly dans le contrôleur de source et configurer le contrôleur de build. Vous pouvez consulter mon billet sur mon activité UpdateAssemblyInfo pour des informations détaillées.
Carpe Diem.
Vous pouvez voir l’exemple complet sur codeplex : http://updateassemblyinfo.codeplex.com/SourceControl/changeset/view/84894#1658227
TeamBuild 2010 : UpdateAssemblyInfo v1.1
17/02/11
Je viens de publier la version 1.1 de mon activité pour TeamBuild 2010 permettant de mettre à jour les attributs de version d’un fichier AssemblyInfo. Cette nouvelle version apporte les modifications suivantes :
- Ajout du support de l’attribut AssemblyInformationalVersion avec les tokens suivant :
- $(version) : la valeur de AssemblyVersion après mise à jour.
- $(fileversion) : la valeur de AssemblyFileVersion après mise à jour.
- $(date:<format>) : la date courante.
- Le niveau de log des messages de succès de mise à jour est passé de High à Normal.
- Ajout de la classe VersionSettings afin de regrouper les paramètres nécessaire à l’activité pour simplifier le paramétrage du workflow.
Le projet d’exemple de workflow a aussi été mis à jour pour utiliser la classe VersionSettings. Si vous avez des remarques, des bogues ou des demandes, n’hésitez pas à passer sur le forum ou saisir une issue sur codeplex.
Carpe Diem.
Builds privées avec TeamBuild 2010 dans Programmez
3/09/10
Un petit billet pour vous signaler la sortie du numéro 133 de Programmez :
Il contient un article écrit par mes soins sur les builds privées avec TeamBuild 2010 ainsi qu’un excellent article de Jason De Oliveira et Fathi Bellahcene sur les principes S.O.L.I.D.
Carpe Diem.
TeamBuild 2010 : Exemple d’utilisation de l’activité UpdateAssemblyInfo
2/08/10
Comme promis je vais vous décrire un exemple d’utilisation de l’activité UpdateAssemblyInfo que j’ai publié sur codeplex.
Commençons d’abord par décrire ce que l’on attend :
- Incrémenter le build number de mon AssemblyFileVersion automatiquement de tous les projets d’une solution lors d’une build. Les numéros de version majeure et mineure pour l’AssemblyVersion et l’AssemblyFileVersion doivent être constants et le numéro de révision doit être à 0.
- Ne pas modifier les sources de la solution afin de laisser les développeurs faire ce qu’ils veulent.
- Le BuildNumber de ma build doit contenir la valeur de AssemblyFileVersion afin que le nom de la build, le label et la drop location soient facilement identifiables.
- Ne pas modifier les numéros de version pour les build de type gated-checkin et les build privées.
- Pouvoir lancer une build en spécifiant qu’il ne faut pas mettre à jour les numéros de version.
Avant de mettre à jour notre template de build je vais configurer la solution pour rendre la mise à jour des versions pour l’ensemble des projets plus simple. Pour cela on ajoute un fichier GlobalAssemblyInfo.cs (ou .vb si vous faite du VB.Net) à la solution en tant que solution items :

Ce fichier va contenir l’ensemble des attributs au niveau assembly que nous voulons voir partager par tous nos projets :
using System.Reflection;
[assembly: AssemblyDescription("Sample project for UpdateAssemblyInfo activity.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Qetza")]
[assembly: AssemblyProduct("UpdateAssemblyInfoSample")]
[assembly: AssemblyCopyright("Copyright © Guillaume Rouchon 2010")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Dans le cas présent nous partageons l’ensemble des attributs décrivant l’assembly à l’exception du titre (AssemblyTitle) et bien entendu les versions d’assembly et de fichier. Il ne reste plus qu’à modifier les projets pour utiliser ce fichier. Pour cela, pour chaque projet on va rajouter ce fichier en tant que lien :

Il est important d’ajouter le fichier en lien afin de ne pas le dupliquer ! Il faut ensuite modifier les fichiers AssemblyInfo.cs des projets afin de supprimer les attributs en doublon. Voila notre solution est prête.
Il est maintenant temps de personnaliser notre template de build. Pour cela le plus simple est de :
- Créer un projet de type Workflow/ActivityLibrary.
- Mettre à jour le Framework visé en spécifiant .Net Framework 4.
- Ajouter les références suivantes :
- Depuis C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PrivateAssemblies
- Microsoft.TeamFoundation.Build.Workflow.dll
- Microsoft.TeamFoundation.TestImpact.BuildIntegration.dll
- Depuis C:\Windows\assembly\GAC_MSIL\Microsoft.TeamFoundation.TestImpact.Client\10.0.0.0__b03f5f7f11d50a3a
- Microsoft.TeamFoundation.TestImpact.Client.dll
- Qetza.TeamFoundation.Build.UpdateAssemblyInfo.dll
- Microsoft.TeamFoundation.Build.Client.dll
- Microsoft.TeamFoundation.VersionControl.Client.dll
- Microsoft.TeamFoundation.WorkItemTracking.Client.dll
- System.Drawing.
- Depuis C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PrivateAssemblies
- Supprimer l’activité par défaut.
- Ajouter une copie du fichier DefaultTemplate.xaml au projet.
Nous sommes maintenant près à personnaliser le template afin d’y ajouter la mise à jour des numéros de version. Voyons comment le faire en répondant aux exigences définit au début du billet :
- L’exigence 1 nous précise comment doivent être mis à jour les numéros de version. Pour répondre à cette exigence nous passerons à l’activité UpdateAssemblyInfo les paramètres suivants :
- AssemblyVersionFormat : “$(current).$(current).0.0″
- AssemblyFileVersionFormat : “$(current).$(current).$(increment).0″
- Afin que le numéro de build soit incrémenté à chaque build, il va falloir stocker quelque part le dernier numéro utilisé. L’exigence 2 nous apporte une contrainte, nous ne pouvons pas utiliser le fichier GlobalAssemblyInfo de la solution car la build ne doit modifier les sources. Le plus simple est donc de stocker une copier du fichier GlobalAssemblyInfo qui sera utilisé uniquement lors de la build. TeamBuild 2010 ne fournissant pas d’activité permettant de faire un check-in le plus simple est de garder ce fichier sur un partage réseau. Il faudra faire attention à ce que le compte de build est les droits de lecture et d’écriture sur ce fichier.
- L’exigence 3 va nous imposer l’endroit où nous allons personnaliser notre template. En effet si nous voulons respecter cette exigence nous allons devoir mettre à jour les numéros de versions avant la mise à jour du BuildNumber, le label et la drop location étant dépendant de cette valeur.
- Pour l’exigence 4 il faudra utiliser des séquences de type InvokeForReason et les paramétrer sur la raison Triggered.
- Enfin pour l’exigence 5 il faudra ajouter des If basé sur un paramètre du workflow.
Avant de modifier le workflow il nous faut définir les paramètres suivant au niveau du workflow afin de le configurer pour chaque BuildDefinition :
- AssemblyVersionFormat : le format de mise à jour du numéro d’assembly.
- AssemblyFileVersionFormat : le format de mise à jour du numéro de fichier.
- AssemblyInfoFilePattern : le pattern de recherche utilisé pour trouver les fichiers à mettre à jour.

Il va aussi nous falloir des variables :
- UpdateAssemblyInfo : un booléen qui indiquera s’il faut ou non faire du versionning. Il sera paramétré en fonction de la valeur de AssemblyInfoFilePattern, si celui-ci est vide on ne fera pas de versionning.
- AssemblyInfoFiles : pour stocker les fichiers à mettre à jour.
- MaxAssemblyVersion : pour stocker le numéro max d’assembly après mise à jour.
- MaxAssemblyFileVersion : pour stocker le numéro max de fichier après mise à jour.

Nous devons donc ajouter le workflow suivant :
- If UpdateAssemblyInfo
- Then
- InvokeForReason Triggered
- FindMatchingFile AssemblyInfoFilePattern
- UpdateAssemblyInfo
- Assign BuildNumberFormat = “$(BuildDefinitionName)_v” + MaxAssemblyFileVersion
- InvokeForReason Triggered
- Then
Ce workflow est à ajouter juste avant la séquence “Update Drop Location” :

Avec ce workflow nous avons mis à jour notre fichier GlobalAssemblyInfo et avons personnalisé le BuildNumber et par conséquent le label et la drop location. Mais il faut encore faire une modification au template. En effet pour l’instant la compilation de la solution ne prendra pas en compte notre fichier. Il va donc falloir modifier la partie sur le BuildAgent pour écraser le fichier GlobalAssemblyInfo de la solution après l’avoir récupéré de TFS mais avant de compiler :
- If UpdateAssemblyInfo
- Then
- InvokeForReason Triggered
- CopyDirectory Path.GetDirectoryName(AssemblyInfoFilePattern) to SourcesDirectory
- InvokeForReason Triggered
- Then
Ce workflow est à ajouter avant le “If CreateLabel” :

Voila nous avons maintenant un template qui utilise l’activité UpdateAssemblyInfo afin de mettre à jour les numéros de version automatiquement.
Afin de faire ressortir le versionning nous allons modifier le paramètre Metadata du workflow pour ajouter nos paramètres dans une catégorie “versionning” :

Notre template est maintenant fini, il ne reste plus qu’à tout mettre dans TFS :
- Ajoutez le template en remplaçant le DefaultTemplate.xaml ou ajoutez-le sous un nouveau nom.
- Ajoutez l’activité Qetza.TeamFoundation.Build.UpdateAssemblyInfo.dll dans TFS pour que le process de build y ait accès. (par exemple dans BuildProcessTemplate/CustomActivities).
- Mettez à jour le build controller afin de lui indiquer le répertoire dans TFS ou se trouve les activités personnalisées :

Et voilà, il ne reste plus qu’à définir une BuildDefinition sur un projet et lancer la build. Lors du lancement d’une build il est possible de surcharger les valeurs par défaut (par exemple pour forcer un changement de version majeure ou mineure) :

Et voilà le résultat :

Maintenant c’est à vous de mettre en place vos politiques de versionning et d’intégrer tout cela dans TeamBuild 2010 !
Carpe Diem.
Vous retrouverez la solution que j’ai utilisée pour ce billet à l’adresse http://blog.qetza.net/wp-content/uploads/2010/08/UpdateAssemblyInfo_v1.0.1.0_Sample.zip.
TeamBuild 2010: Microsoft utilise enfin son outil de build :)
29/07/10
Brian Harry vient d’annoncer via son blog que la division développement de Microsoft venait de réussir son premier build end-to-end de tout Visual Studio en utilisant TeamBuild 2010. Voila une nouvelle preuve qu’il s’agit d’un très bon outils.
Comme le précise Brian cela va leur permettre de tester plus en profondeur les fonctionnalités et notamment de trouver des manques qui pourront être incorporés dans les futurs versions.
Carpe Diem.
Activité UpdateAssemblyInfo pour TeamBuild 2010
5/07/10
Je viens de publier sur codeplex une activité pour mettre à jour les attributs AssemblyVersion et AssemblyFileVersion d’un ou plusieurs fichiers avec TeamBuild 2010 : UpdateAssemblyInfo.
Cette activité permet d’indiquer un format pour mettre à jour les versions spécifiées dans un ou plusieurs fichiers AssemblyInfo. Ce format supporte des marqueurs remplacés dynamiquement lors de l’exécution :
- $(current) : utilise la valeur courante.
- $(increment) : incrémente la valeur courante.
- $(date<format>) : utilise la date courante formatée avec le format spécifié.
- un entier : force la valeur à l’entier spécifié.
Le format doit respecter la structure d’un numéro de version “A.B.C.D”. Par exemple le format suivant “$(current).$(current).$(increment).0″ utilisera les versions majeur et mineur courantes, incrémentera le numéro de buid et forcera la révision à 0.
Promis je fais bientôt un billet sur un exemple d’intégration de cette activité mais pour l’instant je récupère un peu de la chaleur de ces derniers jours (et du manque de sommeil qui va avec
).
Carpe Diem.


