Skip to content

Commit

Permalink
Merge pull request github#126 from osowskit/master
Browse files Browse the repository at this point in the history
Add Ruby webhook server to dismiss reviews
  • Loading branch information
Tom Osowski authored Mar 2, 2017
2 parents 0ffe990 + b75d2ac commit 7090ff0
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 0 deletions.
5 changes: 5 additions & 0 deletions hooks/ruby/dismiss-review-server/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
source "http://rubygems.org"

gem "json", "~> 1.8"
gem 'sinatra', '~> 1.3.5'
gem 'rest-client'
38 changes: 38 additions & 0 deletions hooks/ruby/dismiss-review-server/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
GEM
remote: http://rubygems.org/
specs:
domain_name (0.5.20161129)
unf (>= 0.0.5, < 1.0.0)
http-cookie (1.0.3)
domain_name (~> 0.5)
json (1.8.6)
mime-types (3.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2016.0521)
netrc (0.11.0)
rack (1.6.5)
rack-protection (1.5.3)
rack
rest-client (2.0.1)
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 4.0)
netrc (~> 0.8)
sinatra (1.3.6)
rack (~> 1.4)
rack-protection (~> 1.3)
tilt (~> 1.3, >= 1.3.3)
tilt (1.4.1)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.2)

PLATFORMS
ruby

DEPENDENCIES
json (~> 1.8)
rest-client
sinatra (~> 1.3.5)

BUNDLED WITH
1.14.4
9 changes: 9 additions & 0 deletions hooks/ruby/dismiss-review-server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Dismiss Review Server

A ruby server that listens for GitHub webhook `push` events, based on [the documentation](https://developer.github.com/webhooks/configuring/#writing-the-server), that will dismiss any `APPROVED` [Pull Request Reviews](https://help.github.com/articles/about-pull-request-reviews/).

## Configuration

Follow the [instructions](https://developer.github.com/webhooks/) of setting up a Webhook on GitHub to this server. Set the following environment variables:
- GITHUB_API_TOKEN - (Required) [OAuth token](https://developer.github.com/v3/#authentication) with write access to the repository.
- SECRET_TOKEN - (Optional) [Shared secret token](https://developer.github.com/webhooks/securing/#validating-payloads-from-github) between the GitHub Webhook and this application. Leave this unset if not using a secret token.
99 changes: 99 additions & 0 deletions hooks/ruby/dismiss-review-server/server.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
require 'sinatra'
require 'json'
require 'rest-client'

$github_api_token = ENV['GITHUB_API_TOKEN']
$github_secret_token = ENV['SECRET_TOKEN']

post '/payload' do

# Only validate secret token if set
if !$github_secret_token.nil?
payload_body = request.body.read
verify_signature(payload_body)
end

github_event = request.env['HTTP_X_GITHUB_EVENT']
if github_event == "push"
request.body.rewind
parsed = JSON.parse(request.body.read)

# Get branch information
branch_name = parsed['ref']
removed_slice = branch_name.slice!("refs/heads/")
if removed_slice.nil?
return "Not a branch. Nothing to do."
end

# Get Repository owner
repo_owner = parsed["repository"]["owner"]["name"]

# Create URL to look up Pull Requests for this branch
# e.g. https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}
pulls_url = parsed['repository']['pulls_url']

# Pull off the "{/number}" and search for all Pull Requests
# that include the branch
pulls_url_filtered = pulls_url.split('{').first + "?head=#{repo_owner}:#{branch_name}"
pulls = get(pulls_url_filtered)

# parse pull requests
if pulls.empty?
puts "empty"
else
pulls.each do |pull_request|

# Get all Reviews for a Pull Request via API
review_url_orig = pull_request["url"] + "/reviews"
reviews = get(review_url_orig)

reviews.each do |review|

# Dismiss all Reviews in 'APPROVED' state via API
if review["state"] == "APPROVED"
puts "INFO: found an approved Review"
review_id = review["id"]
dismiss_url = review_url_orig + "/#{review_id}/dismissals"
put(dismiss_url)
end
end.empty? and begin
puts "no reviews"
end
end
end
elsif github_event == "ping"
puts github_event
else
puts github_event
end
"message received"
end

def put(url)
jdata = JSON.generate({ message: "Auto-dismissing"})
headers = {
params:
{
access_token: $github_api_token
},
accept: "application/vnd.github.black-cat-preview+json"
}
response = RestClient.put(url, jdata, headers)
JSON.parse(response.body)
end

def get(url)
headers = {
params: {
access_token: $github_api_token
},
accept: "application/vnd.github.black-cat-preview+json"
}
response = RestClient.get(url, headers)
JSON.parse(response.body)
end

def verify_signature(payload_body)
signature = 'sha1=' + OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha1'), ENV['SECRET_TOKEN'], payload_body)
return halt 500, "Signatures didn't match!" unless Rack::Utils.secure_compare(signature, request.env['HTTP_X_HUB_SIGNATURE'])
end

0 comments on commit 7090ff0

Please sign in to comment.