Skip to main content

Crear un servidor de IC

Crea tu propio sistema de IC utilizando la API de Estados.

Puedes usar la API REST para combinar las confirmaciones con un servicio de pruebas a fin de que cada envío de cambios que hagas se pueda probar y se represente en una solicitud de incorporación de cambios de GitHub. Para obtener más información sobre los puntos de conexión relevantes, consulta "Puntos de conexión de la API de REST para estados de confirmaciones".

Esta guía utilizará la API para demostrar una configuración que puedes utilizar. En nuestro escenario, nosotros:

  • Ejecutaremos nuestra suit de IC cuando se abra una Solicitud de Extracción (configuraremos el estado de IC como pendiente).
  • Cuando finalice la IC, configuraremos el estado de la Solicitud de Extracción como corresponda.

Nuestro sistema de IC y nuestro servidor host serán imaginarios. Podrían ser Travis, Jenkins, o algo completamente distinto. El meollo de esta guía será configurar y ajustar el servidor que administra la comunicación.

Si todavía no lo has hecho, descarga ngrok y aprende a usarlo. Consideramos que es una herramienta muy útil para exponer las aplicaciones locales a Internet.

Note

Como alternativa, puedes usar el reenvío de webhooks para configurar el entorno local para recibir webhooks. Para obtener más información, vea «Uso de la CLI de GitHub para reenviar webhooks para pruebas».

Nota: Puede descargar el código fuente completo de este proyecto desde el repositorio platform-samples.

Escribir tu servidor

Escribiremos una app de Sinatra rápidamente para probar que nuestras conexiones locales estén funcionando. Comencemos con esto:

require 'sinatra'
require 'json'

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

(Si no está familiarizado con el funcionamiento de Sinatra, le recomendamos leer la guía de Sinatra).

Inicia este servidor. De manera predeterminada, Sinatra comienza en el puerto 4567, por lo que también tendrás que configurar ngrok para que empiece a escuchar en este puerto.

Para que este servidor funcione, necesitaremos configurar un repositorio con un webhook. El webhook debe configurarse para que se active cada que se crea o fusiona una solicitud de extracción.

Sigue adelante y crea un repositorio en el que quieras hacer tus experimentos. ¿Podríamos sugerir el repositorio de cucharas y cuchillos de @octocat?

Después de esto, crearás un webhook en el repositorio, le suministrarás la dirección URL que te ha proporcionado ngrok y seleccionarás application/x-www-form-urlencoded como el tipo de contenido.

Haga clic en Update Webhook. Debería ver una respuesta del cuerpo de Well, it worked!. Magnífico. Haga clic en Let me select individual events y seleccione lo siguiente:

  • Estado
  • Solicitud de incorporación de cambios

Estos son los eventos que GitHub enviará al servidor cuando se produzca cualquier acción relevante. Ahora se actualizará el servidor para que solo controle el escenario de solicitud de incorporación de cambios:

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

  case request.env['HTTP_X_GITHUB_EVENT']
  when "pull_request"
    if @payload["action"] == "opened"
      process_pull_request(@payload["pull_request"])
    end
  end
end

helpers do
  def process_pull_request(pull_request)
    puts "It's #{pull_request['title']}"
  end
end

¿Qué sucede? En cada evento que envía GitHub se adjunta un encabezado HTTP X-GitHub-Event. Solo nos interesan los eventos de Solicitud de Extracción por el momento. Desde ahí, se tomará la carga de información y se devolverá el campo de título. En un escenario idóneo, al servidor le interesarían todas las actualizaciones de una solicitud de incorporación de cambios, no solo cuando se abra. Eso garantizaría que todas las cargas pasen la prueba de IC. Pero para efectos de esta demostración, solo nos interesará cuándo se abren.

Para probar esta prueba de concepto, realice algunos cambios en una rama del repositorio de pruebas y abra una solicitud de incorporación de cambios. ¡Tu servidor deberá responder de acuerdo con los casos!

Trabajar con los estados

Después de implementar el servidor, ya se puede comenzar el primer requisito: configurar (y actualizar) los estados de CI. Tenga en cuenta que siempre que actualice el servidor, puede hacer clic en Redeliver para enviar la misma carga. No es necesario crear una solicitud de incorporación de cambios cada vez que realice un cambio.

Como se interactúa con la API GitHub, se usará Octokit.rb para administrar las interacciones. Configuraremos ese cliente con personal access token:

# !!! DO NOT EVER USE HARD-CODED VALUES IN A REAL APP !!!
# Instead, set and test environment variables, like below
ACCESS_TOKEN = ENV['MY_PERSONAL_TOKEN']

before do
  @client ||= Octokit::Client.new(:access_token => ACCESS_TOKEN)
end

Después, solo habrá que actualizar la solicitud de incorporación de cambios en GitHub para dejar claro lo que se procesa en la CI:

def process_pull_request(pull_request)
  puts "Processing pull request..."
  @client.create_status(pull_request['base']['repo']['full_name'], pull_request['head']['sha'], 'pending')
end

Estamos haciendo tres cosas muy básicas aquí:

  • buscando el nombre completo del repositorio
  • buscando el último SHA de la solicitud de extracción
  • configurando el estado como "pendiente"

Eso es todo. A partir de ahora, puede ejecutar el proceso que necesite para ejecutar el conjunto de pruebas. Es posible que tenga que pasar el código a Jenkins, o bien llamar a otro servicio web mediante su API, como Travis. Después, asegúrese de actualizar el estado una vez más. En el ejemplo, simplemente se establecerá en "success":

def process_pull_request(pull_request)
  @client.create_status(pull_request['base']['repo']['full_name'], pull_request['head']['sha'], 'pending')
  sleep 2 # do busy work...
  @client.create_status(pull_request['base']['repo']['full_name'], pull_request['head']['sha'], 'success')
  puts "Pull request processed!"
end

Conclusión

En GitHub, se ha usado una versión de Janky para administrar la CI durante años. El flujo básico es esencial y exactamente el mismo que en el servidor que acabamos de crear. En GitHub, nosotros:

  • Notificamos todo a Jenkins cuando se crea o actualiza una solicitud de extracción (a través de Janky)
  • Esperamos una respuesta del estado de la IC
  • Si el código tiene luz verde, lo fusionamos con la solicitud de extracción

Todas estas comunicaciones se canalizan de vuelta a nuestras salas de chat. No es necesario crear una configuración de CI propia para utilizar este ejemplo. Siempre puede recurrir a las integraciones de GitHub.