tutter 0.0.1 → 0.0.2
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.
- checksums.yaml +4 -4
- data/.gemspec +2 -2
- data/.travis.yml +4 -0
- data/Gemfile +10 -2
- data/README.md +11 -12
- data/Rakefile +4 -0
- data/lib/tutter.rb +51 -20
- data/lib/tutter/action.rb +2 -2
- data/lib/tutter/action/thanks.rb +16 -5
- data/spec/fixtures/new_issue.json +154 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/tutter_spec.rb +32 -0
- metadata +19 -16
- data/bin/tutter +0 -75
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 088744f1c591bb26d27a3185ff95e5005c79c6b9
|
4
|
+
data.tar.gz: fa5ceaf606dda9364f705f6559a0b4d7d54ef416
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 75e9f1d02da92ca932ccab2a97698aa6f77fada6aff141154afe8ad7872fbccd43e35fb21cfb6aeb9778fd3f439f4304202bf14d2bf7d6b47dfdf5768a58b6ff
|
7
|
+
data.tar.gz: 43064843cd32e3542d7ce6d48d842e57d474aa80cc78b5f676b0a4f7781cc48d903fe95c2fc19932e51be8f5a94c8e4846cf01cf7cabf66b2dd24c7746627ca8
|
data/.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
Gem::Specification.new do |s|
|
3
3
|
s.name = 'tutter'
|
4
|
-
s.version = '0.0.
|
4
|
+
s.version = '0.0.2'
|
5
5
|
s.author = 'Johan Haals'
|
6
6
|
s.email = ['johan.haals@gmail.com']
|
7
7
|
s.homepage = 'https://github.com/jhaals/tutter'
|
@@ -15,6 +15,6 @@ Gem::Specification.new do |s|
|
|
15
15
|
|
16
16
|
s.required_ruby_version = '>= 1.8.7'
|
17
17
|
s.add_runtime_dependency 'sinatra', '~> 1.4.4'
|
18
|
-
s.add_runtime_dependency 'octokit', '~> 2.
|
18
|
+
s.add_runtime_dependency 'octokit', '~> 3.2.0'
|
19
19
|
end
|
20
20
|
|
data/.travis.yml
ADDED
data/Gemfile
CHANGED
@@ -1,9 +1,17 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
-
gem 'octokit', '~> 2.
|
3
|
+
gem 'octokit', '~> 3.2.0'
|
4
4
|
gem 'sinatra', '~> 1.4.4'
|
5
5
|
|
6
|
-
group :
|
6
|
+
group :development do
|
7
|
+
gem 'sinatra-reloader'
|
8
|
+
end
|
9
|
+
|
10
|
+
group :test do
|
7
11
|
gem 'sinatra-contrib'
|
8
12
|
gem 'tutter', :path => '.'
|
13
|
+
gem 'rake'
|
14
|
+
gem 'rack'
|
15
|
+
gem 'rspec'
|
16
|
+
gem 'json'
|
9
17
|
end
|
data/README.md
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
# Tutter - Plugin based Github robot
|
2
|
+
[](https://travis-ci.org/JHaals/tutter)
|
3
|
+
|
2
4
|
Tutter is a web app that trigger actions based on Github events(push, pull_reqeust, release, issue, ...)
|
3
5
|
|
4
6
|
# Features
|
@@ -23,21 +25,17 @@ Let's install the `thanks` action that thank anyone that creates an issue in you
|
|
23
25
|
* `action` - action you wish to use for the project
|
24
26
|
* `action_settings` - whatever settings your action require
|
25
27
|
|
26
|
-
### Create the Github
|
27
|
-
|
28
|
+
### Create the Github webhook
|
29
|
+
Hooks can be configured just to send the event that you're interested in. The important part is that `Payload URL` points to the webserver running tutter
|
28
30
|
|
29
|
-
|
31
|
+
https://github.com/ORG/PROJECT/settings/hooks/new
|
30
32
|
|
31
|
-
|
32
|
-
|
33
|
-
--access-token <github_api_token> \
|
34
|
-
--github-web-url https://github.com \
|
35
|
-
--github-api-endpoint https://api.github.com \
|
36
|
-
--events issues
|
33
|
+
Example of how the `thanks` demo-action look like. Tutter listen for issue events and posts back with a greeting.
|
34
|
+

|
37
35
|
|
38
36
|
## Build custom action
|
39
37
|
|
40
|
-
|
38
|
+
See [thanks action](https://github.com/jhaals/tutter/blob/master/lib/tutter/action/thanks.rb)
|
41
39
|
|
42
40
|
#####Required methods and their arguments
|
43
41
|
|
@@ -46,6 +44,7 @@ Another example action [github.com/jhaals/tutter-sppuppet](https://github.com/jh
|
|
46
44
|
settings - contains a hash of action specific settings
|
47
45
|
client - Used to access the github api, all authentication is already done by tutter
|
48
46
|
project - Project name, eg jhaals/tutter
|
47
|
+
event - Event type
|
49
48
|
data - POST data that github send when a hook is triggered
|
50
49
|
|
51
50
|
`run` - Run action
|
@@ -53,7 +52,7 @@ Another example action [github.com/jhaals/tutter-sppuppet](https://github.com/jh
|
|
53
52
|
Tutter uses [octokit.rb](https://github.com/octokit/octokit.rb) to communicate with the Github [API](http://developer.github.com/v3/)
|
54
53
|
|
55
54
|
### Features to implement
|
56
|
-
* Add web hooks in Github automatically
|
57
55
|
* Support multiple actions per project
|
58
56
|
* Authenticate as a Github application
|
59
|
-
* Features your're missing (please contribute)
|
57
|
+
* Features your're missing (please contribute)
|
58
|
+
* Tests!
|
data/Rakefile
ADDED
data/lib/tutter.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'rubygems'
|
1
2
|
require 'octokit'
|
2
3
|
require 'yaml'
|
3
4
|
require 'sinatra'
|
@@ -5,15 +6,20 @@ require 'tutter/action'
|
|
5
6
|
require 'json'
|
6
7
|
|
7
8
|
class Tutter < Sinatra::Base
|
9
|
+
|
10
|
+
configure do
|
11
|
+
set :config_path, ENV['TUTTER_CONFIG_PATH'] || "conf/tutter.yaml"
|
12
|
+
set :config, YAML.load_file(settings.config_path)
|
13
|
+
end
|
14
|
+
|
8
15
|
configure :development do
|
9
16
|
require 'sinatra/reloader'
|
10
17
|
register Sinatra::Reloader
|
11
|
-
set :config, YAML.load_file('conf/tutter.yaml')
|
12
18
|
set :bind, '0.0.0.0'
|
13
19
|
end
|
14
20
|
|
15
|
-
configure :
|
16
|
-
set :
|
21
|
+
configure :test do
|
22
|
+
set :bind, '0.0.0.0'
|
17
23
|
end
|
18
24
|
|
19
25
|
# Return project settings from config
|
@@ -24,13 +30,10 @@ class Tutter < Sinatra::Base
|
|
24
30
|
false
|
25
31
|
end
|
26
32
|
|
27
|
-
|
28
|
-
|
29
|
-
data = JSON.parse request.body.read
|
30
|
-
project = data['repository']['full_name']
|
33
|
+
def try_action event, data
|
34
|
+
project = data['repository']['full_name'] || error(400, 'Bad request')
|
31
35
|
|
32
|
-
conf = get_project_settings(project)
|
33
|
-
return 'Project does not exist in tutter.conf' unless conf
|
36
|
+
conf = get_project_settings(project) || error(404, 'Project does not exist in tutter.conf')
|
34
37
|
|
35
38
|
# Setup octokit endpoints
|
36
39
|
Octokit.configure do |c|
|
@@ -38,26 +41,54 @@ class Tutter < Sinatra::Base
|
|
38
41
|
c.web_endpoint = conf['github_site']
|
39
42
|
end
|
40
43
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
return "Authorization to #{project} failed, please verify your access token"
|
46
|
-
rescue Octokit::TooManyLoginAttempts
|
47
|
-
return "Account for #{project} has been temporary locked down due to to many failed login attempts"
|
44
|
+
if conf['access_token_env_var']
|
45
|
+
access_token = ENV[conf['access_token_env_var']] || ''
|
46
|
+
else
|
47
|
+
access_token = conf['access_token'] || ''
|
48
48
|
end
|
49
49
|
|
50
|
+
client = Octokit::Client.new :access_token => access_token
|
51
|
+
|
50
52
|
# Load action
|
51
53
|
action = Action.create(conf['action'],
|
52
54
|
conf['action_settings'],
|
53
55
|
client,
|
54
56
|
project,
|
57
|
+
event,
|
55
58
|
data)
|
56
59
|
|
57
|
-
action.run
|
58
|
-
|
59
|
-
|
60
|
-
|
60
|
+
status_code, message = action.run
|
61
|
+
|
62
|
+
return status_code, message
|
63
|
+
end
|
64
|
+
|
65
|
+
post '/' do
|
66
|
+
event = env['HTTP_X_GITHUB_EVENT']
|
67
|
+
|
68
|
+
unless event
|
69
|
+
error(500, "Invalid request")
|
70
|
+
end
|
71
|
+
|
72
|
+
# Get a 200 OK message in the Github webhook history
|
73
|
+
# Previously this showed an error.
|
74
|
+
if event == "ping"
|
75
|
+
return 200, "Tutter likes this hook!"
|
76
|
+
end
|
77
|
+
|
78
|
+
# Github send data in JSON format, parse it!
|
79
|
+
begin
|
80
|
+
data = JSON.parse request.body.read
|
81
|
+
rescue JSON::ParserError
|
82
|
+
error(400, 'POST data is not JSON')
|
83
|
+
end
|
84
|
+
|
85
|
+
# Check actions with repo
|
86
|
+
|
87
|
+
if data['repository']
|
88
|
+
return try_action(event, data)
|
89
|
+
end
|
90
|
+
|
91
|
+
error(400, "Unsupported request: #{event}")
|
61
92
|
end
|
62
93
|
|
63
94
|
get '/' do
|
data/lib/tutter/action.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
class Action
|
2
|
-
def self.create(action, settings, client, project, data)
|
2
|
+
def self.create(action, settings, client, project, event, data)
|
3
3
|
begin
|
4
4
|
require "tutter/action/#{action.downcase}"
|
5
5
|
rescue LoadError => e
|
6
6
|
raise "Unsupported action #{action}: #{e}"
|
7
7
|
end
|
8
8
|
class_name = action.split("_").map {|v| v.capitalize }.join
|
9
|
-
const_get(class_name).new settings, client, project, data
|
9
|
+
const_get(class_name).new settings, client, project, data, event
|
10
10
|
end
|
11
11
|
end
|
data/lib/tutter/action/thanks.rb
CHANGED
@@ -2,23 +2,34 @@
|
|
2
2
|
# Thank the person who submit an issue
|
3
3
|
|
4
4
|
class Thanks
|
5
|
-
def initialize(settings, client, project, data)
|
5
|
+
def initialize(settings, client, project, data, event)
|
6
6
|
@settings = settings # action specific settings
|
7
7
|
@client = client # Octokit client
|
8
8
|
@project = project # project name
|
9
|
+
@event = event # Github event
|
9
10
|
@data = data
|
10
11
|
end
|
11
12
|
|
12
13
|
def run
|
13
14
|
# Only trigger if a new issue is created
|
14
|
-
|
15
|
-
|
15
|
+
unless @data['action'] == 'opened'
|
16
|
+
return 200, "Web hook from GitHub for #{@project} does not have status opened. We don't thank people for closing issues"
|
17
|
+
end
|
16
18
|
issue = @data['issue']['number']
|
17
19
|
submitter = @data['issue']['user']['login']
|
18
20
|
comment = "@#{submitter} thanks for submitting this issue!"
|
19
21
|
|
20
|
-
|
21
|
-
|
22
|
+
begin
|
23
|
+
@client.add_comment(@project, issue, comment)
|
24
|
+
return 200, "Commented!"
|
25
|
+
rescue Octokit::NotFound
|
26
|
+
return 404, "Octokit returned 404, this could be an issue with your access token"
|
27
|
+
rescue Octokit::Unauthorized
|
28
|
+
return 401, "Authorization to #{@project} failed, please verify your access token"
|
29
|
+
rescue Octokit::TooManyLoginAttempts
|
30
|
+
return 429, "Account for #{@project} has been temporary locked down due to to many failed login attempts"
|
31
|
+
end
|
32
|
+
# TODO - Verify return data from @client.add_comment
|
22
33
|
end
|
23
34
|
|
24
35
|
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
{
|
2
|
+
"action": "opened",
|
3
|
+
"issue": {
|
4
|
+
"url": "https://api.github.com/repos/JHaals/testing/issues/9",
|
5
|
+
"labels_url": "https://api.github.com/repos/JHaals/testing/issues/9/labels{/name}",
|
6
|
+
"comments_url": "https://api.github.com/repos/JHaals/testing/issues/9/comments",
|
7
|
+
"events_url": "https://api.github.com/repos/JHaals/testing/issues/9/events",
|
8
|
+
"html_url": "https://github.com/JHaals/testing/issues/9",
|
9
|
+
"id": 28705860,
|
10
|
+
"number": 9,
|
11
|
+
"title": "the internet is broken",
|
12
|
+
"user": {
|
13
|
+
"login": "JHaals",
|
14
|
+
"id": 68980,
|
15
|
+
"avatar_url": "https://avatars.githubusercontent.com/u/68980",
|
16
|
+
"gravatar_id": "4e51de553ebfe258f038e040c8b25892",
|
17
|
+
"url": "https://api.github.com/users/JHaals",
|
18
|
+
"html_url": "https://github.com/JHaals",
|
19
|
+
"followers_url": "https://api.github.com/users/JHaals/followers",
|
20
|
+
"following_url": "https://api.github.com/users/JHaals/following{/other_user}",
|
21
|
+
"gists_url": "https://api.github.com/users/JHaals/gists{/gist_id}",
|
22
|
+
"starred_url": "https://api.github.com/users/JHaals/starred{/owner}{/repo}",
|
23
|
+
"subscriptions_url": "https://api.github.com/users/JHaals/subscriptions",
|
24
|
+
"organizations_url": "https://api.github.com/users/JHaals/orgs",
|
25
|
+
"repos_url": "https://api.github.com/users/JHaals/repos",
|
26
|
+
"events_url": "https://api.github.com/users/JHaals/events{/privacy}",
|
27
|
+
"received_events_url": "https://api.github.com/users/JHaals/received_events",
|
28
|
+
"type": "User",
|
29
|
+
"site_admin": false
|
30
|
+
},
|
31
|
+
"labels": [
|
32
|
+
|
33
|
+
],
|
34
|
+
"state": "open",
|
35
|
+
"assignee": null,
|
36
|
+
"milestone": null,
|
37
|
+
"comments": 0,
|
38
|
+
"created_at": "2014-03-04T13:46:06Z",
|
39
|
+
"updated_at": "2014-03-04T13:46:06Z",
|
40
|
+
"closed_at": null,
|
41
|
+
"pull_request": {
|
42
|
+
"html_url": null,
|
43
|
+
"diff_url": null,
|
44
|
+
"patch_url": null
|
45
|
+
},
|
46
|
+
"body": "what to do?"
|
47
|
+
},
|
48
|
+
"repository": {
|
49
|
+
"id": 16474769,
|
50
|
+
"name": "testing",
|
51
|
+
"full_name": "JHaals/testing",
|
52
|
+
"owner": {
|
53
|
+
"login": "JHaals",
|
54
|
+
"id": 68980,
|
55
|
+
"avatar_url": "https://avatars.githubusercontent.com/u/68980",
|
56
|
+
"gravatar_id": "4e51de553ebfe258f038e040c8b25892",
|
57
|
+
"url": "https://api.github.com/users/JHaals",
|
58
|
+
"html_url": "https://github.com/JHaals",
|
59
|
+
"followers_url": "https://api.github.com/users/JHaals/followers",
|
60
|
+
"following_url": "https://api.github.com/users/JHaals/following{/other_user}",
|
61
|
+
"gists_url": "https://api.github.com/users/JHaals/gists{/gist_id}",
|
62
|
+
"starred_url": "https://api.github.com/users/JHaals/starred{/owner}{/repo}",
|
63
|
+
"subscriptions_url": "https://api.github.com/users/JHaals/subscriptions",
|
64
|
+
"organizations_url": "https://api.github.com/users/JHaals/orgs",
|
65
|
+
"repos_url": "https://api.github.com/users/JHaals/repos",
|
66
|
+
"events_url": "https://api.github.com/users/JHaals/events{/privacy}",
|
67
|
+
"received_events_url": "https://api.github.com/users/JHaals/received_events",
|
68
|
+
"type": "User",
|
69
|
+
"site_admin": false
|
70
|
+
},
|
71
|
+
"private": false,
|
72
|
+
"html_url": "https://github.com/JHaals/testing",
|
73
|
+
"description": "this is just for personal tests",
|
74
|
+
"fork": false,
|
75
|
+
"url": "https://api.github.com/repos/JHaals/testing",
|
76
|
+
"forks_url": "https://api.github.com/repos/JHaals/testing/forks",
|
77
|
+
"keys_url": "https://api.github.com/repos/JHaals/testing/keys{/key_id}",
|
78
|
+
"collaborators_url": "https://api.github.com/repos/JHaals/testing/collaborators{/collaborator}",
|
79
|
+
"teams_url": "https://api.github.com/repos/JHaals/testing/teams",
|
80
|
+
"hooks_url": "https://api.github.com/repos/JHaals/testing/hooks",
|
81
|
+
"issue_events_url": "https://api.github.com/repos/JHaals/testing/issues/events{/number}",
|
82
|
+
"events_url": "https://api.github.com/repos/JHaals/testing/events",
|
83
|
+
"assignees_url": "https://api.github.com/repos/JHaals/testing/assignees{/user}",
|
84
|
+
"branches_url": "https://api.github.com/repos/JHaals/testing/branches{/branch}",
|
85
|
+
"tags_url": "https://api.github.com/repos/JHaals/testing/tags",
|
86
|
+
"blobs_url": "https://api.github.com/repos/JHaals/testing/git/blobs{/sha}",
|
87
|
+
"git_tags_url": "https://api.github.com/repos/JHaals/testing/git/tags{/sha}",
|
88
|
+
"git_refs_url": "https://api.github.com/repos/JHaals/testing/git/refs{/sha}",
|
89
|
+
"trees_url": "https://api.github.com/repos/JHaals/testing/git/trees{/sha}",
|
90
|
+
"statuses_url": "https://api.github.com/repos/JHaals/testing/statuses/{sha}",
|
91
|
+
"languages_url": "https://api.github.com/repos/JHaals/testing/languages",
|
92
|
+
"stargazers_url": "https://api.github.com/repos/JHaals/testing/stargazers",
|
93
|
+
"contributors_url": "https://api.github.com/repos/JHaals/testing/contributors",
|
94
|
+
"subscribers_url": "https://api.github.com/repos/JHaals/testing/subscribers",
|
95
|
+
"subscription_url": "https://api.github.com/repos/JHaals/testing/subscription",
|
96
|
+
"commits_url": "https://api.github.com/repos/JHaals/testing/commits{/sha}",
|
97
|
+
"git_commits_url": "https://api.github.com/repos/JHaals/testing/git/commits{/sha}",
|
98
|
+
"comments_url": "https://api.github.com/repos/JHaals/testing/comments{/number}",
|
99
|
+
"issue_comment_url": "https://api.github.com/repos/JHaals/testing/issues/comments/{number}",
|
100
|
+
"contents_url": "https://api.github.com/repos/JHaals/testing/contents/{+path}",
|
101
|
+
"compare_url": "https://api.github.com/repos/JHaals/testing/compare/{base}...{head}",
|
102
|
+
"merges_url": "https://api.github.com/repos/JHaals/testing/merges",
|
103
|
+
"archive_url": "https://api.github.com/repos/JHaals/testing/{archive_format}{/ref}",
|
104
|
+
"downloads_url": "https://api.github.com/repos/JHaals/testing/downloads",
|
105
|
+
"issues_url": "https://api.github.com/repos/JHaals/testing/issues{/number}",
|
106
|
+
"pulls_url": "https://api.github.com/repos/JHaals/testing/pulls{/number}",
|
107
|
+
"milestones_url": "https://api.github.com/repos/JHaals/testing/milestones{/number}",
|
108
|
+
"notifications_url": "https://api.github.com/repos/JHaals/testing/notifications{?since,all,participating}",
|
109
|
+
"labels_url": "https://api.github.com/repos/JHaals/testing/labels{/name}",
|
110
|
+
"releases_url": "https://api.github.com/repos/JHaals/testing/releases{/id}",
|
111
|
+
"created_at": "2014-02-03T09:25:47Z",
|
112
|
+
"updated_at": "2014-02-16T20:25:07Z",
|
113
|
+
"pushed_at": "2014-02-16T20:25:06Z",
|
114
|
+
"git_url": "git://github.com/JHaals/testing.git",
|
115
|
+
"ssh_url": "git@github.com:JHaals/testing.git",
|
116
|
+
"clone_url": "https://github.com/JHaals/testing.git",
|
117
|
+
"svn_url": "https://github.com/JHaals/testing",
|
118
|
+
"homepage": null,
|
119
|
+
"size": 312,
|
120
|
+
"stargazers_count": 0,
|
121
|
+
"watchers_count": 0,
|
122
|
+
"language": null,
|
123
|
+
"has_issues": true,
|
124
|
+
"has_downloads": true,
|
125
|
+
"has_wiki": true,
|
126
|
+
"forks_count": 0,
|
127
|
+
"mirror_url": null,
|
128
|
+
"open_issues_count": 5,
|
129
|
+
"forks": 0,
|
130
|
+
"open_issues": 5,
|
131
|
+
"watchers": 0,
|
132
|
+
"default_branch": "master",
|
133
|
+
"master_branch": "master"
|
134
|
+
},
|
135
|
+
"sender": {
|
136
|
+
"login": "JHaals",
|
137
|
+
"id": 68980,
|
138
|
+
"avatar_url": "https://avatars.githubusercontent.com/u/68980",
|
139
|
+
"gravatar_id": "4e51de553ebfe258f038e040c8b25892",
|
140
|
+
"url": "https://api.github.com/users/JHaals",
|
141
|
+
"html_url": "https://github.com/JHaals",
|
142
|
+
"followers_url": "https://api.github.com/users/JHaals/followers",
|
143
|
+
"following_url": "https://api.github.com/users/JHaals/following{/other_user}",
|
144
|
+
"gists_url": "https://api.github.com/users/JHaals/gists{/gist_id}",
|
145
|
+
"starred_url": "https://api.github.com/users/JHaals/starred{/owner}{/repo}",
|
146
|
+
"subscriptions_url": "https://api.github.com/users/JHaals/subscriptions",
|
147
|
+
"organizations_url": "https://api.github.com/users/JHaals/orgs",
|
148
|
+
"repos_url": "https://api.github.com/users/JHaals/repos",
|
149
|
+
"events_url": "https://api.github.com/users/JHaals/events{/privacy}",
|
150
|
+
"received_events_url": "https://api.github.com/users/JHaals/received_events",
|
151
|
+
"type": "User",
|
152
|
+
"site_admin": false
|
153
|
+
}
|
154
|
+
}
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '../lib/tutter.rb')
|
2
|
+
|
3
|
+
require 'sinatra'
|
4
|
+
require 'rack/test'
|
5
|
+
Tutter.environment = :development
|
6
|
+
set :run, false
|
7
|
+
set :raise_errors, true
|
8
|
+
set :logging, true
|
9
|
+
|
10
|
+
def app
|
11
|
+
Tutter
|
12
|
+
end
|
13
|
+
|
14
|
+
RSpec.configure do |config|
|
15
|
+
config.include Rack::Test::Methods
|
16
|
+
end
|
data/spec/tutter_spec.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
describe 'tutter' do
|
5
|
+
|
6
|
+
it 'should complain about missing project in settings' do
|
7
|
+
post '/', params=JSON.generate({'repository' => {'full_name' => '404'}}), {'HTTP_X_GITHUB_EVENT' => 'fake'}
|
8
|
+
last_response.body.should match /Project does not exist in tutter.conf/
|
9
|
+
last_response.status.should == 404
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should complain about POST data not being JSON' do
|
13
|
+
post '/', params={'broken' => 'data'}, {'HTTP_X_GITHUB_EVENT' => 'fake'}
|
14
|
+
last_response.body.should match /POST data is not JSON/
|
15
|
+
last_response.status.should == 400
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should return documentation URL' do
|
19
|
+
get '/'
|
20
|
+
last_response.body.should match /Source code and documentation/
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'tutter Hello action' do
|
26
|
+
it 'should complain about invalid credentials' do
|
27
|
+
data = IO.read('spec/fixtures/new_issue.json')
|
28
|
+
post '/', params=data, {'HTTP_X_GITHUB_EVENT' => 'fake'}
|
29
|
+
last_response.body.should match /Authorization to JHaals\/testing failed, please verify your access token/
|
30
|
+
last_response.status.should == 401
|
31
|
+
end
|
32
|
+
end
|
metadata
CHANGED
@@ -1,61 +1,64 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tutter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Johan Haals
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-01-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sinatra
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 1.4.4
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 1.4.4
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: octokit
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - ~>
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 2.
|
33
|
+
version: 3.2.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - ~>
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 2.
|
40
|
+
version: 3.2.0
|
41
41
|
description: Tutter is a web app that trigger actions based on Github events(push,
|
42
42
|
pull_reqeust, release, issue, ...)
|
43
43
|
email:
|
44
44
|
- johan.haals@gmail.com
|
45
|
-
executables:
|
46
|
-
- tutter
|
45
|
+
executables: []
|
47
46
|
extensions: []
|
48
47
|
extra_rdoc_files: []
|
49
48
|
files:
|
50
|
-
- .gemspec
|
51
|
-
- .gitignore
|
49
|
+
- ".gemspec"
|
50
|
+
- ".gitignore"
|
51
|
+
- ".travis.yml"
|
52
52
|
- Gemfile
|
53
53
|
- README.md
|
54
|
-
-
|
54
|
+
- Rakefile
|
55
55
|
- conf/tutter.yaml
|
56
56
|
- lib/tutter.rb
|
57
57
|
- lib/tutter/action.rb
|
58
58
|
- lib/tutter/action/thanks.rb
|
59
|
+
- spec/fixtures/new_issue.json
|
60
|
+
- spec/spec_helper.rb
|
61
|
+
- spec/tutter_spec.rb
|
59
62
|
homepage: https://github.com/jhaals/tutter
|
60
63
|
licenses:
|
61
64
|
- Apache 2.0
|
@@ -67,17 +70,17 @@ require_paths:
|
|
67
70
|
- conf
|
68
71
|
required_ruby_version: !ruby/object:Gem::Requirement
|
69
72
|
requirements:
|
70
|
-
- -
|
73
|
+
- - ">="
|
71
74
|
- !ruby/object:Gem::Version
|
72
75
|
version: 1.8.7
|
73
76
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
77
|
requirements:
|
75
|
-
- -
|
78
|
+
- - ">="
|
76
79
|
- !ruby/object:Gem::Version
|
77
80
|
version: '0'
|
78
81
|
requirements: []
|
79
82
|
rubyforge_project:
|
80
|
-
rubygems_version: 2.
|
83
|
+
rubygems_version: 2.2.2
|
81
84
|
signing_key:
|
82
85
|
specification_version: 4
|
83
86
|
summary: Plugin based Github robot
|
data/bin/tutter
DELETED
@@ -1,75 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require 'optparse'
|
3
|
-
require 'octokit'
|
4
|
-
|
5
|
-
options = {}
|
6
|
-
|
7
|
-
OptionParser.new do |opts|
|
8
|
-
opts.banner = "Usage: tutter --project [project] [options]"
|
9
|
-
opts.on("-p", "--project [PROJECT]", "Github project name (jhaals/tutter)") do |p|
|
10
|
-
options[:project] = p
|
11
|
-
end
|
12
|
-
opts.on("-e", "--events [EVENTS]", "Github events that will trigger tutter") do |e|
|
13
|
-
options[:events] = e
|
14
|
-
end
|
15
|
-
opts.on("-u", "--url [URL]", "URL to the tutter service") do |u|
|
16
|
-
options[:url] = u
|
17
|
-
end
|
18
|
-
opts.on("-t", "--access-token [TOKEN]", "Github access token") do |t|
|
19
|
-
options[:access_token] = t
|
20
|
-
end
|
21
|
-
opts.on("--github-api-endpoint [api-endpoint]", "Github API endpoint") do |t|
|
22
|
-
options[:api_endpoint] = t
|
23
|
-
end
|
24
|
-
opts.on("--github-web-url [GITHUBWEBSITE]", "Github website url") do |t|
|
25
|
-
options[:base_url] = t
|
26
|
-
end
|
27
|
-
end.parse!
|
28
|
-
|
29
|
-
if options[:project].nil?
|
30
|
-
puts '--project required'
|
31
|
-
exit 1
|
32
|
-
end
|
33
|
-
|
34
|
-
if options[:url].nil?
|
35
|
-
puts '--url required'
|
36
|
-
exit 1
|
37
|
-
end
|
38
|
-
|
39
|
-
if options[:access_token].nil?
|
40
|
-
puts '--access-token required'
|
41
|
-
exit 1
|
42
|
-
end
|
43
|
-
|
44
|
-
if options[:base_url].nil?
|
45
|
-
puts '--github-web-url required'
|
46
|
-
exit 1
|
47
|
-
end
|
48
|
-
|
49
|
-
if options[:api_endpoint].nil?
|
50
|
-
puts '--github-api-endpoint required'
|
51
|
-
exit 1
|
52
|
-
end
|
53
|
-
|
54
|
-
Octokit.configure do |c|
|
55
|
-
c.api_endpoint = options[:api_endpoint]
|
56
|
-
c.web_endpoint = options[:base_url]
|
57
|
-
end
|
58
|
-
|
59
|
-
client = Octokit::Client.new :access_token => options[:access_token]
|
60
|
-
client.login
|
61
|
-
|
62
|
-
p client.create_hook(
|
63
|
-
options[:project],
|
64
|
-
'web',
|
65
|
-
{
|
66
|
-
:url => options[:url],
|
67
|
-
:content_type => 'json'
|
68
|
-
},
|
69
|
-
{
|
70
|
-
:events => options[:events].split(','),
|
71
|
-
:active => true
|
72
|
-
}
|
73
|
-
)
|
74
|
-
|
75
|
-
|