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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b8a007f7920f1973efc60d3795c4cd8dab52cb3d
4
- data.tar.gz: 0baaf60bb349d17969597985c564bdb68daf1391
3
+ metadata.gz: 45e2aa0edf131bb75fdac7ac306131ba87791958
4
+ data.tar.gz: b6380a094f0d73e15e3922b3b2caea0e90db56b6
5
5
  SHA512:
6
- metadata.gz: dd2ddfff2c1dfa0522871c2a41c84e60b36934e56d5785e52172d5cc4bccb17c99cde8e58d78b580a4181448ba252b9b99a512ee803e694e390598f38536ef23
7
- data.tar.gz: 714bea8499b8c53e358dfca0fe09e75cd97455b97729f49bd99f71d15f6e91b51562c60b0c31386ebdb5cd954325eaa2336a5b91de7bce28f8a820dabee645f1
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 dual-purpose utility for working with GitHub webhooks.
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
@@ -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 'awesome_print'
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
@@ -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
@@ -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
@@ -3,6 +3,7 @@ module LoadRunner
3
3
  # The Sinatra server
4
4
  class Server < ServerBase
5
5
  include ServerHelper
6
+ include SignatureHelper
6
7
 
7
8
  get '/' do
8
9
  "OK"
@@ -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
@@ -1,3 +1,3 @@
1
1
  module LoadRunner
2
- VERSION = "0.0.4"
2
+ VERSION = "0.1.0"
3
3
  end
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/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
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-16 00:00:00.000000000 Z
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: awesome_print
70
+ name: colsole
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '1.8'
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: '1.8'
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/exceptions.rb
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
@@ -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
@@ -1,3 +0,0 @@
1
- module LoadRunner
2
- class Error < StandardError; end
3
- end