speedflow-plugin-jira 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +98 -0
- data/bin/console +7 -0
- data/bin/setup +8 -0
- data/lib/speedflow-plugin-jira.rb +1 -0
- data/lib/speedflow/plugin/jira.rb +47 -0
- data/lib/speedflow/plugin/jira/client.rb +154 -0
- data/lib/speedflow/plugin/jira/configuration.rb +84 -0
- data/lib/speedflow/plugin/jira/formatter/issue_formatter.rb +43 -0
- data/lib/speedflow/plugin/jira/plugin_core.rb +119 -0
- data/lib/speedflow/plugin/jira/prompt.rb +111 -0
- data/lib/speedflow/plugin/jira/version.rb +7 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/speedflow/plugin/jira/client_spec.rb +111 -0
- data/spec/speedflow/plugin/jira/configuration_spec.rb +53 -0
- data/spec/speedflow/plugin/jira/formatter/issue_formatter_spec.rb +29 -0
- data/spec/speedflow/plugin/jira/plugin_core_spec.rb +115 -0
- data/spec/speedflow/plugin/jira/prompt_spec.rb +79 -0
- data/spec/speedflow/plugin/jira_spec.rb +19 -0
- metadata +217 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: e86db3144dfa9255cb647663724cb8e12ec86e76
|
4
|
+
data.tar.gz: 9ea700d99decf1955e7d1df581514fc8bc14ffb2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 04539b08a4ba7828d1a910d44b800187f71b0e1b8efa7d255f1f5fa647fd90567c258b30afb6fc4e2cde46b198d754dc628310d361ee581f2295eb8a386fc3b6
|
7
|
+
data.tar.gz: d115c35351527e4d2554c2f7581b9daff00c14d0c17d82cd98337f5ed53b38366637e9d4dbda072757f26525e32adfb2bf13da48e83bf6dd034bad229a304f7f
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Speedflow
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
# Speedflow Plugin Jira
|
2
|
+
|
3
|
+
[](https://travis-ci.org/speedflow/speedflow-plugin-jira)
|
4
|
+
[](https://badge.fury.io/rb/speedflow-plugin-jira)
|
5
|
+
[](https://codeclimate.com/github/speedflow/speedflow-plugin-jira)
|
6
|
+
[](https://codeclimate.com/github/speedflow/speedflow-plugin-jira/coverage)
|
7
|
+
[](http://inch-ci.org/github/speedflow/speedflow-plugin-jira)
|
8
|
+
|
9
|
+
:package: A Speedflow plugin to work with Jira.
|
10
|
+
|
11
|
+
## How to install?
|
12
|
+
|
13
|
+
`gem install speedflow-plugin-jira`
|
14
|
+
|
15
|
+
## How to configure?
|
16
|
+
|
17
|
+
`.speedflow.yml` :
|
18
|
+
```yml
|
19
|
+
---
|
20
|
+
plugins:
|
21
|
+
- jira
|
22
|
+
|
23
|
+
# ...
|
24
|
+
|
25
|
+
jira:
|
26
|
+
site: "{JIRA_SITE}"
|
27
|
+
username: "{JIRA_USERNAME}"
|
28
|
+
password: "{JIRA_PASSWORD}"
|
29
|
+
```
|
30
|
+
|
31
|
+
`~/.zshrc` or `~/.bashrc` :
|
32
|
+
```sh
|
33
|
+
# Jira
|
34
|
+
export JIRA_SITE="https://xxx.atlassian.net/"
|
35
|
+
export JIRA_USERNAME="..."
|
36
|
+
export JIRA_PASSWORD="..."
|
37
|
+
```
|
38
|
+
|
39
|
+
### How to use in my flow?
|
40
|
+
|
41
|
+
#### Search an issue
|
42
|
+
|
43
|
+
`.speedflow.yml` :
|
44
|
+
```yml
|
45
|
+
#...
|
46
|
+
|
47
|
+
flow:
|
48
|
+
test:
|
49
|
+
- plugin: jira
|
50
|
+
action: search_issue
|
51
|
+
```
|
52
|
+
|
53
|
+
#### Create an issue (beta)
|
54
|
+
|
55
|
+
`.speedflow.yml` :
|
56
|
+
```yml
|
57
|
+
#...
|
58
|
+
|
59
|
+
flow:
|
60
|
+
test:
|
61
|
+
- plugin: jira
|
62
|
+
action: create_issue
|
63
|
+
arguments:
|
64
|
+
title: ~
|
65
|
+
project:
|
66
|
+
default: TEST
|
67
|
+
```
|
68
|
+
|
69
|
+
#### Change issue assignee
|
70
|
+
|
71
|
+
`.speedflow.yml` :
|
72
|
+
```yml
|
73
|
+
#...
|
74
|
+
|
75
|
+
flow:
|
76
|
+
test:
|
77
|
+
- plugin: jira
|
78
|
+
action: change_issue_assignee
|
79
|
+
arguments:
|
80
|
+
assignee:
|
81
|
+
default: "{JIRA_USERNAME}"
|
82
|
+
issue: ~
|
83
|
+
```
|
84
|
+
|
85
|
+
#### Change issue transition
|
86
|
+
|
87
|
+
`.speedflow.yml` :
|
88
|
+
```yml
|
89
|
+
#...
|
90
|
+
|
91
|
+
flow:
|
92
|
+
test:
|
93
|
+
- plugin: jira
|
94
|
+
action: change_issue_transition
|
95
|
+
arguments:
|
96
|
+
transition: ~
|
97
|
+
issue: ~
|
98
|
+
```
|
data/bin/console
ADDED
data/bin/setup
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'speedflow/plugin/jira'
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'speedflow/plugin/jira/version'
|
2
|
+
require 'speedflow/plugin/jira/formatter/issue_formatter'
|
3
|
+
require 'speedflow/plugin/jira/plugin_core'
|
4
|
+
require 'speedflow/plugin/jira/prompt'
|
5
|
+
require 'speedflow/plugin/jira/configuration'
|
6
|
+
require 'speedflow/plugin/jira/client'
|
7
|
+
|
8
|
+
# Speedflow GEM, help you to boost your flow and keep your time.
|
9
|
+
module Speedflow
|
10
|
+
module Plugin
|
11
|
+
# Jira Speedflow plugin.
|
12
|
+
module Jira
|
13
|
+
# TODO: Move this system in the core Utils
|
14
|
+
class << self
|
15
|
+
ACTIONS = [
|
16
|
+
:action_create_issue,
|
17
|
+
:action_search_issue,
|
18
|
+
:action_change_issue_assignee,
|
19
|
+
:action_change_issue_transition
|
20
|
+
].freeze
|
21
|
+
|
22
|
+
# @return [Speedflow::Plugin::Jira.PluginCore] Plugin.
|
23
|
+
attr_writer :plugin
|
24
|
+
|
25
|
+
# Public: Magic method to route to action
|
26
|
+
#
|
27
|
+
# args - Some arguments :)
|
28
|
+
#
|
29
|
+
# Returns nothing.
|
30
|
+
def method_missing(*args)
|
31
|
+
action = args.first
|
32
|
+
|
33
|
+
raise NoMethodError, action unless ACTIONS.include? action
|
34
|
+
|
35
|
+
plugin.new(args.last).send(action)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Public: Plugin.
|
39
|
+
#
|
40
|
+
# Returns Speedflow::Plugin::Jira.PluginCore instance.
|
41
|
+
def plugin
|
42
|
+
@plugin ||= PluginCore
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
require 'jira'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Speedflow
|
5
|
+
module Plugin
|
6
|
+
module Jira
|
7
|
+
# Jira Client
|
8
|
+
class Client
|
9
|
+
include ::Speedflow::Plugin::Jira::Formatter
|
10
|
+
|
11
|
+
# @return [Prompt] Prompt.
|
12
|
+
attr_writer :prompt
|
13
|
+
|
14
|
+
# @return [JIRA::Client] JIRA Client.
|
15
|
+
attr_writer :jira_client
|
16
|
+
|
17
|
+
# Initialize.
|
18
|
+
#
|
19
|
+
# config - Speedflow::Plugin::Jira::Configuration instance.
|
20
|
+
# prompt - Speedflow::Plugin::Jira::Prompt instance.
|
21
|
+
#
|
22
|
+
# Examples
|
23
|
+
#
|
24
|
+
# Client.new({}, Speedflow::Plugin::Jira::Prompt.new)
|
25
|
+
# # => <Speedflow::Plugin::Jira::Client>
|
26
|
+
#
|
27
|
+
# Returns nothing.
|
28
|
+
def initialize(config, prompt)
|
29
|
+
@config = config
|
30
|
+
@prompt = prompt
|
31
|
+
end
|
32
|
+
|
33
|
+
# Public: Search issue.
|
34
|
+
#
|
35
|
+
# project - Project name.
|
36
|
+
# title - Issue title.
|
37
|
+
#
|
38
|
+
# Returns Hash of issue.
|
39
|
+
def search_issue(project, title)
|
40
|
+
safe do
|
41
|
+
jira_client
|
42
|
+
.Issue.jql("PROJECT = \"#{project}\" AND text ~ \"#{title}\"")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Public: Create issue.
|
47
|
+
#
|
48
|
+
# project_key - Project key.
|
49
|
+
# title - Title (summary).
|
50
|
+
# issue_type_id - Issue type (Fixnum).
|
51
|
+
#
|
52
|
+
# Returns Hash of issue.
|
53
|
+
def create_issue(project_key, title, issue_type_id)
|
54
|
+
safe do
|
55
|
+
issue = jira_client.Issue.build
|
56
|
+
data = IssueFormatter.to_create(project_key, title, issue_type_id)
|
57
|
+
issue.save!(data)
|
58
|
+
issue.fetch
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Public: Update issue.
|
63
|
+
#
|
64
|
+
# issue_key - Key of issue.
|
65
|
+
# assignee_name - Assignee name.
|
66
|
+
#
|
67
|
+
# Returns Hash of issue.
|
68
|
+
def update_issue_assignee(issue_key, assignee_name)
|
69
|
+
safe do
|
70
|
+
issue = jira_client.Issue.find(issue_key)
|
71
|
+
data = IssueFormatter.to_assignee(assignee_name)
|
72
|
+
issue.save!(data)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Public: Update issue transition.
|
77
|
+
#
|
78
|
+
# issue_key - Key of issue.
|
79
|
+
# transition_id - Transition ID.
|
80
|
+
#
|
81
|
+
# Returns Hash of issue.
|
82
|
+
def update_issue_transition(issue_key, transition_id)
|
83
|
+
safe do
|
84
|
+
issue = jira_client.Issue.find(issue_key)
|
85
|
+
issue.transitions.build.save!(transition: transition_id)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Public: Jira project.
|
90
|
+
#
|
91
|
+
# project_key - Project key.
|
92
|
+
#
|
93
|
+
# Returns JIRA::Resource.Project.
|
94
|
+
def project(project_key)
|
95
|
+
safe { jira_client.Project.find(project_key) }
|
96
|
+
end
|
97
|
+
|
98
|
+
# Public: Jira projects.
|
99
|
+
#
|
100
|
+
# Returns Hash of projects.
|
101
|
+
def projects
|
102
|
+
safe { jira_client.Project.all }
|
103
|
+
end
|
104
|
+
|
105
|
+
# Public: Jira issue transitions.
|
106
|
+
#
|
107
|
+
# issue_key - Issue key.
|
108
|
+
#
|
109
|
+
# Returns Hash of transitions.
|
110
|
+
def issue_trans(issue_key)
|
111
|
+
safe do
|
112
|
+
issue = jira_client.Issue.find(issue_key, expand: 'transitions')
|
113
|
+
issue.transitions
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Public: Jira issue types.
|
118
|
+
#
|
119
|
+
# Returns Hash of issue types.
|
120
|
+
def issue_types
|
121
|
+
safe { jira_client.Issuetype.all }
|
122
|
+
end
|
123
|
+
|
124
|
+
# Public: Safe process JIRA action.
|
125
|
+
#
|
126
|
+
# Returns nothing.
|
127
|
+
def safe
|
128
|
+
yield
|
129
|
+
rescue ::JIRA::HTTPError => exception
|
130
|
+
prompt.error 'Jira errors'
|
131
|
+
prompt.errors exception
|
132
|
+
abort
|
133
|
+
rescue ::URI::InvalidURIError
|
134
|
+
prompt.error 'Invalid URL'
|
135
|
+
abort
|
136
|
+
end
|
137
|
+
|
138
|
+
# Public: Jira client.
|
139
|
+
#
|
140
|
+
# Returns JIRA::Client instance.
|
141
|
+
def jira_client
|
142
|
+
@jira_client ||= ::JIRA::Client.new(@config.auth)
|
143
|
+
end
|
144
|
+
|
145
|
+
# Public: Prompt.
|
146
|
+
#
|
147
|
+
# Returns ::Speedflow::Plugin::Jira::Prompt instance.
|
148
|
+
def prompt
|
149
|
+
@prompt ||= ::Speedflow::Plugin::Jira::Prompt.new
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Speedflow
|
2
|
+
module Plugin
|
3
|
+
module Jira
|
4
|
+
# Jira Configuration
|
5
|
+
class Configuration
|
6
|
+
CONFIG_KEY = '_config'.freeze
|
7
|
+
PLUGIN_KEY = 'jira'.freeze
|
8
|
+
|
9
|
+
# Initialize.
|
10
|
+
#
|
11
|
+
# arguments - Hash of arguments.
|
12
|
+
#
|
13
|
+
# Examples
|
14
|
+
#
|
15
|
+
# Configuration.new({})
|
16
|
+
# # => <Speedflow::Plugin::Jira::Configuration>
|
17
|
+
#
|
18
|
+
# Returns nothing.
|
19
|
+
def initialize(arguments)
|
20
|
+
@arguments = arguments
|
21
|
+
end
|
22
|
+
|
23
|
+
# Public: Auth configuration.
|
24
|
+
#
|
25
|
+
# Returns Hash of auth configuration.
|
26
|
+
def auth
|
27
|
+
{
|
28
|
+
username: by_config('username'),
|
29
|
+
password: by_config('password'),
|
30
|
+
site: by_config('site'),
|
31
|
+
context_path: by_config('context_path', '/'),
|
32
|
+
auth_type: by_config('auth_type', :basic),
|
33
|
+
read_timeout: by_config('read_timeout', 120)
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
# Public: Get a specific config.
|
38
|
+
#
|
39
|
+
# key - Key of config.
|
40
|
+
# default_value - Default value.
|
41
|
+
#
|
42
|
+
# Returns value of config key.
|
43
|
+
def by_config(key, default_value = '')
|
44
|
+
if @arguments.key?(CONFIG_KEY) &&
|
45
|
+
@arguments[CONFIG_KEY].key?(PLUGIN_KEY)
|
46
|
+
config = @arguments[CONFIG_KEY][PLUGIN_KEY]
|
47
|
+
end
|
48
|
+
config.key?(key) ? config[key] : default_value
|
49
|
+
end
|
50
|
+
|
51
|
+
# Public: Get an input config by key.
|
52
|
+
#
|
53
|
+
# key - Key of config.
|
54
|
+
# default_value - Default value.
|
55
|
+
#
|
56
|
+
# Returns value of input config key.
|
57
|
+
def by_input(key, default_value = '')
|
58
|
+
if @arguments.key?(key)
|
59
|
+
@arguments[key]['value'].to_s
|
60
|
+
else
|
61
|
+
default_value
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Public: Get an input config by key but required.
|
66
|
+
#
|
67
|
+
# key - Key of config.
|
68
|
+
# default_value - Default value.
|
69
|
+
#
|
70
|
+
# Returns value of input config key or Exception.
|
71
|
+
def by_required_input(key, default_value = '')
|
72
|
+
value = by_input(key, default_value)
|
73
|
+
|
74
|
+
# TODO: Improve communication with core for errors
|
75
|
+
if by_input(key).empty?
|
76
|
+
raise Exception, "Required value for '#{key}'."
|
77
|
+
end
|
78
|
+
|
79
|
+
value
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Speedflow
|
2
|
+
module Plugin
|
3
|
+
module Jira
|
4
|
+
# Formatter
|
5
|
+
module Formatter
|
6
|
+
# Issue formatter
|
7
|
+
module IssueFormatter
|
8
|
+
# Public: To create issue.
|
9
|
+
#
|
10
|
+
# project_key - Project Key.
|
11
|
+
# title - Issue title.
|
12
|
+
# issue_type_id - Issue type ID.
|
13
|
+
#
|
14
|
+
# Returns Hash of fields.
|
15
|
+
def self.to_create(project_key, title, issue_type_id)
|
16
|
+
{
|
17
|
+
'fields' => {
|
18
|
+
'project' => { 'key' => project_key.to_s },
|
19
|
+
'summary' => title.to_s,
|
20
|
+
'issuetype' => { 'id' => issue_type_id.to_s }
|
21
|
+
}
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
# Public: To assignee.
|
26
|
+
#
|
27
|
+
# assignee_name - Assignee name.
|
28
|
+
#
|
29
|
+
# Returns Hash of fields.
|
30
|
+
def self.to_assignee(assignee_name)
|
31
|
+
{
|
32
|
+
'fields' => {
|
33
|
+
'assignee' => {
|
34
|
+
'name' => assignee_name.to_s
|
35
|
+
}
|
36
|
+
}
|
37
|
+
}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|