An overview of an afternoon project I noodled around with one day to play with Ruby and Github Webhooks. I surprised myself by creating something somewhat actually useful.
Presentation given to the Kentucky Open Source Society (KyOSS) on July 8, 2015.
12. A common Github webhook use
Your serverGithub servers
A pull request
was just opened
Kick off a build
of the pull request
and test the result
Send results
back to Github
16. The Libfabric project
• Next generation high
performance
networking user stack
• Multi-vendor /
organization
• Open source
• Hosted on Github
17. Libfabric commits
Require a “Signed-off-by” line in Git commit messages
commit d70ebb7b6f7afb51e3026c92c40b6aedae8b1417
Author: Jeff Squyres <jsquyres@cisco.com>
Date: Thu Jul 2 15:03:42 2015 -0700
libfabric.so: bump the Libtool .so version to 2:0:1
Per https://www.gnu.org/software/libtool/manual/libtool.html. Fixes #1118.
Signed-off-by: Jeff Squyres <jsquyres@cisco.com>
18. Libfabric commits
Require a “Signed-off-by” line in Git commit messages
commit d70ebb7b6f7afb51e3026c92c40b6aedae8b1417
Author: Jeff Squyres <jsquyres@cisco.com>
Date: Thu Jul 2 15:03:42 2015 -0700
libfabric.so: bump the Libtool .so version to 2:0:1
Per https://www.gnu.org/software/libtool/manual/libtool.html. Fixes #1118.
Signed-off-by: Jeff Squyres <jsquyres@cisco.com>
commit efd7a5c878f53ba12ed771fa006d57b7f9d264fd
Author: Jithin Jose <jithin.jose@intel.com>
Date: Thu Jul 2 09:05:16 2015 -0700
sockets: fix resource leak in comm buffer
Signed-off-by: Jithin Jose <jithin.jose@intel.com>
19. Libfabric commits
Require a “Signed-off-by” line in Git commit messages
commit d70ebb7b6f7afb51e3026c92c40b6aedae8b1417
Author: Jeff Squyres <jsquyres@cisco.com>
Date: Thu Jul 2 15:03:42 2015 -0700
libfabric.so: bump the Libtool .so version to 2:0:1
Per https://www.gnu.org/software/libtool/manual/libtool.html. Fixes #1118.
Signed-off-by: Jeff Squyres <jsquyres@cisco.com>
commit efd7a5c878f53ba12ed771fa006d57b7f9d264fd
Author: Jithin Jose <jithin.jose@intel.com>
Date: Thu Jul 2 09:05:16 2015 -0700
sockets: fix resource leak in comm buffer
Signed-off-by: Jithin Jose <jithin.jose@intel.com>
commit 621dd04cbe2c9e066602393d508c85d175bebbb9
Author: James Swaro <jswaro@cray.com>
Date: Mon Jun 29 12:28:32 2015 -0500
Initialize param_list to avoid crashing in library destructor
20. Libfabric commits
Require a “Signed-off-by” line in Git commit messages
commit d70ebb7b6f7afb51e3026c92c40b6aedae8b1417
Author: Jeff Squyres <jsquyres@cisco.com>
Date: Thu Jul 2 15:03:42 2015 -0700
libfabric.so: bump the Libtool .so version to 2:0:1
Per https://www.gnu.org/software/libtool/manual/libtool.html. Fixes #1118.
Signed-off-by: Jeff Squyres <jsquyres@cisco.com>
commit efd7a5c878f53ba12ed771fa006d57b7f9d264fd
Author: Jithin Jose <jithin.jose@intel.com>
Date: Thu Jul 2 09:05:16 2015 -0700
sockets: fix resource leak in comm buffer
Signed-off-by: Jithin Jose <jithin.jose@intel.com>
commit 621dd04cbe2c9e066602393d508c85d175bebbb9
Author: James Swaro <jswaro@cray.com>
Date: Mon Jun 29 12:28:32 2015 -0500
Initialize param_list to avoid crashing in library destructor
commit 621dd04cbe2c9e066602393d508c85d175bebbb9
Author: James Swaro <jswaro@cray.com>
Date: Mon Jun 29 12:28:32 2015 -0500
Initialize param_list to avoid crashing in library destructor
Missing Signed-off-by line!
22. Libfabric only accepts commits
via pull requests
Libfabric Github
Git repo
jsquyres Github
forked libfabric repo
Step 1: Jeff makes a Gihub “fork”
of the upstream Libfabric repo
23. Libfabric only accepts commits
via pull requests
Libfabric Github
Git repo
jsquyres Github
forked libfabric repo commit d70ebb7b6f7afb51e3026c92c40b6aedae8b1417
Author: Jeff Squyres <jsquyres@cisco.com>
Date: Thu Jul 2 15:03:42 2015 -0700
libfabric.so: bump the Libtool .so version to 2:0:1
Per https://www.gnu.org/software/libtool/manual/...
Signed-off-by: Jeff Squyres <jsquyres@cisco.com>
Step 2: Jeff makes a commit on his
libfabric fork
24. Libfabric only accepts commits
via pull requests
Libfabric Github
Git repo
jsquyres Github
forked libfabric repo commit d70ebb7b6f7afb51e3026c92c40b6aedae8b1417
Author: Jeff Squyres <jsquyres@cisco.com>
Date: Thu Jul 2 15:03:42 2015 -0700
libfabric.so: bump the Libtool .so version to 2:0:1
Per https://www.gnu.org/software/libtool/manual/...
Signed-off-by: Jeff Squyres <jsquyres@cisco.com>
Step 3: Jeff files a pull request to ask
if his commit can be accepted into
the main Libfabric repo
25. Libfabric only accepts commits
via pull requests
Libfabric Github
Git repo
jsquyres Github
forked libfabric repo commit d70ebb7b6f7afb51e3026c92c40b6aedae8b1417
Author: Jeff Squyres <jsquyres@cisco.com>
Date: Thu Jul 2 15:03:42 2015 -0700
libfabric.so: bump the Libtool .so version to 2:0:1
Per https://www.gnu.org/software/libtool/manual/...
Signed-off-by: Jeff Squyres <jsquyres@cisco.com>
Step 4: A libfabric maintainer accepts
Jeff’s pull request
commit d70ebb7b6f7afb51e3026c92c40b6aedae8b1417
Author: Jeff Squyres <jsquyres@cisco.com>
Date: Thu Jul 2 15:03:42 2015 -0700
libfabric.so: bump the Libtool .so version to 2:0:1
Per https://www.gnu.org/software/libtool/manual/...
Signed-off-by: Jeff Squyres <jsquyres@cisco.com>
commit d70ebb7b6f7afb51e3026c92c40b
Author: Jeff Squyres <jsquyres@cisc
Date: Thu Jul 2 15:03:42 2015 -07
libfabric.so: bump the Libtool
Per https://www.gnu.org/softwar
Signed-off-by: Jeff Squyres <js
27. The missing step
1. Jeff makes a Gihub “fork” of the upstream
Libfabric repo
2. Jeff makes a commit on his libfabric fork
3. Jeff files a pull request to ask if his commit
can be accepted into the main Libfabric repo
4. Libfabric maintainers review the pull request
commit(s)
5. A libfabric maintainer accepts Jeff’s pull
request
28. The missing step
1. Jeff makes a Gihub “fork” of the upstream
Libfabric repo
2. Jeff makes a commit on his libfabric fork
3. Jeff files a pull request to ask if his commit
can be accepted into the main Libfabric repo
4. Libfabric maintainers review the pull request
commit(s)
5. A libfabric maintainer accepts Jeff’s pull
request
29. The missing step
1. Jeff makes a Gihub “fork” of the upstream
Libfabric repo
2. Jeff makes a commit on his libfabric fork
3. Jeff files a pull request to ask if his commit
can be accepted into the main Libfabric repo
4. Libfabric maintainers review the pull request
commit(s)
5. A libfabric maintainer accepts Jeff’s pull
request
Is there a Signed-off-by line?
45. Sinatra “Signed-off-by” Github webhook
Your serverGithub servers
A pull request
was just opened
(or modified)
Check to make sure
each commit has a
Signed-off-by line
Send results
back to Github
46. Github to Sinatra logistics
Github servers
Some web server
verify-
signed-off.rb
Send results
back to Github
48. Setup
require 'rubygems’ # Required by RHEL 6
require 'httparty’ # Used in the body below for HTTP requests
require 'sinatra’ # All the Sinatra glue
require 'json’ # Used in the body below for JSON stuff
# Put Sinatra on port 5000 (a fairly arbitrary choice)
set :port, 5000
# Globals
user_agent = 'ofiwg/signed-off-by-checker'
# Read the Github auth token in from the environment (it wouldn't do
# the hard-code it where it would show up in a public Github repo!)
auth_token = ENV['GITHUB_AUTH_TOKEN
if auth_token == nil then
puts "Someone forgot to set $GITHUB_AUTH_TOKEN before launching me. Aborting!n"
exit 1
end
49. Handle HTTP Get
# Github webhooks are not delivered as HTTP GETs. If we don't have
# this Sinatra method here, Sinatra displays a goofy error message if
# someone just visits "http[s]://url_to_this_script".
# Responds to an HTTP Get for “/”
get '/' do
# Output this plain string and exit
'Nothing to see here but us chickens'
end
50. Handle HTTP Post
# Respond to an HTTP Post to “/”
post '/' do
# Parse the JSON into the “push” variable
push = JSON.parse(request.body.read)
repo_name = push['repository']['full_name']
# If this is not a push on a pull request (i.e., if there's no
# commits to examine, such as if this is a test webhook ping from
# github), then just return HTTP status 200 (i.e., success) with a
# handy message that you can see in the Github webhook debug logs.
if push['action'] == nil || (push['action'] != 'synchronize' &&
push['action'] != 'opened') then
# Returns an HTTP 200 status and a plain string
return [200, ‘Nothing for this bot to do!']
end
…continues…
51. Get all commits on this pull request
# Get _all_ commits associated with this pull request
commits_url = push['pull_request']['commits_url']
commits = HTTParty.get(commits_url,
:headers => {
'Content-Type' => 'application/json',
'User-Agent' => user_agent,
'Authorization' => "token #{auth_token}" }
)
# Setup some variables
happy = true
targetURL = 'https://github.com/ofiwg/libfabric/wiki#how-to-contribute'
debug_message = "checking debug URL: #{commits_url}nn"
final_message = ''
…continues…
52. Start analyzing the commit messages
# Loop over all the commit meta data we just downloaded
commits.each_with_index do |commit, index|
sha = commit['sha']
status_url = “https://api.github.com/repos/#{repo_name}/statuses/#{sha}”
status = { 'context' => 'Signed-off-by checker’ }
# Look for a Signed-off-by string in this commit
if /Signed-off-by/.match commit['commit']['message']
status['state'] = 'success'
status['description'] = 'This commit is signed off'
else
status['state'] = 'failure'
status['description'] = 'This commit is not signed off'
status['target_url'] = targetURL
happy = false
end
final_message = status['description']
…continues…
53. Is this the last commit?
if index == (commits.length - 1) && index > 0 then
if happy then
status['state'] = 'success'
status['description'] = 'All commits were signed off. Yay!'
else
status['state'] = 'failure'
status['description'] = 'At least one commit was not signed off'
status['target_url’] = targetURL
end
final_message = status['description']
end
…continues…
54. Send back the results for this commit
HTTParty.post(status_url,
:body => status.to_json,
:headers => {
'Content-Type' => 'application/json',
'User-Agent' => user_agent,
'Authorization' => "token #{auth_token}" }
)
end
…continues…
55. All done!
# Return HTTP status 200 and a message that shows up in the
# Github webhook debug logs
return [200, ”Thanks for playing -- #{final_message}"]
end