Skip to main content

CI 서버 빌드

상태 API를 사용하여 고유한 CI 시스템을 빌드합니다.

REST API를 사용하여 커밋을 테스트 서비스와 함께 연결하여 수행되는 모든 푸시를 테스트하고 GitHub Enterprise Cloud 끌어오기 요청으로 나타낼 수 있도록 합니다. 관련 엔드포인트에 대한 자세한 내용은 "커밋 상태에 대한 REST API 엔드포인트"을(를) 참조하세요.

이 가이드에서는 해당 API로 사용할 수 있는 설정을 보여 줍니다. 이 시나리오에서는 다음을 수행합니다.

  • 끌어오기 요청이 열릴 때 CI 제품군을 실행합니다(CI 상태를 보류 중으로 설정).
  • CI가 완료되면 그에 따라 끌어오기 요청의 상태를 설정합니다.

CI 시스템 및 호스트 서버는 상상한 그대로가 됩니다. Travis, Jenkins 또는 완전히 다른 무언가가 될 수 있습니다. 이 가이드의 핵심은 통신을 관리하는 서버를 설정하고 구성하는 것입니다.

아직 다운로드하지 않은 경우 ngrok을 다운로드하고 사용 방법을 알아보세요. 로컬 애플리케이션을 인터넷에 노출하는 데 매우 유용한 도구라고 합니다.

참고: 또는 웹후크 전달을 사용하여 웹후크를 수신하도록 로컬 환경을 설정할 수 있습니다. 자세한 내용은 "GitHub CLI를 사용하여 테스트용 웹후크 전달하기"을(를) 참조하세요.

참고: 플랫폼 샘플 리포지토리에서 이 프로젝트에 대한 전체 소스 코드를 다운로드할 수 있습니다.

서버 작성

로컬 연결이 작동하는지 증명하기 위해 빠른 Sinatra 앱을 작성합니다. 먼저 다음을 살펴보겠습니다.

require 'sinatra'
require 'json'

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

(Sinatra의 작동 방식에 익숙하지 않은 경우 가이드를 읽는 것이 좋습니다.)

이 서버를 시작합니다. 기본적으로 Sinatra는 포트 4567에서 시작되므로 ngrok도 수신 대기를 시작하도록 구성할 수 있습니다.

이 서버가 작동하려면 웹후크를 사용하여 리포지토리를 설정해야 합니다. 끌어오기 요청을 만들거나 병합할 때마다 webhook가 실행되도록 구성해야 합니다.

계속 진행하여 편안하게 사용할 수 있는 리포지토리를 만듭니다. @octocat의 스푼/나이프 리포지토리를 제안해보겠습니다.

그런 다음, 리포지토리에 새 webhook를 만들고, ngrok에서 제공한 URL을 피드하고, 콘텐츠 형식으로 application/x-www-form-urlencoded를 선택합니다.

웹후크 업데이트를 클릭합니다. Well, it worked!라는 응답이 표시되어야 합니다. 좋습니다! 개별 이벤트 선택을 클릭하고 다음을 선택합니다.

  • 상태
  • 끌어오기 요청

관련 작업이 발생할 때마다 이벤트 GitHub Enterprise Cloud에서 서버로 보내는 이벤트입니다. 지금 바로 끌어오기 요청 시나리오를 처리하도록 서버를 업데이트해 보겠습니다.__

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

무슨 일입니까? GitHub Enterprise Cloud이 전송하는 모든 이벤트에는 X-GitHub-Event HTTP 헤더가 첨부되었습니다. 지금은 PR 이벤트만 신경을 써야 합니다. 여기에서 정보의 페이로드를 가져와서 제목 필드를 반환합니다. 이상적인 시나리오에서는 끌어오기 요청이 열릴 때 뿐만 아니라 업데이트될 때마다 서버가 관계됩니다. 이렇게 하면 모든 새 푸시가 CI 테스트를 통과해야 합니다. 하지만 이 데모에서는 언제 열릴지만 생각합니다.

이 개념 증명을 테스트하려면 테스트 리포지토리의 분기를 몇 가지 변경하고 끌어오기 요청을 엽니다. 서버가 그에 따라 응답해야 합니다!

상태 작업

서버를 준비하면 CI 상태를 설정(및 업데이트)하는 첫 번째 요구 사항을 시작할 준비가 된 것입니다. 서버를 업데이트할 때마다 Redeliver를 클릭하여 동일한 페이로드를 보낼 수 있습니다. 변경할 때마다 새 끌어오기 요청을 수행할 필요가 없습니다.

GitHub API와 상호 작용하고 있으므로 Octokit.rb를 사용하여 상호 작용을 관리합니다. 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

그 후에는 CI에서 처리 중임을 분명히 하기 위해 GitHub Enterprise Cloud에 대한 끌어오기 요청을 업데이트하기만 하면 됩니다.

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

여기서는 세 가지 매우 기본적인 작업을 수행합니다.

  • 리포지토리의 전체 이름을 찾습니다.
  • 끌어오기 요청의 마지막 SHA를 찾습니다.
  • 상태를 “보류 중”으로 설정합니다.

정말 간단하죠. 여기에서 테스트 제품군을 실행하기 위해 필요한 모든 프로세스를 실행할 수 있습니다. 코드를 Jenkins에 전달하거나 Travis와 같은 API를 통해 다른 웹 서비스를 호출할 수 있습니다. 그 후에는 상태를 다시 한 번 업데이트해야 합니다. 이 예제에서는 "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

결론

GitHub에서는 여러 해 동안 Janky 버전을 사용하여 CI를 관리해 왔습니다. 기본 흐름은 기본적으로 위에서 빌드한 서버와 동일합니다. GitHub에서는 다음을 수행합니다.

  • 끌어오기 요청을 만들거나 업데이트할 때 Jenkins에 실행(Janky를 통해)
  • CI 상태에 대한 응답을 기다립니다.
  • 코드가 녹색이면 끌어오기 요청을 병합합니다.

이 모든 통신은 채팅방으로 다시 유입됩니다. 이 예제를 사용하기 위해 고유한 CI 설정을 빌드할 필요가 없습니다. 항상 GitHub 통합에 의존할 수 있습니다.