gitall 1.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/gitall +58 -0
- data/lib/cli/app.rb +0 -0
- data/lib/gitall/gitall.rb +200 -0
- data/lib/gitall/logger.rb +21 -0
- data/lib/gitall/parsers/bitbucket.rb +13 -0
- data/lib/gitall/parsers/github.rb +191 -0
- data/lib/gitall/parsers/gitlab.rb +103 -0
- data/lib/gitall/plugins/admin.rb +78 -0
- data/lib/gitall/plugins/chancontrol.rb +127 -0
- data/lib/gitall/plugins/eval.rb +17 -0
- data/lib/gitall/plugins/git.rb +28 -0
- data/lib/gitall/version.rb +3 -0
- data/lib/views/_403.erb +1 -0
- metadata +224 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 023bf7ff2db1c44f15f8f8f66d02356ee0d5d88c53a4e4b1b78a374873041e7a
|
4
|
+
data.tar.gz: c0f0f44647496761ff884cb2380ea5891d27ad41ee9f8c5c3bcfab55e6912ff4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f385058ddb774533779b5efb63a53ca3ca46094575fabf15ca43444d7a8fa93806c481059bd394a5eeb61eadbde2947396a3e54e2aa6906d5156e612a4ce9c87
|
7
|
+
data.tar.gz: d3a6e33ff86b316dc41042f809731624a5777c537a2dd22d28b6252d2cb39f6ccd6095aaf2f965e02bfd465142debc4ed88bf255fd9f1291a6140d9b0e47d8e6
|
data/bin/gitall
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
3
|
+
require './bot_version.rb'
|
4
|
+
require 'sinatra/base'
|
5
|
+
require 'json'
|
6
|
+
require 'cinch'
|
7
|
+
require 'cinch/plugins/basic_ctcp'
|
8
|
+
require 'cinch/plugins/identify'
|
9
|
+
require 'ostruct'
|
10
|
+
require 'recursive-open-struct'
|
11
|
+
require 'yaml'
|
12
|
+
require 'unirest'
|
13
|
+
require 'base64'
|
14
|
+
require 'active_support/all'
|
15
|
+
Thread.abort_on_exception = true
|
16
|
+
|
17
|
+
# @note Load the plugins
|
18
|
+
require 'gitallchancontrol.rb'
|
19
|
+
require './lib/admin.rb'
|
20
|
+
require './lib/logger.rb'
|
21
|
+
require './lib/eval.rb'
|
22
|
+
|
23
|
+
# @note Load the parsers
|
24
|
+
require 'gitall/parsers/gitlab'
|
25
|
+
require 'gitall/parsers/github.rb'
|
26
|
+
|
27
|
+
# Cinch
|
28
|
+
|
29
|
+
$cfg = YAML.load_file(`echo ~/.gitall-rc.yml`.chomp!)
|
30
|
+
$bots = Hash.new
|
31
|
+
$threads = Array.new
|
32
|
+
|
33
|
+
# For the sake of this example, we'll create an ORM-like model and give it an
|
34
|
+
# authenticate method, that checks if a given password matches.
|
35
|
+
class User < Struct.new :nickname, :password, :type
|
36
|
+
def authenticate(pass)
|
37
|
+
password == pass
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Simulate a database.
|
42
|
+
$users = []
|
43
|
+
@users = YAML.load_file(`echo ~/.gitall-rc.yml`.chomp!)['users']
|
44
|
+
@users.each do |user, hash|
|
45
|
+
password = hash['password']
|
46
|
+
role = hash['role']
|
47
|
+
$users << User.new(user, password, role)
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
$bots.each do |key, bot|
|
52
|
+
puts "Starting IRC connection for #{key}..."
|
53
|
+
$threads << Thread.new { bot.start }
|
54
|
+
end
|
55
|
+
$threads << Thread.new {
|
56
|
+
WebHook.run! if __FILE__ == $PROGRAM_NAME
|
57
|
+
}
|
58
|
+
$threads.each(&:join)
|
data/lib/cli/app.rb
ADDED
File without changes
|
@@ -0,0 +1,200 @@
|
|
1
|
+
require 'recursive_open_struct'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
require 'parsers/github'
|
5
|
+
require 'parsers/gitlab'
|
6
|
+
|
7
|
+
require 'plugins/admin'
|
8
|
+
require 'plugins/chancontrol'
|
9
|
+
require 'plugins/git'
|
10
|
+
require 'plugins/eval'
|
11
|
+
|
12
|
+
module GitAll
|
13
|
+
CFG = File.open(Pathname(Dir.home).join('gitall-rc.yml'), 'r').read
|
14
|
+
USERS = CFG['users']
|
15
|
+
PROJECTS = CFG['projects']
|
16
|
+
# Houses all the gitall bots and their data
|
17
|
+
|
18
|
+
class Users
|
19
|
+
attr :users
|
20
|
+
@users = []
|
21
|
+
|
22
|
+
class User < Struct.new :nickname, :password, :type
|
23
|
+
def authenticate(pass)
|
24
|
+
password == pass
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
USERS.each do |user, hash|
|
29
|
+
password = hash['password']
|
30
|
+
role = hash['role']
|
31
|
+
@users << User.new(user, password, role)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
class Bots
|
35
|
+
attr :bots, :config
|
36
|
+
|
37
|
+
@bots = {}
|
38
|
+
@config = GitAll::CFG
|
39
|
+
|
40
|
+
|
41
|
+
|
42
|
+
def add_bots
|
43
|
+
@config['networks'].each do |name, ncfg|
|
44
|
+
bot = Cinch::Bot.new do
|
45
|
+
configure do |c|
|
46
|
+
c.server = ncfg.fetch('server')
|
47
|
+
c.port = ncfg.fetch('port')
|
48
|
+
c.nick = ncfg.fetch('nickname')
|
49
|
+
c.user = ncfg.fetch('username')
|
50
|
+
c.realname = ncfg.fetch('realname')
|
51
|
+
c.plugins.prefix = Regexp.new(ncfg.fetch('prefix'))
|
52
|
+
c.plugins.plugins << Cinch::Plugins::Identify
|
53
|
+
identify_with = ncfg.fetch('identify-with')
|
54
|
+
case identify_with
|
55
|
+
when 'nickserv'
|
56
|
+
begin
|
57
|
+
c.plugins.options[Cinch::Plugins::Identify] = {
|
58
|
+
:username => ncfg.fetch('sasl-username'),
|
59
|
+
:password => ncfg.fetch('sasl-password'),
|
60
|
+
:type => :nickserv,
|
61
|
+
}
|
62
|
+
rescue KeyError
|
63
|
+
# ignored
|
64
|
+
end
|
65
|
+
when 'sasl'
|
66
|
+
begin
|
67
|
+
c.sasl.username = ncfg.fetch('sasl-username')
|
68
|
+
c.sasl.password = ncfg.fetch('sasl-password')
|
69
|
+
rescue KeyError
|
70
|
+
# ignored
|
71
|
+
end
|
72
|
+
when 'cert'
|
73
|
+
begin
|
74
|
+
c.ssl.client_cert = ncfg.fetch('certfp')
|
75
|
+
rescue KeyError
|
76
|
+
# ignored
|
77
|
+
end
|
78
|
+
when 'none'
|
79
|
+
# Don't identify
|
80
|
+
else
|
81
|
+
# noop
|
82
|
+
end
|
83
|
+
c.channels = ncfg.fetch('channels')
|
84
|
+
c.ssl.use = ncfg.fetch('ssl')
|
85
|
+
c.ssl.verify = ncfg.fetch('sslverify')
|
86
|
+
c.messages_per_second = ncfg.fetch('mps')
|
87
|
+
# Global configuration. This means that all plugins / matchers that
|
88
|
+
# implement authentication make use of the :login strategy, with a user
|
89
|
+
# level of :users.
|
90
|
+
c.authentication = Cinch::Configuration::Authentication.new
|
91
|
+
c.authentication.strategy = :login
|
92
|
+
c.authentication.level = :users
|
93
|
+
# The UserLogin plugin will call this lambda when a user runs !register.
|
94
|
+
#c.authentication.registration = lambda { |nickname, password|
|
95
|
+
# If you were using an ORM, you'd do something like
|
96
|
+
# `User.create(:nickname => nickname, :password => password)` here.
|
97
|
+
# return false if Users.users.one? { |user| user.nickname == nickname }
|
98
|
+
# Users.users << User.new(nickname, password, 'user')
|
99
|
+
#}
|
100
|
+
# The UserLogin plugin will call this lambda when a user runs !login. Note:
|
101
|
+
# the class it returns must respond to #authenticate with 1 argument (the
|
102
|
+
# password the user tries to login with).
|
103
|
+
c.authentication.fetch_user = lambda { |nickname|
|
104
|
+
# If you were using an ORM, you'd probably do something like
|
105
|
+
# `User.first(:nickname => nickname)` here.
|
106
|
+
Users.users.find { |user| user.nickname == nickname } }
|
107
|
+
# The Authentication mixin will call these lambdas to check if a user is
|
108
|
+
# allowed to run a command.
|
109
|
+
c.authentication.users = lambda { |user| user.type == 'user' }
|
110
|
+
c.authentication.admins = lambda { |user| user.type == 'admin' }
|
111
|
+
c.plugins.plugins << Cinch::Plugins::UserLogin
|
112
|
+
c.plugins.plugins << Cinch::Plugins::BasicCTCP
|
113
|
+
c.plugins.options[Cinch::Plugins::BasicCTCP][:replies] = {
|
114
|
+
version: Version::Bot.version,
|
115
|
+
source: 'https://gitlab.com/gitall/gitall'
|
116
|
+
}
|
117
|
+
c.plugins.plugins << ChanControl
|
118
|
+
c.plugins.options[ChanControl][:authentication_level] = :admins
|
119
|
+
c.plugins.plugins << Admin
|
120
|
+
c.plugins.options[Admin][:authentication_level] = :admins
|
121
|
+
c.plugins.plugins << Eval
|
122
|
+
c.plugins.options[Eval][:authentication_level] = :admins
|
123
|
+
c.plugins.plugins << Cinch::Plugins::UserList
|
124
|
+
c.plugins.options[Cinch::Plugins::UserList][:authentication_level] = :admins
|
125
|
+
end
|
126
|
+
end
|
127
|
+
bot.loggers.clear
|
128
|
+
bot.loggers << GitLogger.new(name, File.open("log/gitall-#{name}.log", 'a'))
|
129
|
+
bot.loggers << GitLogger.new(name, STDOUT)
|
130
|
+
bot.loggers.level = :debug
|
131
|
+
self.bots[name] = bot
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
class WebHook < Sinatra::Base
|
136
|
+
set :port, 8008
|
137
|
+
set :bind, '127.0.0.1'
|
138
|
+
set :environment, 'production'
|
139
|
+
set :threaded, true
|
140
|
+
post '/hook/?' do
|
141
|
+
request.body.rewind
|
142
|
+
payload = request.body.read
|
143
|
+
json = JSON.load(payload)
|
144
|
+
j = RecursiveOpenStruct.new(json)
|
145
|
+
repo = ''
|
146
|
+
if request.env.key? 'HTTP_X_GITLAB_TOKEN'
|
147
|
+
repo = j.project.path_with_namespace
|
148
|
+
resp = GitLabParser.parse json
|
149
|
+
phash = PROJECTS[repo]
|
150
|
+
if phash['token'] == request.env['HTTP_X_GITLAB_TOKEN']
|
151
|
+
channels = phash['channels']
|
152
|
+
channels.each do |channet|
|
153
|
+
channel = channet.split(',')[0]
|
154
|
+
net = channet.split(',')[1]
|
155
|
+
resp.each do |n|
|
156
|
+
Bots.bots[net].Channel(channel).send("#{n}")
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
elsif request.env.key? 'HTTP_X_HUB_SIGNATURE'
|
161
|
+
if !j.repository.full_name.nil?
|
162
|
+
repo = j.repository.full_name
|
163
|
+
elsif !j.organization.login.nil?
|
164
|
+
repo = j.organization.login
|
165
|
+
else
|
166
|
+
end
|
167
|
+
# phash includes orgs and repos
|
168
|
+
phash = PROJECTS[repo.to_sym]
|
169
|
+
token = phash['token']
|
170
|
+
sent_token = request.env['HTTP_X_HUB_SIGNATURE']
|
171
|
+
signature = "sha1=#{OpenSSL::HMAC.hexdigest('sha1', token, payload.strip).chomp}"
|
172
|
+
resp = GitHubParser.parse json, request.env['HTTP_X_GITHUB_EVENT']
|
173
|
+
if signature.to_s == sent_token.to_s
|
174
|
+
channels = phash['channels'.to_sym]
|
175
|
+
channels.each {
|
176
|
+
|channet|
|
177
|
+
channel = channet.split(',')[0]
|
178
|
+
network = channet.split(',')[1]
|
179
|
+
resp.each {
|
180
|
+
|n|
|
181
|
+
GitAll::Bots.bots[network].Channel(channel).send("#{n}")
|
182
|
+
}
|
183
|
+
}
|
184
|
+
end
|
185
|
+
|
186
|
+
elsif request.env.key?('HTTP_X_GOGS_EVENT')
|
187
|
+
|
188
|
+
elsif request.env.key?('HTTP_X_EVENT_KEY')
|
189
|
+
# BitBucket's Webhooks
|
190
|
+
# Requires HTTPS and does not
|
191
|
+
# implement a secret unless set into
|
192
|
+
# the url.
|
193
|
+
status 404
|
194
|
+
body 'bitbucket not implemented'
|
195
|
+
else
|
196
|
+
[404, "I can't help with that"]
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# lib/logger.rb
|
2
|
+
# Ken Spencer <ken@electrocode.net>
|
3
|
+
#
|
4
|
+
# This module is part of GitAll and is released under the
|
5
|
+
# MIT license: http://opensource.org/licenses/MIT
|
6
|
+
|
7
|
+
require 'cinch'
|
8
|
+
|
9
|
+
class GitLogger < Cinch::Logger::FormattedLogger
|
10
|
+
def initialize(network, *args)
|
11
|
+
@network = network
|
12
|
+
super(*args)
|
13
|
+
end
|
14
|
+
|
15
|
+
def format_general(message)
|
16
|
+
message.gsub!(/[^[:print:][:space:]]/) do |m|
|
17
|
+
colorize(m.inspect[1..-2], :bg_white, :black)
|
18
|
+
end
|
19
|
+
"[#{@network}] #{message}"
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# lib/bitbucket.rb
|
2
|
+
# Ken Spencer <ken@electrocode.net>
|
3
|
+
#
|
4
|
+
# This module is part of GitAll and is released under the
|
5
|
+
# MIT license: http://opensource.org/licenses/MIT
|
6
|
+
|
7
|
+
class BitBucketParser
|
8
|
+
# @param [Object] json json object
|
9
|
+
# @param [Object] event the github event
|
10
|
+
def self.parse(json, event)
|
11
|
+
ec, e = event.split(':')
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,191 @@
|
|
1
|
+
# lib/github.rb
|
2
|
+
# Ken Spencer <ken@electrocode.net>
|
3
|
+
#
|
4
|
+
# This module is part of GitAll and is released under the
|
5
|
+
# MIT license: http://opensource.org/licenses/MIT
|
6
|
+
|
7
|
+
# GitHub Event Parsing
|
8
|
+
# noinspection RubyUnusedLocalVariable
|
9
|
+
require 'cinch'
|
10
|
+
class GitHubParser
|
11
|
+
# @param [Object] json json object
|
12
|
+
# @param [Object] event the github event
|
13
|
+
def self.parse(json, event)
|
14
|
+
j = RecursiveOpenStruct.new(json)
|
15
|
+
response = []
|
16
|
+
case event
|
17
|
+
when 'ping'
|
18
|
+
zen = j.zen
|
19
|
+
id = j.hook_id
|
20
|
+
response << "Hook #{id} [PING] '#{zen}'"
|
21
|
+
when 'issue_comment'
|
22
|
+
when 'member'
|
23
|
+
when 'membership'
|
24
|
+
when 'milestone'
|
25
|
+
when 'label'
|
26
|
+
# "action":"created",
|
27
|
+
# "label":{
|
28
|
+
# "url":"https://api.github.com/repos/baxterandthehackers/public-repo/labels/blocked",
|
29
|
+
# "name":"blocked",
|
30
|
+
# "color":"ff0000"
|
31
|
+
# },
|
32
|
+
action = j.action
|
33
|
+
l = j.label
|
34
|
+
repo = j.repository.full_name
|
35
|
+
user = j.sender.login
|
36
|
+
lurl = l.url
|
37
|
+
lname = l.name
|
38
|
+
case action
|
39
|
+
when 'created', 'deleted'
|
40
|
+
response << "[#{repo}] #{user} #{action} label #{lname} <#{lurl}>"
|
41
|
+
when 'edited'
|
42
|
+
old = l.changes.name.from
|
43
|
+
new = lname
|
44
|
+
if old != new
|
45
|
+
response << "[#{repo}] #{user} #{action} Old: #{old} New: #{new}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
when 'team'
|
49
|
+
when 'team_add'
|
50
|
+
when 'fork'
|
51
|
+
f = RecursiveOpenStruct.new(j.forkee)
|
52
|
+
user = j.sender.login
|
53
|
+
fork = f.full_name
|
54
|
+
repo = j.repository.full_name
|
55
|
+
response << "[#{repo}] #{user} forked the repository to #{fork}"
|
56
|
+
when 'pull_request'
|
57
|
+
p = RecursiveOpenStruct.new(j.pull_request)
|
58
|
+
action = j.action
|
59
|
+
case action
|
60
|
+
when 'opened'
|
61
|
+
when 'closed'
|
62
|
+
end
|
63
|
+
when 'pull_request_review'
|
64
|
+
action = j.action
|
65
|
+
case action
|
66
|
+
when 'created'
|
67
|
+
when 'deleted'
|
68
|
+
end
|
69
|
+
when 'pull_request_review_comment'
|
70
|
+
c = RecursiveOpenStruct.new(j.comment)
|
71
|
+
action = j.action
|
72
|
+
case action
|
73
|
+
when 'created'
|
74
|
+
when 'deleted'
|
75
|
+
when 'edited'
|
76
|
+
end
|
77
|
+
when 'commit_comment'
|
78
|
+
when 'gollum'
|
79
|
+
p = j.pages
|
80
|
+
action = j.action
|
81
|
+
when 'create'
|
82
|
+
when 'delete'
|
83
|
+
when 'organization'
|
84
|
+
action = j.action
|
85
|
+
case action
|
86
|
+
when 'member_add'
|
87
|
+
when 'member_del'
|
88
|
+
end
|
89
|
+
when 'repository'
|
90
|
+
r = RecursiveOpenStruct.new(j.repository)
|
91
|
+
action = j.action
|
92
|
+
repo = r.full_name
|
93
|
+
user = j.sender.login
|
94
|
+
case action
|
95
|
+
when 'created'
|
96
|
+
response << "#{user} created repository #{repo}"
|
97
|
+
when 'deleted'
|
98
|
+
# XXX: Only triggers on Organization webhooks
|
99
|
+
response << "#{user} deleted #{r.full_name}"
|
100
|
+
end
|
101
|
+
when 'release'
|
102
|
+
r = RecursiveOpenStruct.new(j.release)
|
103
|
+
tag = r.tag_name
|
104
|
+
action = j.action
|
105
|
+
repo = j.repository.full_name
|
106
|
+
case action
|
107
|
+
when 'published'
|
108
|
+
response << "[#{repo}] released #{tag}!"
|
109
|
+
else
|
110
|
+
response << "[#{repo}] #{action} something!"
|
111
|
+
response << "**\u000304This is a fallback for when new actions are added to the 'ReleaseEvent'**"
|
112
|
+
response << 'Please submit an issue at https://github.com/IotaSpencer/gitall'
|
113
|
+
response << ' or join #gitall on the freenode or ElectroCode IRC networks.'
|
114
|
+
end
|
115
|
+
when 'watch'
|
116
|
+
# XXX: possibly add user's profile url if option set
|
117
|
+
response << "[#{repo}] #{user} starred the repository!"
|
118
|
+
when 'issue'
|
119
|
+
repo = j.repository.full_name
|
120
|
+
url = shorten(j.issue.url)
|
121
|
+
action = j.action
|
122
|
+
id = j.issue.number
|
123
|
+
title = j.issue.title
|
124
|
+
user = j.issue.user.name
|
125
|
+
# assigned", "unassigned", "labeled", "unlabeled", "opened", "edited",
|
126
|
+
# "milestoned", "demilestoned", "closed", or "reopened".
|
127
|
+
case action
|
128
|
+
when 'assigned'
|
129
|
+
# do stuff ...
|
130
|
+
when 'unassigned'
|
131
|
+
# do stuff ...
|
132
|
+
when 'labeled'
|
133
|
+
label = j.label.name
|
134
|
+
response << "[#{repo}] #{user} added #{label}"
|
135
|
+
when 'unlabeled'
|
136
|
+
# do stuff ...
|
137
|
+
when 'milestoned'
|
138
|
+
response << "[#{repo}] #{user} milestoned issue ##{id} "
|
139
|
+
when 'demilestoned'
|
140
|
+
# do stuff ...
|
141
|
+
when 'reopened'
|
142
|
+
response << "[#{repo}] #{user} reopened ##{id}"
|
143
|
+
|
144
|
+
when 'opened'
|
145
|
+
response << "[#{repo}] #{user} opened an issue ##{id} - #{title} <#{url}>"
|
146
|
+
when 'closed'
|
147
|
+
response << "[#{repo}] #{user} closed issue ##{id} - #{title} <#{url}>"
|
148
|
+
when 'edited'
|
149
|
+
response << "[#{repo}] #{user} edited issue ##{id} - #{title} <#{url}>"
|
150
|
+
end
|
151
|
+
when 'push'
|
152
|
+
repo = j.repository.full_name
|
153
|
+
branch = j.ref.split('/')[-1]
|
154
|
+
commits = j.commits
|
155
|
+
added = 0
|
156
|
+
removed = 0
|
157
|
+
modified = 0
|
158
|
+
commits.each do |h|
|
159
|
+
added += h['added'].length
|
160
|
+
removed += h['removed'].length
|
161
|
+
modified += h['modified'].length
|
162
|
+
end
|
163
|
+
pusher = j.pusher.name
|
164
|
+
commit_count = commits.length
|
165
|
+
compare_url = shorten(j.compare)
|
166
|
+
response << "[#{repo}] #{pusher} pushed #{commit_count} commit(s) [+#{added}/-#{removed}/±#{modified}] to [#{branch}] <#{compare_url}>"
|
167
|
+
if commits.length > 3
|
168
|
+
coms = commits[0..2]
|
169
|
+
coms.each do |n|
|
170
|
+
id = n.dig('id')
|
171
|
+
id = id[0...7]
|
172
|
+
msg = n.dig('message').lines[0].chomp
|
173
|
+
author = n.dig 'committer', 'name'
|
174
|
+
response << "#{author} — #{msg} [#{id}]"
|
175
|
+
end
|
176
|
+
response << "and #{commits.length - 3} commits..."
|
177
|
+
else
|
178
|
+
commits.each do |n|
|
179
|
+
id = n.dig('id')
|
180
|
+
id = id[0...7]
|
181
|
+
msg = n.dig('message').lines[0].chomp
|
182
|
+
author = n.dig 'committer', 'name'
|
183
|
+
response << "#{author} — #{msg} [#{id}]"
|
184
|
+
end
|
185
|
+
end
|
186
|
+
else
|
187
|
+
'format not implemented'
|
188
|
+
end
|
189
|
+
response
|
190
|
+
end
|
191
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# lib/gitlab.rb
|
2
|
+
# Ken Spencer <ken@electrocode.net>
|
3
|
+
#
|
4
|
+
# This module is part of GitAll and is released under the
|
5
|
+
# MIT license: http://opensource.org/licenses/MIT
|
6
|
+
|
7
|
+
# GitLab Event Parsing
|
8
|
+
class GitLabParser
|
9
|
+
def GitLabParser.parse(json)
|
10
|
+
j = RecursiveOpenStruct.new(json)
|
11
|
+
response = []
|
12
|
+
kind = j.object_kind
|
13
|
+
case kind
|
14
|
+
when 'note'
|
15
|
+
repo = j.project.path_with_namespace
|
16
|
+
ntype = j.object_attributes.noteable_type
|
17
|
+
case ntype
|
18
|
+
when 'MergeRequest'
|
19
|
+
mr_note = j.object_attributes.note
|
20
|
+
mr_url = shorten(j.object_attributes.url)
|
21
|
+
mr_title = j.merge_request.title
|
22
|
+
mr_id = j.merge_request.iid
|
23
|
+
mr_user = j.user.name
|
24
|
+
response << "[#{repo}] #{mr_user} commented on Merge Request ##{mr_id} \u2014 #{mr_note}"
|
25
|
+
response << "'#{mr_title}' => #{mr_url}"
|
26
|
+
when 'Commit'
|
27
|
+
c_note = j.object_attributes.note
|
28
|
+
c_sha = j.commit.id[0...7]
|
29
|
+
c_url = shorten(j.object_attributes.url)
|
30
|
+
c_user = j.user.name
|
31
|
+
response << "[#{repo}] #{c_user} commented on commit (#{c_sha}) \u2014 #{c_note} <#{c_url}>"
|
32
|
+
when 'Issue'
|
33
|
+
i_id = j.issue.iid
|
34
|
+
i_url = shorten(j.object_attributes.url)
|
35
|
+
i_msg = j.object_attributes.note
|
36
|
+
i_title = j.issue.title
|
37
|
+
i_user = j.user.name
|
38
|
+
response << "[#{repo}] #{i_user} commented on Issue ##{i_id} (#{i_title}) \u2014 #{i_msg} <#{i_url}>"
|
39
|
+
else
|
40
|
+
# type code here
|
41
|
+
end
|
42
|
+
when 'issue'
|
43
|
+
i_repo = j.project.path_with_namespace
|
44
|
+
i_user = j.user.name
|
45
|
+
i_un = j.user.username
|
46
|
+
i_id = j.object_attributes.iid
|
47
|
+
i_title = j.object_attributes.title
|
48
|
+
i_action = j.object_attributes.action
|
49
|
+
i_url = shorten(j.object_attributes.url)
|
50
|
+
response << "[#{i_repo}] #{i_user}(#{i_un}) #{i_action} issue ##{i_id} - #{i_title} <#{i_url}>"
|
51
|
+
when 'merge_request'
|
52
|
+
mr_name = j.user.name
|
53
|
+
mr_user = j.user.username
|
54
|
+
mr_url = shorten(j.url)
|
55
|
+
mr_spath = j.object_attributes.source.path_with_namespace
|
56
|
+
mr_sbranch = j.object_attributes.source_branch
|
57
|
+
mr_tpath = j.object_attributes.target.path_with_namespace
|
58
|
+
mr_tbranch = j.object_attributes.target_branch
|
59
|
+
mr_lcmessage = j.object_attributes.last_commit.message
|
60
|
+
mr_lcsha = j.object_attributes.last_commit.id[0...7]
|
61
|
+
response << "#{mr_name}(#{mr_user}) opened a merge request. #{mr_spath}[#{mr_sbranch}] ~> #{mr_tpath}[#{mr_tbranch}]"
|
62
|
+
response << "[#{mr_lcsha}] \u2014 #{mr_lcmessage} <#{mr_url}>"
|
63
|
+
when 'push' # comes to
|
64
|
+
# shove
|
65
|
+
branch = j.ref.split('/')[-1]
|
66
|
+
commits = j.commits
|
67
|
+
added = 0
|
68
|
+
removed = 0
|
69
|
+
modified = 0
|
70
|
+
commits.each do |h|
|
71
|
+
added += h['added'].length
|
72
|
+
removed += h['removed'].length
|
73
|
+
modified += h['modified'].length
|
74
|
+
end
|
75
|
+
owner = j.project.namespace
|
76
|
+
project = j.project.name
|
77
|
+
pusher = j.user_name
|
78
|
+
commit_count = j.total_commits_count
|
79
|
+
repo_url = shorten(j.project.web_url)
|
80
|
+
response << "[#{owner}/#{project}] #{pusher} pushed #{commit_count} commit(s) [+#{added}/-#{removed}/±#{modified}] to [#{branch}] at <#{repo_url}>"
|
81
|
+
if commits.length > 3
|
82
|
+
coms = commits[0..2]
|
83
|
+
coms.each do |n|
|
84
|
+
id = n['id']
|
85
|
+
msg = n['message'].lines[0]
|
86
|
+
author = n['author']['name']
|
87
|
+
response << "#{author} — #{msg.chomp!} [#{id[0...7]}]"
|
88
|
+
end
|
89
|
+
response << "and #{commits.from(3).length} commits..."
|
90
|
+
else
|
91
|
+
commits.each do |n|
|
92
|
+
id = n['id'][0...7]
|
93
|
+
msg = n['message'].lines[0]
|
94
|
+
author = n['author']['name']
|
95
|
+
response << "#{author} — #{msg.chomp!} [#{id}]"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
else
|
99
|
+
# type code here
|
100
|
+
end
|
101
|
+
return response
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# lib/admin.rb
|
2
|
+
# Ken Spencer <ken@electrocode.net>
|
3
|
+
#
|
4
|
+
# This module is part of GitAll and is released under the
|
5
|
+
# MIT license: http://opensource.org/licenses/MIT
|
6
|
+
|
7
|
+
require 'cinch'
|
8
|
+
require 'cinch/extensions/authentication'
|
9
|
+
require 'yaml'
|
10
|
+
require 'recursive-open-struct'
|
11
|
+
|
12
|
+
# @class Admin Plugin
|
13
|
+
class Admin
|
14
|
+
include Cinch::Plugin
|
15
|
+
include Cinch::Extensions::Authentication
|
16
|
+
match /quit$/, method: :do_Quit, group: :quit
|
17
|
+
match /quit (.+)$/, method: :do_Quit, group: :quit
|
18
|
+
|
19
|
+
match /join$/, method: :do_Join, group: :join
|
20
|
+
match /join (.+)/, method: :do_Join, group: :join
|
21
|
+
|
22
|
+
match /announce$/, method: :do_Announce, group: :announce
|
23
|
+
match /announce (.+)$/, method: :do_Announce, group: :announce
|
24
|
+
match /global$/, method: :do_Announce, group: :announce
|
25
|
+
match /global (.+)$/, method: :do_Announce, group: :announce
|
26
|
+
|
27
|
+
def do_Announce(m, msg = nil)
|
28
|
+
return unless authenticated? m
|
29
|
+
if msg.nil?
|
30
|
+
command = m.command
|
31
|
+
m.reply "Syntax: !#{command} Message to announce..."
|
32
|
+
else
|
33
|
+
$bots.each do |net, bot|
|
34
|
+
info("Announcing to #{net}")
|
35
|
+
debug("Announcing '#{msg}'")
|
36
|
+
bot.channels.each do |c|
|
37
|
+
Channel(c).send("[GLOBAL - #{m.user}@#{m.bot.irc.isupport.fetch('NETWORK')}] #{msg}",
|
38
|
+
notice=false)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def do_Quit(m, msg = nil)
|
45
|
+
return unless authenticated? m
|
46
|
+
if msg.nil?
|
47
|
+
$bots.each do |net, bot|
|
48
|
+
info("Exiting from #{net}")
|
49
|
+
bot.quit('QUIT received!')
|
50
|
+
end
|
51
|
+
else
|
52
|
+
$bots.each do |net, bot|
|
53
|
+
info("Exiting from #{net}")
|
54
|
+
bot.quit(msg)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
$threads.each(&:exit)
|
58
|
+
end
|
59
|
+
def do_Join(m, channels = nil)
|
60
|
+
return unless authenticated? m
|
61
|
+
if channels.nil?
|
62
|
+
m.reply 'Syntax: join #channel[,#channel2,#channel3]'
|
63
|
+
else
|
64
|
+
chans = channels.split(',')
|
65
|
+
chans.each do |chan|
|
66
|
+
Channel(chan).join
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
def do_Part(m, channels = nil, reasons = nil)
|
71
|
+
return unless authenticated? m
|
72
|
+
if channels.nil? && reasons.nil?
|
73
|
+
m.reply 'Syntax: part #channel1[,#channel2,#channel3] [reason1[,reason2,reason3]]'
|
74
|
+
else
|
75
|
+
m.reply 'Not implemented yet'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
# lib/chancontrol.rb
|
2
|
+
# Ken Spencer <ken@electrocode.net>
|
3
|
+
#
|
4
|
+
# This module is part of GitAll and is released under the
|
5
|
+
# MIT license: http://opensource.org/licenses/MIT
|
6
|
+
|
7
|
+
require 'cinch'
|
8
|
+
require 'cinch/extensions/authentication'
|
9
|
+
require 'yaml'
|
10
|
+
require 'recursive-open-struct'
|
11
|
+
require 'strgen'
|
12
|
+
# @note ChanControl Plugin
|
13
|
+
|
14
|
+
class ChanControl
|
15
|
+
include Cinch::Plugin
|
16
|
+
include Cinch::Extensions::Authentication
|
17
|
+
|
18
|
+
# Write to the config
|
19
|
+
# @param [Hash] msg the data to write
|
20
|
+
def toFile(msg)
|
21
|
+
data = msg
|
22
|
+
File.open(`echo ~/.gitall-rc.yml`.chomp, 'w') {|f| f.write(data.to_yaml) }
|
23
|
+
end
|
24
|
+
|
25
|
+
# Load the config
|
26
|
+
# @return [Hash] load the current config
|
27
|
+
def deFile
|
28
|
+
begin
|
29
|
+
parsed = YAML.load(File.open(`echo ~/.gitall-rc.yml`.chomp, 'r'))
|
30
|
+
rescue ArgumentError => e
|
31
|
+
puts "Could not parse YAML: #{e.message}"
|
32
|
+
end
|
33
|
+
parsed
|
34
|
+
end
|
35
|
+
|
36
|
+
match /padd$/, method: :padd, group: :padd
|
37
|
+
match /padd (\S+) (\S+) (\S+) (\S+)/, method: :padd, group: :padd
|
38
|
+
|
39
|
+
match /list$/, method: :listchans, group: :listchans
|
40
|
+
match /list (\S+)/, method: :listchans, group: :listchans
|
41
|
+
|
42
|
+
match /token$/, method: :getToken, group: :token
|
43
|
+
match /token ([0-9]+)/, method: :getToken, group: :token
|
44
|
+
|
45
|
+
# @param [Message]
|
46
|
+
# @param [String] namespace the Repository to watch
|
47
|
+
# @param [String] host the Git Service Website
|
48
|
+
# @param [String] token Secret Token @seealso {ChanControl#getToken}
|
49
|
+
# @param [ChannelList] channels | separated list of channels in the format
|
50
|
+
# of #channel,net
|
51
|
+
def padd(m, namespace = nil, host = nil, token = nil, channels = nil)
|
52
|
+
if namespace.nil?
|
53
|
+
m.reply 'Syntax: padd {OWNER/PROJECT} {github, gitlab, bitbucket}
|
54
|
+
XXXXXXTOKEN #channel,network[|#channel2,network|#channel3,network2]'
|
55
|
+
m.reply 'GitALL works best when using owner/repo webhooks, organization hooks have not been tested.'
|
56
|
+
else
|
57
|
+
return unless authenticated? m
|
58
|
+
config = deFile
|
59
|
+
if config[:projects].has_key? namespace
|
60
|
+
m.user.send("#{m.user.nick}: #{namespace} already exists in the
|
61
|
+
config.")
|
62
|
+
else
|
63
|
+
config[:projects][namespace] = {
|
64
|
+
host: host,
|
65
|
+
token: token,
|
66
|
+
channels: channels.split('|')
|
67
|
+
}
|
68
|
+
toFile(config)
|
69
|
+
project = deFile().dig(:projects, namespace)
|
70
|
+
m.user.send("Inputted: #{project}")
|
71
|
+
end
|
72
|
+
# @param [String] host
|
73
|
+
def cap_host(host)
|
74
|
+
case host.downcase
|
75
|
+
when 'github'
|
76
|
+
'GitHub.com'
|
77
|
+
when 'gitlab'
|
78
|
+
'GitLab.com'
|
79
|
+
when 'bitbucket'
|
80
|
+
'BitBucket.org'
|
81
|
+
end
|
82
|
+
end
|
83
|
+
m.user.send("Remember to add the webhook to #{cap_host(host)} if you
|
84
|
+
haven't already.")
|
85
|
+
info("Project added: #{project}")
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# @param [Message] m message object
|
90
|
+
# @param [Integer] length token length
|
91
|
+
# @return [String] Token
|
92
|
+
def getToken(m, length = nil)
|
93
|
+
token = Strgen.generate do |c|
|
94
|
+
if length.nil?
|
95
|
+
c.length = 30
|
96
|
+
else
|
97
|
+
if length.to_i > 100
|
98
|
+
c.length = 100
|
99
|
+
m.reply 'Truncating to 100 characters due to spam concerns'
|
100
|
+
else
|
101
|
+
c.length = length
|
102
|
+
end
|
103
|
+
end
|
104
|
+
c.alpha = true
|
105
|
+
c.numbers = true
|
106
|
+
c.repeat = false
|
107
|
+
c.symbols = false
|
108
|
+
c.exclude = %w[1 i I l L 0 o O]
|
109
|
+
end
|
110
|
+
m.user.send "Token: #{token}"
|
111
|
+
end
|
112
|
+
|
113
|
+
# @param [Channel] channel name of channel
|
114
|
+
# @note Ensures that the channel is joined or known of
|
115
|
+
# @returns Boolean true/false
|
116
|
+
|
117
|
+
def self.joined(channel)
|
118
|
+
Channel(channel) ? true : false
|
119
|
+
end
|
120
|
+
# @param [Object] m Object
|
121
|
+
|
122
|
+
def listchans(m, project = nil)
|
123
|
+
return unless authenticated? m
|
124
|
+
project_hash = deFile['projects'][project]
|
125
|
+
m.reply "Name: #{project} Host: #{project_hash['host'.to_sym]} Channels: #{project_hash['channels'.to_sym].join(" \xB7 ")}"
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'cinch'
|
2
|
+
class Eval
|
3
|
+
include Cinch::Plugin
|
4
|
+
include Cinch::Extensions::Authentication
|
5
|
+
|
6
|
+
match /eval$/, method: :do_eval, group: :doeval
|
7
|
+
match /eval (.*)/, method: :do_eval, group: :doeval
|
8
|
+
|
9
|
+
def do_eval(m, string = nil)
|
10
|
+
if string.nil?
|
11
|
+
m.reply "Syntax: !eval [CODE...]"
|
12
|
+
else
|
13
|
+
return unless authenticated? m
|
14
|
+
m.reply(eval(string))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# lib/git.rb
|
2
|
+
# Ken Spencer <ken@electrocode.net>
|
3
|
+
#
|
4
|
+
# This module is part of GitAll and is released under the
|
5
|
+
# MIT license: http://opensource.org/licenses/MIT
|
6
|
+
|
7
|
+
require 'cinch'
|
8
|
+
require 'cinch/extensions/authentication'
|
9
|
+
require 'unirest'
|
10
|
+
class ChanControl
|
11
|
+
include Cinch::Plugin
|
12
|
+
include Cinch::Extensions::Authentication
|
13
|
+
|
14
|
+
match /(\s+)\:(\S)\/(\S+)\#(\S)/, :method => :getIssue
|
15
|
+
|
16
|
+
def getIssue(m, host, user, repo, issue)
|
17
|
+
case host
|
18
|
+
when 'gl'
|
19
|
+
m.reply("https://gitlab.com/#{user}/#{repo}/issues/#{issue}")
|
20
|
+
when 'gh'
|
21
|
+
m.reply("https://github.com/#{user}/#{repo}/issue/#{issue}")
|
22
|
+
when 'bb'
|
23
|
+
m.reply("https://bitbucket.org/#{user}/#{repo}/issue/#{issue}")
|
24
|
+
else
|
25
|
+
m.user.notice("I don't know that git-service host")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/views/_403.erb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Invalid / Missing 'Secret' or 'Token'
|
metadata
ADDED
@@ -0,0 +1,224 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gitall
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.1.5
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ken Spencer
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-06-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: cinch
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 2.3.4
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 2.3.4
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sinatra
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.0'
|
34
|
+
- - ">="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 2.0.2
|
37
|
+
type: :runtime
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - "~>"
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '2.0'
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 2.0.2
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: sinatra-contrib
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 2.0.2
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 2.0.2
|
57
|
+
type: :runtime
|
58
|
+
prerelease: false
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - "~>"
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 2.0.2
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: 2.0.2
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: thor
|
69
|
+
requirement: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - "~>"
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0.20'
|
74
|
+
type: :runtime
|
75
|
+
prerelease: false
|
76
|
+
version_requirements: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - "~>"
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0.20'
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: paint
|
83
|
+
requirement: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - "~>"
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '2.0'
|
88
|
+
type: :runtime
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - "~>"
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '2.0'
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: git
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - "~>"
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '1.3'
|
102
|
+
type: :runtime
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - "~>"
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '1.3'
|
109
|
+
- !ruby/object:Gem::Dependency
|
110
|
+
name: logging
|
111
|
+
requirement: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - "~>"
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '2.2'
|
116
|
+
type: :runtime
|
117
|
+
prerelease: false
|
118
|
+
version_requirements: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - "~>"
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '2.2'
|
123
|
+
- !ruby/object:Gem::Dependency
|
124
|
+
name: pry
|
125
|
+
requirement: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - "~>"
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '0.11'
|
130
|
+
type: :runtime
|
131
|
+
prerelease: false
|
132
|
+
version_requirements: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - "~>"
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0.11'
|
137
|
+
- !ruby/object:Gem::Dependency
|
138
|
+
name: bundler
|
139
|
+
requirement: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - "~>"
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '1.16'
|
144
|
+
type: :development
|
145
|
+
prerelease: false
|
146
|
+
version_requirements: !ruby/object:Gem::Requirement
|
147
|
+
requirements:
|
148
|
+
- - "~>"
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: '1.16'
|
151
|
+
- !ruby/object:Gem::Dependency
|
152
|
+
name: rake
|
153
|
+
requirement: !ruby/object:Gem::Requirement
|
154
|
+
requirements:
|
155
|
+
- - "~>"
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '10.0'
|
158
|
+
type: :development
|
159
|
+
prerelease: false
|
160
|
+
version_requirements: !ruby/object:Gem::Requirement
|
161
|
+
requirements:
|
162
|
+
- - "~>"
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: '10.0'
|
165
|
+
- !ruby/object:Gem::Dependency
|
166
|
+
name: rspec
|
167
|
+
requirement: !ruby/object:Gem::Requirement
|
168
|
+
requirements:
|
169
|
+
- - "~>"
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
version: '3.0'
|
172
|
+
type: :development
|
173
|
+
prerelease: false
|
174
|
+
version_requirements: !ruby/object:Gem::Requirement
|
175
|
+
requirements:
|
176
|
+
- - "~>"
|
177
|
+
- !ruby/object:Gem::Version
|
178
|
+
version: '3.0'
|
179
|
+
description: A git based webhook receiver for GitHub, GitLab, and Gogs
|
180
|
+
email:
|
181
|
+
- me@iotaspencer.me
|
182
|
+
executables:
|
183
|
+
- gitall
|
184
|
+
extensions: []
|
185
|
+
extra_rdoc_files: []
|
186
|
+
files:
|
187
|
+
- bin/gitall
|
188
|
+
- lib/cli/app.rb
|
189
|
+
- lib/gitall/gitall.rb
|
190
|
+
- lib/gitall/logger.rb
|
191
|
+
- lib/gitall/parsers/bitbucket.rb
|
192
|
+
- lib/gitall/parsers/github.rb
|
193
|
+
- lib/gitall/parsers/gitlab.rb
|
194
|
+
- lib/gitall/plugins/admin.rb
|
195
|
+
- lib/gitall/plugins/chancontrol.rb
|
196
|
+
- lib/gitall/plugins/eval.rb
|
197
|
+
- lib/gitall/plugins/git.rb
|
198
|
+
- lib/gitall/version.rb
|
199
|
+
- lib/views/_403.erb
|
200
|
+
homepage: https://gitlab.com/gitall/gitall
|
201
|
+
licenses:
|
202
|
+
- MIT
|
203
|
+
metadata: {}
|
204
|
+
post_install_message:
|
205
|
+
rdoc_options: []
|
206
|
+
require_paths:
|
207
|
+
- lib
|
208
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
209
|
+
requirements:
|
210
|
+
- - "~>"
|
211
|
+
- !ruby/object:Gem::Version
|
212
|
+
version: '2'
|
213
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
214
|
+
requirements:
|
215
|
+
- - ">="
|
216
|
+
- !ruby/object:Gem::Version
|
217
|
+
version: '0'
|
218
|
+
requirements: []
|
219
|
+
rubyforge_project:
|
220
|
+
rubygems_version: 2.7.6
|
221
|
+
signing_key:
|
222
|
+
specification_version: 4
|
223
|
+
summary: Git Based Webservices Webhook Receiver
|
224
|
+
test_files: []
|