Vous souhaitez intégrer la plateforme GitHub ? Vous êtes au bon endroit. Ce guide vous aidera à créer une application offrant une expérience optimale à vos utilisateurs et à vérifier qu’elle interagit de manière fiable avec l’API.
Sécuriser les charges utiles fournies à partir de GitHub
Il est très important de sécuriser les charges utiles qui sont envoyées à partir de GitHub. Même si aucune information personnelle (comme les mots de passe) n’est transmise dans une charge utile, la fuite d’informations, quel que soit leur type, n’est pas une bonne chose. Parmi les informations susceptibles d’être sensibles figurent l’adresse e-mail du commiteur ou le nom des dépôts privés.
Vous pouvez effectuer plusieurs étapes pour sécuriser la réception des charges utiles fournies par GitHub :
- Vérifiez que votre serveur de réception utilise une connexion HTTPS. Par défaut, GitHub vérifie les certificats SSL lors de la livraison des charges utiles.
- Fournissez un jeton secret pour être sûr que les charges utiles proviennent de GitHub. En appliquant un jeton secret, vous garantissez que toutes les données reçues par votre serveur proviennent uniquement de GitHub. Dans l’idéal, vous devez fournir un jeton secret différent pour chaque utilisateur de votre service. De cette façon, si un jeton est compromis, aucun autre utilisateur ne sera affecté.
Favoriser le travail asynchrone par rapport au travail synchrone
GitHub s’attend à ce que les intégrations répondent sous 30 secondes à compter de la réception de la charge utile webhook. Si votre service prend plus de temps que cela, GitHub met fin à la connexion et la charge utile est perdue.
Étant donné qu’il est impossible de prédire la rapidité de votre service, vous devez tout réaliser dans un travail en arrière-plan. Resque (pour Ruby), RQ (pour Python) ou RabbitMQ (pour Java) sont des exemples de bibliothèques qui peuvent gérer la mise en file d’attente et le traitement des travaux en arrière-plan.
Notez que même si un travail en arrière-plan est en cours d’exécution, GitHub s’attend toujours à ce que votre serveur réponde sous 30 secondes. Votre serveur doit confirmer qu’il a reçu la charge utile en envoyant une réponse. Il est essentiel que votre service effectue toutes les validations d’une charge utile dès que possible, afin que vous puissiez signaler correctement si votre serveur va poursuivre ou non avec la requête.
Utiliser les codes d’état HTTP appropriés dans une réponse à GitHub
Chaque webhook comprend sa propre section « Livraisons récentes », qui indique si un déploiement a réussi ou non.
Vous devez utiliser des codes d’état HTTP appropriés pour informer les utilisateurs. Vous pouvez utiliser des codes comme 201
ou 202
pour accuser réception d’une charge utile qui ne sera pas traitée (par exemple, une charge utile fournie par une branche qui n’est pas celle par défaut). Réservez le code d’erreur 500
aux erreurs graves.
Fournir autant d’informations que possible à l’utilisateur
Les utilisateurs peuvent explorer les réponses du serveur que vous renvoyez à GitHub. Assurez-vous que vos messages sont clairs et informatifs.
Suivre les redirections que l’API envoie
GitHub est explicite lorsqu’il indique à quel moment une ressource a été déplacée. Pour cela, il fournit un code d’état de redirection. Vous devez suivre ces redirections. Chaque réponse de redirection définit l’en-tête Location
avec le nouvel URI auquel accéder. Si vous recevez une redirection, il est préférable de mettre à jour votre code pour suivre le nouvel URI, dans le cas où vous demanderiez un chemin déprécié susceptible d’être supprimé.
Nous avons fourni la liste des codes d’état HTTP à surveiller lorsque vous concevez votre application en vue de suivre les redirections.
N’analysez pas manuellement les URL
Souvent, les réponses d’API contiennent des données sous la forme d’URL. Par exemple, lors d’une demande de dépôt, nous allons envoyer une clé appelée clone_url
avec une URL que vous pourrez utiliser pour cloner le dépôt.
Pour la stabilité de votre application, vous ne devez pas essayer d’analyser ces données, ni de deviner et de construire le format des futures URL. Votre application sera susceptible de ne plus fonctionner si nous décidons de modifier l’URL.
Par exemple, lors d’une utilisation de résultats paginés, il est souvent tentant de construire des URL avec ?page=<number>
à la fin. Ne cédez pas à cette tentation. Pour plus d’informations sur le suivi fiable des résultats paginés, consultez « Utilisation de la pagination dans l’API REST ».
Vérifier le type d’événement et l’action avant de traiter l’événement
Il existe plusieurs types d’événements webhook, et chaque événement peut avoir plusieurs actions. À mesure que le nombre de fonctionnalités GitHub augmente, nous pouvons parfois ajouter de nouveaux types d’événements ou ajouter de nouvelles actions aux types d’événements existants. Assurez-vous que votre application vérifie explicitement le type et l’action d’un événement avant d’effectuer un traitement webhook. L’en-tête de demande X-GitHub-Event
peut être utilisé pour savoir quel événement a été reçu afin que le traitement puisse être géré de manière appropriée. De même, la charge utile a une clé de niveau supérieur action
qui peut être utilisée pour savoir quelle action a été effectuée sur l’objet concerné.
Par exemple, si vous avez configuré un webhook GitHub pour tout recevoir (« Send me everything »), votre application recevra les nouveaux types d’événements et les nouvelles actions à mesure qu’ils sont ajoutés. Il n’est donc pas recommandé d’utiliser n’importe quelle sorte de clause catch-all else. Prenez l’exemple de code suivant :
# Not recommended: a catch-all else clause
def receive
event_type = request.headers["X-GitHub-Event"]
payload = request.body
case event_type
when "repository"
process_repository(payload)
when "issues"
process_issues(payload)
else
process_pull_requests
end
end
Dans cet exemple de code, les méthodes process_repository
et process_issues
seront correctement appelées si un événement repository
ou issues
a été reçu. Toutefois, tout autre type d’événement entraînera l’appel de process_pull_requests
. Si de nouveaux types d’événements sont ajoutés, cela entraînera un comportement incorrect et les nouveaux types d’événements seront traités de la même façon qu’un événement pull_request
.
Au lieu de cela, nous vous suggérons de vérifier explicitement les types d’événements et d’agir en conséquence. Dans l’exemple de code suivant, nous vérifions explicitement un événement pull_request
, et la clause else
journalise simplement que nous avons reçu un nouveau type d’événement :
# Recommended: explicitly check each event type
def receive
event_type = request.headers["X-GitHub-Event"]
payload = JSON.parse(request.body)
case event_type
when "repository"
process_repository(payload)
when "issues"
process_issue(payload)
when "pull_request"
process_pull_requests(payload)
else
puts "Oooh, something new from GitHub: #{event_type}"
end
end
Étant donné que chaque événement peut également avoir plusieurs actions, il est recommandé que les actions soient vérifiées de la même manière. Par exemple, IssuesEvent
a plusieurs actions possibles. Elles incluent notamment opened
quand le problème est créé, closed
quand le problème est fermé et assigned
quand le problème est affecté à une personne.
Comme pour l’ajout de types d’événements, nous pouvons ajouter de nouvelles actions aux événements existants. Il n’est donc pas recommandé d’utiliser n’importe quelle clause catch-all else lorsque vous vérifiez l’action d’un événement. Au lieu de cela, nous vous suggérons de vérifier explicitement les actions d’événement comme nous l’avons fait avec le type d’événement. Voici un exemple très similaire à ce que nous avons suggéré pour les types d’événements ci-dessus :
# Recommended: explicitly check each action
def process_issue(payload)
case payload["action"]
when "opened"
process_issue_opened(payload)
when "assigned"
process_issue_assigned(payload)
when "closed"
process_issue_closed(payload)
else
puts "Oooh, something new from GitHub: #{payload["action"]}"
end
end
Dans cet exemple, l’action closed
est vérifiée avant l’appel de la méthode process_closed
. Toutes les actions non identifiées sont journalisées en vue d’une consultation future.
Gestion des erreurs d’API
Même si votre code ne peut pas générer de bogue, vous pouvez rencontrer des erreurs successives lorsque vous tentez d’accéder à l’API.
Au lieu d’ignorer les codes d’état 4xx
et 5xx
, vérifiez que vous interagissez correctement avec l’API. Par exemple, si un point de terminaison demande une chaîne et que vous transmettez une valeur numérique, vous recevrez une erreur de validation 5xx
et votre appel échouera. De même, toute tentative d’accès à un point de terminaison non autorisé ou inexistant entraîne une erreur 4xx
.
Le fait d’ignorer intentionnellement toutes les erreurs de validation peut entraîner la suspension de votre application pour abus.