github-hooker 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore CHANGED
@@ -1,4 +1,3 @@
1
1
  *.gem
2
2
  .bundle
3
- Gemfile.lock
4
3
  pkg/*
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile CHANGED
@@ -2,3 +2,10 @@ source "http://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in github-hooker.gemspec
4
4
  gemspec
5
+
6
+ gem 'rake'
7
+ gem 'rspec'
8
+ gem 'webmock'
9
+ gem 'guard'
10
+ gem 'guard-bundler'
11
+ gem 'guard-rspec'
data/Gemfile.lock ADDED
@@ -0,0 +1,54 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ github-hooker (0.1.0)
5
+ active_support (~> 3.0.0)
6
+ rest-client (~> 1.6.7)
7
+ thor (~> 0.14.6)
8
+
9
+ GEM
10
+ remote: http://rubygems.org/
11
+ specs:
12
+ active_support (3.0.0)
13
+ activesupport (= 3.0.0)
14
+ activesupport (3.0.0)
15
+ addressable (2.2.6)
16
+ crack (0.3.1)
17
+ diff-lcs (1.1.3)
18
+ ffi (1.0.11)
19
+ guard (1.0.0)
20
+ ffi (>= 0.5.0)
21
+ thor (~> 0.14.6)
22
+ guard-bundler (0.1.3)
23
+ bundler (>= 1.0.0)
24
+ guard (>= 0.2.2)
25
+ guard-rspec (0.6.0)
26
+ guard (>= 0.10.0)
27
+ mime-types (1.17.2)
28
+ rake (0.9.2.2)
29
+ rest-client (1.6.7)
30
+ mime-types (>= 1.16)
31
+ rspec (2.8.0)
32
+ rspec-core (~> 2.8.0)
33
+ rspec-expectations (~> 2.8.0)
34
+ rspec-mocks (~> 2.8.0)
35
+ rspec-core (2.8.0)
36
+ rspec-expectations (2.8.0)
37
+ diff-lcs (~> 1.1.2)
38
+ rspec-mocks (2.8.0)
39
+ thor (0.14.6)
40
+ webmock (1.7.10)
41
+ addressable (~> 2.2, > 2.2.5)
42
+ crack (>= 0.1.7)
43
+
44
+ PLATFORMS
45
+ ruby
46
+
47
+ DEPENDENCIES
48
+ github-hooker!
49
+ guard
50
+ guard-bundler
51
+ guard-rspec
52
+ rake
53
+ rspec
54
+ webmock
data/Guardfile ADDED
@@ -0,0 +1,15 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ group :backend do
5
+ guard :bundler do
6
+ watch('Gemfile')
7
+ end
8
+
9
+ guard :rspec, :cli => '--color --format doc' do
10
+ watch(%r{^spec/.+_spec\.rb$})
11
+ watch(%r{^support/.+\.rb$})
12
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
13
+ watch('spec/spec_helper.rb') { "spec" }
14
+ end
15
+ end
data/bin/github-hooker ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.expand_path("../../lib", __FILE__)
4
+ require "thor"
5
+ require 'github-hooker'
6
+ require 'github-hooker/cli'
7
+
8
+ Github::Hooker::CLI.start
9
+
10
+ # :vim:ft=ruby
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
18
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
19
  s.require_paths = ["lib"]
20
20
 
21
- # specify any dependencies here; for example:
22
- # s.add_development_dependency "rspec"
23
- # s.add_runtime_dependency "rest-client"
21
+ s.add_dependency "rest-client", "~> 1.6.7"
22
+ s.add_dependency "thor", "~> 0.14.6"
23
+ s.add_dependency "active_support", "~> 3.0.0"
24
24
  end
data/lib/github-hooker.rb CHANGED
@@ -1,6 +1,44 @@
1
1
  require "github-hooker/version"
2
+ require 'net/http'
3
+ require 'json'
4
+ require 'yaml'
5
+ require 'restclient'
6
+ require 'active_support/core_ext/hash/reverse_merge'
2
7
 
3
8
  module Github
4
9
  module Hooker
10
+ def self.hooks(repo)
11
+ url = "https://api.github.com/repos/#{repo}/hooks"
12
+ github_api(:get, url)
13
+ end
14
+
15
+ def self.add_hook(repo, payload={})
16
+ url = "https://api.github.com/repos/#{repo}/hooks"
17
+ payload = payload.reverse_merge(:active => true)
18
+ github_api(:post, url, :payload => payload.to_json)
19
+ end
20
+
21
+ def self.delete_hook(repo, hook)
22
+ url = "https://api.github.com/repos/#{repo}/hooks/#{hook}"
23
+ github_api(:delete, url)
24
+ end
25
+
26
+ def self.config
27
+ @config ||= YAML.load_file(File.expand_path(config_filename))
28
+ end
29
+
30
+ def self.github_api(method, url, options={})
31
+ options.reverse_merge!(
32
+ :method => method,
33
+ :url => url,
34
+ :user => config["user"],
35
+ :password => config["password"]
36
+ )
37
+ JSON.parse(RestClient::Request.execute(options))
38
+ end
39
+
40
+ def self.config_filename
41
+ "~/.github-hooker.yml"
42
+ end
5
43
  end
6
44
  end
@@ -0,0 +1,73 @@
1
+ module Github
2
+ module Hooker
3
+ class CLI < Thor
4
+ desc "list user/repo", "List hooks in the given repository"
5
+ def list(repo)
6
+ handle_404 do
7
+ check_config!
8
+ hooks = Github::Hooker.hooks(repo)
9
+ hooks.each do |hook|
10
+ puts "#{hook['url']}"
11
+ puts "> name: #{hook['name']}"
12
+ puts "> events: #{hook['events'].join(", ")}"
13
+ puts "> config: #{hook['config']}"
14
+ puts
15
+ end unless hooks.nil?
16
+ end
17
+ end
18
+
19
+ desc "campfire user/repo events", "Add a campfire hook in the given repository. Events must be separated by commas."
20
+ method_option :room, :required => true
21
+ method_option :subdomain, :required => true
22
+ def campfire(repo, events)
23
+ handle_404 do
24
+ check_config!
25
+ events = split_events(events)
26
+ Github::Hooker.add_hook(repo, :name => "campfire", :events => events, :config => options)
27
+ end
28
+ end
29
+
30
+ desc "web user/repo events", "Add a web hook in the given repository. Events must be separated by commas."
31
+ method_option :url, :required => true
32
+ def web(repo, events)
33
+ handle_404 do
34
+ check_config!
35
+ events = split_events(events)
36
+ Github::Hooker.add_hook(repo, :name => "web", :events => events, :config => options)
37
+ end
38
+ end
39
+
40
+ desc "delete user/repo hook", "Delete the hook 1111 from the given repository"
41
+ def delete(repo, hook)
42
+ handle_404 do
43
+ check_config!
44
+ Github::Hooker.delete_hook(repo, hook)
45
+ end
46
+ end
47
+
48
+ private
49
+ def handle_404
50
+ yield
51
+ rescue RestClient::ResourceNotFound
52
+ resource_not_found_message!
53
+ end
54
+
55
+ def split_events(events)
56
+ events.split(",").map(&:strip)
57
+ end
58
+
59
+ def check_config!
60
+ error("~/.github-hooker.yml is not present. Please set 'user', 'password' and 'campfire_token'.") unless File.exist?(File.expand_path(Github::Hooker.config_filename))
61
+ end
62
+
63
+ def resource_not_found_message!
64
+ error("Resource Not Found (404): This repository may not exist or you may not have access to it.")
65
+ end
66
+
67
+ def error(message)
68
+ puts message
69
+ exit 1
70
+ end
71
+ end
72
+ end
73
+ end
@@ -1,5 +1,5 @@
1
1
  module Github
2
2
  module Hooker
3
- VERSION = "0.0.1"
3
+ VERSION = "0.1.0"
4
4
  end
5
5
  end
@@ -0,0 +1,47 @@
1
+ [
2
+ {
3
+ "updated_at": "2012-01-26T16:11:55Z",
4
+ "last_response": {
5
+ "message": "",
6
+ "code": 200
7
+ },
8
+ "created_at": "2012-01-26T13:29:53Z",
9
+ "events": [
10
+ "push",
11
+ "issues",
12
+ "issue_comment",
13
+ "commit_comment",
14
+ "pull_request"
15
+ ],
16
+ "name": "campfire",
17
+ "config": {
18
+ "long_url": "1",
19
+ "token": "aaaaaaaaaaaaaaaaa",
20
+ "subdomain": "company",
21
+ "room": "room"
22
+ },
23
+ "id": 157257,
24
+ "url": "https://api.github.com/repos/user/repo/hooks/157257",
25
+ "active": true
26
+ },
27
+ {
28
+ "updated_at": "2012-01-26T13:56:25Z",
29
+ "last_response": {
30
+ "message": null,
31
+ "code": null
32
+ },
33
+ "created_at": "2012-01-26T13:55:42Z",
34
+ "events": [
35
+ "issue_comment"
36
+ ],
37
+ "name": "web",
38
+ "config": {
39
+ "content_type": "form",
40
+ "url": "http://mycallback.com/callback",
41
+ "secret": null
42
+ },
43
+ "id": 157271,
44
+ "url": "https://api.github.com/repos/user/repo/hooks/157271",
45
+ "active": true
46
+ }
47
+ ]
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+ require 'fileutils'
3
+ require 'thor'
4
+ require 'github-hooker'
5
+ require 'github-hooker/cli'
6
+
7
+ describe "github-hooker" do
8
+ subject { Github::Hooker::CLI.new }
9
+
10
+ before do
11
+ Github::Hooker.stub(:config_filename).and_return("/tmp/.github-hooker.yml")
12
+ FileUtils.touch(Github::Hooker.config_filename)
13
+ stub_config!
14
+ end
15
+
16
+ describe "list" do
17
+ it "calls Github::Hooker with the correct arguments" do
18
+ hooks = [
19
+ {
20
+ "url" => "http://github/hooks/123",
21
+ "name" => "web",
22
+ "events" => ["event1", "event2"],
23
+ "config" => {
24
+ "url" => "http://example.com/callback"
25
+ }
26
+ }
27
+ ]
28
+ Github::Hooker.stub(:hooks).with("user/repo").and_return(hooks)
29
+ subject.list("user/repo")
30
+ end
31
+
32
+ it "handles 404 errors in github API" do
33
+ WebMock.stub_request(:get, "https://user:password@api.github.com/repos/user/non-existent-repo/hooks").
34
+ to_return(:status => 404, :body => "NotFound", :headers => {})
35
+
36
+ $stdout.should_receive(:puts).with("Resource Not Found (404): This repository may not exist or you may not have access to it.")
37
+ expect { subject.list("user/non-existent-repo") }.to raise_error(SystemExit)
38
+ end
39
+ end
40
+
41
+ describe "campfire" do
42
+ it "calls Github::Hooker with the correct arguments" do
43
+ Github::Hooker.stub(:add_hook).with("user/repo", {:name => "campfire", :events => ["pull_requests", "issue"], :config => {}})
44
+ subject.campfire("user/repo", "pull_requests, issue")
45
+ end
46
+ end
47
+
48
+ describe "web" do
49
+ it "calls Github::Hooker with the correct arguments" do
50
+ Github::Hooker.stub(:add_hook).with("user/repo", {:name => "web", :events => ["pull_requests", "issue"], :config => {}})
51
+ subject.web("user/repo", "pull_requests, issue")
52
+ end
53
+ end
54
+
55
+ describe "delete" do
56
+ it "calls Github::Hooker with the correct arguments" do
57
+ Github::Hooker.stub(:delete_hook).with("user/repo", 1010)
58
+ subject.delete("user/repo", 1010)
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+ require 'github-hooker'
3
+
4
+ describe Github::Hooker do
5
+ context "given a valid credential" do
6
+ before do
7
+ stub_config!
8
+ end
9
+
10
+ it "lists the hooks in the given repo" do
11
+ WebMock.stub_request(:get, "https://user:password@api.github.com/repos/user/repo/hooks").
12
+ to_return(:status => 200, :body => fixture_file("list_hooks.json"), :headers => {})
13
+
14
+ list = subject.hooks("user/repo")
15
+
16
+ list[0]["url"].should == "https://api.github.com/repos/user/repo/hooks/157257"
17
+ list[1]["url"].should == "https://api.github.com/repos/user/repo/hooks/157271"
18
+ end
19
+
20
+ it "adds a new campfire hook in the given repo" do
21
+ WebMock.stub_request(:post, "https://user:password@api.github.com/repos/user/repo/hooks").
22
+ with(:body => "{\"active\":\"true\",\"name\":\"campfire\",\"events\":[\"pull_request\",\"issue_comment\"],\"config\":{\"subdomain\":\"company\",\"room\":\"my room\",\"token\":\"abcde\",\"long_url\":\"true\"}}").
23
+ to_return(:status => 200, :body => "{}", :headers => {})
24
+
25
+ hook_options = {
26
+ :name => "campfire",
27
+ :events => ["pull_request", "issue_comment"],
28
+ :active => "true",
29
+ :config => {
30
+ :subdomain => "company",
31
+ :room => "my room",
32
+ :token => "abcde",
33
+ :long_url => "true"
34
+ }
35
+ }
36
+ subject.add_hook("user/repo", hook_options)
37
+ end
38
+
39
+ it "adds a new web hook in the given repo" do
40
+ WebMock.stub_request(:post, "https://user:password@api.github.com/repos/user/repo/hooks").
41
+ with(:body => "{\"active\":\"true\",\"name\":\"web\",\"events\":[\"pull_request\",\"issue\"],\"config\":{\"url\":\"http://example.com/callback\"}}").
42
+ to_return(:status => 200, :body => "{}", :headers => {})
43
+
44
+ hook_options = {
45
+ :name => "web",
46
+ :events => ["pull_request", "issue"],
47
+ :active => "true",
48
+ :config => {
49
+ :url => "http://example.com/callback"
50
+ }
51
+ }
52
+ subject.add_hook("user/repo", hook_options)
53
+ end
54
+
55
+ it "deletes a hook in the given repo" do
56
+ WebMock.stub_request(:delete, "https://user:password@api.github.com/repos/user/repo/hooks/1010").
57
+ to_return(:status => 200, :body => "{}", :headers => {})
58
+
59
+ subject.delete_hook("user/repo", 1010)
60
+ end
61
+ end
62
+ end
63
+
64
+ def fixture_file(name)
65
+ File.read(File.expand_path("../../spec/fixtures/#{name}", __FILE__))
66
+ end
@@ -0,0 +1,10 @@
1
+ require 'webmock/rspec'
2
+
3
+ Dir[File.expand_path("../support/**/*.rb", __FILE__)].each { |f| require f }
4
+
5
+ RSpec.configure do |config|
6
+ config.treat_symbols_as_metadata_keys_with_true_values = true
7
+ config.run_all_when_everything_filtered = true
8
+ config.filter_run :focus
9
+ config.mock_framework = :rspec
10
+ end
@@ -0,0 +1,3 @@
1
+ def stub_config!
2
+ Github::Hooker.stub(:config).and_return({ "user" => "user", "password" => "password", "campfire_token" => "token" })
3
+ end
metadata CHANGED
@@ -1,71 +1,106 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: github-hooker
3
- version: !ruby/object:Gem::Version
4
- hash: 29
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 0
9
- - 1
10
- version: 0.0.1
11
6
  platform: ruby
12
- authors:
13
- - "George Guimara\xCC\x83es"
7
+ authors:
8
+ - George Guimarães
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2012-01-30 00:00:00 Z
19
- dependencies: []
20
-
21
- description: " hook them all "
22
- email:
12
+ date: 2012-02-06 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rest-client
16
+ requirement: &70239803941600 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.6.7
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70239803941600
25
+ - !ruby/object:Gem::Dependency
26
+ name: thor
27
+ requirement: &70239803941060 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 0.14.6
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70239803941060
36
+ - !ruby/object:Gem::Dependency
37
+ name: active_support
38
+ requirement: &70239803932200 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 3.0.0
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70239803932200
47
+ description: ! ' hook them all '
48
+ email:
23
49
  - george@plataformatec.com.br
24
- executables: []
25
-
50
+ executables:
51
+ - github-hooker
26
52
  extensions: []
27
-
28
53
  extra_rdoc_files: []
29
-
30
- files:
54
+ files:
31
55
  - .gitignore
56
+ - .rspec
32
57
  - Gemfile
58
+ - Gemfile.lock
59
+ - Guardfile
33
60
  - Rakefile
61
+ - bin/github-hooker
34
62
  - github-hooker.gemspec
35
63
  - lib/github-hooker.rb
64
+ - lib/github-hooker/cli.rb
36
65
  - lib/github-hooker/version.rb
37
- homepage: ""
66
+ - spec/fixtures/list_hooks.json
67
+ - spec/github-hooker/cli_spec.rb
68
+ - spec/github-hooker_spec.rb
69
+ - spec/spec_helper.rb
70
+ - spec/support/config_stub.rb
71
+ homepage: ''
38
72
  licenses: []
39
-
40
73
  post_install_message:
41
74
  rdoc_options: []
42
-
43
- require_paths:
75
+ require_paths:
44
76
  - lib
45
- required_ruby_version: !ruby/object:Gem::Requirement
77
+ required_ruby_version: !ruby/object:Gem::Requirement
46
78
  none: false
47
- requirements:
48
- - - ">="
49
- - !ruby/object:Gem::Version
50
- hash: 3
51
- segments:
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ segments:
52
84
  - 0
53
- version: "0"
54
- required_rubygems_version: !ruby/object:Gem::Requirement
85
+ hash: 61845188583111008
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
87
  none: false
56
- requirements:
57
- - - ">="
58
- - !ruby/object:Gem::Version
59
- hash: 3
60
- segments:
88
+ requirements:
89
+ - - ! '>='
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ segments:
61
93
  - 0
62
- version: "0"
94
+ hash: 61845188583111008
63
95
  requirements: []
64
-
65
96
  rubyforge_project: github-hooker
66
- rubygems_version: 1.8.10
97
+ rubygems_version: 1.8.11
67
98
  signing_key:
68
99
  specification_version: 3
69
100
  summary: hook them all
70
- test_files: []
71
-
101
+ test_files:
102
+ - spec/fixtures/list_hooks.json
103
+ - spec/github-hooker/cli_spec.rb
104
+ - spec/github-hooker_spec.rb
105
+ - spec/spec_helper.rb
106
+ - spec/support/config_stub.rb