bugzilla 0.10.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.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/.travis.yml +17 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Dockerfile +5 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +76 -0
- data/LICENSE.txt +21 -0
- data/README.md +48 -0
- data/Rakefile +26 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/bugzilla.gemspec +34 -0
- data/lib/bugzilla.rb +12 -0
- data/lib/bugzilla/api_template.rb +44 -0
- data/lib/bugzilla/bug.rb +356 -0
- data/lib/bugzilla/bugzilla.rb +149 -0
- data/lib/bugzilla/classification.rb +74 -0
- data/lib/bugzilla/group.rb +43 -0
- data/lib/bugzilla/plugin.rb +67 -0
- data/lib/bugzilla/plugins/nvbugzilla.rb +49 -0
- data/lib/bugzilla/plugins/rhbugzilla.rb +210 -0
- data/lib/bugzilla/product.rb +179 -0
- data/lib/bugzilla/skeleton.rb +42 -0
- data/lib/bugzilla/user.rb +182 -0
- data/lib/bugzilla/utils.rb +53 -0
- data/lib/bugzilla/version.rb +27 -0
- data/lib/bugzilla/xmlrpc.rb +92 -0
- metadata +211 -0
@@ -0,0 +1,179 @@
|
|
1
|
+
# product.rb
|
2
|
+
# Copyright (C) 2010-2012 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# Authors:
|
5
|
+
# Akira TAGOH <tagoh@redhat.com>
|
6
|
+
#
|
7
|
+
# This library is free software: you can redistribute it and/or
|
8
|
+
# modify it under the terms of the GNU Lesser General Public
|
9
|
+
# License as published by the Free Software Foundation, either
|
10
|
+
# version 3 of the License, or (at your option) any later version.
|
11
|
+
#
|
12
|
+
# This library is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
require 'bugzilla/api_template'
|
21
|
+
|
22
|
+
module Bugzilla
|
23
|
+
# rdoc
|
24
|
+
#
|
25
|
+
# === Bugzilla::Product
|
26
|
+
#
|
27
|
+
# Bugzilla::Product class is to access
|
28
|
+
# the Bugzilla::WebService::Product API that allows you to
|
29
|
+
# list the available Products and get information about them.
|
30
|
+
#
|
31
|
+
|
32
|
+
class Product < APITemplate
|
33
|
+
# rdoc
|
34
|
+
#
|
35
|
+
# ==== Bugzilla::Product#selectable_products
|
36
|
+
#
|
37
|
+
# Returns Hash table for the products information that the user
|
38
|
+
# can search on. the Hash key is the product name and containing
|
39
|
+
# a Hash table which contains id, name, description,
|
40
|
+
# is_active, default_milestone, has_uncomfirmed, classification,
|
41
|
+
# components, versions and milestones. please see
|
42
|
+
# http://www.bugzilla.org/docs/tip/en/html/api/Bugzilla/WebService/Product.html#get
|
43
|
+
# for more details.
|
44
|
+
#
|
45
|
+
|
46
|
+
def selectable_products
|
47
|
+
ids = get_selectable_products
|
48
|
+
Hash[*get(ids)['products'].map { |x| [x['name'], x] }.flatten]
|
49
|
+
end # def selectable_products
|
50
|
+
|
51
|
+
# rdoc
|
52
|
+
#
|
53
|
+
# ==== Bugzilla::Product#enterable_products
|
54
|
+
#
|
55
|
+
# Returns Hash table for the products information that the user
|
56
|
+
# can enter bugs against. the Hash key is the product name and
|
57
|
+
# containing a Hash table which contains id, name, description,
|
58
|
+
# is_active, default_milestone, has_uncomfirmed, classification,
|
59
|
+
# components, versions and milestones. please see
|
60
|
+
# http://www.bugzilla.org/docs/tip/en/html/api/Bugzilla/WebService/Product.html#get
|
61
|
+
# for more details.
|
62
|
+
#
|
63
|
+
|
64
|
+
def enterable_products
|
65
|
+
ids = get_enterable_products
|
66
|
+
Hash[*get(ids)['products'].map { |x| [x['name'], x] }.flatten]
|
67
|
+
end # def enterable_products
|
68
|
+
|
69
|
+
# rdoc
|
70
|
+
#
|
71
|
+
# ==== Bugzilla::Product#accessible_products
|
72
|
+
#
|
73
|
+
# Returns Hash table for the products information that the user
|
74
|
+
# can search or enter bugs against. the Hash key is the product
|
75
|
+
# name and containing a Hash table which contains id, name, description,
|
76
|
+
# is_active, default_milestone, has_uncomfirmed, classification,
|
77
|
+
# components, versions and milestones. please see
|
78
|
+
# http://www.bugzilla.org/docs/tip/en/html/api/Bugzilla/WebService/Product.html#get
|
79
|
+
# for more details.
|
80
|
+
#
|
81
|
+
|
82
|
+
def accessible_products
|
83
|
+
ids = get_accessible_products
|
84
|
+
Hash[*get(ids)['products'].map { |x| [x['name'], x] }.flatten]
|
85
|
+
end # def accessible_products
|
86
|
+
|
87
|
+
# rdoc
|
88
|
+
#
|
89
|
+
# ==== Bugzilla::Product#get_selectable_products
|
90
|
+
#
|
91
|
+
# Raw Bugzilla API to obtain the products that the user can
|
92
|
+
# search on.
|
93
|
+
#
|
94
|
+
# See http://www.bugzilla.org/docs/tip/en/html/api/Bugzilla/WebService/Product.html
|
95
|
+
#
|
96
|
+
|
97
|
+
# rdoc
|
98
|
+
#
|
99
|
+
# ==== Bugzilla::Product#get_enterable_products
|
100
|
+
#
|
101
|
+
# Raw Bugzilla API to obtain the products that the user can
|
102
|
+
# enter bugs against.
|
103
|
+
#
|
104
|
+
# See http://www.bugzilla.org/docs/tip/en/html/api/Bugzilla/WebService/Product.html
|
105
|
+
#
|
106
|
+
|
107
|
+
# rdoc
|
108
|
+
#
|
109
|
+
# ==== Bugzilla::Product#get_accessible_products
|
110
|
+
#
|
111
|
+
# Raw Bugzilla API to obtain the products that the user can
|
112
|
+
# search or enter bugs against.
|
113
|
+
#
|
114
|
+
# See http://www.bugzilla.org/docs/tip/en/html/api/Bugzilla/WebService/Product.html
|
115
|
+
#
|
116
|
+
|
117
|
+
# rdoc
|
118
|
+
#
|
119
|
+
# ==== Bugzilla::Product#get(params)
|
120
|
+
#
|
121
|
+
# Raw Bugzilla API to obtain a list of information about the products
|
122
|
+
# passed to it.
|
123
|
+
#
|
124
|
+
# See http://www.bugzilla.org/docs/tip/en/html/api/Bugzilla/WebService/Product.html
|
125
|
+
#
|
126
|
+
|
127
|
+
protected
|
128
|
+
|
129
|
+
def _get_selectable_products(cmd, *_args)
|
130
|
+
@iface.call(cmd)
|
131
|
+
end # def _get_selectable_products
|
132
|
+
|
133
|
+
def _get_enterable_products(cmd, *_args)
|
134
|
+
@iface.call(cmd)
|
135
|
+
end # def _get_entrable_products
|
136
|
+
|
137
|
+
def _get_accessible_products(cmd, *_args)
|
138
|
+
@iface.call(cmd)
|
139
|
+
end # def _get_accessible_products
|
140
|
+
|
141
|
+
def _get(cmd, ids, *_args)
|
142
|
+
# This is still in experimental and apparently the behavior was changed since 4.2.
|
143
|
+
# We don't keep the backward-compatibility and just require the proper version here.
|
144
|
+
requires_version(cmd, 4.2)
|
145
|
+
|
146
|
+
params = {}
|
147
|
+
|
148
|
+
if ids.is_a?(Hash)
|
149
|
+
raise ArgumentError, format('Invalid parameter: %s', ids.inspect) unless ids.include?('ids') || ids.include?('names')
|
150
|
+
params[:ids] = ids['ids'] || ids['names']
|
151
|
+
elsif ids.is_a?(Array)
|
152
|
+
r = ids.map { |x| x.is_a?(Integer) ? x : nil }.compact
|
153
|
+
if r.length != ids.length
|
154
|
+
params[:names] = ids
|
155
|
+
else
|
156
|
+
params[:ids] = ids
|
157
|
+
end
|
158
|
+
else
|
159
|
+
if ids.is_a?(Integer)
|
160
|
+
params[:ids] = [ids]
|
161
|
+
else
|
162
|
+
params[:names] = [ids]
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
@iface.call(cmd, params)
|
167
|
+
end # def _get
|
168
|
+
|
169
|
+
def __create(cmd, *args)
|
170
|
+
# FIXME
|
171
|
+
end # def _create
|
172
|
+
|
173
|
+
def __update(cmd, *_args)
|
174
|
+
requires_version(cmd, 4.4)
|
175
|
+
|
176
|
+
# FIXME
|
177
|
+
end # def _update
|
178
|
+
end # class Product
|
179
|
+
end # module Bugzilla
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# skeleton.rb
|
2
|
+
# Copyright (C) 2010-2014 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# Authors:
|
5
|
+
# Akira TAGOH <tagoh@redhat.com>
|
6
|
+
#
|
7
|
+
# This library is free software: you can redistribute it and/or
|
8
|
+
# modify it under the terms of the GNU Lesser General Public
|
9
|
+
# License as published by the Free Software Foundation, either
|
10
|
+
# version 3 of the License, or (at your option) any later version.
|
11
|
+
#
|
12
|
+
# This library is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
module Bugzilla
|
21
|
+
# rdoc
|
22
|
+
#
|
23
|
+
# === Bugzilla::Skeleton
|
24
|
+
#
|
25
|
+
|
26
|
+
class Skeleton
|
27
|
+
def initialize(iface)
|
28
|
+
@iface = iface
|
29
|
+
end # def initialize
|
30
|
+
|
31
|
+
def method_missing(symbol, *args)
|
32
|
+
m = "_#{symbol}"
|
33
|
+
klass = self.class.to_s.sub(/\ABugzilla::/, '')
|
34
|
+
fm = "#{klass}.#{symbol}"
|
35
|
+
if respond_to?(m, true)
|
36
|
+
__send__(m, fm, *args)
|
37
|
+
else
|
38
|
+
raise NoMethodError, format('No such Bugzilla APIs: %s.%s', klass, symbol)
|
39
|
+
end
|
40
|
+
end # def method_missing
|
41
|
+
end # class Skeleton
|
42
|
+
end # module Bugzilla
|
@@ -0,0 +1,182 @@
|
|
1
|
+
# user.rb
|
2
|
+
# Copyright (C) 2010-2014 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# Authors:
|
5
|
+
# Akira TAGOH <tagoh@redhat.com>
|
6
|
+
#
|
7
|
+
# This library is free software: you can redistribute it and/or
|
8
|
+
# modify it under the terms of the GNU Lesser General Public
|
9
|
+
# License as published by the Free Software Foundation, either
|
10
|
+
# version 3 of the License, or (at your option) any later version.
|
11
|
+
#
|
12
|
+
# This library is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
require 'yaml'
|
21
|
+
require 'bugzilla/api_template'
|
22
|
+
|
23
|
+
module Bugzilla
|
24
|
+
# rdoc
|
25
|
+
#
|
26
|
+
# === Bugzilla::User
|
27
|
+
#
|
28
|
+
# Bugzilla::User class is to access the
|
29
|
+
# Bugzilla::WebService::User API that allows you to create
|
30
|
+
# User Accounts and log in/out using an existing account.
|
31
|
+
#
|
32
|
+
|
33
|
+
class User < APITemplate
|
34
|
+
# rdoc
|
35
|
+
#
|
36
|
+
# ==== Bugzilla::User#session(user, password)
|
37
|
+
#
|
38
|
+
# Keeps the bugzilla session during doing something in the block.
|
39
|
+
#
|
40
|
+
|
41
|
+
def session(user, password)
|
42
|
+
key, fname = authentication_method
|
43
|
+
|
44
|
+
# TODO
|
45
|
+
# make those variables available
|
46
|
+
host = @iface.instance_variable_get(:@xmlrpc).instance_variable_get(:@host)
|
47
|
+
|
48
|
+
conf = load_authentication_token(fname)
|
49
|
+
|
50
|
+
val = conf.fetch(host, nil)
|
51
|
+
|
52
|
+
if !val.nil?
|
53
|
+
if key == :token
|
54
|
+
@iface.token = val
|
55
|
+
else
|
56
|
+
@iface.cookie = val
|
57
|
+
end
|
58
|
+
yield
|
59
|
+
elsif user.nil? || password.nil?
|
60
|
+
yield
|
61
|
+
return
|
62
|
+
else
|
63
|
+
login('login' => user, 'password' => password, 'remember' => true)
|
64
|
+
yield
|
65
|
+
end
|
66
|
+
|
67
|
+
conf[host] = @iface.send(key) if %i[token cookie].include? key
|
68
|
+
|
69
|
+
save_authentication_token(fname, conf)
|
70
|
+
key
|
71
|
+
end # def session
|
72
|
+
|
73
|
+
# rdoc
|
74
|
+
#
|
75
|
+
# ==== Bugzilla::User#get_userinfo(params)
|
76
|
+
#
|
77
|
+
|
78
|
+
def get_userinfo(user)
|
79
|
+
p = {}
|
80
|
+
ids = []
|
81
|
+
names = []
|
82
|
+
|
83
|
+
if user.is_a?(Array)
|
84
|
+
user.each do |u|
|
85
|
+
names << u if u.is_a?(String)
|
86
|
+
id << u if u.is_a?(Integer)
|
87
|
+
end
|
88
|
+
elsif user.is_a?(String)
|
89
|
+
names << user
|
90
|
+
elsif user.is_a?(Integer)
|
91
|
+
ids << user
|
92
|
+
else
|
93
|
+
raise ArgumentError, format('Unknown type of arguments: %s', user.class)
|
94
|
+
end
|
95
|
+
|
96
|
+
result = get('ids' => ids, 'names' => names)
|
97
|
+
|
98
|
+
result['users']
|
99
|
+
end # def get_userinfo
|
100
|
+
|
101
|
+
# rdoc
|
102
|
+
#
|
103
|
+
# ==== Bugzilla::User#login(params)
|
104
|
+
#
|
105
|
+
# Raw Bugzilla API to log into Bugzilla.
|
106
|
+
#
|
107
|
+
# See http://www.bugzilla.org/docs/tip/en/html/api/Bugzilla/WebService/User.html
|
108
|
+
#
|
109
|
+
|
110
|
+
# rdoc
|
111
|
+
#
|
112
|
+
# ==== Bugzilla::User#logout
|
113
|
+
#
|
114
|
+
# Raw Bugzilla API to log out the user.
|
115
|
+
#
|
116
|
+
# See http://www.bugzilla.org/docs/tip/en/html/api/Bugzilla/WebService/User.html
|
117
|
+
#
|
118
|
+
|
119
|
+
protected
|
120
|
+
|
121
|
+
def load_authentication_token(fname)
|
122
|
+
if File.exist?(fname) && File.lstat(fname).mode & 0o600 == 0o600
|
123
|
+
YAML.safe_load(File.open(fname).read)
|
124
|
+
else
|
125
|
+
{}
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def save_authentication_token(fname, conf)
|
130
|
+
File.open(fname, 'w') { |f| f.chmod(0o600); f.write(conf.to_yaml) }
|
131
|
+
end
|
132
|
+
|
133
|
+
def is_token_supported?
|
134
|
+
check_version('4.4.3')[0] == true
|
135
|
+
rescue StandardError
|
136
|
+
false
|
137
|
+
end
|
138
|
+
|
139
|
+
# it returns an array with authentication type and the name of the storage
|
140
|
+
def authentication_method
|
141
|
+
# if version supported, use token, otherwise cookie
|
142
|
+
if is_token_supported?
|
143
|
+
[:token, File.join(ENV['HOME'], '.ruby-bugzilla-token.yml')]
|
144
|
+
else
|
145
|
+
[:cookie, File.join(ENV['HOME'], '.ruby-bugzilla-cookie.yml')]
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def _login(cmd, *args)
|
150
|
+
raise ArgumentError, 'Invalid parameters' unless args[0].is_a?(Hash)
|
151
|
+
|
152
|
+
res = @iface.call(cmd, args[0])
|
153
|
+
@iface.token = res['token'] unless res['token'].nil?
|
154
|
+
|
155
|
+
res
|
156
|
+
end # def _login
|
157
|
+
|
158
|
+
def _logout(cmd, *_args)
|
159
|
+
@iface.call(cmd)
|
160
|
+
end # def _logout
|
161
|
+
|
162
|
+
def __offer_account_by_email(cmd, *args)
|
163
|
+
# FIXME
|
164
|
+
end # def _offer_account_by_email
|
165
|
+
|
166
|
+
def __create(cmd, *args)
|
167
|
+
# FIXME
|
168
|
+
end # def _create
|
169
|
+
|
170
|
+
def __update(cmd, *args)
|
171
|
+
# FIXME
|
172
|
+
end # def _update
|
173
|
+
|
174
|
+
def _get(cmd, *args)
|
175
|
+
raise ArgumentError, 'Invalid parameters' unless args[0].is_a?(Hash)
|
176
|
+
|
177
|
+
requires_version(cmd, 3.4)
|
178
|
+
res = @iface.call(cmd, args[0])
|
179
|
+
# FIXME
|
180
|
+
end # def _get
|
181
|
+
end # class User
|
182
|
+
end # module Bugzilla
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Bugzilla
|
2
|
+
module Utils
|
3
|
+
def get_proxy(info)
|
4
|
+
uri = info[:Proxy] || ENV['http_proxy']
|
5
|
+
proxy_uri = uri.nil? ? nil : URI.parse(uri)
|
6
|
+
proxy_host = proxy_uri.nil? ? nil : proxy_uri.host
|
7
|
+
proxy_port = proxy_uri.nil? ? nil : proxy_uri.port
|
8
|
+
[proxy_host, proxy_port]
|
9
|
+
end
|
10
|
+
|
11
|
+
def get_xmlrpc(conf = {}, opts = {})
|
12
|
+
info = conf
|
13
|
+
uri = URI.parse(info[:URL])
|
14
|
+
host = uri.host
|
15
|
+
port = uri.port
|
16
|
+
path = uri.path.empty? ? nil : uri.path
|
17
|
+
proxy_host, proxy_port = get_proxy(info)
|
18
|
+
timeout = opts[:timeout].nil? ? 60 : opts[:timeout]
|
19
|
+
yield host if block_given? # if you want to run some pre hook
|
20
|
+
xmlrpc = XMLRPC.new(host, port: port, path: path, proxy_host:
|
21
|
+
proxy_host, proxy_port: proxy_port, timeout:
|
22
|
+
timeout, http_basic_auth_user: uri.user,
|
23
|
+
http_basic_auth_pass: uri.password, debug: opts[:debug])
|
24
|
+
[xmlrpc, host]
|
25
|
+
end
|
26
|
+
def read_config(opts)
|
27
|
+
fname = opts[:config].nil? ? @defaultyamlfile : opts[:config]
|
28
|
+
begin
|
29
|
+
# TODO: fix config file
|
30
|
+
# Psych doesnt allow Symbol as class
|
31
|
+
# conf = YAML.safe_load(File.open(fname).read)
|
32
|
+
conf = YAML.load(File.open(fname).read)
|
33
|
+
rescue Errno::ENOENT
|
34
|
+
conf = {}
|
35
|
+
end
|
36
|
+
conf.each do |_k, v|
|
37
|
+
load(v[:Plugin]) if v.is_a?(Hash) && v.include?(:Plugin)
|
38
|
+
end
|
39
|
+
conf
|
40
|
+
end # def read_config
|
41
|
+
|
42
|
+
def save_config(opts, conf)
|
43
|
+
fname = opts[:config].nil? ? @defaultyamlfile : opts[:config]
|
44
|
+
if File.exist?(fname)
|
45
|
+
st = File.lstat(fname)
|
46
|
+
if st.mode & 0o600 != 0o600
|
47
|
+
raise format('The permissions of %s has to be 0600', fname)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
File.open(fname, 'w') { |f| f.chmod(0o600); f.write(conf.to_yaml) }
|
51
|
+
end # def save_config
|
52
|
+
end
|
53
|
+
end
|