schleuder-gitlab-ticketing 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +191 -0
- data/lib/schleuder-gitlab-ticketing.rb +6 -0
- data/lib/schleuder-gitlab-ticketing/config.rb +45 -0
- data/lib/schleuder-gitlab-ticketing/gitlab_config.rb +11 -0
- data/lib/schleuder-gitlab-ticketing/list.rb +198 -0
- data/lib/schleuder-gitlab-ticketing/version.rb +3 -0
- data/lib/schleuder/filters/post_decryption/99_gitlab_ticketing.rb +25 -0
- metadata +104 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b59177cf964bf88408cc0d315ba893e8c5a8379fc250b1df318f36c136d1a2b0
|
4
|
+
data.tar.gz: 7b407e3792310e646fe68c949eb7d1b71d15bd617b89e2c85178a29492046cab
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1b448ce81e1cac8ae9ddeb6fa66d7517bc927fa5e3bafa283caa51fee703aca240870848aa6d205b6a2171614834780e250997770f1f2f90e52885e88270e2d6
|
7
|
+
data.tar.gz: 26164f54b6bca5e1fdfd5abb23208e87281028e4c5798279b2bdb98da3a8df7b3e391b9ed9e7fb6fc57d630cab243be3b629d32d45e6b42593f983ebac5ad7e8
|
data/README.md
ADDED
@@ -0,0 +1,191 @@
|
|
1
|
+
Schleuder Gitlab Ticketing
|
2
|
+
==========================
|
3
|
+
|
4
|
+
A schleuder filter/plugin to hook lists into the issue tracker of a gitlab project.
|
5
|
+
|
6
|
+
Background
|
7
|
+
----------
|
8
|
+
|
9
|
+
Schleuderlists are not only a helpful tool for communication within groups, they can also be
|
10
|
+
used for newsletters, or by using its famous remailer capabilities to be used as a contact
|
11
|
+
address for a project or as a help desk.
|
12
|
+
|
13
|
+
In the latter two cases keeping an overview of the different interactions can become somewhat
|
14
|
+
cumbersome, especially in a bigger collective where not everybody is able to dedicate the same
|
15
|
+
amount of time/attention to the contact address / help desk. Hence it is easy that a certain
|
16
|
+
thread (and so task) on the list is getting lost. Having some kind of ticketing system in place
|
17
|
+
can help to easily keep track of what is done, what is in progress and what should be looked at.
|
18
|
+
|
19
|
+
Additionally, folks do not like to double the work and hence as much as possible should be done
|
20
|
+
while emails flow over the list.
|
21
|
+
|
22
|
+
This schleuder filter / plugin allows to map emails through an id in the subject to issues in
|
23
|
+
a gitlab project. Additionally, it opens an issue on new emails or closes issues if the subject
|
24
|
+
indicates that the job is done.
|
25
|
+
|
26
|
+
The gitlab issues are mainly used to keep the state of a certain email thread and contains only
|
27
|
+
as much plaintext information as was transmitted in plaintext over the wire. This means it only
|
28
|
+
stores From:, Subject: and Message-Id: as issue comments.
|
29
|
+
|
30
|
+
How it works
|
31
|
+
------------
|
32
|
+
|
33
|
+
The filter / plugin hooks into the filter process list in schleuder. First schleuder will check
|
34
|
+
whether there is a configuration for the current list, as well as whether this configuration
|
35
|
+
is correct. Otherwise the filter is immediately skipped.
|
36
|
+
|
37
|
+
Schleuder then dispatches the processing to the specific list instance, which checks whether
|
38
|
+
the email comes from a sender that shall be ignored (e.g. well known spammers or announce lists)
|
39
|
+
or whether the subject matches any of the configured subject filters. The email is also ignored
|
40
|
+
if the well known `X-Spam-Flag` header is set to `yes`.
|
41
|
+
|
42
|
+
If none of that matches, the email is being processed and first the email's subject is analyzed
|
43
|
+
to get an already existing ticket id. The plugin expects something like `Subject: my subject [gp#123]`,
|
44
|
+
where gp is a configureable project identifier and 123 matches an issue id in gitlab. The brackets
|
45
|
+
enclose the ticket identifier and can be anywhere within the subject.
|
46
|
+
|
47
|
+
If no ticket id can be found or no issue can be found in gitlab a new issue will be created in
|
48
|
+
gitlab. The ticket id will be appended to the subject, a faulty ticket id will be replaced.
|
49
|
+
|
50
|
+
If a ticket can be found, a comment is added to the issue, that includes the sender email address,
|
51
|
+
as well as the Subject and Message-ID of the email.
|
52
|
+
|
53
|
+
Additionally, if the email is sent from an email address, that is a member of the gitlab project
|
54
|
+
the ticket will be assigned to said user. Furthermore, the label `inprocess` is added to ticket
|
55
|
+
to indicate that someone of the project is working on that thread.
|
56
|
+
|
57
|
+
If the ticket is already closed it will be re-opened.
|
58
|
+
|
59
|
+
If the subject contains: `[ok]` the ticket will be closed and the label `inprocess` removed. An
|
60
|
+
already closed ticket stays closed.
|
61
|
+
|
62
|
+
That's it.
|
63
|
+
|
64
|
+
Prerequisits
|
65
|
+
------------
|
66
|
+
|
67
|
+
* ruby >=2.1
|
68
|
+
* schleuder >= 3.3.0
|
69
|
+
* A working schleuder installation and a schleuder list
|
70
|
+
* A gitlab project and a dedicated user and its API token
|
71
|
+
|
72
|
+
Installation
|
73
|
+
------------
|
74
|
+
|
75
|
+
* Install the gem (depends on the gitlab gem)
|
76
|
+
* Link `lib/schleuder/filters/post_decrpytion/99_gitlab_ticketing.rb` into `/usr/local/lib/schleuder/filters/post_decryption/`,
|
77
|
+
so the plugin gets loaded.
|
78
|
+
|
79
|
+
Configuration
|
80
|
+
-------------
|
81
|
+
|
82
|
+
The plugin is looking for a configuration in `/etc/schleuder/gitlab.yml`. The configuration file
|
83
|
+
expects a `gitlab` and a lists `configuration` section:
|
84
|
+
|
85
|
+
```
|
86
|
+
gitlab:
|
87
|
+
endpoint: https://gitlab.example.com/api/v4
|
88
|
+
token: xxxx
|
89
|
+
|
90
|
+
lists:
|
91
|
+
test@schleuder.example.com:
|
92
|
+
project: tickets
|
93
|
+
namespace: support
|
94
|
+
```
|
95
|
+
|
96
|
+
The key of the lists configuration indicates the listname on schleuder side, which matches its
|
97
|
+
email address. A list's setting requires 2 configuration options: `project` & `namespace` which
|
98
|
+
map to the path within gitlab, where the project exists. Namespace can either be the group or
|
99
|
+
the users name, depending of where a project lives.
|
100
|
+
|
101
|
+
The plugin supports working for multiple lists, as well as allows individual gitlab configuration
|
102
|
+
for different lists:
|
103
|
+
|
104
|
+
```
|
105
|
+
gitlab:
|
106
|
+
endpoint: https://gitlab.example.com/api/v4
|
107
|
+
token: xxxx
|
108
|
+
lists:
|
109
|
+
test@schleuder.example.com:
|
110
|
+
project: tickets
|
111
|
+
namespace: support
|
112
|
+
test2@schleuder.example.com:
|
113
|
+
gitlab:
|
114
|
+
endpoint: https://gitlab2.example.com/api/v4
|
115
|
+
token: aaaa
|
116
|
+
```
|
117
|
+
|
118
|
+
Additionally, you can specify filters based on the sender or the subject. They must be valid ruby
|
119
|
+
regexps and can also be specified on a global and local level.
|
120
|
+
|
121
|
+
```
|
122
|
+
gitlab:
|
123
|
+
endpoint: https://gitlab.example.com/api/v4
|
124
|
+
token: xxxx
|
125
|
+
|
126
|
+
subject_filters:
|
127
|
+
- '\[announce\]'
|
128
|
+
sender_filters:
|
129
|
+
- '^spammer@example\.com$'
|
130
|
+
|
131
|
+
lists:
|
132
|
+
test@schleuder.example.com:
|
133
|
+
project: tickets
|
134
|
+
namespace: support
|
135
|
+
subject_filters:
|
136
|
+
- 'ignore me'
|
137
|
+
test2@schleuder.example.com:
|
138
|
+
gitlab:
|
139
|
+
endpoint: https://gitlab2.example.com/api/v4
|
140
|
+
token: aaaa
|
141
|
+
sender_filters:
|
142
|
+
- 'noreply@example\.com'
|
143
|
+
|
144
|
+
```
|
145
|
+
|
146
|
+
Additionally, you can specify a specifc identifier to more easily identify a particular ticket id in
|
147
|
+
the subject:
|
148
|
+
|
149
|
+
```
|
150
|
+
lists:
|
151
|
+
test@schleuder.example.com:
|
152
|
+
project: tickets
|
153
|
+
namespace: support
|
154
|
+
ticket_prefix: ourid
|
155
|
+
```
|
156
|
+
|
157
|
+
This will look for the following string in a subject: `[ourid#\d+]`. By default it would look for:
|
158
|
+
`[gl/test#\d+]`
|
159
|
+
|
160
|
+
Todo
|
161
|
+
----
|
162
|
+
|
163
|
+
This plugin is in a working state and has been tested by multiple use cases for nearly a year.
|
164
|
+
|
165
|
+
Some more ideas:
|
166
|
+
|
167
|
+
* Use schleuder's verification capabilities to further prove that the email comes from a list member.
|
168
|
+
* Hook into schleuder's plugin capabilities, to allow more ticket actions (e.g. assign, labels, ...)
|
169
|
+
|
170
|
+
Contributing
|
171
|
+
------------
|
172
|
+
|
173
|
+
Please see [CONTRIBUTING.md](CONTRIBUTING.md).
|
174
|
+
|
175
|
+
|
176
|
+
Mission statement
|
177
|
+
-----------------
|
178
|
+
|
179
|
+
Please see [MISSION_STATEMENT.md](MISSION_STATEMENT.md).
|
180
|
+
|
181
|
+
|
182
|
+
Code of Conduct
|
183
|
+
---------------
|
184
|
+
|
185
|
+
We adopted a code of conduct. Please read [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md).
|
186
|
+
|
187
|
+
|
188
|
+
License
|
189
|
+
-------
|
190
|
+
|
191
|
+
GNU GPL 3.0. Please see [LICENSE.txt](LICENSE.txt).
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module SchleuderGitlabTicketing
|
2
|
+
class Config
|
3
|
+
include SchleuderGitlabTicketing::GitlabConfig
|
4
|
+
|
5
|
+
def initialize(config_path='/etc/schleuder/gitlab.yml')
|
6
|
+
@config = if File.exists?(config_path)
|
7
|
+
YAML.load_file(config_path)
|
8
|
+
else
|
9
|
+
{}
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# returns true if mail was handled
|
14
|
+
# returns 'config-error' if list-config is not properly
|
15
|
+
# returns nil if list is not configured to handle
|
16
|
+
# gitlab plugin
|
17
|
+
def process_list(list_name, mail)
|
18
|
+
if l = lists[list_name]
|
19
|
+
if l.configured?
|
20
|
+
l.process(mail)
|
21
|
+
else
|
22
|
+
'config-error'
|
23
|
+
end
|
24
|
+
else
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def lists
|
30
|
+
@lists ||= read_lists
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
def read_lists
|
35
|
+
Hash(@config['lists']).inject({}) do |res,a|
|
36
|
+
n,v = a
|
37
|
+
v['gitlab'] ||= gitlab
|
38
|
+
v['subject_filters'] = Array(v['subject_filters']) + Array(@config['subject_filters'])
|
39
|
+
v['sender_filters'] = Array(v['sender_filters']) + Array(@config['sender_filters'])
|
40
|
+
res[n] = SchleuderGitlabTicketing::List.new(n,v)
|
41
|
+
res
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module SchleuderGitlabTicketing
|
2
|
+
module GitlabConfig
|
3
|
+
def gitlab
|
4
|
+
@gitlab ||= if @config['gitlab']['endpoint'] && @config['gitlab']['token']
|
5
|
+
Gitlab.client(endpoint: @config['gitlab']['endpoint'], private_token: @config['gitlab']['token'])
|
6
|
+
else
|
7
|
+
nil
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,198 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'gitlab'
|
3
|
+
require 'set'
|
4
|
+
module SchleuderGitlabTicketing
|
5
|
+
class List
|
6
|
+
include SchleuderGitlabTicketing::GitlabConfig
|
7
|
+
|
8
|
+
def initialize(name, config)
|
9
|
+
@name = name
|
10
|
+
@config = config
|
11
|
+
end
|
12
|
+
|
13
|
+
def configured?
|
14
|
+
unless @config['project'] && @config['namespace'] && @config['gitlab'] && gitlab && project
|
15
|
+
return false
|
16
|
+
end
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
20
|
+
def process(mail)
|
21
|
+
return false if ignore_mail?(mail)
|
22
|
+
ticket_id = get_ticket_id(mail.subject)
|
23
|
+
ticket = ticket_id ? get_ticket(ticket_id) : nil
|
24
|
+
|
25
|
+
if (title = clean_subject(mail.subject)).nil? || title.empty?
|
26
|
+
title = "Request from #{mail.from.first}"
|
27
|
+
end
|
28
|
+
desc = desc(mail)
|
29
|
+
updates = {}
|
30
|
+
labels = Set.new
|
31
|
+
|
32
|
+
if !ticket
|
33
|
+
ticket = create_ticket(title, desc)
|
34
|
+
ticket_id = ticket.iid
|
35
|
+
mail.subject = update_subject(mail.subject, ticket_id)
|
36
|
+
else
|
37
|
+
labels = Set.new(ticket.labels)
|
38
|
+
comment_ticket(ticket_id,desc)
|
39
|
+
assignee_id = team_member_id(mail.from.first)
|
40
|
+
if assignee_id && ((as = ticket.assignee).nil? || as.id != assignee_id)
|
41
|
+
updates[:assignee_id] = assignee_id
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
bc = be_closed?(mail.subject)
|
46
|
+
tc = ticket_closed?(ticket)
|
47
|
+
|
48
|
+
if !tc && bc
|
49
|
+
labels.delete('inprocess')
|
50
|
+
updates[:state_event] = 'close'
|
51
|
+
elsif !tc && !bc
|
52
|
+
labels << 'inprocess' if updates[:assignee_id]
|
53
|
+
elsif tc && !bc
|
54
|
+
labels << 'inprocess'
|
55
|
+
updates[:state_event] = 'reopen'
|
56
|
+
end
|
57
|
+
if labels.empty? && (updates[:state_event] == 'close')
|
58
|
+
# make sure we remove the inprocess label
|
59
|
+
updates[:labels] = ''
|
60
|
+
elsif !labels.empty? && (labels.to_a.sort != ticket.labels.sort)
|
61
|
+
updates[:labels] = labels.to_a.join(',')
|
62
|
+
end
|
63
|
+
update_ticket(ticket_id, updates)
|
64
|
+
true
|
65
|
+
end
|
66
|
+
|
67
|
+
def gitlab
|
68
|
+
@gitlab ||= if @config['gitlab'].is_a?(Gitlab::Client)
|
69
|
+
@config['gitlab']
|
70
|
+
else
|
71
|
+
super
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def sender_filters
|
76
|
+
Array(@config['sender_filters'])
|
77
|
+
end
|
78
|
+
def subject_filters
|
79
|
+
Array(@config['subject_filters'])
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
def desc(mail)
|
84
|
+
res = []
|
85
|
+
res << "From: #{mail.from.first}"
|
86
|
+
res << "Message-Id: #{mail.message_id}"
|
87
|
+
res << "Subject: #{mail.subject || '[not set]'}"
|
88
|
+
res.join("\n\n")
|
89
|
+
end
|
90
|
+
|
91
|
+
def be_closed?(subject)
|
92
|
+
!(subject =~ /\[ok\]/).nil?
|
93
|
+
end
|
94
|
+
|
95
|
+
def ticket_closed?(ticket)
|
96
|
+
ticket.state == 'closed'
|
97
|
+
end
|
98
|
+
|
99
|
+
def update_ticket(ticket_id,updates)
|
100
|
+
return if updates.empty?
|
101
|
+
gitlab.edit_issue(project.id, ticket_id, updates)
|
102
|
+
rescue Gitlab::Error::NotFound => e
|
103
|
+
nil
|
104
|
+
end
|
105
|
+
|
106
|
+
def create_ticket(title, desc)
|
107
|
+
opts = { description: desc }
|
108
|
+
gitlab.create_issue(project.id, title, opts)
|
109
|
+
end
|
110
|
+
|
111
|
+
def comment_ticket(ticket_id, desc)
|
112
|
+
gitlab.create_issue_note(project.id, ticket_id, desc)
|
113
|
+
end
|
114
|
+
|
115
|
+
def get_ticket(id)
|
116
|
+
gitlab.issue(project.id, id)
|
117
|
+
rescue Gitlab::Error::NotFound => e
|
118
|
+
nil
|
119
|
+
end
|
120
|
+
|
121
|
+
def get_ticket_id(str)
|
122
|
+
if str && (m = str.match(/.*\[#{Regexp.escape(ticket_prefix)}\#(\d+)\].*/)) && m[1]
|
123
|
+
m[1].to_i
|
124
|
+
else
|
125
|
+
nil
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def project
|
130
|
+
@project ||= gitlab.search_projects(@config['project']).find{|p| p.namespace.name == @config['namespace'] && p.name == @config['project'] }
|
131
|
+
rescue Gitlab::Error::NotFound => e
|
132
|
+
nil
|
133
|
+
end
|
134
|
+
|
135
|
+
def issues
|
136
|
+
gitlab.issues(p.id)
|
137
|
+
end
|
138
|
+
|
139
|
+
def team_member_id(email)
|
140
|
+
if user_id = find_user_id(email)
|
141
|
+
user_id if project_member?(project, user_id)
|
142
|
+
else
|
143
|
+
nil
|
144
|
+
end
|
145
|
+
rescue Gitlab::Error::NotFound => e
|
146
|
+
nil
|
147
|
+
end
|
148
|
+
|
149
|
+
def project_member?(project, user_id)
|
150
|
+
begin
|
151
|
+
gitlab.team_member(project.id, user_id)
|
152
|
+
rescue Gitlab::Error::NotFound
|
153
|
+
gitlab.group_member(project.namespace.id, user_id)
|
154
|
+
end
|
155
|
+
rescue Gitlab::Error::NotFound => e
|
156
|
+
nil
|
157
|
+
end
|
158
|
+
|
159
|
+
def find_user_id(username_or_email)
|
160
|
+
users = gitlab.user_search(username_or_email)
|
161
|
+
# did we look for an email => exact match
|
162
|
+
# or by username?
|
163
|
+
user = if username_or_email =~ /@/
|
164
|
+
users.first
|
165
|
+
else
|
166
|
+
users.find do |u|
|
167
|
+
u.name == username_or_email || u.username == username_or_email
|
168
|
+
end
|
169
|
+
end
|
170
|
+
user.nil? ? nil : user.id
|
171
|
+
rescue Gitlab::Error::NotFound => e
|
172
|
+
nil
|
173
|
+
end
|
174
|
+
|
175
|
+
def ignore_mail?(mail)
|
176
|
+
return true if mail.respond_to?(:[]) && mail['X-Spam-Flag'].to_s.downcase == 'yes'
|
177
|
+
return true if sender_filters.any?{|s| mail.from.first =~ /#{s}/ }
|
178
|
+
return true if subject_filters.any?{|s| mail.subject =~ /#{s}/ }
|
179
|
+
false
|
180
|
+
end
|
181
|
+
|
182
|
+
def ticket_prefix
|
183
|
+
@ticket_prefix ||= (@config['ticket_prefix'] || "gl/#{@config['project']}")
|
184
|
+
end
|
185
|
+
|
186
|
+
def clean_subject(subj)
|
187
|
+
subj.nil? ? nil : subj.gsub(/^(Re|Fw):\s*/,'').gsub(/\[[<>]?#{list_subj}\]\s*/,'').gsub(/\s*\[#{Regexp.escape(ticket_prefix)}#\d+\](\s*$)?/,'').gsub(/\s*\[ok\](\s*$)?/,'').strip
|
188
|
+
end
|
189
|
+
|
190
|
+
def list_subj
|
191
|
+
@list_subj ||= (@config['list_subj'] || @name.split('@',2).first)
|
192
|
+
end
|
193
|
+
|
194
|
+
def update_subject(subject,ticket_id)
|
195
|
+
[subject.nil? ? nil : subject.gsub(/(\s)?\[#{Regexp.escape(ticket_prefix)}#\d+\]/,''), "[#{ticket_prefix}##{ticket_id}]"].compact.join(' ')
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Schleuder
|
2
|
+
module Filters
|
3
|
+
def self.gitlab_ticketing(list, mail)
|
4
|
+
@gt_config ||= begin
|
5
|
+
require 'schleuder-gitlab-ticketing'
|
6
|
+
SchleuderGitlabTicketing::Config.new
|
7
|
+
end
|
8
|
+
|
9
|
+
res = @gt_config.process_list(list.email, mail)
|
10
|
+
if res.nil?
|
11
|
+
list.logger.debug('No gitlab ticketing enabled for list')
|
12
|
+
elsif res == 'config-error'
|
13
|
+
list.logger.error('gitlab ticketing not correctly configured')
|
14
|
+
elsif res == false
|
15
|
+
list.logger.debug('Email skipped by list configuration')
|
16
|
+
end
|
17
|
+
nil
|
18
|
+
# make sure we catch any error with that filter
|
19
|
+
# so we don't affect list processing
|
20
|
+
rescue Exception => e
|
21
|
+
list.logger.notify_admin "Unable to process the following mail with gitlab-ticketing:\n\n#{e}\n\n#{e.backtrace.join("\n")}", mail.original_message, 'Error while processing mail with gitlab-ticketing'
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: schleuder-gitlab-ticketing
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- schleuder dev team
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-02-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: gitlab
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.8'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.8'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: schleuder
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.3'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.5'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.5'
|
55
|
+
description: Schleuder Gitlab Ticketing combines a schleuder list with the issue tracker
|
56
|
+
of a gitlab project and operates as a state tracker of threads on the list. This
|
57
|
+
allows one to keep an overview on the state of various requests on a help desk powered
|
58
|
+
by schleuder
|
59
|
+
email: team@schleuder.org
|
60
|
+
executables: []
|
61
|
+
extensions: []
|
62
|
+
extra_rdoc_files: []
|
63
|
+
files:
|
64
|
+
- README.md
|
65
|
+
- lib/schleuder-gitlab-ticketing.rb
|
66
|
+
- lib/schleuder-gitlab-ticketing/config.rb
|
67
|
+
- lib/schleuder-gitlab-ticketing/gitlab_config.rb
|
68
|
+
- lib/schleuder-gitlab-ticketing/list.rb
|
69
|
+
- lib/schleuder-gitlab-ticketing/version.rb
|
70
|
+
- lib/schleuder/filters/post_decryption/99_gitlab_ticketing.rb
|
71
|
+
homepage: https://schleuder.org/
|
72
|
+
licenses:
|
73
|
+
- GPL-3.0
|
74
|
+
metadata:
|
75
|
+
homepage_uri: https://schleuder.org/
|
76
|
+
documentation_uri: https://schleuder.org/docs/
|
77
|
+
changelog_uri: https://0xacab.org/schleuder/schleuder-gitlab-ticketing/blob/master/CHANGELOG.md
|
78
|
+
source_code_uri: https://0xacab.org/schleuder/schleuder-gitlab-ticketing/
|
79
|
+
bug_tracker_uri: https://0xacab.org/schleuder/schleuder-gitlab-ticketing/issues
|
80
|
+
mailing_list_uri: https://lists.nadir.org/mailman/listinfo/schleuder-announce/
|
81
|
+
post_install_message: "\n\n To activate the filter plugin you will need to link\n
|
82
|
+
\ lib/schleuder/filters/post_decryption/99_gitlab_ticketing.rb\n to /usr/local/lib/schleuder/filters/post_decryption/\n\n
|
83
|
+
\ "
|
84
|
+
rdoc_options: []
|
85
|
+
require_paths:
|
86
|
+
- lib
|
87
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: 2.1.0
|
92
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
requirements: []
|
98
|
+
rubyforge_project: "[none]"
|
99
|
+
rubygems_version: 2.7.8
|
100
|
+
signing_key:
|
101
|
+
specification_version: 4
|
102
|
+
summary: Schleuder Gitlab Ticketing is a filter plugin for schleuder to hook a list
|
103
|
+
into a gitlab issue tracker
|
104
|
+
test_files: []
|