I. Introduction▲
Dans une démarche de transparence, responsabilisez votre équipe, justifiez et récompensez les efforts de chacun par l'automatisation du partage quotidien d'indicateurs de qualité, factuels et visuels.
Tous les modules et scripts PowerShell détaillés dans ce tutoriel sont compilés dans le tfsKit disponible sur GITHUB.
II. Connexion à TFS▲
II-A. Charger les assemblies TFS▲
La première étape afin de travailler avec TFS et PowerShell est de charger les assemblies TFS dans votre session PowerShell.
Sur une machine avec Visual Studio 2015 installé, le chemin par défaut pour les API TFS est :
Vous pouvez les charger depuis le chemin par défaut, autrement je conseille de les exporter dans un répertoire pour générer un kit stand alone qui peut être lancé depuis n'importe quel client, même si TFS n'est pas installé, ou s'il l'est mais dans une version différente du serveur (utiliser les assemblies du serveur).
Vous devez ajouter les types suivants à votre script PowerShell pour être en mesure d'interroger TFS et votre serveur de build :
Avec les dépendances, la liste des dll impliquées est plus large. Pour exporter les dll, sélectionnez les membres suivants :
Les assemblies nécessaires pour interroger TFS 2015 ou 2013 sont disponibles sur GITHUB.
II-A-1. Code▲
Les assemblies peuvent être chargées avec la cmdLet Add-Type désignée pour charger des classes .NET dans votre session PowerShell.
2.
3.
4.
5.
6.
7.
8.
# Renseigne votre chemin assemblies
$assembliesPath
=
"F:\GitHub\Powershell\tfsKit\Assemblies"
# Renseigne votre liste TFS assemblies
$tfsAssemblies
=
(
"Microsoft.TeamFoundation.Client.dll"
,"Microsoft.TeamFoundation.Build.Client.dll"
,"Microsoft.TeamFoundation.TestManagement.Client.dll"
,"Microsoft.TeamFoundation.WorkItemTracking.Client.dll"
,"Microsoft.VisualStudio.Services.Client.dll"
,"Microsoft.TeamFoundation.WorkItemTracking.Client.DataStoreLoader.dll"
,"Microsoft.TeamFoundation.Build.Common.dll"
)
# importe assemblies
$tfsAssemblies
| %
{ Add-
Type -Path
(
[IO.Path]::Combine
(
$assembliesPath
, $_
)) }
Cet exemple simple ne nous permet pas d'avoir le détail de l'erreur si l'import échoue. Pour cela nous devons récupérer, depuis l'exception, la propriété LoaderExceptions.
Comme tous les noms d'assemblies commencent par « Microsoft » et finissent par « .dll », nous pouvons aussi raccourcir l'appel.
2.
3.
4.
5.
6.
7.
8.
9.
try
{
$assembliesShortName
=
@(
"TeamFoundation.Client"
,"TeamFoundation.Build.Client"
,"TeamFoundation.TestManagement.Client"
,"TeamFoundation.WorkItemTracking.Client"
,"VisualStudio.Services.Client"
,"TeamFoundation.WorkItemTracking.Client.DataStoreLoader"
,"TeamFoundation.Build.Common"
)
$assembliesShortName
| %
{ Add-
Type -Path
(
[IO.Path]::Combine
(
$global
:AssembliesFolder, "Microsoft.
$_
.dll"
)) }
}
catch
[System.Reflection.ReflectionTypeLoadException]
{
Write-
Error $
(
$_
.Exception | Select-
Object LoaderExceptions | Out-
String)
}
Dans Module-TFS.psm1, nous utilisons le wrapper Add-Assemblies du Module-IO.psm1, nous utilisons également ce module pour les fonctions de Login.
# importe TFS assemblies
Add-As
semblies @(
"TeamFoundation.Client"
,"TeamFoundation.Build.Client"
,"TeamFoundation.TestManagement.Client"
,"TeamFoundation.WorkItemTracking.Client"
,"VisualStudio.Services.Client"
,"TeamFoundation.WorkItemTracking.Client.DataStoreLoader"
,"TeamFoundation.Build.Common"
)
II-B. Se connecter à votre collection de projets TFS▲
Pour effectuer des requêtes à travers votre collection de projets TFS, vous devez instancier un objet TfsTeamProjectCollection depuis l'URI de la collection TFS et vos accès TFS. Pour cette action, nous utilisons la méthode static GetTeamProjectCollection de la classe TfsTeamProjectCollectionFactory du namespace Microsoft.TeamFoundation.Client.
Ensuite, pour s'assurer d'être authentifié à une collection de projets TFS valide, nous utilisons la méthode EnsureAuthenticated de l'objet TfsTeamProjectCollection ; cette méthode définit la propriété HasAuthenticated (Boolean) de l'objet source, et s'assure que la collection de projets est valide (aucune erreur n'est retournée lors de l'instanciation de l'objet. Si votre URI ou vos accès sont faux, vous aurez une erreur lors de l'exécution de la méthode EnsureAuthenticated).
La méthode GetTeamProjectCollection possède plusieurs surcharges, notez que Microsoft marque avec l'attribut obsolète les surcharges utilisant des accès TFS.
Nom |
Description |
---|---|
Obtient l'instance TfsTeamProjectCollection associée au serveur de l'URI spécifié. |
|
Obtient l'instance TfsTeamProjectCollection associée à l'instance de RegisteredProjectCollection spécifiée. |
|
Obsolète. Obtient l'instance TfsTeamProjectCollection associée au serveur de l'URI spécifié et du fournisseur d'identification de repli. |
|
Obsolète. Obtient l'instance TfsTeamProjectCollection associée à l'instance de RegisteredProjectCollection spécifiée et au fournisseur d'informations d'accès. |
|
Récupère l'objet TfsTeamProjectCollection qui est utilisé pour un serveur donné. |
Puisque Microsoft marque avec l'attribut obsolète les surcharges utilisant des accès TFS, les moyens supportés pour gérer les accès sont :
|
II-B-1. Code▲
Comme les accès sont enregistrés dans nos cookies, l'URI de la collection TFS est le seul paramètre obligatoire dont nous avons besoin pour appeler la méthode GetTeamProjectCollection.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
$tfsCollectionUri
=
[System.Uri]"https://tfs.myprojectname.com/DefaultCollection"
$projectsCollection
=
[Microsoft.TeamFoundation.Client.TfsTeamProjectCollectionFactory]::GetTeamProjectCollection
(
$tfsCollectionUri
) # Cette méthode ne lance jamais d'exceptions
$projectsCollection
.EnsureAuthenticated
(
) # Cette méthode lève une exception sur un mauvais URI ou une mauvaise identification
if
(
$projectsCollection
.HasAuthenticated)
{
# Liste des actions
}
else
{
Write-
Warning "you are not authenticated to
$tfsCollectionUri
"
# Ce cas ne devrait jamais arriver vu qu'EnsureAuthenticated() lance une exception sur un mauvais URI ou une mauvaise identification
}
II-C. Obtenir les services de votre collection de projets TFS▲
Plusieurs services sont utiles depuis une collection de projets TFS :
- builds servers : collection de serveurs qui font tourner les builds TFS ; ils sont nécessaires pour interroger les builds TFS.
- work item store : connection work item tracking client sur les serveurs Team Foundation ; ce service est nécessaire pour interroger les projets TFS.
- test management service : objet principal de l'API test management client, ce service est nécessaire pour obtenir les résultats des tests unitaires, ainsi que la couverture de code (dépendant d'un projet TFS).
Pour obtenir ces services, nous utilisons la méthode GetService de l'objet TfsTeamProjectCollection. Cette méthode retourne une instance du service requêté s'il peut être trouvé, ou une ‘reference null' dans le cas contraire.
- Pour obtenir la collection builds servers, nous requêtons une interface IBuildServer du namespace Microsoft.TeamFoundation.Build.Client.
- Pour obtenir le service work item store, nous requêtons une classe WorkItemStore depuis le namespace Microsoft.TeamFoundation.WorkItemTracking.Client.
- Pour obtenir le Test management service, nous requêtons une interface ITestManagementService, depuis Microsoft.TeamFoundation.TestManagement.Client.
II-C-1. Code▲
2.
3.
4.
5.
$buildServer
=
$projectsCollection
.GetService
(
[Microsoft.TeamFoundation.Build.Client.IBuildServer])
$workItemStore
=
$projectsCollection
.GetService
(
[Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItemStore])
$testManagementService
=
$projectsCollection
.GetService
(
[Microsoft.TeamFoundation.TestManagement.Client.ITestManagementService])
II-D. Fonction : connexion à TFS, obtenir la collection de projets et les services TFS▲
Retrouvez la Function Get-TfsConnection dans le module Module-TFS.psm1 sur GITHUB.
III. Obtenir les données de builds TFS▲
Comme nous l'avons vu dans les sections précédentes, il est utile d'obtenir le service build server de la collection de projets, car ce service nous permet d'interroger les builds.
Les exemples suivants partent du prédicat que vous avez instancié un build server dans le champ $buildServer
.
III-A. Obtenir une build TFS▲
L'interface IBuildServer du namespace Microsoft.TeamFoundation.Build.Client possède la méthode QueryBuilds, voici ses surcharges :
Nom |
Description |
---|---|
Obtient toutes les versions pour un projet d'équipe. |
|
Obtient toutes les versions pour une définition de build. |
|
Obtient toutes les versions pour une spécification de définition d'une build. |
|
Obtient un seul résultat de requête de version pour les spécifications d'une build particulière. |
|
Obtient les résultats de la requête de build pour la liste des spécifications de la build. |
|
Obtient toutes les versions pour un projet d'équipe et une définition. |
La surcharge la plus simple pour obtenir les informations utilise le nom du projet et le nom de la build comme paramètres. Elle retourne les informations complètes (QueryOptions =
"All"
, InformationTypes =
"*"
) de toutes les occurrences de la build, mais c'est un processus lourd (jusqu'à à 1 Go de mémoire utilisé) et très long, environ 16 minutes (les exemples ont été chronométrés depuis une build d'intégration continue âgée de six mois).
III-A-1. Code▲
Temps d'exécution : 983757 ms |
$tfsBuilds
=
$buildServer
.QueryBuilds
(
"yourProjectName"
, "yourBuildName"
)
La surcharge la plus versatile utilise un objet IBuildDetailSpec comme paramètre. Elle nous offre un contrôle complet sur l'interrogation à l'aide des propriétés suivantes :
Name |
Description |
---|---|
Obtient ou définit le nombre de builds souhaité. Les caractères génériques sont pris en charge. |
|
Obtient la spécification de définition de version pour les builds souhaitées. |
|
Obtient l'URI de version pour les builds souhaitées. |
|
Obtient ou définit les types d'informations qui seront renvoyés à partir d'une ou de plusieurs requête(s). |
|
Obtient ou définit le nombre maximal de builds à renvoyer par définition. |
|
Obtient ou définit la fin de l'intervalle de temps des builds spécifiées. |
|
Obtient ou définit la date et l'heure de révision les plus anciennes des builds souhaitées. |
|
Obtient ou définit la valeur de début de l'intervalle de temps de fin des builds spécifiées. |
|
Obtient ou définit la qualité des builds souhaitées. |
|
Obtient ou définit des options pour interroger les builds supprimées. |
|
Obtient ou définit les données supplémentaires que retourneront les requêtes. |
|
Obtient ou définit le schéma de commande à utiliser lorsque l'utilisateur définit un nombre maximum de builds. |
|
Obtient ou définit le motif des builds souhaitées. |
|
Obtient ou définit l'utilisateur pour lequel la build a été demandée. |
|
Obtient ou définit les statuts des builds souhaitées. |
Si vous voulez interroger toutes les occurrences d'une build, vous pouvez choisir de retourner le niveau minimum d'informations (QueryOptions =
"None"
, InformationTypes =
$null
) ; le processus est bien plus rapide, environ 0,3 seconde.
III-A-2. Code▲
Temps d 'exécution : 319 ms |
2.
3.
4.
5.
6.
$buildSpecification
=
$buildServer
.CreateBuildDetailSpec
(
"yourProjectName"
, "yourBuildName"
)
$buildSpecification
.QueryOptions =
"None"
$buildSpecification
.InformationTypes =
$null
$tfsBuilds
=
$buildServer
.QueryBuilds
(
$buildSpecification
)
Si vous interrogez un numéro de build, vous interrogez une seule occurrence. Le processus reste rapide même si vous demandez toutes les informations disponibles pour la build, environ 1,7 seconde.
Temps d'exécution : 1726 ms |
2.
3.
4.
5.
$buildSpecification
=
$buildServer
.CreateBuildDetailSpec
(
"yourProjectName"
, "yourBuildName"
)
$buildSpecification
.BuildNumber =
"yourBuildNumber"
$tfsBuild
=
$buildServer
.QueryBuilds
(
$buildSpecification
)
Notre but est souvent d'interroger la dernière occurrence d'une build pour un nom de build donné. Comme nous ne pouvons pas deviner le BuildNumber de cette occurrence, combiner les deux exemples précédents nous permet d'obtenir toutes les informations de la dernière occurrence d'une build en un minimum de temps (les informations apportées par la propriété QueryOptions ne sont pas nécessaires) ; le processus a été chronométré à environ 2,1 secondes.
Temps d'exécution : 2131 ms |
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
$buildSpecification
=
$buildServer
.CreateBuildDetailSpec
(
"yourProjectName"
, "yourBuildName"
)
$buildSpecification
.QueryOptions =
"None"
$buildSpecification
.InformationTypes =
$null
$tfsBuilds
=
$buildServer
.QueryBuilds
(
$buildSpecification
)
# by default, QueryOrder property on build specification is StartTimeAscending
$tfsLastBuildNumber
=
(
$tfsBuilds
.Builds | ? { $_
.Status -ne
"InProgress"
} | Select-
Object -Last
1
).BuildNumber
$buildSpecification
.InformationTypes =
"*"
$buildSpecification
.BuildNumber =
$tfsLastBuildNumber
$tfsBuild
=
$buildServer
.QueryBuilds
(
$buildSpecification
)
III-B. Fonction : obtenir une build TFS▲
Retrouvez la Function Get-TfsBuilds dans le module Module-TFS.psm1 sur GITHUB.
III-C. Compilation, analyse de code, tests unitaires & couverture de code▲
Les exemples suivants partent du prédicat que vous avez instancié une build TFS.
III-C-1. Obtenir les avertissements et erreurs de la build▲
Les résultats de la compilation et du code analysis sont imbriqués dans les erreurs et les avertissements de la build.
Pour obtenir les erreurs de la build, nous utilisons la méthode GetBuildErrors de la classe InformationNodeConverters depuis le namespace Microsoft.TeamFoundation.Build.Client.
Pour obtenir les avertissements de la build, nous utilisons la méthode GetBuildEWarnings de la classe InformationNodeConverters depuis le namespace Microsoft.TeamFoundation.Build.Client.
Ces deux méthodes acceptent une interface IBuildDetails comme paramètre (la fonction Get-TfsBuilds retourne les builds comme objet BuildDetails) et retournent une liste de BuildWarning ou BuildError.
Ensuite pour séparer les résultats de compilation et le code analysis, nous pouvons trier les résultats grâce aux propriétés ErrorType et WarningType.
III-C-2. Code▲
2.
3.
4.
5.
6.
7.
$buildErrors
=
[Microsoft.TeamFoundation.Build.Client.InformationNodeConverters]::GetBuildErrors
(
$tfsBuild
)
$buildWarnings
=
[Microsoft.TeamFoundation.Build.Client.InformationNodeConverters]::GetBuildWarnings
(
$tfsBuild
)
$compilationErrors
=
$buildErrors
| ? { $_
.ErrorType -eq
"Compilation"
}
$compilationWarnings
=
$buildWarnings
| ? { $_
.WarningType -eq
"Compilation"
}
$codeAnalysisErrors
=
$buildErrors
| ? { $_
.ErrorType -eq
"StaticAnalysis"
}
$codeAnalysisWarnings
=
$buildWarnings
| ? { $_
.WarningType -eq
"StaticAnalysis"
}
III-D. Obtenir les résultats des tests unitaires et la couverture de code▲
Le service TestManagementService est nécessaire pour obtenir les tests unitaires et la couverture de code, nous avons vu précédemment comment l'obtenir.
Depuis ce service, nous pouvons obtenir une interface ITestManagementTeamProject à l'aide de la méthode GetTeamProject qui utilise le nom du projet comme paramètre.
L'interface ITestManagementTeamProject possède les helpers undefined & CoverageAnalysisManager.
Pour obtenir les résultats des tests unitaires, nous utilisons la méthode TestRuns.ByBuild. Pour obtenir la couverture de code nous utilisons la méthode CoverageAnalysisManager.QueryBuildCoverage. Ces deux méthodes prennent l'URI d'une build comme paramètre (Uri est un membre de l'objet BuildDetails). La méthode QueryBuilCoverage utilise aussi l'énumération CoverageQueryFlags comme indicateur pour définir la quantité de données à retourner.
III-D-1. Code▲
2.
3.
4.
5.
$managementService
=
$tfsBuilds
.Tfs.TestManagementService.GetTeamProject
(
"yourProjectName"
)
$unitTests
=
$managementService
.TestRuns.ByBuild
(
$tfsBuild
.Uri)
$codeCoverage
=
$managementService
.CoverageAnalysisManager.QueryBuildCoverage
(
$tfsBuild
.Uri,[Microsoft.TeamFoundation.TestManagement.Client.CoverageQueryFlags]::BlockData -bor
[Microsoft.TeamFoundation.TestManagement.Client.CoverageQueryFlags]::Functions -bor
[Microsoft.TeamFoundation.TestManagement.Client.CoverageQueryFlags]::Modules)
III-E. Fonction : obtenir le détail d'une build▲
Retrouvez la Function Get-TfsBuildDetails dans le module Module-TFS.psm1 sur GITHUB.
III-F. Fonction : obtenir le détail de la dernière occurrence d'une build▲
Retrouvez la Function Get-TfsLastBuildDetails dans le module Module-TFS.psm1 sur GITHUB.
IV. Partagez les données de la build▲
IV-A. Mise en forme HTML▲
Tous les objets renvoyés par les fonctions ci-dessus sont formatés sous forme de tableau à une dimension, néanmoins le type des occurrences du tableau varie : Collections.Hashtable, Collections.Specialized.OrderedDictionary ou PSCustomObject.
Pour les convertir en tableau HTML, il nous faut d'abord obtenir les en-têtes :
- pour les types Collections.Hashtable ou Collections.Specialized.OrderedDictionary, les en-têtes sont obtenus via la propriété : Keys ;
- pour les types PSCustomObject, les en-têtes sont obtenus via la cmdLet : Get-Member.
Nom |
Description |
---|---|
Fournit un objet réservé qui est utilisé lorsque le constructeur PSObject(), qui n'a pas de paramètres, est utilisé. |
|
Représente une collection de clés/valeurs qui sont organisées en fonction du code de hachage de la clé. |
|
Représente une collection de clés/valeurs accessibles par la clé ou l'index. |
|
Obtient un objet ICollection contenant les clés dans la collection OrderedDictionary. |
|
Obtient les propriétés et les méthodes des objets. |
IV-A-1. Code▲
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
if
(
$testLine
-is
[Collections.Hashtable] -or
$testLine
-is
[Collections.Specialized.OrderedDictionary])
{
$propertiesName
=
$testLine
.Keys
}
elseif
(
$testLine
-is
[PSCustomObject])
{
$propertiesName
=
$testLine
| Get-
Member -MemberType
NoteProperty
}
else
{
Throw
"this method only allow PsCustomObject or Hashtable content"
}
Maintenant que nous avons les en-têtes, nous pouvons construire les tableaux HTML avec en TH le nom des propriétés et en TD leurs valeurs.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
# Écrire le début du tableau
$htmlTable
+=
"<table>
$([Environment]::NewLine)"
# Écrire l'en-tête du tableau
$htmlTable
+=
"
`t
<tr
$($TrClass
)>"
foreach
(
$propertyName
in
$propertiesName
)
{
$htmlTable
+=
"<th
$($ThClass
)>
$propertyName
</th>"
}
$htmlTable
+=
"</tr>
$([Environment]::NewLine)"
# Écrire les lignes du tableau
foreach
(
$entity
in
$Object
)
{
$htmlTable
+=
"
`t
<tr>"
foreach
(
$propertyName
in
$propertiesName
)
{
$propertyValue
=
[Web.HttpUtility]::HtmlEncode
(
$entity
.$propertyName
)
$htmlTable
+=
"<td>
$propertyValue
</td>"
}
$htmlTable
+=
"</tr>
$([Environment]::NewLine)"
}
# Écrire la fin du tableau
$htmlTable
+=
"</table>"
IV-B. Fonction : convertir les objets PowerShell en tableau HTML▲
Retrouvez la Function Write-ObjectToHtml dans le module Module-IO.psm1 sur GITHUB.
IV-C. Envoi d'emails▲
La première chose à faire pour envoyer un e-mail, c'est de connaître les paramètres de son compte email. Pour Gmail, par exemple, je les ai obtenus sur une page de support Google :
- Server : smtp.googlemail.com ;
- Port : 587 ;
- UseSsl : true.
Le 2e point d'attention, c'est la sauvegarde des accès. Pour cela PowerShell propose le format crypté CLIXML et les fonctions Get-Credential, Export-Clixml et Import-Clixml.
2.
3.
4.
5.
6.
7.
8.
9.
$emailCredentialsFilePath
=
"C:\Example\mail@
$($env
:username)@
$($env
:computername).clixml"
# enregistrer les accès :
Get-
Credential -Message
"Please enter your Email credentials"
| Export-
Clixml $emailCredentialsFilePath
# appeler les accès :
$emailCredentials
=
Import-
Clixml $emailCredentialsFilePath
Tout est prêt pour commencer à envoyer des e-mails ; la fonction Send-MailMessage est la plus pratique, mais elle montre ses limites lors de lancements frénétiques répétés pour les tests. Pour contourner ce problème, on peut construire une méthode qui instancie et dispose proprement les objets System.Net.Mail.SmtpClient et System.Net.Mail.MailMessage.
Nom |
Description |
---|---|
Envoie un message électronique |
|
Permet aux applications d'envoyer des e-mails en utilisant le protocole SMTP (Simple Mail Transfer Protocol). |
|
Représente un message électronique qui peut être envoyé à l'aide de la classe SmtpClient. |
|
Obtient un objet d'identification basé sur un nom d'utilisateur et un mot de passe |
|
Crée une représentation basée sur XML d'un objet ou de plusieurs objets et le(s) stocke dans un fichier. |
|
Importe un fichier CLIXML et crée des objets correspondants dans Windows PowerShell. |
IV-C-1. Code▲
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
# get email title and recipients
$subject
=
"Build report CI-SOAT_20170227.1"
$recipients
=
@{scrumMaster@soat.fr, ProductOwner@soat.fr, Architect@soat.fr, ProjectDirector@soat.fr}
$attachments
=
@{"C:\Example\Compilation.html"
, "C:\Example\UnitTests.html"
, "C:\Example\CodeCoverage.html"
}
Write-
Verbose "Sending email
$subject
to
$recipients
"
# i use System.Net.Mail.SmtpClient Object instead of Send-MailMessage function to get more controls and dispose functionnality
try
{
# Créer des objets de messagerie et de serveur
$message
=
New-
Object -TypeName
System.Net.Mail.MailMessage
$smtp
=
New-
Object -TypeName
System.Net.Mail.SmtpClient
(
$buildInfoData
.BuildReports.Mail.Server)
# Créer un message
$recipients
| %
{ $message
.To.Add
(
$_
) }
$message
.Subject =
$subject
$message
.From
=
New-
Object System.Net.Mail.MailAddress
(
$emailCredentials
.UserName)
$message
.Body =
$mailHtml
$message
.IsBodyHtml =
$true
$attachments
| %
{ $message
.Attachments.Add
(
$
(
New-
Object System.Net.Mail.Attachment $_
)) }
# Créer un serveur SMTP
$smtp
=
New-
Object -TypeName
System.Net.Mail.SmtpClient
(
[string]$buildInfoData
.BuildReports.Mail.Server)
$smtp
.Port =
[int]$buildInfoData
.BuildReports.Mail.Port
$smtp
.Credentials =
[System.Net.ICredentialsByHost]$emailCredentials
$smtp
.EnableSsl =
[bool]$buildInfoData
.BuildReports.Mail.UseSsl
# Envoyer le message
$smtp
.Send
(
$message
)
Write-
Host "Email message sent"
}
catch
{
Write-
Warning "
$($_
.Exception | Select Message, Source, ErrorCode, InnerException, StackTrace | Format-
List | Out-
String)"
}
finally
{
Write-
Verbose "Disposing Smtp Object"
$message
.Dispose
(
)
$smtp
.Dispose
(
)
}
IV-D. Script : partagez vos indicateurs de qualité▲
Le fichier de données au format XML BuildInfo.xml contient les paramètres et le Template HTML.
Le script PowerShell Send-BuildInfos.ps1 effectue tout ce que nous avons vu dans cet article. Les entrées sont stockées dans BuildInfo.xml, TFS est interrogé via le Module-TFS.psm1, les fonctions de Login et de conversion HTML sont fournies par Module-IO.psm1, toutes les ressources sont disponibles sur GITHUB.
V. Conclusion▲
Vous avez maintenant tous les éléments en main pour télécharger ou produire un script PowerShell, qui lancé à partir d'un poste client ayant accès à votre serveur TFS, partagera vos indicateurs de qualité vers la liste d'e-mails de votre choix.
Vous pouvez définir une tâche planifiée pour partager le résultat de la dernière occurrence d'une build tous les jours, ou l'ajouter en action post build d'une build d'intégration.
Vous pouvez également charger le module-Tfs.psm1 dans une session PowerShell pour interroger votre serveur en temps réel en ajoutant des conditions sur les statuts de la build ou les dates.