loadrunner 0.0.4 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +11 -2
- data/lib/load_runner/client.rb +9 -0
- data/lib/load_runner/command_line.rb +29 -4
- data/lib/load_runner/docopt.txt +22 -0
- data/lib/load_runner/git_hub_api.rb +48 -0
- data/lib/load_runner/runner.rb +8 -0
- data/lib/load_runner/server.rb +1 -0
- data/lib/load_runner/server_helper.rb +0 -18
- data/lib/load_runner/signature_helper.rb +21 -0
- data/lib/load_runner/version.rb +1 -1
- data/lib/loadrunner.rb +4 -2
- metadata +21 -7
- data/lib/load_runner/_server.rb +0 -44
- data/lib/load_runner/exceptions.rb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 45e2aa0edf131bb75fdac7ac306131ba87791958
|
4
|
+
data.tar.gz: b6380a094f0d73e15e3922b3b2caea0e90db56b6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a8775a42b092fb08485fdf72525ed2dcaa48f59f908f593c4ba8859a22739abdb671b0d3edfc92f3cc086198d875cccc5bc8322190f2202998846182506667be
|
7
|
+
data.tar.gz: 3fe722e065dab62c742d337c006b2cd2ccea46920cd2a70692a645250d721d609b47574e5af23c1d0d50d040df22cb5afa64e3c760384eb04e397430a4ed65c5
|
data/README.md
CHANGED
@@ -8,13 +8,16 @@ LoadRunner - GitHub Webhook Server and Event Simulator
|
|
8
8
|
|
9
9
|
---
|
10
10
|
|
11
|
-
LoadRunner is a
|
11
|
+
LoadRunner is a multi-purpose utility for working with GitHub webhooks and
|
12
|
+
statuses.
|
12
13
|
|
13
14
|
It provides these features:
|
14
15
|
|
15
16
|
- A webserver that responds to GitHub webhook events and can run any
|
16
17
|
arbitrary script writtn in any language.
|
17
|
-
- A command line utility for testing your webhook server configuration
|
18
|
+
- A command line utility for testing your webhook server configuration by
|
19
|
+
sending simulated events.
|
20
|
+
- A command line utility for sending status updates to pull requests.
|
18
21
|
|
19
22
|
---
|
20
23
|
|
@@ -43,3 +46,9 @@ Getting Started
|
|
43
46
|
$ cat output.txt
|
44
47
|
|
45
48
|
|
49
|
+
For more options, see the [documentation][1] or run
|
50
|
+
|
51
|
+
$ loadrunner --help
|
52
|
+
|
53
|
+
|
54
|
+
[1]: http://www.rubydoc.info/gems/loadrunner
|
data/lib/load_runner/client.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'httparty'
|
2
2
|
|
3
3
|
module LoadRunner
|
4
|
+
|
5
|
+
# Send simulated GitHub events to any webhook server
|
4
6
|
class Client
|
5
7
|
include HTTParty
|
6
8
|
attr_accessor :secret_token, :base_url, :payload
|
@@ -11,11 +13,18 @@ module LoadRunner
|
|
11
13
|
self.class.base_uri base_url
|
12
14
|
end
|
13
15
|
|
16
|
+
# Send a simulated event using a shorthand syntax. opts can contain
|
17
|
+
# any of these:
|
18
|
+
# * +repo+: repository name
|
19
|
+
# * +ref+: ref ID (for example +ref/heads/branchname+)
|
20
|
+
# * +branch+: branch name
|
21
|
+
# * +tag+: tag name
|
14
22
|
def send(event=:push, opts={})
|
15
23
|
payload = build_payload opts
|
16
24
|
send_payload event, payload
|
17
25
|
end
|
18
26
|
|
27
|
+
# Send a simulated event. Payload can be a hash or a JSON string.
|
19
28
|
def send_payload(event, payload)
|
20
29
|
@payload = payload.is_a?(String) ? payload : payload.to_json
|
21
30
|
headers = headers event
|
@@ -1,12 +1,13 @@
|
|
1
1
|
require 'singleton'
|
2
2
|
require 'docopt'
|
3
|
-
require '
|
3
|
+
require 'colsole'
|
4
4
|
|
5
5
|
module LoadRunner
|
6
6
|
|
7
7
|
# Handles the command line interface
|
8
8
|
class CommandLine
|
9
9
|
include Singleton
|
10
|
+
include Colsole
|
10
11
|
|
11
12
|
attr_reader :args
|
12
13
|
|
@@ -28,15 +29,14 @@ module LoadRunner
|
|
28
29
|
# delegate action to other, more specialized methods.
|
29
30
|
def handle
|
30
31
|
return send if args['send']
|
32
|
+
return status if args['status']
|
31
33
|
return server if args['server']
|
32
34
|
end
|
33
35
|
|
34
36
|
def send
|
35
37
|
client = Client.new client_opts
|
36
38
|
response = client.send args['EVENT'], payload_opts
|
37
|
-
|
38
|
-
puts "Reesponse code: #{response.code}" if response.respond_to? :code
|
39
|
-
ap response
|
39
|
+
show response
|
40
40
|
end
|
41
41
|
|
42
42
|
def server
|
@@ -44,6 +44,20 @@ module LoadRunner
|
|
44
44
|
Server.run!
|
45
45
|
end
|
46
46
|
|
47
|
+
def status
|
48
|
+
api = GitHubAPI.new
|
49
|
+
opts = {
|
50
|
+
state: args['STATE'],
|
51
|
+
target_url: args['--url'],
|
52
|
+
context: args['--context'],
|
53
|
+
description: args['--desc']
|
54
|
+
}
|
55
|
+
|
56
|
+
response = api.status args['REPO'], args['SHA'], opts
|
57
|
+
|
58
|
+
show response
|
59
|
+
end
|
60
|
+
|
47
61
|
def client_opts
|
48
62
|
{
|
49
63
|
base_url: args['URL'],
|
@@ -65,5 +79,16 @@ module LoadRunner
|
|
65
79
|
result[:ref] = ref
|
66
80
|
result
|
67
81
|
end
|
82
|
+
|
83
|
+
# Print the response json to stdout, and the response code to stderr.
|
84
|
+
def show(response)
|
85
|
+
puts JSON.pretty_generate response
|
86
|
+
|
87
|
+
if response.respond_to? :code
|
88
|
+
code = response.code.to_s
|
89
|
+
color = code =~ /^2\d\d/ ? :txtgrn : :txtred
|
90
|
+
say! "!#{color}!Response Code: #{code}"
|
91
|
+
end
|
92
|
+
end
|
68
93
|
end
|
69
94
|
end
|
data/lib/load_runner/docopt.txt
CHANGED
@@ -3,6 +3,7 @@ LoadRunner
|
|
3
3
|
Usage:
|
4
4
|
loadrunner server [--port N --bind IP]
|
5
5
|
loadrunner send URL REPO EVENT [REF]
|
6
|
+
loadrunner status REPO SHA STATE [--context TEXT --desc TEXT --url URL]
|
6
7
|
loadrunner (-h|--help|--version)
|
7
8
|
|
8
9
|
Commands:
|
@@ -12,6 +13,9 @@ Commands:
|
|
12
13
|
send
|
13
14
|
Send a simulated GitHub event to a webhook server.
|
14
15
|
|
16
|
+
status
|
17
|
+
Send status update to a github pull request.
|
18
|
+
|
15
19
|
Parameters:
|
16
20
|
URL
|
17
21
|
The URL of the webhook server. This server should have a /payload
|
@@ -31,6 +35,12 @@ Parameters:
|
|
31
35
|
* branch=branch_name
|
32
36
|
* raw ref string (for example refs/tags/tagname)
|
33
37
|
|
38
|
+
SHA
|
39
|
+
Commit SHA string.
|
40
|
+
|
41
|
+
STATE
|
42
|
+
One of 'success', 'pending', 'error', 'failure'
|
43
|
+
|
34
44
|
Options:
|
35
45
|
--port N
|
36
46
|
Set the port of the webhook server.
|
@@ -38,6 +48,14 @@ Options:
|
|
38
48
|
--bind IP
|
39
49
|
Set the listening address of the webhook server.
|
40
50
|
|
51
|
+
--context TEXT
|
52
|
+
Indicate what service is sending this status.
|
53
|
+
|
54
|
+
--url URL
|
55
|
+
The target URL to associate with this status.
|
56
|
+
|
57
|
+
--desc TEXT
|
58
|
+
A short description of the status.
|
41
59
|
|
42
60
|
Environment Variables:
|
43
61
|
GITHUB_SECRET_TOKEN=y0urAP1k3y
|
@@ -54,4 +72,8 @@ Examples:
|
|
54
72
|
loadrunner server
|
55
73
|
loadrunner server --bind 0.0.0.0 --port 3000
|
56
74
|
|
75
|
+
# Send a status
|
76
|
+
loadrunner status me/myrepo 018b0ac... pending
|
77
|
+
loadrunner status me/myrepo 018b0ac... success --context "My CI"
|
78
|
+
|
57
79
|
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
|
3
|
+
module LoadRunner
|
4
|
+
# Communicate with GitHub
|
5
|
+
class GitHubAPI
|
6
|
+
include HTTParty
|
7
|
+
|
8
|
+
base_uri 'https://api.github.com'
|
9
|
+
|
10
|
+
# Send status update to a pull request. Supported options:
|
11
|
+
# * +state+: :pending, :success, :failure or :error
|
12
|
+
# * +context+: any string
|
13
|
+
# * +description+: any string
|
14
|
+
# * +target_url+: any valid URL
|
15
|
+
def status(repo, sha, opts={})
|
16
|
+
# sha = '018b0ac55dbf0d8e1eef6df46e04dfef8bea9b96'
|
17
|
+
message = {
|
18
|
+
body: {
|
19
|
+
state: (opts[:state] ? opts[:state].to_s : 'pending'),
|
20
|
+
context: (opts[:context] || 'LoadRunner'),
|
21
|
+
description: opts[:description],
|
22
|
+
target_url: opts[:target_url]
|
23
|
+
}.to_json
|
24
|
+
}
|
25
|
+
self.class.post "/repos/#{repo}/statuses/#{sha}", message.merge(request_options)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def request_options
|
31
|
+
{
|
32
|
+
headers: headers
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
def headers
|
37
|
+
{
|
38
|
+
"Authorization" => "token #{secret_token}",
|
39
|
+
"User-Agent" => "LoadRunner"
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
def secret_token
|
44
|
+
ENV['GITHUB_ACCESS_TOKEN']
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
data/lib/load_runner/runner.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
module LoadRunner
|
2
2
|
|
3
|
+
# Executes event handlers
|
3
4
|
class Runner
|
4
5
|
attr_reader :opts
|
5
6
|
attr_accessor :response
|
@@ -8,6 +9,8 @@ module LoadRunner
|
|
8
9
|
@opts = opts
|
9
10
|
end
|
10
11
|
|
12
|
+
# Execute all matching handlers based on the input payload. This method
|
13
|
+
# populates the `#response` object, and returns true on success.
|
11
14
|
def execute
|
12
15
|
set_environment_vars
|
13
16
|
|
@@ -35,6 +38,7 @@ module LoadRunner
|
|
35
38
|
|
36
39
|
private
|
37
40
|
|
41
|
+
# Find all handlers that fit the payload meta data.
|
38
42
|
def locate_handlers
|
39
43
|
handlers = []
|
40
44
|
|
@@ -45,17 +49,21 @@ module LoadRunner
|
|
45
49
|
handlers
|
46
50
|
end
|
47
51
|
|
52
|
+
# Execute all handlers.
|
48
53
|
def execute_all(handlers)
|
49
54
|
handlers.each do |handler|
|
50
55
|
run_bg handler
|
51
56
|
end
|
52
57
|
end
|
53
58
|
|
59
|
+
# Run a command in the background.
|
54
60
|
def run_bg(cmd)
|
55
61
|
job = fork { exec cmd }
|
56
62
|
Process.detach job
|
57
63
|
end
|
58
64
|
|
65
|
+
# Set all payload meta data as environment variables so that the
|
66
|
+
# handler can use them.
|
59
67
|
def set_environment_vars
|
60
68
|
opts.each { |key, value| ENV[key.to_s.upcase] = value }
|
61
69
|
end
|
data/lib/load_runner/server.rb
CHANGED
@@ -1,23 +1,5 @@
|
|
1
1
|
module LoadRunner
|
2
2
|
module ServerHelper
|
3
|
-
def verify_signature(payload_body, signature)
|
4
|
-
return :no_client if secret_token and !signature
|
5
|
-
return :no_server if !secret_token and signature
|
6
|
-
return :ok if !secret_token and !signature
|
7
|
-
|
8
|
-
expected_signature = generate_signature payload_body
|
9
|
-
signature_match = Rack::Utils.secure_compare(expected_signature, signature)
|
10
|
-
return signature_match ? :ok : :mismatch
|
11
|
-
end
|
12
|
-
|
13
|
-
def generate_signature(payload_body)
|
14
|
-
'sha1=' + OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha1'), secret_token, payload_body)
|
15
|
-
end
|
16
|
-
|
17
|
-
def secret_token
|
18
|
-
ENV['GITHUB_SECRET_TOKEN']
|
19
|
-
end
|
20
|
-
|
21
3
|
def halt_messages
|
22
4
|
{
|
23
5
|
no_client: "Client did not send a signature",
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module LoadRunner
|
2
|
+
module SignatureHelper
|
3
|
+
def verify_signature(payload_body, signature)
|
4
|
+
return :no_client if secret_token and !signature
|
5
|
+
return :no_server if !secret_token and signature
|
6
|
+
return :ok if !secret_token and !signature
|
7
|
+
|
8
|
+
expected_signature = generate_signature payload_body
|
9
|
+
signature_match = Rack::Utils.secure_compare(expected_signature, signature)
|
10
|
+
return signature_match ? :ok : :mismatch
|
11
|
+
end
|
12
|
+
|
13
|
+
def generate_signature(payload_body)
|
14
|
+
'sha1=' + OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha1'), secret_token, payload_body)
|
15
|
+
end
|
16
|
+
|
17
|
+
def secret_token
|
18
|
+
ENV['GITHUB_SECRET_TOKEN']
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/load_runner/version.rb
CHANGED
data/lib/loadrunner.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
require 'load_runner/version'
|
2
|
-
require 'load_runner/exceptions'
|
3
2
|
|
4
|
-
require 'load_runner/
|
3
|
+
require 'load_runner/signature_helper'
|
5
4
|
require 'load_runner/server_helper'
|
5
|
+
require 'load_runner/git_hub_api'
|
6
|
+
|
7
|
+
require 'load_runner/runner'
|
6
8
|
require 'load_runner/server_base'
|
7
9
|
require 'load_runner/server'
|
8
10
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: loadrunner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Danny Ben Shitrit
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-08-
|
11
|
+
date: 2017-08-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httparty
|
@@ -67,19 +67,19 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '5.1'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: colsole
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
75
|
+
version: '0.5'
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
82
|
+
version: '0.5'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: runfile
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -178,6 +178,20 @@ dependencies:
|
|
178
178
|
- - "~>"
|
179
179
|
- !ruby/object:Gem::Version
|
180
180
|
version: '0.7'
|
181
|
+
- !ruby/object:Gem::Dependency
|
182
|
+
name: yard
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
184
|
+
requirements:
|
185
|
+
- - "~>"
|
186
|
+
- !ruby/object:Gem::Version
|
187
|
+
version: '0.9'
|
188
|
+
type: :development
|
189
|
+
prerelease: false
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - "~>"
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0.9'
|
181
195
|
description: Run your GitHub webhook server and Send simulated github events
|
182
196
|
email: db@dannyben.com
|
183
197
|
executables:
|
@@ -187,15 +201,15 @@ extra_rdoc_files: []
|
|
187
201
|
files:
|
188
202
|
- README.md
|
189
203
|
- bin/loadrunner
|
190
|
-
- lib/load_runner/_server.rb
|
191
204
|
- lib/load_runner/client.rb
|
192
205
|
- lib/load_runner/command_line.rb
|
193
206
|
- lib/load_runner/docopt.txt
|
194
|
-
- lib/load_runner/
|
207
|
+
- lib/load_runner/git_hub_api.rb
|
195
208
|
- lib/load_runner/runner.rb
|
196
209
|
- lib/load_runner/server.rb
|
197
210
|
- lib/load_runner/server_base.rb
|
198
211
|
- lib/load_runner/server_helper.rb
|
212
|
+
- lib/load_runner/signature_helper.rb
|
199
213
|
- lib/load_runner/version.rb
|
200
214
|
- lib/loadrunner.rb
|
201
215
|
homepage: https://github.com/DannyBen/loadrunner
|
data/lib/load_runner/_server.rb
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
require 'sinatra'
|
2
|
-
require "sinatra/reloader" if development?
|
3
|
-
require 'json'
|
4
|
-
require 'active_support/core_ext/hash/indifferent_access'
|
5
|
-
require 'byebug'
|
6
|
-
|
7
|
-
set port: 3000
|
8
|
-
set bind: '0.0.0.0'
|
9
|
-
|
10
|
-
ENV['SECRET_TOKEN'] = '123'
|
11
|
-
|
12
|
-
post '/payload' do
|
13
|
-
request.env['HTTP_X_HUB_SIGNATURE']
|
14
|
-
|
15
|
-
request.body.rewind
|
16
|
-
payload_body = request.body.read
|
17
|
-
|
18
|
-
verify_signature payload_body
|
19
|
-
|
20
|
-
push = ActiveSupport::HashWithIndifferentAccess.new JSON.parse payload_body
|
21
|
-
|
22
|
-
branch = push[:ref] =~ /refs\/head/ ? push[:ref].sub('refs/heads/', '') : nil;
|
23
|
-
tag = push[:ref] =~ /refs\/tags/ ? push[:ref].sub('refs/tags/', '') : nil;
|
24
|
-
|
25
|
-
result = {
|
26
|
-
event: request.env['HTTP_X_GITHUB_EVENT'],
|
27
|
-
repo: push[:repository][:name],
|
28
|
-
branch: branch,
|
29
|
-
tag: tag
|
30
|
-
# payload: push
|
31
|
-
}
|
32
|
-
|
33
|
-
result.inspect
|
34
|
-
end
|
35
|
-
|
36
|
-
post '/debug' do
|
37
|
-
request.env['HTTP_X_HUB_SIGNATURE']
|
38
|
-
end
|
39
|
-
|
40
|
-
def verify_signature(payload_body)
|
41
|
-
signature = 'sha1=' + OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha1'), ENV['SECRET_TOKEN'], payload_body)
|
42
|
-
signature_match = Rack::Utils.secure_compare(signature, request.env['HTTP_X_HUB_SIGNATURE'])
|
43
|
-
return halt 401, "Bad Signature" unless signature_match
|
44
|
-
end
|