danger-yajp 0.0.2 → 1.0.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 +4 -4
- data/.github/workflows/create-tag.yml +39 -0
- data/.rubocop.yml +1 -0
- data/Gemfile.lock +40 -38
- data/README.md +31 -15
- data/danger-yajp.gemspec +4 -4
- data/lib/yajp/gem_version.rb +1 -1
- data/lib/yajp/issue.rb +70 -0
- data/lib/yajp/plugin.rb +71 -34
- data/spec/support/remotelink.json +1 -0
- data/spec/yajp_spec.rb +38 -13
- metadata +14 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 171560c106cee13af1c63bb6ab841c70503578850d3a88d1a5a4523c2de88e1a
|
4
|
+
data.tar.gz: f3243d0163c4a6d7f40596dcd72b7fd8d8a2ed3f8ef19454c3f4b49751c3125c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '09526c08a590bbf1406eb835ce929083f491eb09289814457aa82ad4d32426fc6555dce7ee400459d32936ddc980d43db4fe583eea29d848750f2486a0a7834b'
|
7
|
+
data.tar.gz: 5cca801bdd4e3fd040c7d8b26730d98ccb2d11bc73c03e8577cd3f0d50e9093012e60316fa1fcef80b9ec631375ce80aaf3224b78001a3d3ee730c8c065a408a
|
@@ -0,0 +1,39 @@
|
|
1
|
+
name: Create release
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: main
|
6
|
+
|
7
|
+
jobs:
|
8
|
+
build:
|
9
|
+
name: Retrieve version + create release
|
10
|
+
runs-on: ubuntu-latest
|
11
|
+
|
12
|
+
steps:
|
13
|
+
- uses: actions/checkout@v2
|
14
|
+
with:
|
15
|
+
fetch-depth: 0
|
16
|
+
|
17
|
+
- name: Set up Ruby 2.6
|
18
|
+
uses: actions/setup-ruby@v1
|
19
|
+
with:
|
20
|
+
ruby-version: 2.6.x
|
21
|
+
|
22
|
+
- name: Retrieve version
|
23
|
+
id: version
|
24
|
+
run: |
|
25
|
+
version=$(ruby -e 'require "./lib/yajp/gem_version.rb"' -e 'puts Yajp::VERSION')
|
26
|
+
echo "TAG_NAME=$version" >> $GITHUB_ENV
|
27
|
+
latest_tag=$(git describe --tags --abbrev=0)
|
28
|
+
echo 'VERSION_DESCRIPTION<<EOF' >> $GITHUB_ENV
|
29
|
+
git log --pretty='format:%h %s' ${latest_tag}..HEAD >> $GITHUB_ENV
|
30
|
+
echo $'\nEOF' >> $GITHUB_ENV
|
31
|
+
|
32
|
+
- name: Create release
|
33
|
+
uses: actions/create-release@v1
|
34
|
+
env:
|
35
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
36
|
+
with:
|
37
|
+
tag_name: ${{ env.TAG_NAME }}
|
38
|
+
release_name: v${{ env.TAG_NAME }}
|
39
|
+
body: ${{ env.VERSION_DESCRIPTION }}
|
data/.rubocop.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
danger-yajp (0.0
|
4
|
+
danger-yajp (1.0.0)
|
5
5
|
danger-plugin-api
|
6
6
|
jira-ruby
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
activesupport (6.0
|
11
|
+
activesupport (6.1.0)
|
12
12
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
13
|
-
i18n (>=
|
14
|
-
minitest (
|
15
|
-
tzinfo (~>
|
16
|
-
zeitwerk (~> 2.
|
13
|
+
i18n (>= 1.6, < 2)
|
14
|
+
minitest (>= 5.1)
|
15
|
+
tzinfo (~> 2.0)
|
16
|
+
zeitwerk (~> 2.3)
|
17
17
|
addressable (2.7.0)
|
18
18
|
public_suffix (>= 2.0.2, < 5.0)
|
19
19
|
ast (2.4.1)
|
@@ -29,8 +29,9 @@ GEM
|
|
29
29
|
concurrent-ruby (1.1.7)
|
30
30
|
cork (0.3.0)
|
31
31
|
colored2 (~> 3.1)
|
32
|
-
crack (0.4.
|
33
|
-
|
32
|
+
crack (0.4.5)
|
33
|
+
rexml
|
34
|
+
danger (8.2.1)
|
34
35
|
claide (~> 1.0)
|
35
36
|
claide-plugins (>= 0.9.2)
|
36
37
|
colored2 (~> 3.1)
|
@@ -46,14 +47,16 @@ GEM
|
|
46
47
|
danger-plugin-api (1.0.0)
|
47
48
|
danger (> 2.0)
|
48
49
|
diff-lcs (1.4.4)
|
49
|
-
faraday (1.
|
50
|
+
faraday (1.3.0)
|
51
|
+
faraday-net_http (~> 1.0)
|
50
52
|
multipart-post (>= 1.2, < 3)
|
51
53
|
ruby2_keywords
|
52
54
|
faraday-http-cache (2.2.0)
|
53
55
|
faraday (>= 0.8)
|
54
|
-
|
56
|
+
faraday-net_http (1.0.0)
|
57
|
+
ffi (1.14.2-x64-mingw32)
|
55
58
|
formatador (0.2.5)
|
56
|
-
git (1.
|
59
|
+
git (1.8.1)
|
57
60
|
rchardet (~> 1.8)
|
58
61
|
guard (2.16.2)
|
59
62
|
formatador (>= 0.2.4)
|
@@ -70,9 +73,9 @@ GEM
|
|
70
73
|
guard-compat (~> 1.1)
|
71
74
|
rspec (>= 2.99.0, < 4.0)
|
72
75
|
hashdiff (1.0.1)
|
73
|
-
i18n (1.8.
|
76
|
+
i18n (1.8.7)
|
74
77
|
concurrent-ruby (~> 1.0)
|
75
|
-
jira-ruby (2.1.
|
78
|
+
jira-ruby (2.1.4)
|
76
79
|
activesupport
|
77
80
|
atlassian-jwt
|
78
81
|
multipart-post
|
@@ -82,7 +85,7 @@ GEM
|
|
82
85
|
rexml
|
83
86
|
kramdown-parser-gfm (1.1.0)
|
84
87
|
kramdown (~> 2.0)
|
85
|
-
listen (3.
|
88
|
+
listen (3.4.0)
|
86
89
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
87
90
|
rb-inotify (~> 0.9, >= 0.9.10)
|
88
91
|
lumberjack (1.2.8)
|
@@ -96,50 +99,50 @@ GEM
|
|
96
99
|
nenv (~> 0.1)
|
97
100
|
shellany (~> 0.0)
|
98
101
|
oauth (0.5.4)
|
99
|
-
octokit (4.
|
102
|
+
octokit (4.20.0)
|
100
103
|
faraday (>= 0.9)
|
101
104
|
sawyer (~> 0.8.0, >= 0.5.3)
|
102
105
|
open4 (1.3.4)
|
103
|
-
parallel (1.
|
104
|
-
parser (
|
106
|
+
parallel (1.20.1)
|
107
|
+
parser (3.0.0.0)
|
105
108
|
ast (~> 2.4.1)
|
106
109
|
pry (0.13.1)
|
107
110
|
coderay (~> 1.1)
|
108
111
|
method_source (~> 1.0)
|
109
112
|
public_suffix (4.0.6)
|
110
113
|
rainbow (3.0.0)
|
111
|
-
rake (13.0.
|
114
|
+
rake (13.0.3)
|
112
115
|
rb-fsevent (0.10.4)
|
113
116
|
rb-inotify (0.10.1)
|
114
117
|
ffi (~> 1.0)
|
115
118
|
rchardet (1.8.0)
|
116
|
-
regexp_parser (
|
119
|
+
regexp_parser (2.0.3)
|
117
120
|
rexml (3.2.4)
|
118
121
|
rspec (3.10.0)
|
119
122
|
rspec-core (~> 3.10.0)
|
120
123
|
rspec-expectations (~> 3.10.0)
|
121
124
|
rspec-mocks (~> 3.10.0)
|
122
|
-
rspec-core (3.10.
|
125
|
+
rspec-core (3.10.1)
|
123
126
|
rspec-support (~> 3.10.0)
|
124
|
-
rspec-expectations (3.10.
|
127
|
+
rspec-expectations (3.10.1)
|
125
128
|
diff-lcs (>= 1.2.0, < 2.0)
|
126
129
|
rspec-support (~> 3.10.0)
|
127
|
-
rspec-mocks (3.10.
|
130
|
+
rspec-mocks (3.10.1)
|
128
131
|
diff-lcs (>= 1.2.0, < 2.0)
|
129
132
|
rspec-support (~> 3.10.0)
|
130
|
-
rspec-support (3.10.
|
131
|
-
rubocop (1.
|
133
|
+
rspec-support (3.10.1)
|
134
|
+
rubocop (1.7.0)
|
132
135
|
parallel (~> 1.10)
|
133
136
|
parser (>= 2.7.1.5)
|
134
137
|
rainbow (>= 2.2.2, < 4.0)
|
135
|
-
regexp_parser (>= 1.8)
|
138
|
+
regexp_parser (>= 1.8, < 3.0)
|
136
139
|
rexml
|
137
|
-
rubocop-ast (>=
|
140
|
+
rubocop-ast (>= 1.2.0, < 2.0)
|
138
141
|
ruby-progressbar (~> 1.7)
|
139
142
|
unicode-display_width (>= 1.4.0, < 2.0)
|
140
|
-
rubocop-ast (1.
|
143
|
+
rubocop-ast (1.4.0)
|
141
144
|
parser (>= 2.7.1.5)
|
142
|
-
ruby-progressbar (1.
|
145
|
+
ruby-progressbar (1.11.0)
|
143
146
|
ruby2_keywords (0.0.2)
|
144
147
|
sawyer (0.8.2)
|
145
148
|
addressable (>= 2.3.5)
|
@@ -148,16 +151,15 @@ GEM
|
|
148
151
|
terminal-table (1.8.0)
|
149
152
|
unicode-display_width (~> 1.1, >= 1.1.1)
|
150
153
|
thor (1.0.1)
|
151
|
-
|
152
|
-
|
153
|
-
thread_safe (~> 0.1)
|
154
|
+
tzinfo (2.0.4)
|
155
|
+
concurrent-ruby (~> 1.0)
|
154
156
|
unicode-display_width (1.7.0)
|
155
|
-
webmock (3.
|
157
|
+
webmock (3.11.0)
|
156
158
|
addressable (>= 2.3.6)
|
157
159
|
crack (>= 0.3.2)
|
158
160
|
hashdiff (>= 0.4.0, < 2.0.0)
|
159
|
-
yard (0.9.
|
160
|
-
zeitwerk (2.4.
|
161
|
+
yard (0.9.26)
|
162
|
+
zeitwerk (2.4.2)
|
161
163
|
|
162
164
|
PLATFORMS
|
163
165
|
x64-mingw32
|
@@ -169,10 +171,10 @@ DEPENDENCIES
|
|
169
171
|
guard-rspec (~> 4.7)
|
170
172
|
pry
|
171
173
|
rake (~> 13.0)
|
172
|
-
rspec (~> 3
|
173
|
-
rubocop (~> 1
|
174
|
-
webmock (~> 3
|
175
|
-
yard (~> 0.9
|
174
|
+
rspec (~> 3)
|
175
|
+
rubocop (~> 1)
|
176
|
+
webmock (~> 3)
|
177
|
+
yard (~> 0.9)
|
176
178
|
|
177
179
|
BUNDLED WITH
|
178
180
|
2.1.4
|
data/README.md
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
# Yet Another Jira Plugin
|
2
2
|
|
3
|
-
[](LICENSE)
|
4
|
+
[](https://rubygems.org/gems/danger-yajp)
|
5
|
+
[](https://libraries.io/rubygems/danger-yajp)
|
4
6
|
|
5
|
-
Yet Another Jira Plugin (in short: yajp) is a [Danger](https://danger.systems/ruby/) plugin that provides methods to easily find and manipulate issues from within the Dangerfile. The major difference with the existing Jira plugins is the ability to transition and update issues with the same feeling as manipulating PR data from Danger. This plugin was build in the same mind as Danger, meaning that you will find methods to easily manipulate Jira data, but no predefined warning and/or message.
|
7
|
+
Yet Another Jira Plugin (in short: yajp) is a [Danger](https://danger.systems/ruby/) plugin that provides methods to easily find and manipulate issues from within the Dangerfile. The major difference with the existing Jira plugins is the ability to transition and update issues with the same feeling as manipulating PR data from Danger. This plugin was build in the same mind as Danger, meaning that you will find methods to easily manipulate Jira data, but no predefined warning and/or message. It also does that by expanding the Issue class from `jira-ruby`.
|
6
8
|
|
7
9
|
Inspired by [danger-jira](https://github.com/RestlessThinker/danger-jira), from which I borrowed the issue search, and by [danger-jira_sync](https://github.com/roverdotcom/danger-jira_sync) for their usage of the awesome [jira-ruby](https://github.com/sumoheavy/jira-ruby) gem.
|
8
10
|
|
@@ -16,12 +18,12 @@ gem 'danger-yajp'
|
|
16
18
|
|
17
19
|
## Usage
|
18
20
|
|
19
|
-
You first need to define the environment variables `DANGER_JIRA_URL`, `DANGER_JIRA_USER` and `
|
21
|
+
You first need to define the environment variables `DANGER_JIRA_URL`, `DANGER_JIRA_USER` and `DANGER_JIRA_API_TOKEN` in your CI environment, for example:
|
20
22
|
|
21
23
|
```
|
22
24
|
DANGER_JIRA_URL: https://jira.company.com/jira
|
23
25
|
DANGER_JIRA_USER: username
|
24
|
-
|
26
|
+
DANGER_JIRA_API_TOKEN: abcd12345
|
25
27
|
```
|
26
28
|
|
27
29
|
### Find issues
|
@@ -43,26 +45,40 @@ end
|
|
43
45
|
|
44
46
|
### Transition / update issues
|
45
47
|
|
46
|
-
yajp allows to easily transition and update issues without the hassle of building custom json in the Dangerfile. The inputs are:
|
48
|
+
yajp allows to easily transition and update issues without the hassle of building custom json in the Dangerfile. The methods are available in the issue object, or to handle multiple issues in the plugin object. The inputs are:
|
47
49
|
|
48
|
-
*
|
49
|
-
*
|
50
|
-
* Any number of fields to be updated in
|
50
|
+
* For the transition action, the ID or name of the transition (which is not the name of the status)
|
51
|
+
* When using the methods from the plugin object, the issues to handled, which is by default the issues found when the command `find_issues` was last run.
|
52
|
+
* Any number of fields to be updated in a hash: `key: value`
|
51
53
|
|
54
|
+
Example 1: transition all the issues found after running `find_issues`:
|
52
55
|
```rb
|
53
|
-
jira.
|
56
|
+
jira.transition_all('done', assignee: { name: 'username' }, customfield_11005: 'example')
|
54
57
|
```
|
55
58
|
|
56
|
-
|
59
|
+
Example 2: update a single issue:
|
60
|
+
```rb
|
61
|
+
issue.update(assignee: { name: 'username' }, customfield_11005: 'example')
|
62
|
+
```
|
63
|
+
|
64
|
+
The `transition` and `transition_all` methods only take fields available in the transition screen. Use the `split_transition_fields` method to separate the fields available in the transition screen, or use the `transition_and_update_all` method to transition and update issues (and automatically dispatch the fields to the correct action).
|
57
65
|
|
58
66
|
> Transition IDs can be found in Jira under Project Workflow > Edit Workflow in Text Mode.
|
59
67
|
|
68
|
+
### Reference the PR as a remote link
|
69
|
+
|
70
|
+
yajp can reference the PR as a remote link on Jira. It will use the icon of GitLab or Github depending on what you use. The remote link will use the URL of the PR as a `globalId` to not create duplicates. Optionnaly, you can specify the relationship with the issue (default is `relates to`), and the status, either as an object (eg. `{ "resolved": true, "icon": {...} }`) or as a boolean that will set the value of the property `resolved`. By default, no status is sent.
|
71
|
+
|
72
|
+
```rb
|
73
|
+
jira.pr_as_remotelink(issue, false)
|
74
|
+
```
|
75
|
+
|
60
76
|
### Issue URL
|
61
77
|
|
62
|
-
Use `
|
78
|
+
Use `link` to retrieve the browse URL of the Jira issue.
|
63
79
|
|
64
80
|
```rb
|
65
|
-
message "<a href='#{
|
81
|
+
message "<a href='#{issue.link}'>#{issue.key} - #{issue.summary}</a>"
|
66
82
|
```
|
67
83
|
|
68
84
|
### API
|
@@ -82,13 +98,13 @@ if issues.empty?
|
|
82
98
|
warn 'This PR does not contain any Jira issue.'
|
83
99
|
else
|
84
100
|
issues.each do |issue|
|
85
|
-
message "<a href='#{
|
101
|
+
message "<a href='#{issue.link}'>#{issue.key} - #{issue.summary}</a>"
|
86
102
|
|
87
103
|
case issue.status.name
|
88
104
|
when 'In Progress'
|
89
|
-
jira.
|
105
|
+
jira.transition_and_update_all(10, issue: issue, assignee: { name: 'username' }, customfield_11005: 'example')
|
90
106
|
when 'To Do', 'Blocked'
|
91
|
-
warn "Issue <a href='#{
|
107
|
+
warn "Issue <a href='#{issue.link}'>#{issue.key}</a> is not in Dev status, please make sure the issue you're working on is in the correct status"
|
92
108
|
end
|
93
109
|
end
|
94
110
|
end
|
data/danger-yajp.gemspec
CHANGED
@@ -29,12 +29,12 @@ Gem::Specification.new do |spec|
|
|
29
29
|
spec.add_development_dependency 'rake', '~> 13.0'
|
30
30
|
|
31
31
|
# Testing support
|
32
|
-
spec.add_development_dependency 'rspec', '~> 3
|
33
|
-
spec.add_development_dependency 'webmock', '~> 3
|
32
|
+
spec.add_development_dependency 'rspec', '~> 3'
|
33
|
+
spec.add_development_dependency 'webmock', '~> 3'
|
34
34
|
|
35
35
|
# Linting code and docs
|
36
|
-
spec.add_development_dependency 'rubocop', '~> 1
|
37
|
-
spec.add_development_dependency 'yard', '~> 0.9
|
36
|
+
spec.add_development_dependency 'rubocop', '~> 1'
|
37
|
+
spec.add_development_dependency 'yard', '~> 0.9'
|
38
38
|
|
39
39
|
# Makes testing easy via `bundle exec guard`
|
40
40
|
spec.add_development_dependency 'guard', '~> 2.16'
|
data/lib/yajp/gem_version.rb
CHANGED
data/lib/yajp/issue.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'jira-ruby'
|
4
|
+
|
5
|
+
module Danger
|
6
|
+
# This class extends (aka monkey patch) the `JIRA::Resource::Issue` class with straightforward methods to easily transition and update issues.
|
7
|
+
#
|
8
|
+
class JIRA::Resource::Issue
|
9
|
+
# Get the browse URL of the issue.
|
10
|
+
#
|
11
|
+
# @return [String] the URL of the issue
|
12
|
+
#
|
13
|
+
def link
|
14
|
+
"#{ENV['DANGER_JIRA_URL']}/browse/#{key}"
|
15
|
+
end
|
16
|
+
|
17
|
+
# Update the issue.
|
18
|
+
#
|
19
|
+
# @example Update the fields `assignee` and `customfield_11005`
|
20
|
+
# issue.update(assignee: { name: 'username' }, customfield_11005: 'example')
|
21
|
+
#
|
22
|
+
# @param [Hash] fields Fields to update
|
23
|
+
#
|
24
|
+
# @return [Boolean] `true` if the issue was updated successfully, `false` otherwise.
|
25
|
+
#
|
26
|
+
def update(**fields)
|
27
|
+
return if fields.empty?
|
28
|
+
|
29
|
+
save({ fields: fields })
|
30
|
+
end
|
31
|
+
|
32
|
+
# Transition the issue using the ID or name of the transition. Transition IDs can be found in Jira under Project Workflow > Edit Workflow in Text Mode.
|
33
|
+
# The transition name is the text that appears on the issue screen to transition it.
|
34
|
+
# The fields that can be updated with this method are only the fields available in the transition screen of the transition. Otherwise use `transition_and_update`.
|
35
|
+
#
|
36
|
+
# @example Transition the issue and set the fields `assignee` and `customfield_11005` available on the transition screens
|
37
|
+
# jira.transition(my_issue, 10, assignee: { name: 'username' }, customfield_11005: 'example')
|
38
|
+
#
|
39
|
+
# @param [Integer, String] transition_id ID or name of the transition
|
40
|
+
# @param [Hash] fields Fields that can be updated on the transition screen
|
41
|
+
#
|
42
|
+
# @return [Boolean] `true` if the issue was transitioned successfully, `false` otherwise.
|
43
|
+
#
|
44
|
+
def transition(transition_id, **fields)
|
45
|
+
if transition_id.kind_of?(String)
|
46
|
+
transition_id = get_transition_id(transition_id)
|
47
|
+
|
48
|
+
return false if transition_id == -1
|
49
|
+
end
|
50
|
+
data = { transition: { id: transition_id.to_s } }
|
51
|
+
data[:fields] = fields unless fields.empty?
|
52
|
+
|
53
|
+
transitions.build.save(data)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Retrieve the ID of the transition matching the given name.
|
57
|
+
#
|
58
|
+
# @param [String] name
|
59
|
+
#
|
60
|
+
# @return [Integer] the ID of the transition, or -1 if no match was found
|
61
|
+
#
|
62
|
+
def get_transition_id(name)
|
63
|
+
transitions.all.each do |transition|
|
64
|
+
return transition.id if transition.name.casecmp?(name)
|
65
|
+
end
|
66
|
+
|
67
|
+
return -1
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/yajp/plugin.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require_relative 'issue'
|
4
4
|
|
5
5
|
module Danger
|
6
6
|
# Yet Another Jira Plugin (in short: yajp) provides methods to easily find and manipulate issues from within the Dangerfile.
|
@@ -18,13 +18,13 @@ module Danger
|
|
18
18
|
# warn 'This PR does not contain any Jira issue.'
|
19
19
|
# else
|
20
20
|
# issues.each do |issue|
|
21
|
-
# message "<a href='#{
|
21
|
+
# message "<a href='#{issue.link}'>#{issue.key} - #{issue.summary}</a>"
|
22
22
|
#
|
23
23
|
# case issue.status.name
|
24
24
|
# when 'In Progress'
|
25
|
-
#
|
25
|
+
# issue.transition(10, assignee: { name: 'username' }, customfield_11005: 'example')
|
26
26
|
# when 'To Do', 'Blocked'
|
27
|
-
# warn "Issue <a href='#{
|
27
|
+
# warn "Issue <a href='#{issue.link}'>#{issue.key}</a> is not in Dev status, please make sure the issue you're working on is in the correct status"
|
28
28
|
# end
|
29
29
|
# end
|
30
30
|
# end
|
@@ -69,11 +69,11 @@ module Danger
|
|
69
69
|
# jira.find_issues('KEY', search_title: false, search_branch: true)
|
70
70
|
#
|
71
71
|
# @param [Array<String>] key An array of Jira project keys like `['KEY', 'JIRA']`, or a single `String` with a Jira project key
|
72
|
-
# @param [Boolean] search_title Option to search Jira issues from PR title
|
73
|
-
# @param [Boolean] search_commits Option to search Jira issues from from commit messages
|
74
|
-
# @param [Boolean] search_branch Option to search Jira issues from the name of the PR branch
|
72
|
+
# @param [Boolean] search_title Option to search Jira issues from PR title
|
73
|
+
# @param [Boolean] search_commits Option to search Jira issues from from commit messages
|
74
|
+
# @param [Boolean] search_branch Option to search Jira issues from the name of the PR branch
|
75
75
|
#
|
76
|
-
# @return [Array<JIRA::Issue>] An array containing all the unique issues found in the PR.
|
76
|
+
# @return [Array<JIRA::Resource::Issue>] An array containing all the unique issues found in the PR.
|
77
77
|
#
|
78
78
|
def find_issues(key, search_title: true, search_commits: false, search_branch: false)
|
79
79
|
regexp = build_regexp_from_key(key)
|
@@ -84,29 +84,28 @@ module Danger
|
|
84
84
|
jira_issues.concat(search_branch(regexp)) if search_branch
|
85
85
|
jira_issues.concat(search_pr_body(regexp)) if jira_issues.empty?
|
86
86
|
|
87
|
-
jira_issues.uniq.map { |issue_key| @api.Issue.find(issue_key) }
|
87
|
+
@issues = jira_issues.uniq(&:downcase).map { |issue_key| @api.Issue.find(issue_key) }
|
88
88
|
end
|
89
89
|
|
90
|
-
# Transition the given Jira issue(s) using the ID of the transition. Transition IDs can be found in Jira under Project Workflow > Edit Workflow in Text Mode.
|
90
|
+
# Transition the given Jira issue(s) using the ID or name of the transition. Transition IDs can be found in Jira under Project Workflow > Edit Workflow in Text Mode.
|
91
|
+
# The transition name is the text that appears on the issue screen to transition it.
|
91
92
|
# The fields that can be updated with this method are only the fields available in the transition screen of the transition. Otherwise use `transition_and_update`.
|
92
93
|
#
|
93
|
-
# @example Transition the issue `my_issue` and set the fields `assignee` and `customfield_11005` available on the transition screens
|
94
|
-
# jira.
|
94
|
+
# @example Transition the issue `my_issue` using the transition 'done' and set the fields `assignee` and `customfield_11005` available on the transition screens
|
95
|
+
# jira.transition_all(my_issue, 'done', assignee: { name: 'username' }, customfield_11005: 'example')
|
95
96
|
#
|
96
|
-
# @param [
|
97
|
-
# @param [
|
97
|
+
# @param [Integer, String] transition_id ID or name of the transition
|
98
|
+
# @param [Array<JIRA::Resource::Issue>, JIRA::Resource::Issue] issue An array of issues, or a single issue
|
98
99
|
# @param [Hash] fields Fields that can be updated on the transition screen
|
99
100
|
#
|
100
101
|
# @return [Boolean] `true` if all the issues were transitioned successfully, `false` otherwise.
|
101
102
|
#
|
102
|
-
def
|
103
|
+
def transition_all(transition_id, issue: @issues, **fields)
|
103
104
|
issues = issue.kind_of?(Array) ? issue : [] << issue
|
104
|
-
data = { transition: { id: transition_id.to_s } }
|
105
|
-
data[:fields] = fields unless fields.empty?
|
106
105
|
result = true
|
107
106
|
|
108
107
|
issues.each do |key|
|
109
|
-
result &= key.
|
108
|
+
result &= key.transition(transition_id, **fields)
|
110
109
|
end
|
111
110
|
|
112
111
|
return result
|
@@ -115,21 +114,21 @@ module Danger
|
|
115
114
|
# Update the given Jira issue(s).
|
116
115
|
#
|
117
116
|
# @example Update the issue `my_issue` and set the fields `assignee` and `customfield_11005`
|
118
|
-
# jira.
|
117
|
+
# jira.update_all(my_issue, assignee: { name: 'username' }, customfield_11005: 'example')
|
119
118
|
#
|
120
|
-
# @param [Array<JIRA::Issue
|
119
|
+
# @param [Array<JIRA::Resource::Issue>, JIRA::Resource::Issue] issue An array of issue, or a single issue
|
121
120
|
# @param [Hash] fields Fields to update
|
122
121
|
#
|
123
122
|
# @return [Boolean] `true` if all the issues were updated successfully, `false` otherwise.
|
124
123
|
#
|
125
|
-
def
|
124
|
+
def update_all(issue: @issues, **fields)
|
126
125
|
return if fields.empty?
|
127
126
|
|
128
127
|
issues = issue.kind_of?(Array) ? issue : [] << issue
|
129
128
|
result = true
|
130
129
|
|
131
130
|
issues.each do |key|
|
132
|
-
result &= key.
|
131
|
+
result &= key.update(**fields)
|
133
132
|
end
|
134
133
|
|
135
134
|
return result
|
@@ -137,7 +136,7 @@ module Danger
|
|
137
136
|
|
138
137
|
# Utility to split the given fields into fields that can be updated on the transition screen corresponding to the `transition_id` of the given `issue`.
|
139
138
|
#
|
140
|
-
# @param [JIRA::Issue] issue
|
139
|
+
# @param [JIRA::Resource::Issue] issue
|
141
140
|
# @param [Integer] transition_id
|
142
141
|
# @param [Hash] fields Fields to split
|
143
142
|
#
|
@@ -161,31 +160,51 @@ module Danger
|
|
161
160
|
# and use the other fields with the update action.
|
162
161
|
#
|
163
162
|
# @example Transition the issue `my_issue` and set the fields `assignee` and `customfield_11005`
|
164
|
-
# jira.
|
163
|
+
# jira.transition_and_update_all(my_issue, 10, assignee: { name: 'username' }, customfield_11005: 'example')
|
165
164
|
#
|
166
|
-
# @param [Array<JIRA::Issue>] issue An array of issues, or a single `JIRA::Issue`
|
167
165
|
# @param [Integer] transition_id
|
166
|
+
# @param [Array<JIRA::Resource::Issue>, JIRA::Resource::Issue] issue An array of issues, or a single issue
|
168
167
|
# @param [Hash] fields Fields to update
|
169
168
|
#
|
170
169
|
# @return [Boolean] `true` if all the issues were transitioned and updated successfully, `false` otherwise.
|
171
170
|
#
|
172
|
-
def
|
171
|
+
def transition_and_update_all(transition_id, issue: @issues, **fields)
|
173
172
|
issues = issue.kind_of?(Array) ? issue : [] << issue
|
174
173
|
result = issues.first.split_transition_fields(transition_id, fields)
|
175
174
|
transition_fields = result[:transition_fields]
|
176
175
|
fields = result[:other_fields]
|
177
176
|
|
178
|
-
result = transition(
|
179
|
-
result & update(issues, **fields)
|
177
|
+
result = transition(transition_id, issue: issues, **transition_fields)
|
178
|
+
result & update(issue: issues, **fields)
|
180
179
|
end
|
181
180
|
|
182
|
-
#
|
181
|
+
# Add a remote link to the PR in the given Jira issues. It uses the link of the PR as the `globalId` of the remote link, thus avoiding to create duplicates each time the PR is updated.
|
182
|
+
#
|
183
|
+
# @param [Array<JIRA::Resource::Issue>, JIRA::Resource::Issue] issue An array of issues, or a single issue
|
184
|
+
# @param [<String>] relation Option to set the relationship of the remote link
|
185
|
+
# @param [<Hash>, <Boolean>] status Option to set the status property of the remote link, it can be <Hash> or a <Boolean> that will set the value of the property `resolved`
|
183
186
|
#
|
184
|
-
# @
|
187
|
+
# @return [Boolean] `true` if all the remote links were added successfully, `false` otherwise.
|
185
188
|
#
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
+
def pr_as_remotelink(issue, relation: 'relates to', status: nil)
|
190
|
+
issues = issue.kind_of?(Array) ? issue : [] << issue
|
191
|
+
result = true
|
192
|
+
|
193
|
+
remote_link_prop = { object: { url: pr_link, title: vcs_host.pr_title, icon: link_icon } }
|
194
|
+
remote_link_prop[:globalId] = pr_link
|
195
|
+
remote_link_prop[:relationship] = relation
|
196
|
+
|
197
|
+
if status.kind_of?(Hash)
|
198
|
+
remote_link_prop[:object][:status] = status
|
199
|
+
elsif !status.nil?
|
200
|
+
remote_link_prop[:object][:status] = { resolved: status }
|
201
|
+
end
|
202
|
+
|
203
|
+
issues.each do |key|
|
204
|
+
result &= key.remotelink.build.save(remote_link_prop)
|
205
|
+
end
|
206
|
+
|
207
|
+
return result
|
189
208
|
end
|
190
209
|
|
191
210
|
private
|
@@ -196,9 +215,27 @@ module Danger
|
|
196
215
|
github
|
197
216
|
end
|
198
217
|
|
218
|
+
def pr_link
|
219
|
+
return @pr_link unless @pr_link.nil?
|
220
|
+
|
221
|
+
if defined? @dangerfile.gitlab
|
222
|
+
@pr_link = vcs_host.pr_json['web_url']
|
223
|
+
else
|
224
|
+
@pr_link = vcs_host.pr_json['html_url']
|
225
|
+
end
|
226
|
+
|
227
|
+
return @pr_link
|
228
|
+
end
|
229
|
+
|
230
|
+
def link_icon
|
231
|
+
return { title: 'Gitlab', url16x16: 'https://gitlab.com/favicon.ico' } if defined? @dangerfile.gitlab
|
232
|
+
|
233
|
+
{ title: 'Github', url16x16: 'https://github.com/favicon.ico' }
|
234
|
+
end
|
235
|
+
|
199
236
|
def build_regexp_from_key(key)
|
200
237
|
keys = key.kind_of?(Array) ? key.join('|') : key
|
201
|
-
return /((?:#{keys})-[0-9]+)/
|
238
|
+
return /((?:#{keys})-[0-9]+)/i
|
202
239
|
end
|
203
240
|
|
204
241
|
def search_title(regexp)
|
@@ -0,0 +1 @@
|
|
1
|
+
{"object":{"url":"https://github.com/test/pull/1234","title":"PR Title","icon":{"title":"Github","url16x16":"https://github.com/favicon.ico"},"status":{"resolved":true}},"globalId":"https://github.com/test/pull/1234","relationship":"relates to"}
|
data/spec/yajp_spec.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require_relative 'spec_helper'
|
4
4
|
|
5
|
+
# rubocop:disable Metrics/ModuleLength
|
5
6
|
module Danger
|
6
7
|
describe Danger::DangerYajp do
|
7
8
|
before do
|
@@ -46,9 +47,9 @@ module Danger
|
|
46
47
|
end
|
47
48
|
|
48
49
|
it 'can find jira issues via branch name' do
|
49
|
-
allow(plugin).to receive_message_chain('github.branch_for_head').and_return('bugfix/
|
50
|
+
allow(plugin).to receive_message_chain('github.branch_for_head').and_return('bugfix/web-126')
|
50
51
|
issues = plugin.search_branch(plugin.build_regexp_from_key('WEB'))
|
51
|
-
expect(issues).to eq(['
|
52
|
+
expect(issues).to eq(['web-126'])
|
52
53
|
end
|
53
54
|
|
54
55
|
it 'can find jira issues in pr body' do
|
@@ -61,17 +62,19 @@ module Danger
|
|
61
62
|
issue = Object.new
|
62
63
|
|
63
64
|
def issue.find(key)
|
64
|
-
|
65
|
+
# The find method in jira-ruby plugin is not case sensitive, hence the upcase.
|
66
|
+
return key.upcase
|
65
67
|
end
|
66
68
|
|
67
69
|
allow_any_instance_of(JIRA::Client).to receive(:Issue).and_return(issue)
|
68
70
|
|
69
71
|
allow(plugin).to receive_message_chain('github.pr_title').and_return('Fix for WEB-128 and WEB-129')
|
70
|
-
allow(plugin).to receive_message_chain('github.branch_for_head').and_return('bugfix/
|
72
|
+
allow(plugin).to receive_message_chain('github.branch_for_head').and_return('bugfix/web-128')
|
71
73
|
issues = plugin.find_issues('WEB', search_branch: true)
|
72
74
|
expect(issues).to eq(['WEB-128', 'WEB-129'])
|
73
75
|
end
|
74
76
|
|
77
|
+
# rubocop:disable Naming/VariableNumber
|
75
78
|
it 'can split transition field from other fields' do
|
76
79
|
json = File.read("#{File.dirname(__FILE__)}/support/transitions.all.json")
|
77
80
|
url = "#{ENV['DANGER_JIRA_URL']}/rest/api/2/issue/WEB-130/transitions"
|
@@ -89,13 +92,16 @@ module Danger
|
|
89
92
|
|
90
93
|
it 'can transition an issue' do
|
91
94
|
expected_json = '{"transition":{"id":"2"},"fields":{"assignee":{"name":"username"},"customfield_11005":"example"}}'
|
92
|
-
|
93
|
-
|
95
|
+
issue_id = Random.rand(1000)
|
96
|
+
url = "#{ENV['DANGER_JIRA_URL']}/rest/api/2/issue/#{issue_id}/transitions"
|
97
|
+
issue = plugin.api.Issue.build({ 'id' => issue_id, 'key' => 'WEB-131' })
|
98
|
+
transition_1 = issue.transitions.build({ 'id' => '2', 'name' => 'TEST' })
|
99
|
+
transition_2 = issue.transitions.build({ 'id' => '3', 'name' => 'FAKE' })
|
94
100
|
|
95
|
-
|
101
|
+
allow_any_instance_of(JIRA::HasManyProxy).to receive(:all).and_return([transition_1, transition_2])
|
96
102
|
stub = stub_request(:post, url).
|
97
103
|
with(body: expected_json)
|
98
|
-
result = plugin.
|
104
|
+
result = plugin.transition_all('test', issue: issue, assignee: { name: 'username' }, customfield_11005: 'example')
|
99
105
|
|
100
106
|
expect(stub).to have_been_requested.once
|
101
107
|
expect(result).to be true
|
@@ -104,18 +110,37 @@ module Danger
|
|
104
110
|
it 'can update issues' do
|
105
111
|
expected_json = '{"fields":{"assignee":{"name":"username"},"customfield_11005":"example"}}'
|
106
112
|
uri_template = Addressable::Template.new "#{ENV['DANGER_JIRA_URL']}/rest/api/2/issue/{issue}"
|
107
|
-
issue1 = plugin.api.Issue.build
|
108
|
-
issue2 = plugin.api.Issue.build
|
113
|
+
issue1 = plugin.api.Issue.build({ 'id' => Random.rand(1000), 'self' => "#{ENV['DANGER_JIRA_URL']}/rest/api/2/issue/WEB-132", 'key' => 'WEB-132' })
|
114
|
+
issue2 = plugin.api.Issue.build({ 'id' => Random.rand(1000), 'self' => "#{ENV['DANGER_JIRA_URL']}/rest/api/2/issue/WEB-133", 'key' => 'WEB-133' })
|
109
115
|
|
110
|
-
allow(issue1).to receive(:key_value).and_return('WEB-132')
|
111
|
-
allow(issue2).to receive(:key_value).and_return('WEB-133')
|
112
116
|
stub = stub_request(:put, uri_template).
|
113
117
|
with(body: expected_json)
|
114
|
-
result = plugin.
|
118
|
+
result = plugin.update_all(issue: [issue1, issue2], assignee: { name: 'username' }, customfield_11005: 'example')
|
115
119
|
|
116
120
|
expect(stub).to have_been_requested.twice
|
117
121
|
expect(result).to be true
|
118
122
|
end
|
123
|
+
# rubocop:enable Naming/VariableNumber
|
124
|
+
|
125
|
+
it 'can add remote link' do
|
126
|
+
pr_title = 'PR Title'
|
127
|
+
pr_json = { 'html_url' => 'https://github.com/test/pull/1234' }
|
128
|
+
url = "#{ENV['DANGER_JIRA_URL']}/rest/api/2/issue/WEB-134/remotelink"
|
129
|
+
json = File.read("#{File.dirname(__FILE__)}/support/remotelink.json")
|
130
|
+
issue = plugin.api.Issue.build
|
131
|
+
|
132
|
+
allow(issue).to receive(:key_value).and_return('WEB-134')
|
133
|
+
allow(dangerfile.github).to receive(:pr_json).and_return(pr_json)
|
134
|
+
allow(dangerfile.github).to receive(:pr_title).and_return(pr_title)
|
135
|
+
|
136
|
+
stub = stub_request(:post, url).
|
137
|
+
with(body: json)
|
138
|
+
result = plugin.pr_as_remotelink(issue, status: true)
|
139
|
+
|
140
|
+
expect(stub).to have_been_requested.once
|
141
|
+
expect(result).to be true
|
142
|
+
end
|
119
143
|
end
|
120
144
|
end
|
121
145
|
end
|
146
|
+
# rubocop:enable Metrics/ModuleLength
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: danger-yajp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- juliendms
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: danger-plugin-api
|
@@ -72,56 +72,56 @@ dependencies:
|
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '3
|
75
|
+
version: '3'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '3
|
82
|
+
version: '3'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: webmock
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '3
|
89
|
+
version: '3'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '3
|
96
|
+
version: '3'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: rubocop
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: 1
|
103
|
+
version: '1'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: 1
|
110
|
+
version: '1'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: yard
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: 0.9
|
117
|
+
version: '0.9'
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: 0.9
|
124
|
+
version: '0.9'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: guard
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -171,6 +171,7 @@ executables: []
|
|
171
171
|
extensions: []
|
172
172
|
extra_rdoc_files: []
|
173
173
|
files:
|
174
|
+
- ".github/workflows/create-tag.yml"
|
174
175
|
- ".github/workflows/gem-push.yml"
|
175
176
|
- ".gitignore"
|
176
177
|
- ".rubocop.yml"
|
@@ -185,8 +186,10 @@ files:
|
|
185
186
|
- lib/danger_plugin.rb
|
186
187
|
- lib/danger_yajp.rb
|
187
188
|
- lib/yajp/gem_version.rb
|
189
|
+
- lib/yajp/issue.rb
|
188
190
|
- lib/yajp/plugin.rb
|
189
191
|
- spec/spec_helper.rb
|
192
|
+
- spec/support/remotelink.json
|
190
193
|
- spec/support/transitions.all.json
|
191
194
|
- spec/yajp_spec.rb
|
192
195
|
homepage: https://github.com/juliendms/danger-yajp
|
@@ -215,5 +218,6 @@ summary: Yet Another Jira Plugin is a danger plugin to find issues, access their
|
|
215
218
|
and perform operations on them.
|
216
219
|
test_files:
|
217
220
|
- spec/spec_helper.rb
|
221
|
+
- spec/support/remotelink.json
|
218
222
|
- spec/support/transitions.all.json
|
219
223
|
- spec/yajp_spec.rb
|