Skip to main content

Enterprise Server 3.20 est actuellement disponible en tant que version candidate.

Livraison de déploiements

À l’aide de l’API REST Déploiements, vous pouvez créer des outils personnalisés qui interagissent avec votre serveur et une application tierce.

Vous pouvez utiliser l’API REST pour déployer vos projets hébergés dans GitHub sur un serveur dont vous êtes propriétaire. Pour plus d’informations sur les points de terminaison permettant de gérer les déploiements et les états, consultez Points de terminaison d’API REST pour les déploiements. Vous pouvez également utiliser l’API REST pour coordonner vos déploiements au moment où votre code arrive sur la branche par défaut. Pour plus d’informations, consultez « Création d’un serveur CI ».

Ce guide utilise l’API REST pour illustrer une configuration possible. Dans notre scénario, nous allons :

  • Fusionner une pull request.
  • Une fois l’intégration continue (CI) terminée, nous définirons l’état de la demande de tirage en conséquence.
  • Une fois que le pull request est fusionné, nous lancerons notre déploiement sur notre serveur.

Notre système CI et notre serveur hôte seront le fruit de notre imagination. Il pourrait s’agir de Heroku, d’Amazon, ou de toute autre chose. Ce guide porte principalement sur l’installation et la configuration du serveur gérant la communication.

Si vous ne l’avez pas déjà fait, veillez à télécharger ngrok, puis apprenez à l’utiliser. Cet outil est très utile pour exposer des applications locales sur Internet.

Remarque : Vous pouvez télécharger le code source complet de ce projet à partir du dépôt platform-samples.

Écriture de votre serveur

Nous allons écrire rapidement une application Sinatra pour prouver que nos connexions locales fonctionnent. Commençons par ceci :

require 'sinatra'
require 'json'

post '/event_handler' do
  payload = JSON.parse(params[:payload])
  "Well, it worked!"
end

(Si vous n’êtes pas familiarisé avec le fonctionnement de Sinatra, nous vous recommandons de lire le guide Sinatra.)

Démarrez ce serveur. Par défaut, Sinatra démarre sur le port 4567. Vous devez également donc configurer ngrok pour qu’il commence à écouter ce port.

Pour que ce serveur fonctionne, nous devons configurer un dépôt avec un webhook. Le webhook doit être configuré pour se déclencher à chaque création ou fusion d'une pull request.

Créez un dépôt dans lequel vous vous sentez à l’aise pour expérimenter. Pouvons-nous suggérer le dépôt Spoon/Knife d’@octocat ?

Après cela, vous allez créer un webhook dans votre dépôt, en lui fournissant l’URL que ngrok vous a donnée et en choisissant application/x-www-form-urlencoded comme type de contenu.

Cliquez sur Mettre à jour le webhook. Vous devriez voir la réponse de corps suivante : Well, it worked!. Très bien ! Cliquez sur Me laisser sélectionner des événements individuels, puis sélectionnez ce qui suit :

  • Déploiement
  • état du déploiement
  • Demande de tirage (pull request)

Il s’agit des événements que GitHub enverra à notre serveur chaque fois que l’action appropriée se produira. Nous allons tout de suite configurer notre serveur pour simplement gérer lorsqu'un pull request est fusionné.

post '/event_handler' do
  @payload = JSON.parse(params[:payload])

  case request.env['HTTP_X_GITHUB_EVENT']
  when "pull_request"
    if @payload["action"] == "closed" && @payload["pull_request"]["merged"]
      puts "A pull request was merged! A deployment should start now..."
    end
  end
end

Que se passe-t-il ? Chaque événement que GitHub envoie est accompagné d'un en-tête HTTP X-GitHub-Event. Pour l’instant, nous allons uniquement nous occuper des événements de demande de tirage. Lorsqu'une pull request est fusionnée (son état est closed, et merged est true), nous déclenchons un déploiement.

Pour tester cette preuve de concept, apportez des modifications à une branche dans votre dépôt de test, ouvrez une pull request et fusionnez-la. Votre serveur doit répondre en conséquence !

Travail avec les déploiements

Avec notre serveur en place, le code en cours d'examen et notre pull request fusionnée, nous voulons que notre projet soit déployé.

Nous allons commencer par modifier notre écouteur d’événements pour traiter les demandes de tirage lors de leur fusion, et commencer à prêter attention aux déploiements :

when "pull_request"
  if @payload["action"] == "closed" && @payload["pull_request"]["merged"]
    start_deployment(@payload["pull_request"])
  end
when "deployment"
  process_deployment(@payload)
when "deployment_status"
  update_deployment_status
end

À partir des informations de la requête d'extraction, nous allons commencer par remplir la méthode start_deployment :

def start_deployment(pull_request)
  user = pull_request['user']['login']
  payload = JSON.generate(:environment => 'production', :deploy_user => user)
  @client.create_deployment(pull_request['head']['repo']['full_name'], pull_request['head']['sha'], {:payload => payload, :description => "Deploying my sweet branch"})
end

Des déploiements peuvent avoir des métadonnées attachées, sous la forme d’une payload et d’une description. Bien que ces valeurs soient facultatives, elles sont utiles pour la journalisation et la représentation des informations.

Lorsqu'un nouveau déploiement est créé, un événement entièrement distinct est déclenché. C’est pourquoi nous avons un nouveau cas switch dans le gestionnaire d’événements pour deployment. Vous pouvez utiliser ces informations pour être averti lors du déclenchement d’un déploiement.

Les déploiements pouvant prendre un peu de temps, nous voulons écouter divers événements, tels que le moment de création du déploiement et l’état dans lequel il se trouve.

Simulons un déploiement qui effectue un certain travail, et observons son effet sur la sortie. Commençons par compléter notre méthode process_deployment :

def process_deployment
  payload = JSON.parse(@payload['payload'])
  # you can send this information to your chat room, monitor, pager, etc.
  puts "Processing '#{@payload['description']}' for #{payload['deploy_user']} to #{payload['environment']}"
  sleep 2 # simulate work
  @client.create_deployment_status("repos/#{@payload['repository']['full_name']}/deployments/#{@payload['id']}", 'pending')
  sleep 2 # simulate work
  @client.create_deployment_status("repos/#{@payload['repository']['full_name']}/deployments/#{@payload['id']}", 'success')
end

Enfin, nous allons simuler le stockage des informations d’état en tant que sortie de console :

def update_deployment_status
  puts "Deployment status for #{@payload['id']} is #{@payload['state']}"
end

Décomposons ce qui se passe. Un nouveau déploiement est créé par start_deployment, ce qui déclenche l’événement deployment. À partir de là, nous appelons process_deployment pour simuler le travail effectué. Pendant ce traitement, nous effectuons également un appel à create_deployment_status, qui permet à un récepteur de savoir ce qui se passe lorsque nous basculons l’état sur pending.

Une fois le déploiement terminé, nous définissons l’état sur success.

Conclusion

Chez GitHub, nous avons utilisé une version de Heaven pour gérer nos déploiements depuis longtemps. Un flux commun est essentiellement le même que celui du serveur que nous avons généré ci-dessus :

  • Attendez une réponse sur l’état des vérifications de CI (réussite ou échec)
  • Si les vérifications requises passent, fusionnez la pull request.
  •         `Heaven` prend le code fusionné et le déploie sur des serveurs de préproduction et de production
    
  • En attendant, Heaven avertit également tout le monde de la build, via Hubot assis dans nos salles de conversation

Et voilà ! Vous n’avez pas besoin de générer votre propre configuration de déploiement pour utiliser cet exemple. Vous pouvez toujours vous appuyer sur des intégrations GitHub.