Loupe

Azure Dev Ops : appeler les APIs REST depuis une tâche PowerShell

Dans cet article, nous verrons comment appeler et utiliser les APIs REST depuis une tâche PowerShell de VSTS.

Mais pourquoi ?

Vous ne le savez peut être pas mais il y a deux choses dont je suis un grand fan :

  • Le système de PullRequest - la relecture de code par vos développeurs pairs.
  • Les tests unitaires et d'intégration dont parle si bien Vivien ou Teddy.

Sur un projet de plusieurs mois, il n'est pas rare de voir apparaître plusieurs centaines de tests et cela est une très bonne chose. Aussi, pour m'assurer que rien de non-fonctionnel ne parte sur une branche considérée comme stable, ces tests sont joués sur des builds dont le succès est obligatoire pour valider une PR.

Capture d’écran 2019-03-29 à 18.44.43.png

À l'heure actuelle, chaque commit sur une branche dont une PR est issue déclenche une nouvelle build. Si vos builds commencent à prendre du temps (ne serait-ce que 10 minutes) et que votre équipe commence à être conséquente (en nombre de développeurs) vous vous retrouvez vite avec une chaîne de build saturée. Chaque nouvelle PullRequest que vous créez vous fait crier "Ô rage, Ô désespoir, je vais devoir attendre 3 plombes". Imaginons, et cela n'est bien sûr qu'une supposition, que les membres de votre équipe oublient de vérifier sur leur machine de développement (tester c'est douter, ne l'oublions pas...) que tout compile et que les tests passent, et le phénomène s'accentue encore plus. Bon j'avoue que cela m'arrive aussi :D

Une PR est un système de revue de code pour vérifier que le fonctionnel est bien appliqué et qu'aucune défaillance technique n'est introduite. Dans la majorité des cas, il y a des petits points à améliorer (n'oublions pas que nous sommes français, le 20/20 n'existe pas) et il faut faire des améliorations du code initial. Chaque nouveau commit re-déclenche des builds. Si cela est fait en plusieurs commits poussés sur la branche de la PR, c'est à chaque fois une nouvelle pièce dans la machine à déclencher des builds.

Dans notre équipe, certains membres sont désignés volontaires et doivent valider les PRs de façon obligatoire pour qu'elles puissent être complétées. Ainsi, pour solutionner notre problème de chaîne de build saturée, j'ai eu envie de bloquer volontairement les builds tant qu'au moins un relecteur obligatoire n'a pas approuvé la PR. Cela permet d'éviter au moins la première salve de builds et de laisser le temps de faire des correctifs si nécessaire. Il m'a donc fallu trouver un moyen technique de le faire et le plus évident pour moi a été de créer une tâche de type PowerShell dans ma build pour appliquer cette condition obligatoire. Bien sûr, vous pourriez appliquer cette technique a tout autre besoin.

On peut évidemment résoudre ce problème en ajoutant des agents mais il paraît qu'il y a une notion abstraite de coût qui empêche cela et que Florent en a parlé sur ce blog avec un titre fait exprès pour que l'on clique dessus.

Créer la tâche PowerShell et ne le faire que pour les PR

L'API REST se base sur une authentification à base de Token OAuth. Non, je ne sauterai pas sur l'occasion pour mettre un lien vers ma série sur OpenId Connect (même pas chiche de cliquer sur le lien !) La pipeline de build vous permet d'y accéder sous la forme d'une variable d'environnement une fois la demande faite. Pour cela, on sélectionne l'agent et on coche la case "Allow scripts to access the OAuth token".

Capture d’écran 2019-03-29 à 19.04.11.png

L'étape suivante consiste créer la tâche de type PowerShell. On clique donc sur le petit + et on choisit (captain Obvious est là).... "PowerShell". On définira un script de type inline qui ne sera donc pas stocké dans notre code source. Son écriture sera faite plus tard dans l'article.

Ensuite, nous allons mettre une condition sur la tâche pour ne la jouer que si l'on est dans une PR. On configure donc dans "Control Options" pour être sur une "Custom Condition" que l'on renseigne sur cette valeur (youhou c'est du code et on aime ça!) :

 in(variables['Build.Reason'], 'PullRequest')

Capture d’écran 2019-03-29 à 19.05.13.png

Appeler l'API VSTS Rest 

L'appel lui même à l'API est très simple. On se base sur l'exemple de code de la documentation qui permet d'avoir et d'utiliser les bonnes variables d'environnement aux bons endroits pour appeler l'endpoint retournant les infos sur une PullRequest. 

$url = "$($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$env:SYSTEM_TEAMPROJECTID/_apis/git/pullrequests/$($env:SYSTEM_PULLREQUEST_PULLREQUESTID)?api-version=5.0"
$json = Invoke-RestMethod -Uri $url -Headers @{
    Authorization = "Bearer $env:SYSTEM_ACCESSTOKEN"
}

On se retrouvera ici avec un objet PowerShell dans la variable $json contenant les informations demandées.

Vérifier si un relecteur obligatoire a approuvé la PR

Il est maintenant nécessaire de parcourir cet objet via PowerShell pour savoir si un noeud de la propriété "reviewers" avec la propriété isRequired à true a été voté 5 (approved with suggestions) ou 10 (approved). Rien de plus simple... quand on connaît PowerShell. Comme ce n'est pas mon cas, j'ai demandé à mon grand guru PowerShell Olivier qui, après avoir essayé de négocier une AzureFunction (car c'est quand même cool), m'a donné ce magnifique code.

$col = $json.reviewers | where { ($_.vote -eq 5 -or $_.vote -eq 10) -and $_.isRequired -eq $true } | select -First 1

'Mon royaume pour une ligne de code".

Faire échouer la build

Il ne reste plus qu'à utiliser ce résultat pour faire échouer la build. Heureusement, VSTS nous donne tout ce qu'il faut pour cela et ce code permettra d'écrire un message d'erreur et d'indiquer que nous sommes sur un échec.

if ( $col -eq $null) {
    Write-Host "##vso[task.logissue type=error;]A required reviewer approval is mandatory for the build to succeed. Thank you for your time."
    Write-Host "##vso[task.complete result=Failed;]DONE"
 }

Capture d’écran 2019-03-29 à 19.03.30.png

C'est pas souvent que l'on écrit un article si long pour faire échouer une build ^^

Happy coding :)

Photo de profil

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus