Étude de cas : Automatisation de rapports GitHub avec PowerShell
Contexte
Dans un environnement DevOps moderne, il est fréquent de devoir surveiller et analyser l'activité de dépôts GitHub : nombre de commits, contributeurs actifs, issues ouvertes, pull requests, etc. Cette étude de cas vous guidera dans la création d'un script PowerShell qui automatise la collecte de ces données via l'API GitHub et génère un rapport structuré.
Objectifs d'apprentissage
À la fin de cette étude de cas, vous serez capable de :
- Utiliser
Invoke-RestMethodpour interagir avec une API REST - Manipuler des données JSON retournées par une API
- Transformer des données brutes en objets PowerShell structurés
- Générer des rapports au format JSON et HTML
- Créer un script d'automatisation complet et réutilisable
Prérequis
- PowerShell installé sur votre machine Linux
- Connexion Internet pour accéder à l'API GitHub
- Connaissances de base sur JSON (vues la semaine dernière)
Partie 1 : Exploration de l'API GitHub
L'API GitHub est publique et permet d'obtenir de nombreuses informations sur les dépôts sans authentification (avec des limites de taux). La documentation complète est disponible à https://docs.github.com/en/rest.
Étape 1.1 : Tester une requête simple
Lancez PowerShell (
pwsh).Faites une première requête pour obtenir les informations sur un dépôt public. Utilisez par exemple le dépôt PowerShell lui-même :
$repoInfo = Invoke-RestMethod -Uri "https://api.github.com/repos/PowerShell/PowerShell"
- Examinez le résultat :
$repoInfo
Question : Quel type d'objet a été retourné ? Utilisez Get-Member pour explorer.
- Affichez des propriétés spécifiques :
$repoInfo.name
$repoInfo.description
$repoInfo.stargazers_count
$repoInfo.forks_count
$repoInfo.open_issues_count
À remarquer : Invoke-RestMethod a automatiquement converti la réponse JSON en un objet PowerShell. Vous pouvez accéder aux propriétés directement avec la notation par point.
Étape 1.2 : Obtenir la liste des contributeurs
- Récupérez les contributeurs du dépôt :
$contributors = Invoke-RestMethod -Uri "https://api.github.com/repos/PowerShell/PowerShell/contributors"
- Examinez le résultat :
$contributors | Select-Object -First 5
Question : Combien de contributeurs y a-t-il au total ? (Indice : $contributors.Count)
- Affichez les 10 principaux contributeurs par nombre de commits :
$contributors | Select-Object login, contributions | Sort-Object contributions -Descending | Select-Object -First 10
Étape 1.3 : Obtenir les issues récentes
- Récupérez les issues ouvertes :
$issues = Invoke-RestMethod -Uri "https://api.github.com/repos/PowerShell/PowerShell/issues?state=open&per_page=10"
- Affichez les titres des issues :
$issues | Select-Object number, title, state
- Comptez les issues par état (note : l'API retourne aussi les pull requests dans les issues) :
$issues | Group-Object state
Partie 2 : Création d'un script de collecte de données
Maintenant que vous comprenez comment interroger l'API, créons un script structuré.
Étape 2.1 : Créer le script de base
- Créez un nouveau fichier script :
nano rapport-github.ps1
- Ajoutez le contenu suivant (structure de base avec paramètres) :
#!/usr/bin/env pwsh
param(
[Parameter(Mandatory=$true)]
[string]$Owner,
[Parameter(Mandatory=$true)]
[string]$Repo
)
# URL de base de l'API GitHub
$baseUrl = "https://api.github.com"
# Fonction pour afficher un message de statut
function Write-Status {
param([string]$Message)
Write-Host "[$((Get-Date).ToString('HH:mm:ss'))] $Message" -ForegroundColor Cyan
}
Write-Status "Début de la collecte de données pour $Owner/$Repo"
# À compléter dans les prochaines étapes
- Sauvegardez et rendez le script exécutable :
chmod +x rapport-github.ps1
Étape 2.2 : Ajouter la collecte des informations de base
Ajoutez ce code après le message de début :
# Collecter les informations de base du dépôt
Write-Status "Récupération des informations du dépôt..."
try {
$repoInfo = Invoke-RestMethod -Uri "$baseUrl/repos/$Owner/$Repo"
Write-Status "Dépôt trouvé : $($repoInfo.name)"
} catch {
Write-Host "Erreur : Impossible de récupérer les informations du dépôt." -ForegroundColor Red
Write-Host $_.Exception.Message -ForegroundColor Red
exit 1
}
À remarquer : Nous utilisons un bloc try/catch pour gérer les erreurs (par exemple, si le dépôt n'existe pas).
Étape 2.3 : Ajouter la collecte des contributeurs
Ajoutez après la section précédente :
# Collecter les contributeurs
Write-Status "Récupération des contributeurs..."
try {
$contributors = Invoke-RestMethod -Uri "$baseUrl/repos/$Owner/$Repo/contributors?per_page=100"
Write-Status "Nombre de contributeurs : $($contributors.Count)"
} catch {
Write-Host "Avertissement : Impossible de récupérer les contributeurs." -ForegroundColor Yellow
$contributors = @()
}
Étape 2.4 : Ajouter la collecte des commits récents
Ajoutez :
# Collecter les commits récents (derniers 30 jours)
Write-Status "Récupération des commits récents..."
$dateSince = (Get-Date).AddDays(-30).ToString("yyyy-MM-ddTHH:mm:ssZ")
try {
$commits = Invoke-RestMethod -Uri "$baseUrl/repos/$Owner/$Repo/commits?since=$dateSince&per_page=100"
Write-Status "Nombre de commits (30 derniers jours) : $($commits.Count)"
} catch {
Write-Host "Avertissement : Impossible de récupérer les commits." -ForegroundColor Yellow
$commits = @()
}
À remarquer : Nous utilisons Get-Date pour calculer la date d'il y a 30 jours et la formatons selon les attentes de l'API GitHub.
Étape 2.5 : Tester le script
- Exécutez le script avec un dépôt public :
./rapport-github.ps1 -Owner "PowerShell" -Repo "PowerShell"
- Vérifiez que les messages de statut s'affichent correctement.
Question : Que se passe-t-il si vous essayez avec un dépôt qui n'existe pas ?
Partie 3 : Génération du rapport
Maintenant que nous collectons les données, créons un rapport structuré.
Étape 3.1 : Créer un objet de rapport
Ajoutez à la fin de votre script :
# Créer l'objet rapport
Write-Status "Génération du rapport..."
$rapport = [PSCustomObject]@{
DateGeneration = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
Depot = @{
Nom = $repoInfo.name
NomComplet = $repoInfo.full_name
Description = $repoInfo.description
URL = $repoInfo.html_url
Langage = $repoInfo.language
Etoiles = $repoInfo.stargazers_count
Forks = $repoInfo.forks_count
IssuesOuvertes = $repoInfo.open_issues_count
DateCreation = $repoInfo.created_at
DerniereMAJ = $repoInfo.updated_at
}
Statistiques = @{
NombreContributeurs = $contributors.Count
NombreCommits30Jours = $commits.Count
Top5Contributeurs = $contributors |
Sort-Object contributions -Descending |
Select-Object -First 5 |
ForEach-Object {
[PSCustomObject]@{
Utilisateur = $_.login
Contributions = $_.contributions
}
}
}
}
À remarquer : Nous créons un objet personnalisé structuré avec toutes les informations collectées. Cela facilite l'exportation dans différents formats.
Étape 3.2 : Exporter en JSON
Ajoutez :
# Exporter en JSON
$jsonFile = "rapport-$Owner-$Repo-$(Get-Date -Format 'yyyyMMdd').json"
$rapport | ConvertTo-Json -Depth 5 | Out-File $jsonFile
Write-Status "Rapport JSON généré : $jsonFile"
Étape 3.3 : Générer un rapport HTML
Ajoutez :
# Générer un rapport HTML
$htmlContent = @"
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<title>Rapport GitHub - $($rapport.Depot.NomComplet)</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; background-color: #f5f5f5; }
.container { max-width: 900px; margin: 0 auto; background: white; padding: 30px; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); }
h1 { color: #0366d6; border-bottom: 2px solid #0366d6; padding-bottom: 10px; }
h2 { color: #24292e; margin-top: 30px; }
.info-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 15px; margin: 20px 0; }
.info-item { background: #f6f8fa; padding: 15px; border-radius: 5px; }
.info-label { font-weight: bold; color: #586069; font-size: 14px; }
.info-value { font-size: 18px; color: #24292e; margin-top: 5px; }
table { width: 100%; border-collapse: collapse; margin: 20px 0; }
th { background: #0366d6; color: white; padding: 12px; text-align: left; }
td { padding: 12px; border-bottom: 1px solid #e1e4e8; }
tr:hover { background: #f6f8fa; }
.footer { margin-top: 30px; text-align: center; color: #586069; font-size: 14px; }
</style>
</head>
<body>
<div class="container">
<h1>📊 Rapport d'analyse GitHub</h1>
<p><strong>Dépôt :</strong> $($rapport.Depot.NomComplet)</p>
<p><strong>Date de génération :</strong> $($rapport.DateGeneration)</p>
<h2>Informations générales</h2>
<div class="info-grid">
<div class="info-item">
<div class="info-label">⭐ Étoiles</div>
<div class="info-value">$($rapport.Depot.Etoiles)</div>
</div>
<div class="info-item">
<div class="info-label">🔱 Forks</div>
<div class="info-value">$($rapport.Depot.Forks)</div>
</div>
<div class="info-item">
<div class="info-label">❗ Issues ouvertes</div>
<div class="info-value">$($rapport.Depot.IssuesOuvertes)</div>
</div>
<div class="info-item">
<div class="info-label">💻 Langage principal</div>
<div class="info-value">$($rapport.Depot.Langage)</div>
</div>
</div>
<h2>Activité récente</h2>
<div class="info-grid">
<div class="info-item">
<div class="info-label">👥 Contributeurs</div>
<div class="info-value">$($rapport.Statistiques.NombreContributeurs)</div>
</div>
<div class="info-item">
<div class="info-label">📝 Commits (30 jours)</div>
<div class="info-value">$($rapport.Statistiques.NombreCommits30Jours)</div>
</div>
</div>
<h2>Top 5 contributeurs</h2>
<table>
<tr>
<th>Utilisateur</th>
<th>Contributions</th>
</tr>
"@
foreach ($contrib in $rapport.Statistiques.Top5Contributeurs) {
$htmlContent += @"
<tr>
<td>$($contrib.Utilisateur)</td>
<td>$($contrib.Contributions)</td>
</tr>
"@
}
$htmlContent += @"
</table>
<div class="footer">
<p>Rapport généré avec PowerShell sur Linux 🐧</p>
</div>
</div>
</body>
</html>
"@
$htmlFile = "rapport-$Owner-$Repo-$(Get-Date -Format 'yyyyMMdd').html"
$htmlContent | Out-File $htmlFile
Write-Status "Rapport HTML généré : $htmlFile"
Étape 3.4 : Tester le script complet
- Exécutez le script :
./rapport-github.ps1 -Owner "PowerShell" -Repo "PowerShell"
- Vérifiez que les fichiers JSON et HTML ont été créés :
ls -l rapport-*.json rapport-*.html
Ouvrez le fichier HTML dans un navigateur pour voir le rapport visuel.
Examinez le fichier JSON :
pwsh -Command "Get-Content rapport-*.json | ConvertFrom-Json | Format-List"
Partie 4 : Réflexion
Questions de réflexion :
Question 1 : Dans ce projet, vous avez utilisé Invoke-RestMethod qui convertit automatiquement le JSON en objets PowerShell. Comparez $repoInfo.stargazers_count en PowerShell versus l'équivalent bash avec curl | jq (voir commande ci-dessous). Lequel est plus lisible et maintenable ?
curl -s "https://api.github.com/repos/PowerShell/PowerShell" | jq '.stargazers_count'
Question 2: Retrouvez les commandes PowerShell que vous avez utilisé pour trier et filtrer les contributeurs avec Sort-Object et Select-Object. Comparez avec l'équivalent bash ci-dessous. Qu'est-ce que cela vous dit sur la manipulation d'objets versus la manipulation de texte ?
curl -s "https://api.github.com/repos/PowerShell/PowerShell/contributors" | jq '.[] | {login: .login, contributions: .contributions}' | sort -k2 -nr | head -n 5
Question 3: Imaginez que votre organisation utilise GitHub, GitLab ET Jira, et vous devez créer des rapports pour les trois plateformes. Quel est l'avantage d'utiliser PowerShell comme langage unique plutôt que différents scripts bash ?
Question 4: Votre script génère à la fois du JSON et du HTML. Dans un contexte DevOps, pourquoi ce double format est-il utile ? Pensez aux dashboards, aux intégrations avec d'autres systèmes, et aux archives.
Question 5: Si vous deviez ajouter l'envoi du rapport par email ou le publier sur Slack, chercheriez-vous d'abord un module PowerShell ou écririez-vous du code bash avec curl ? Justifiez votre choix.
Question 6: Imaginez une organisation avec des serveurs Windows (Active Directory) et Linux (web servers) - ce qui est d'ailleurs le cas de la grande majorité des entreprises ! Vous devez automatiser la collecte de données des deux environnements. Quel est l'avantage d'utiliser PowerShell comme langage unique pour cette tâche ?
Question 7: Dans un pipeline CI/CD (GitHub Actions, GitLab CI), les runners peuvent être sous Linux ou Windows. Comment le fait d'écrire vos scripts en PowerShell portable facilite-t-il la maintenance ?
Question 8: PowerShell n'est pas toujours le meilleur choix. Donnez deux situations où vous préféreriez utiliser bash plutôt que PowerShell sous Linux.
Conclusion
Félicitations ! Vous avez créé un script d'automatisation complet qui :
- Interroge une API REST publique
- Manipule des données JSON
- Génère des rapports structurés en plusieurs formats
- Gère les erreurs de manière robuste
- Utilise des paramètres pour être réutilisable
Ce type de script représente un cas d'usage typique de PowerShell sous Linux dans un contexte DevOps moderne. Les compétences que vous avez développées sont directement applicables à l'automatisation d'interactions avec d'autres APIs (AWS, Azure, GitLab, Jira, etc.).
Ressources supplémentaires
- Documentation API GitHub : https://docs.github.com/en/rest
- PowerShell Gallery : https://www.powershellgallery.com/
- Guide Invoke-RestMethod : https://learn.microsoft.com/powershell/module/microsoft.powershell.utility/invoke-restmethod