Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
This repository was archived by the owner on Nov 1, 2017. It is now read-only.

Commitfe8b0c2

Browse files
committed
Where there was two, now there is one
1 parent17df458 commitfe8b0c2

File tree

4 files changed

+195
-86
lines changed

4 files changed

+195
-86
lines changed
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
---
2+
title:Building a CI server | GitHub API
3+
---
4+
5+
#Building a CI server
6+
7+
* TOC
8+
{:toc}
9+
10+
The[Status API][status API] is responsible for tying together commits with
11+
a testing service, so that every push you make can be tested and represented
12+
in a GitHub pull request.
13+
14+
This guide will use that API to demonstrate a setup that you can use.
15+
In our scenario, we will:
16+
17+
* Run our CI suite when a Pull Request is opened (we'll set the CI status to pending).
18+
* When the CI is finished, we'll set the Pull Request's status accordingly.
19+
20+
Our CI system and host server will be figments of our imagination. They could be
21+
Travis, Jenkins, or something else entirely. The crux of this guide will be setting up
22+
and configuring the server managing the communication.
23+
24+
If you haven't already, be sure to[download ngrok][ngrok], and learn how
25+
to[use it][using ngrok]. We find it to be a very useful tool for exposing local
26+
connections.
27+
28+
Note: you can download the complete source code for this project
29+
[from the platform-samples repo][platform samples].
30+
31+
##Writing your server
32+
33+
We'll write a quick Sinatra app to prove that our local connections are working.
34+
Let's start with this:
35+
36+
#!ruby
37+
require 'sinatra'
38+
require 'json'
39+
40+
post '/event_handler' do
41+
payload = JSON.parse(params[:payload])
42+
"Well, it worked!"
43+
end
44+
45+
46+
(If you're unfamiliar with how Sinatra works, we recommend[reading the Sinatra guide][Sinatra].)
47+
48+
Start this server up. By default, Sinatra starts on port`9393`, so you'll want
49+
to configure ngrok to start listening for that, too.
50+
51+
In order for this server to work, we'll need to set a repository up with a webhook.
52+
The webhook should be configured to fire whenever a Pull Request is created, or merged.
53+
Go ahead and create a repository you're comfortable playing around in. Might we
54+
suggest[@octocat's Spoon/Knife repository](https://github.com/octocat/Spoon-Knife)?
55+
After that, you'll create a new webhook in your repository, feeding it the URL
56+
that ngrok gave you:
57+
58+
![A new ngrok URL](/images/webhooks_recent_deliveries.png)
59+
60+
Click**Update webhook**. You should see a body response of`Well, it worked!`.
61+
Great! Click on**Let me select individual events.**, and select the following:
62+
63+
* Status
64+
* Pull Request
65+
66+
These are the events GitHub will send to our server whenever the relevant action
67+
occurs. Let's update our server to*just* handle the Pull Request scenario right now:
68+
69+
#!ruby
70+
post '/event_handler' do
71+
@payload = JSON.parse(params[:payload])
72+
73+
case request.env['HTTP_X_GITHUB_EVENT']
74+
when "pull_request"
75+
if @payload["action"] == "opened"
76+
process_pull_request(@payload["pull_request"])
77+
end
78+
end
79+
end
80+
81+
helpers do
82+
def process_pull_request(pull_request)
83+
puts "It's #{pull_request['title']}"
84+
end
85+
end
86+
87+
What's going on? Every event that GitHub sends out attached a`X-GitHub-Event`
88+
HTTP header. We'll only care about the PR events for now. From there, we'll
89+
take the payload of information, and return the title field. In an ideal scenario,
90+
our server would be concerned with every time a pull request is updated, not just
91+
when it's updated. That would make sure that every new push passes the CI tests.
92+
But for this demo, we'll just worry about when it's opened.
93+
94+
To test out this proof-of-concept, make some changes in a branch in your test
95+
repository, and open a pull request. Your server should respond accordingly!
96+
97+
##Working with statuses
98+
99+
With our server in place, we're ready to start our first requirement, which is
100+
setting (and updating) CI statuses. Note that at any time you update your server,
101+
you can click**Redeliver** to send the same payload. There's no need to make a
102+
new pull request every time you make a change!
103+
104+
Since we're interacting with the GitHub API, we'll use[Octokit.rb][octokit.rb]
105+
to manage our interactions. We'll configure that client with
106+
[a personal access token][access token]:
107+
108+
#!ruby
109+
# !!! DO NOT EVER USE HARD-CODED VALUES IN A REAL APP !!!
110+
# Instead, set and test environment variables, like below
111+
ACCESS_TOKEN = ENV['MY_PERSONAL_TOKEN']
112+
113+
before do
114+
@client ||= Octokit::Client.new(:access_token => ACCESS_TOKEN)
115+
end
116+
117+
After that, we'll just need to update the pull request on GitHub to make clear
118+
that we're processing on the CI:
119+
120+
#!ruby
121+
def process_pull_request(pull_request)
122+
puts "Processing pull request..."
123+
@client.create_status(pull_request['head']['repo']['full_name'], pull_request['head']['sha'], 'pending')
124+
end
125+
126+
We're doing three very basic things here:
127+
128+
* we're looking up the full name of the repository
129+
* we're looking up the last SHA of the pull request
130+
* we're setting the status to "pending"
131+
132+
That's it! From here, you can run whatever process you need to in order to execute
133+
your test suite. Maybe you're going to pass off your code to Jenkins, or call
134+
on another web service via its API, like[Travis][travis api]. After that, you'd
135+
be sure to update the status once more. In our example, we'll just set it to`"success"`:
136+
137+
#!ruby
138+
def process_pull_request(pull_request)
139+
@client.create_status(pull_request['head']['repo']['full_name'], pull_request['head']['sha'], 'pending')
140+
sleep 2 # do busy work...
141+
@client.create_status(pull_request['head']['repo']['full_name'], pull_request['head']['sha'], 'success')
142+
puts "Pull request processed!"
143+
end
144+
145+
##Conclusion
146+
147+
At GitHub, we've used a version of[Janky][janky] to manage our CI for years.
148+
The basic flow is essentially the exact same as the server we've built above.
149+
At GitHub, we:
150+
151+
* Fire to Jenkins when a pull request is created or updated (via Janky)
152+
* Wait for a response on the state of the CI
153+
* If the code is green, we merge the pull request
154+
155+
All of this communication is funneled back to our chat rooms. You don't need to
156+
build your own CI or deployment setup to use this example.
157+
You can always rely on[third-party services][integrations].
158+
159+
[deploy API]:/v3/repos/deployments/
160+
[status API]:/v3/repos/statuses/
161+
[ngrok]:https://ngrok.com/
162+
[using ngrok]:/webhooks/configuring/#using-ngrok
163+
[platform samples]:https://github.com/github/platform-samples/tree/master/api/ruby/building-a-ci-server
164+
[Sinatra]:http://www.sinatrarb.com/
165+
[webhook]:/webhooks/
166+
[octokit.rb]:https://github.com/octokit/octokit.rb
167+
[access token]:https://help.github.com/articles/creating-an-access-token-for-command-line-use
168+
[travis api]:https://api.travis-ci.org/docs/
169+
[janky]:https://github.com/github/janky
170+
[heaven]:https://github.com/atmos/heaven
171+
[hubot]:https://github.com/github/hubot
172+
[integrations]:https://github.com/integrations

‎content/guides/constructing-a-basic-ci-server.md‎renamed to ‎content/guides/delivering-deployments.md‎

Lines changed: 21 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
---
2-
title:Constructing a basic CI server | GitHub API
2+
title:Delivering deployments | GitHub API
33
---
44

5-
#Constructing a basic CI server
5+
#Delivering deployments
66

77
* TOC
88
{:toc}
@@ -12,15 +12,15 @@ the capability to launch them on a production server that you own. Combined with
1212
[the status API][status API], you'll be able to coordinate your deployments
1313
the moment your code lands on`master`.
1414

15-
This guide willcombine these twoAPI to demonstratean end-to-endsetup that
16-
you can use.In our scenario, we will:
15+
This guide willuse thatAPI to demonstrateasetup that you can use.
16+
In our scenario, we will:
1717

18-
*Run our CI suite whena Pull Request is opened (we'll set the CI status to pending).
18+
*Mergea Pull Request
1919
* When the CI is finished, we'll set the Pull Request's status accordingly.
2020
* When the Pull Request is merged, we'll run our deployment to our server.
2121

2222
Our CI system and host server will be figments of our imagination. They could be
23-
Travis, Jenkins, Heroku,orAmazon. The crux of this guide will be setting up
23+
Heroku, Amazon,orsomething else entirely. The crux of this guide will be setting up
2424
and configuring the server managing the communication.
2525

2626
If you haven't already, be sure to[download ngrok][ngrok], and learn how
@@ -62,112 +62,50 @@ that ngrok gave you:
6262
Click**Update webhook**. You should see a body response of`Well, it worked!`.
6363
Great! Click on**Let me select individual events.**, and select the following:
6464

65-
* Status
6665
* Deployment
6766
* Deployment status
6867
* Pull Request
6968

7069
These are the events GitHub will send to our server whenever the relevant action
71-
occurs.Let's update our server to*just* handle the Pull Request scenario right now:
70+
occurs.We'll configure our server to*just* handle the Pull Request scenario right now:
7271

7372
#!ruby
7473
post '/event_handler' do
7574
@payload = JSON.parse(params[:payload])
7675

7776
case request.env['HTTP_X_GITHUB_EVENT']
7877
when "pull_request"
79-
if @payload["action"] == "opened"
80-
process_pull_request(@payload["pull_request"])
78+
if @payload["action"] == "closed" && @payload["pull_request"]["merged"]
79+
puts "A pull request was merged! A dpeloyment should start now..."
8180
end
8281
end
8382
end
8483

85-
helpers do
86-
def process_pull_request(pull_request)
87-
puts "It's #{pull_request['title']}"
88-
end
89-
end
90-
9184
What's going on? Every event that GitHub sends out attached a`X-GitHub-Event`
92-
HTTP header. We'll only care about the PR events for now. From there, we'll
93-
take the payload of information, and return the title field. In an ideal scenario,
94-
our server would be concerned with every time a pull request is updated, not just
95-
when it's updated. That would make sure that every new push passes the CI tests.
96-
But for this demo, we'll just worry about when it's opened.
85+
HTTP header. We'll only care about the PR events for now. When a pull request is
86+
merged (its state is`closed`, and`merged` is`true`), we'll kick off a deployment.
9787

9888
To test out this proof-of-concept, make some changes in a branch in your test
99-
repository, and open a pull request. Your server should respond accordingly!
100-
101-
##Working with statuses
102-
103-
With our server in place, we're ready to start our first requirement, which is
104-
setting (and updating) CI statuses. Note that at any time you update your server,
105-
you can click**Redeliver** to send the same payload. There's no need to make a
106-
new pull request every time you make a change!
107-
108-
Since we're interacting with the GitHub API, we'll use[Octokit.rb][octokit.rb]
109-
to manage our interactions. We'll configure that client with
110-
[a personal access token][access token]:
111-
112-
#!ruby
113-
# !!! DO NOT EVER USE HARD-CODED VALUES IN A REAL APP !!!
114-
# Instead, set and test environment variables, like below
115-
ACCESS_TOKEN = ENV['MY_PERSONAL_TOKEN']
116-
117-
before do
118-
@client ||= Octokit::Client.new(:access_token => ACCESS_TOKEN)
119-
end
120-
121-
After that, we'll just need to update the pull request on GitHub to make clear
122-
that we're processing on the CI:
123-
124-
#!ruby
125-
def process_pull_request(pull_request)
126-
puts "Processing pull request..."
127-
@client.create_status(pull_request['head']['repo']['full_name'], pull_request['head']['sha'], 'pending')
128-
end
129-
130-
We're doing three very basic things here:
131-
132-
* we're looking up the full name of the repository
133-
* we're looking up the last SHA of the pull request
134-
* we're setting the status to "pending"
135-
136-
That's it! From here, you can run whatever process you need to in order to execute
137-
your test suite. Maybe you're going to pass off your code to Jenkins, or call
138-
on another web service via its API, like[Travis][travis api]. After that, you'd
139-
be sure to update the status once more. In our example, we'll just set it to`"success"`:
140-
141-
#!ruby
142-
def process_pull_request(pull_request)
143-
@client.create_status(pull_request['head']['repo']['full_name'], pull_request['head']['sha'], 'pending')
144-
sleep 2 # do busy work...
145-
@client.create_status(pull_request['head']['repo']['full_name'], pull_request['head']['sha'], 'success')
146-
puts "Pull request processed!"
147-
end
89+
repository, open a pull request, and merge it. Your server should respond accordingly!
14890

14991
##Working with deployments
15092

151-
Our CI tests have passed, andthe codehas beenreviewed. When the pull request
93+
With our server in place,the codebeingreviewed, and our pull request
15294
is merged, we want our project to be deployed to the production server.
15395

154-
We'll start by modifying our event listener topay attention whenpull requests
155-
have been merged:
96+
We'll start by modifying our event listener toprocesspull requests when they're
97+
merged, and start paying attention to deployments:
15698

15799
#!ruby
158100
when "pull_request"
159-
if @payload["action"] == "opened"
160-
process_pull_request(@payload["pull_request"])
161-
elsif @payload["action"] == "closed" && @payload["pull_request"]["merged"]
101+
if @payload["action"] == "closed" && @payload["pull_request"]["merged"]
162102
start_deployment(@payload["pull_request"])
163103
end
164104
when "deployment"
165105
process_deployment(@payload)
166106
end
167107

168-
When a pull request is merged (its state is`closed`, and`merged` is`true`), we'll
169-
kick off a deployment. Based on the information from the pull request, we'll fill
170-
out the`start_deployment` method:
108+
Based on the information from the pull request, we'll fill out the`start_deployment` method:
171109

172110
#!ruby
173111
def start_deployment(pull_request)
@@ -225,25 +163,23 @@ that this pattern is the exact same as when we updated our CI status.
225163

226164
##Conclusion
227165

228-
At GitHub, we've usedversions of[Janky][janky] and[Heaven][heaven] to manage
166+
At GitHub, we've useda version of[Heaven][heaven] to manage
229167
our deployments for years. The basic flow is essentially the exact same as the
230168
server we've built above. At GitHub, we:
231169

232-
* Fire to Jenkins when a pull request is created or updated (via Janky)
233170
* Wait for a response on the state of the CI
234171
* If the code is green, we merge the pull request
235172
* Heaven takes the merged code, and deploys it to our production servers
236173
* In the meantime, Heaven also notifies everyone about the build, via[Hubot][hubot] sitting in our chat rooms
237174

238175
That's it! You don't need to build your own CI or deployment setup to use this example.
239-
You can always rely on third-party services like Travis CI, Heroku, or any number
240-
[of additional integrators][integrations].
176+
You can always rely on[third-party services][integrations].
241177

242178
[deploy API]:/v3/repos/deployments/
243-
[status API]:/v3/repos/statuses/
179+
[status API]:/guides/building-a-ci-server
244180
[ngrok]:https://ngrok.com/
245181
[using ngrok]:/webhooks/configuring/#using-ngrok
246-
[platform samples]:https://github.com/github/platform-samples/tree/master/api/ruby/building-a-deployment-server
182+
[platform samples]:https://github.com/github/platform-samples/tree/master/api/ruby/delivering-deployments
247183
[Sinatra]:http://www.sinatrarb.com/
248184
[webhook]:/webhooks/
249185
[octokit.rb]:https://github.com/octokit/octokit.rb

‎layouts/guides.html‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ <h2><a href="/v3/">API</a></h2>
2828
<li><h3><ahref="/guides/rendering-data-as-graphs/">Rendering data as graphs</a></h3></li>
2929
<li><h3><ahref="/guides/working-with-comments/">Working with comments</a></h3></li>
3030
<li><h3><ahref="/guides/traversing-with-pagination/">Traversing with pagination</a></h3></li>
31-
<li><h3><ahref="/guides/constructing-a-basic-ci-server/">Constructing a basic CI server</a></h3></li>
31+
<li><h3><ahref="/guides/building-a-ci-server/">Building a CI server</a></h3></li>
32+
<li><h3><ahref="/guides/delivering-deployments/">Delivering deployments</a></h3></li>
3233
</ul>
3334
</div>
3435

‎static/images/electrocat.png‎

25.4 KB
Loading

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp