jira-auto-tool 1.2.3 → 1.3.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/.ruby-version +1 -0
- data/README.md +47 -9
- data/ext/no_wrappers_win.rb +6 -0
- data/features/configure_environment.feature +48 -8
- data/features/control_http_request_rate_limit.feature +8 -2
- data/features/create_sprints_using_existing_ones_as_reference.feature +31 -3
- data/lib/jira/auto/tool/environment_loader.rb +25 -1
- data/lib/jira/auto/tool/helpers/environment_based_value.rb +6 -1
- data/lib/jira/auto/tool/performer/planning_increment_sprint_creator.rb +4 -3
- data/lib/jira/auto/tool/project/ticket_fields.rb +6 -6
- data/lib/jira/auto/tool/rate_limited_jira_client.rb +3 -3
- data/lib/jira/auto/tool/ticket.rb +18 -3
- data/lib/jira/auto/tool/version.rb +1 -1
- data/lib/jira/auto/tool.rb +23 -22
- data/lib/tasks/version.rake +1 -1
- data/spec/jira/auto/tool/environment_loader_spec.rb +64 -9
- data/spec/jira/auto/tool/performer/planning_increment_sprint_creator_spec.rb +76 -13
- data/spec/jira/auto/tool/ticket_fields_spec.rb +63 -0
- data/spec/jira/auto/tool_spec.rb +12 -5
- data/spec/spec_helper.rb +2 -2
- metadata +20 -6
- data/bin/setup +0 -8
- data/bin/setup-dev-win.bat +0 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 01e73565bdbb82263685fcd3f903a96f53606fd2a742dcd7baf290767535e231
|
|
4
|
+
data.tar.gz: 6caf206fb9f7754362edf4ec3fd1c2c85ba82f13a95711f8716e968b63deb85e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1f195ea5c9cbeb1a525cc3b9684d71f0a791b05935510f221bfc347b173165abc70598ceacf01918cee660172f385a9ed1ac824aaeecaa78d4cc6894683a6cf5
|
|
7
|
+
data.tar.gz: 807721d720cde7b2142a8c5cae279ea20fe857d79a107e90efa62742f8fa5cb298a5cde6333463085cd00ac6e702101237d4ec0b421d923f2e0e90e65c934952
|
data/.ruby-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.4.8
|
data/README.md
CHANGED
|
@@ -4,15 +4,33 @@
|
|
|
4
4
|

|
|
5
5
|
|
|
6
6
|
****
|
|
7
|
-
The purpose of this tool it
|
|
7
|
+
The purpose of this tool is to make it easier to make adjustments to the sprints of multiple teams.
|
|
8
8
|
See the [feature files](./features) for some behavior examples.
|
|
9
9
|
|
|
10
10
|
## Table of Contents
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
- [Principles](#principles)
|
|
13
|
+
- [Installation](#installation)
|
|
14
|
+
- [Setup](#setup)
|
|
15
|
+
- [Usage](#usage)
|
|
16
|
+
- [Warning](#warning)
|
|
17
|
+
- [Add Sprints](#add-sprints)
|
|
18
|
+
- [Adjusting The End Date Of Sprints](#adjusting-the-end-date-of-sprints)
|
|
19
|
+
- [Align Time In Sprint Dates](#align-time-in-sprint-dates)
|
|
20
|
+
- [List Sprints](#list-sprints)
|
|
21
|
+
- [List Sprint Prefixes (Teams)](#list-sprint-prefixes-teams)
|
|
22
|
+
- [Rename Sprints](#rename-sprints)
|
|
23
|
+
- [Team Sprint Mapping](#team-sprint-mapping)
|
|
24
|
+
- [Team Ticket Sprint Dispatching](#team-ticket-sprint-dispatching)
|
|
25
|
+
- [Development](#development)
|
|
26
|
+
- [Install Dependencies](#install-dependencies)
|
|
27
|
+
- [Continuous Testing While Making Changes](#continuous-testing-while-making-changes)
|
|
28
|
+
- [Experiment Using An Interactive Prompt](#experiment-using-an-interactive-prompt)
|
|
29
|
+
- [Install Locally](#install-locally)
|
|
30
|
+
- [Release](#release)
|
|
31
|
+
- [Contributing](#contributing)
|
|
32
|
+
- [License](#license)
|
|
33
|
+
- [Code of Conduct](#code-of-conduct)
|
|
16
34
|
|
|
17
35
|
## Principles
|
|
18
36
|
|
|
@@ -49,7 +67,7 @@ will use the existing ones as a reference for the prefix and the length of the s
|
|
|
49
67
|
```
|
|
50
68
|
2. Adjust the file to your context.
|
|
51
69
|
|
|
52
|
-
The following environment variables have to be set to use this tool. **Except** for
|
|
70
|
+
The following environment variables have to be set to use this tool. **Except** for the `JIRA_API_TOKEN` that should
|
|
53
71
|
be done via the configuration file.
|
|
54
72
|
|
|
55
73
|
Some explanations:
|
|
@@ -72,9 +90,9 @@ Optional environment variables:
|
|
|
72
90
|
See [sprint filtering](./features/sprint_filtering.feature).
|
|
73
91
|
- `JIRA_CONTEXT_PATH` - Context path for Jira instance (if needed typically "/jira").
|
|
74
92
|
- `JIRA_HTTP_DEBUG` - Enable HTTP debug logging (set to "true" or "false").
|
|
75
|
-
- `JAT_RATE_LIMIT_PER_INTERVAL` - Rate limit for Jira API calls (e.g., "1")
|
|
76
|
-
See [Control Jira HTTP request rate.](./features/control_http_request_rate_limit.feature).
|
|
77
93
|
- `JAT_RATE_INTERVAL_IN_SECONDS` - Interval for rate limiting in seconds (e.g., "1").
|
|
94
|
+
- `JAT_RATE_LIMIT_PER_INTERVAL` - Rate limit for Jira API calls (e.g., "1")
|
|
95
|
+
See [Control Jira HTTP request rate](./features/control_http_request_rate_limit.feature).
|
|
78
96
|
|
|
79
97
|
## Usage
|
|
80
98
|
|
|
@@ -106,6 +124,15 @@ to the teams respective sprint prefixes.
|
|
|
106
124
|
jira-auto-tool --sprint-add=25.4.3,4
|
|
107
125
|
```
|
|
108
126
|
|
|
127
|
+
### Adjusting The End Date Of Sprints
|
|
128
|
+
|
|
129
|
+
The following is going to
|
|
130
|
+
[adjust the end date of sprints](./features/update_sprint_end_date_and_shift_following_ones.feature)
|
|
131
|
+
named `sprint_prefix_25.1.5` and shift the subsequent ones by adjust their start and end dates:
|
|
132
|
+
```bash
|
|
133
|
+
jira-auto-tool --sprint-update-end-date=25.1.5,"2025-02-25 16:00:00 UTC"
|
|
134
|
+
```
|
|
135
|
+
|
|
109
136
|
### Align Time In Sprint Dates
|
|
110
137
|
|
|
111
138
|
````bash
|
|
@@ -170,7 +197,18 @@ To install this gem onto your local machine, run `bundle exec rake install`.
|
|
|
170
197
|
|
|
171
198
|
### Release
|
|
172
199
|
|
|
173
|
-
|
|
200
|
+
1. Bump the gem version:
|
|
201
|
+
```bash
|
|
202
|
+
bundle exec rake version:bump[{major|minor|patch}]
|
|
203
|
+
```
|
|
204
|
+
2. Release the version to [rubygems.org](https://rubygems.org):
|
|
205
|
+
```bash
|
|
206
|
+
bundle exec rake release
|
|
207
|
+
```
|
|
208
|
+
which will:
|
|
209
|
+
* create a git tag for the version
|
|
210
|
+
* push git commits and the created tag
|
|
211
|
+
* push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
174
212
|
|
|
175
213
|
## Contributing
|
|
176
214
|
|
|
@@ -63,7 +63,7 @@ Feature: Environment Configuration Management
|
|
|
63
63
|
Please remove first before running this again!
|
|
64
64
|
"""
|
|
65
65
|
|
|
66
|
-
Scenario: Tool successfully loads the config
|
|
66
|
+
Scenario: Tool successfully loads the config from the current directory and hides secret values when listing them
|
|
67
67
|
Given a file named "jira-auto-tool.env.yaml.erb" with:
|
|
68
68
|
"""
|
|
69
69
|
---
|
|
@@ -104,7 +104,7 @@ Feature: Environment Configuration Management
|
|
|
104
104
|
| JAT_RATE_LIMIT_IMPLEMENTATION | |
|
|
105
105
|
| JAT_RATE_LIMIT_PER_INTERVAL | |
|
|
106
106
|
| JAT_TICKETS_FOR_TEAM_SPRINT_TICKET_DISPATCHER_JQL | project = PROJ AND Sprint IS EMPTY |
|
|
107
|
-
| JIRA_API_TOKEN |
|
|
107
|
+
| JIRA_API_TOKEN | **** |
|
|
108
108
|
| JIRA_BOARD_NAME | Team Board |
|
|
109
109
|
| JIRA_BOARD_NAME_REGEX | ART 16|unconventional board name |
|
|
110
110
|
| JIRA_CONTEXT_PATH | /jira |
|
|
@@ -116,7 +116,7 @@ Feature: Environment Configuration Management
|
|
|
116
116
|
+---------------------------------------------------+------------------------------------+
|
|
117
117
|
"""
|
|
118
118
|
|
|
119
|
-
Scenario: Tool looks first for configuration in the current directory
|
|
119
|
+
Scenario: Tool looks first for configuration in the current directory (hiding secret when listing)
|
|
120
120
|
Given a file named "./jira-auto-tool.env.yaml.erb" with:
|
|
121
121
|
"""
|
|
122
122
|
---
|
|
@@ -136,8 +136,16 @@ Feature: Environment Configuration Management
|
|
|
136
136
|
"""
|
|
137
137
|
Using configuration from ./jira-auto-tool.env.yaml.erb
|
|
138
138
|
"""
|
|
139
|
+
And the output should match:
|
|
140
|
+
"""
|
|
141
|
+
JIRA_API_TOKEN\s+\|\s\*{4}
|
|
142
|
+
"""
|
|
143
|
+
And the output should match:
|
|
144
|
+
"""
|
|
145
|
+
JIRA_USERNAME\s+\|\scurrent@company.com
|
|
146
|
+
"""
|
|
139
147
|
|
|
140
|
-
Scenario: Tool looks for home directory config folder when no config file in the current directory
|
|
148
|
+
Scenario: Tool looks for home directory config folder when no config file in the current directory (hiding secret when listing)
|
|
141
149
|
Given a file named "./jira-auto-tool.env.yaml.erb" does not exist
|
|
142
150
|
And a file named "~/.config/jira-auto-tool/jira-auto-tool.env.yaml.erb" with:
|
|
143
151
|
"""
|
|
@@ -150,14 +158,23 @@ Feature: Environment Configuration Management
|
|
|
150
158
|
"""
|
|
151
159
|
Using configuration from .+/.config/jira-auto-tool/jira-auto-tool.env.yaml.erb
|
|
152
160
|
"""
|
|
161
|
+
And the output should match:
|
|
162
|
+
"""
|
|
163
|
+
JIRA_API_TOKEN\s+\|\s\*{4}\s+
|
|
164
|
+
"""
|
|
165
|
+
And the output should match:
|
|
166
|
+
"""
|
|
167
|
+
JIRA_USERNAME\s+\|\shome@company.com
|
|
168
|
+
"""
|
|
153
169
|
|
|
154
|
-
Scenario: Tool uses the existing environment values if no config file found
|
|
170
|
+
Scenario: Tool uses the existing environment values if no config file found (hiding secret when listing)
|
|
155
171
|
Given the following files should not exist:
|
|
156
172
|
| ./jira-auto-tool.env.yaml.erb |
|
|
157
173
|
| ~/.config/jira-auto-tool/jira-auto-tool.env.yaml.erb |
|
|
158
174
|
And the following environment variables are set:
|
|
159
|
-
| name | value
|
|
160
|
-
| JIRA_API_TOKEN | token-value
|
|
175
|
+
| name | value |
|
|
176
|
+
| JIRA_API_TOKEN | token-value |
|
|
177
|
+
| JIRA_USERNAME | env@company.com |
|
|
161
178
|
When I successfully run `jira-auto-tool --env-list`
|
|
162
179
|
Then the output should match:
|
|
163
180
|
"""
|
|
@@ -167,5 +184,28 @@ Feature: Environment Configuration Management
|
|
|
167
184
|
"""
|
|
168
185
|
And the output should match:
|
|
169
186
|
"""
|
|
170
|
-
JIRA_API_TOKEN\s
|
|
187
|
+
JIRA_API_TOKEN\s+\|\s\*{4}
|
|
188
|
+
"""
|
|
189
|
+
And the output should match:
|
|
190
|
+
"""
|
|
191
|
+
JIRA_USERNAME\s+\|\senv@company.com
|
|
171
192
|
"""
|
|
193
|
+
|
|
194
|
+
Scenario: Tool displays a useful error message in case of error
|
|
195
|
+
Given a file named "./jira-auto-tool.env.yaml.erb" with:
|
|
196
|
+
"""
|
|
197
|
+
---
|
|
198
|
+
JIRA_USERNAME: "error@company.com"
|
|
199
|
+
JIRA_API_TOKEN: "error-token"
|
|
200
|
+
JIRA_SITE_URL: "https://home.atlassian.net"
|
|
201
|
+
<%
|
|
202
|
+
raise "This is meant to fail while loading!"
|
|
203
|
+
%>
|
|
204
|
+
"""
|
|
205
|
+
When I run `jira-auto-tool --env-list`
|
|
206
|
+
Then it should fail with:
|
|
207
|
+
"""
|
|
208
|
+
ERROR Jira::Auto::Tool::EnvironmentLoader : ./jira-auto-tool.env.yaml.erb:6: failed to load with the following error: (RuntimeError)
|
|
209
|
+
This is meant to fail while loading!
|
|
210
|
+
"""
|
|
211
|
+
|
|
@@ -4,7 +4,13 @@ Feature: Control the HTTP request rate limit
|
|
|
4
4
|
I need the ability to control the HTTP request limit
|
|
5
5
|
|
|
6
6
|
Scenario Outline: Limiting the request rate
|
|
7
|
-
Given
|
|
7
|
+
Given a Jira Scrum board
|
|
8
|
+
And the board only has the following sprints:
|
|
9
|
+
| name | length | start_date | state |
|
|
10
|
+
| ART-16_CRM_24.4.1 | 2-week | 2024-12-01 11:00:00 UTC | closed |
|
|
11
|
+
| ART-16_E2E-Test_24.4.2 | 4-day | 2024-12-05 11:00:00 UTC | future |
|
|
12
|
+
| ART-32_Platform_24.4.7 | 3-week | 2024-10-07 11:00:00 UTC | future |
|
|
13
|
+
And the following environment variables are set:
|
|
8
14
|
| name | value |
|
|
9
15
|
| JAT_RATE_INTERVAL_IN_SECONDS | <rate_interval_in_seconds> |
|
|
10
16
|
| JAT_RATE_LIMIT_IMPLEMENTATION | <jat_rate_limit_implementation> |
|
|
@@ -14,7 +20,7 @@ Feature: Control the HTTP request rate limit
|
|
|
14
20
|
Examples:
|
|
15
21
|
| jat_rate_limit_implementation | rate_limit_per_interval | rate_interval_in_seconds | minimal_time | maximal_time |
|
|
16
22
|
| | 0 | 0 | 0 | 5 |
|
|
17
|
-
| in_process | 1 |
|
|
23
|
+
| in_process | 1 | 1 | 1 | 20 |
|
|
18
24
|
| redis | 1 | 2 | 1 | 20 |
|
|
19
25
|
| redis | 1 | 10 | 18 | 120 |
|
|
20
26
|
|
|
@@ -5,14 +5,14 @@ Feature: Add sprints using existing ones as reference
|
|
|
5
5
|
|
|
6
6
|
Background:
|
|
7
7
|
Given a Jira Scrum board
|
|
8
|
-
|
|
8
|
+
|
|
9
|
+
Scenario: Add several sprints using existing sprint prefixes
|
|
10
|
+
Given the board only has the following sprints:
|
|
9
11
|
| comment | name | length | start_date | state |
|
|
10
12
|
| none added since closed | Food_Supply_25.1.3 | 2-week | 2025-02-01 11:00:00 UTC | closed |
|
|
11
13
|
| "sprints | Food_Delivery_25.1.4 | 4-day | 2025-02-01 11:00:00 UTC | future |
|
|
12
14
|
| expected to be | Food_Market_25.2.1 | 3-week | 2025-02-01 11:00:00 UTC | active |
|
|
13
15
|
| added" | Food_Restaurant_25.2.1 | 4-week | 2025-02-21 11:00:00 UTC | future |
|
|
14
|
-
|
|
15
|
-
Scenario: Add several sprints using existing sprint prefixes
|
|
16
16
|
When I successfully run `jira-auto-tool --sprint-add=25.3.1,4`
|
|
17
17
|
Then afterwards the board only has the following sprints:
|
|
18
18
|
| name | start_date | state |
|
|
@@ -34,6 +34,12 @@ Feature: Add sprints using existing ones as reference
|
|
|
34
34
|
| Food_Restaurant_25.3.4 | 2025-06-13 11:00:00 UTC | future |
|
|
35
35
|
|
|
36
36
|
Scenario: Add several planning interval sprints
|
|
37
|
+
Given the board only has the following sprints:
|
|
38
|
+
| comment | name | length | start_date | state |
|
|
39
|
+
| none added since closed | Food_Supply_25.1.3 | 2-week | 2025-02-01 11:00:00 UTC | closed |
|
|
40
|
+
| "sprints | Food_Delivery_25.1.4 | 4-day | 2025-02-01 11:00:00 UTC | future |
|
|
41
|
+
| expected to be | Food_Market_25.2.1 | 3-week | 2025-02-01 11:00:00 UTC | active |
|
|
42
|
+
| added" | Food_Restaurant_25.2.1 | 4-week | 2025-02-21 11:00:00 UTC | future |
|
|
37
43
|
When I successfully run `jira-auto-tool --sa=25.2.2,3 --sa=25.3.1,4 --sa=25.4.1,5`
|
|
38
44
|
Then afterwards the board only has the following sprints:
|
|
39
45
|
| name | start_date | state |
|
|
@@ -77,3 +83,25 @@ Feature: Add sprints using existing ones as reference
|
|
|
77
83
|
| Food_Restaurant_25.4.3 | 2025-11-28 11:00:00 UTC | future |
|
|
78
84
|
| Food_Restaurant_25.4.4 | 2025-12-26 11:00:00 UTC | future |
|
|
79
85
|
| Food_Restaurant_25.4.5 | 2026-01-23 11:00:00 UTC | future |
|
|
86
|
+
|
|
87
|
+
Scenario: Adding sprints is not creating duplicates or ones anterior to last sprints of prefixes
|
|
88
|
+
Given the board only has the following sprints:
|
|
89
|
+
| comment | name | length | start_date | state |
|
|
90
|
+
| none added since closed | Food_Supply_25.1.3 | 2-week | 2025-02-01 11:00:00 UTC | closed |
|
|
91
|
+
| all sprints added | Food_Delivery_25.1.4 | 4-day | 2025-02-01 11:00:00 UTC | future |
|
|
92
|
+
| the last 3 added since the first already exist | Food_Market_25.2.1 | 3-week | 2025-02-01 11:00:00 UTC | active |
|
|
93
|
+
| none added because would be anterior existing sprint | Food_Restaurant_25.3.1 | 4-week | 2025-02-21 11:00:00 UTC | future |
|
|
94
|
+
When I successfully run `jira-auto-tool --sa=25.2.1,4`
|
|
95
|
+
Then afterwards the board only has the following sprints:
|
|
96
|
+
| name | start_date | state |
|
|
97
|
+
| Food_Supply_25.1.3 | 2025-02-01 11:00:00 UTC | closed |
|
|
98
|
+
| Food_Delivery_25.1.4 | 2025-02-01 11:00:00 UTC | future |
|
|
99
|
+
| Food_Delivery_25.2.1 | 2025-02-05 11:00:00 UTC | future |
|
|
100
|
+
| Food_Delivery_25.2.2 | 2025-02-09 11:00:00 UTC | future |
|
|
101
|
+
| Food_Delivery_25.2.3 | 2025-02-13 11:00:00 UTC | future |
|
|
102
|
+
| Food_Delivery_25.2.4 | 2025-02-17 11:00:00 UTC | future |
|
|
103
|
+
| Food_Market_25.2.1 | 2025-02-01 11:00:00 UTC | active |
|
|
104
|
+
| Food_Market_25.2.2 | 2025-02-22 11:00:00 UTC | future |
|
|
105
|
+
| Food_Market_25.2.3 | 2025-03-15 11:00:00 UTC | future |
|
|
106
|
+
| Food_Market_25.2.4 | 2025-04-05 11:00:00 UTC | future |
|
|
107
|
+
| Food_Restaurant_25.3.1 | 2025-02-21 11:00:00 UTC | future |
|
|
@@ -46,11 +46,18 @@ module Jira
|
|
|
46
46
|
def tool_environment
|
|
47
47
|
Environment.constants.sort.to_h do |constant|
|
|
48
48
|
constant_as_string = constant.to_s
|
|
49
|
+
actual_value = ENV.fetch(constant_as_string, nil)
|
|
50
|
+
value_to_display = environment_variable_holds_a_secret?(constant_as_string) ? "****" : actual_value
|
|
49
51
|
|
|
50
|
-
[constant_as_string,
|
|
52
|
+
[constant_as_string, value_to_display]
|
|
51
53
|
end
|
|
52
54
|
end
|
|
53
55
|
|
|
56
|
+
def environment_variable_holds_a_secret?(env_var_name)
|
|
57
|
+
method_name = env_var_name.to_s.downcase
|
|
58
|
+
tool.send("#{method_name}_holds_a_secret?")
|
|
59
|
+
end
|
|
60
|
+
|
|
54
61
|
def file_path
|
|
55
62
|
File.exist?(current_dir_file_path) ? current_dir_file_path : config_dir_file_path
|
|
56
63
|
end
|
|
@@ -81,10 +88,27 @@ module Jira
|
|
|
81
88
|
|
|
82
89
|
def config_values
|
|
83
90
|
@config_values ||= YAML.safe_load(config_file_content) || {}
|
|
91
|
+
rescue StandardError => e
|
|
92
|
+
error_line = e.backtrace_locations.first.lineno
|
|
93
|
+
message = <<~EOEMSG
|
|
94
|
+
#{file_path}:#{error_line}: failed to load with the following error:
|
|
95
|
+
#{e.message}
|
|
96
|
+
EOEMSG
|
|
97
|
+
|
|
98
|
+
raise message
|
|
84
99
|
end
|
|
85
100
|
|
|
86
101
|
def config_file_content
|
|
87
102
|
@config_file_content ||= File.exist?(file_path) ? ERB.new(File.read(file_path)).result(binding) : ""
|
|
103
|
+
rescue StandardError => e
|
|
104
|
+
error_line = e.backtrace_locations.first.lineno
|
|
105
|
+
|
|
106
|
+
message = <<~EOEMSG
|
|
107
|
+
#{file_path}:#{error_line}: failed to load with the following error:
|
|
108
|
+
#{e.message}
|
|
109
|
+
EOEMSG
|
|
110
|
+
|
|
111
|
+
raise message
|
|
88
112
|
end
|
|
89
113
|
|
|
90
114
|
def table
|
|
@@ -6,12 +6,13 @@ module Jira
|
|
|
6
6
|
module Helpers
|
|
7
7
|
module EnvironmentBasedValue
|
|
8
8
|
# TODO: overly complex - simplify by moving this to the Config and define a Configurable module
|
|
9
|
-
def define_overridable_environment_based_value(method_name)
|
|
9
|
+
def define_overridable_environment_based_value(method_name, holds_a_secret)
|
|
10
10
|
define_reader(method_name)
|
|
11
11
|
define_predicate(method_name)
|
|
12
12
|
define_reader_accepting_default_value(method_name)
|
|
13
13
|
define_writer(method_name)
|
|
14
14
|
define_environment_variable_name_constant(method_name)
|
|
15
|
+
define_holds_a_secret_predicate(method_name, holds_a_secret)
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
def define_reader(method_name)
|
|
@@ -32,6 +33,10 @@ module Jira
|
|
|
32
33
|
end
|
|
33
34
|
end
|
|
34
35
|
|
|
36
|
+
def define_holds_a_secret_predicate(method_name, holds_a_secret)
|
|
37
|
+
define_method(:"#{method_name}_holds_a_secret?") { holds_a_secret }
|
|
38
|
+
end
|
|
39
|
+
|
|
35
40
|
def define_reader_accepting_default_value(method_name)
|
|
36
41
|
define_method(:"#{method_name}_when_defined_else") do |value|
|
|
37
42
|
if config.key?(method_name)
|
|
@@ -21,9 +21,10 @@ module Jira
|
|
|
21
21
|
parsed_new_name = Sprint::Name.new_with(sprint_prefix.name, sprint_suffix)
|
|
22
22
|
|
|
23
23
|
iteration_count.times do |_iteration|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
unless parsed_new_name <= last_sprint.parsed_name
|
|
25
|
+
last_sprint = create_sprint_for(last_sprint, parsed_new_name.to_s)
|
|
26
|
+
sprint_prefix << last_sprint
|
|
27
|
+
end
|
|
27
28
|
|
|
28
29
|
parsed_new_name = parsed_new_name.next_in_planning_interval
|
|
29
30
|
end
|
|
@@ -39,12 +39,12 @@ module Jira
|
|
|
39
39
|
def each_issue_type_field
|
|
40
40
|
tool.jira_client.Createmeta.all({ projectKeys: project.key, "expand" => "projects.issuetypes.fields" })
|
|
41
41
|
.each do |createmeta|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
createmeta.attrs["issuetypes"].each do |issue_type|
|
|
43
|
+
issue_type_name = issue_type["name"]
|
|
44
|
+
issue_type["fields"].each_value do |field|
|
|
45
|
+
yield(issue_type_name, field)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
48
|
end
|
|
49
49
|
end
|
|
50
50
|
|
|
@@ -33,11 +33,11 @@ module Jira
|
|
|
33
33
|
|
|
34
34
|
alias original_request request
|
|
35
35
|
|
|
36
|
-
def request(*
|
|
36
|
+
def request(*)
|
|
37
37
|
if rate_limit_per_interval == NO_RATE_LIMIT_PER_INTERVAL
|
|
38
|
-
original_request(*
|
|
38
|
+
original_request(*)
|
|
39
39
|
else
|
|
40
|
-
rate_limit { original_request(*
|
|
40
|
+
rate_limit { original_request(*) }
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
43
|
|
|
@@ -42,8 +42,23 @@ module Jira
|
|
|
42
42
|
%i[key summary sprint implementation_team expected_start_date]
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
+
# Compatibility helper to access Issue fields across Jira API versions
|
|
46
|
+
# - jira-ruby v2: JIRA::Resource::Issue responds to #fields
|
|
47
|
+
# - jira-ruby v3: fields are nested under #attrs['fields']
|
|
48
|
+
def ticket_fields
|
|
49
|
+
if jira_ticket.respond_to?(:fields)
|
|
50
|
+
jira_ticket.fields
|
|
51
|
+
else
|
|
52
|
+
raise "attrs not found in #{jira_ticket}!" unless jira_ticket.respond_to?(:attrs)
|
|
53
|
+
|
|
54
|
+
attrs = jira_ticket.attrs
|
|
55
|
+
attrs["fields"] || attrs[:fields] ||
|
|
56
|
+
raise("fields not found in #{attrs} from #{jira_ticket}!")
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
45
60
|
def sprint
|
|
46
|
-
|
|
61
|
+
ticket_fields.fetch(tool.jira_sprint_field.id)
|
|
47
62
|
end
|
|
48
63
|
|
|
49
64
|
def jira_client
|
|
@@ -96,8 +111,8 @@ module Jira
|
|
|
96
111
|
def jira_field_value(field_id = caller_locations(1, 1).first.base_label)
|
|
97
112
|
log.debug { "jira_field_value(#{field_id})" }
|
|
98
113
|
|
|
99
|
-
field =
|
|
100
|
-
raise "#{id}: value not found in #{
|
|
114
|
+
field = ticket_fields.fetch(field_id) do |id|
|
|
115
|
+
raise "#{id}: value not found in #{ticket_fields}"
|
|
101
116
|
end
|
|
102
117
|
|
|
103
118
|
log.debug { "jira_field_value(#{field_id}), field: #{field}" }
|
data/lib/jira/auto/tool.rb
CHANGED
|
@@ -139,27 +139,28 @@ module Jira
|
|
|
139
139
|
jira_base_url + url
|
|
140
140
|
end
|
|
141
141
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
142
|
+
HOLDS_A_SECRET = true
|
|
143
|
+
ENVIRONMENT_BASED_VALUE_SYMBOLS =
|
|
144
|
+
([[:jira_api_token, HOLDS_A_SECRET]] + %i[
|
|
145
|
+
art_sprint_regex
|
|
146
|
+
expected_start_date_field_name
|
|
147
|
+
implementation_team_field_name
|
|
148
|
+
jat_rate_interval_in_seconds
|
|
149
|
+
jat_rate_limit_implementation
|
|
150
|
+
jat_rate_limit_per_interval
|
|
151
|
+
jat_tickets_for_team_sprint_ticket_dispatcher_jql
|
|
152
|
+
jira_board_name
|
|
153
|
+
jira_board_name_regex
|
|
154
|
+
jira_context_path
|
|
155
|
+
jira_http_debug
|
|
156
|
+
jira_project_key
|
|
157
|
+
jira_site_url
|
|
158
|
+
jira_sprint_field_name
|
|
159
|
+
jira_username
|
|
160
|
+
].collect { |value_name| [value_name, !HOLDS_A_SECRET] }).freeze
|
|
161
|
+
|
|
162
|
+
ENVIRONMENT_BASED_VALUE_SYMBOLS.each do |method_name, holds_a_secret|
|
|
163
|
+
define_overridable_environment_based_value(method_name, holds_a_secret)
|
|
163
164
|
end
|
|
164
165
|
|
|
165
166
|
def board_controller
|
|
@@ -207,7 +208,7 @@ module Jira
|
|
|
207
208
|
end
|
|
208
209
|
|
|
209
210
|
def tickets(jql = "project = #{project.key}")
|
|
210
|
-
jira_client.Issue.jql(jql).collect { |jira_ticket| Ticket.new(self, jira_ticket) }
|
|
211
|
+
jira_client.Issue.jql(jql, fields: ["*all"]).collect { |jira_ticket| Ticket.new(self, jira_ticket) }
|
|
211
212
|
rescue StandardError => e
|
|
212
213
|
raise <<~EOEM
|
|
213
214
|
Error fetching project tickets: Something went wrong:
|
data/lib/tasks/version.rake
CHANGED
|
@@ -5,6 +5,7 @@ require "rspec"
|
|
|
5
5
|
module Jira
|
|
6
6
|
module Auto
|
|
7
7
|
class Tool
|
|
8
|
+
# rubocop:disable Metrics/ClassLength
|
|
8
9
|
class EnvironmentLoader
|
|
9
10
|
RSpec.describe EnvironmentLoader do
|
|
10
11
|
let(:environment_loader) { described_class.new(tool, auto_setup: auto_setup) }
|
|
@@ -56,7 +57,7 @@ module Jira
|
|
|
56
57
|
end
|
|
57
58
|
|
|
58
59
|
describe "#tool_environment" do
|
|
59
|
-
let(:environment_keys) { %i[
|
|
60
|
+
let(:environment_keys) { %i[JIRA_SITE_URL JIRA_USERNAME JIRA_API_TOKEN] }
|
|
60
61
|
|
|
61
62
|
before do
|
|
62
63
|
allow(Environment).to receive(:constants).and_return(environment_keys)
|
|
@@ -64,14 +65,29 @@ module Jira
|
|
|
64
65
|
environment_keys.each do |environment_key|
|
|
65
66
|
allow(ENV).to receive(:fetch).with(environment_key.to_s, nil).and_return("#{environment_key} value")
|
|
66
67
|
end
|
|
68
|
+
|
|
69
|
+
allow(tool).to receive_messages(
|
|
70
|
+
jira_api_token_holds_a_secret?: true,
|
|
71
|
+
jira_site_url_holds_a_secret?: false,
|
|
72
|
+
jira_username_holds_a_secret?: false
|
|
73
|
+
)
|
|
67
74
|
end
|
|
68
75
|
|
|
69
76
|
it do
|
|
70
|
-
expect(environment_loader.tool_environment)
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
77
|
+
expect(environment_loader.tool_environment)
|
|
78
|
+
.to eq(
|
|
79
|
+
"JIRA_API_TOKEN" => "****",
|
|
80
|
+
"JIRA_SITE_URL" => "JIRA_SITE_URL value",
|
|
81
|
+
"JIRA_USERNAME" => "JIRA_USERNAME value"
|
|
82
|
+
)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
describe "#environment_variable_holds_a_secret?" do
|
|
87
|
+
it "allows checking that the corresponding constant is a secret or not" do
|
|
88
|
+
allow(tool).to receive(:jira_api_token_holds_a_secret?).and_return(true)
|
|
89
|
+
|
|
90
|
+
expect(environment_loader).to be_environment_variable_holds_a_secret("JIRA_API_TOKEN")
|
|
75
91
|
end
|
|
76
92
|
end
|
|
77
93
|
|
|
@@ -132,10 +148,12 @@ module Jira
|
|
|
132
148
|
end
|
|
133
149
|
|
|
134
150
|
describe "#setup" do
|
|
135
|
-
|
|
136
|
-
allow(environment_loader).to receive_messages(file_path: "
|
|
151
|
+
before do
|
|
152
|
+
allow(environment_loader).to receive_messages(file_path: "path/to/config/file.yaml")
|
|
137
153
|
allow(environment_loader).to receive_messages(config_file_content: "file_content")
|
|
154
|
+
end
|
|
138
155
|
|
|
156
|
+
it "sets up the value according to the configuration file content" do
|
|
139
157
|
allow(YAML)
|
|
140
158
|
.to receive(:safe_load)
|
|
141
159
|
.with("file_content")
|
|
@@ -147,10 +165,25 @@ module Jira
|
|
|
147
165
|
|
|
148
166
|
environment_loader.send(:setup)
|
|
149
167
|
end
|
|
168
|
+
|
|
169
|
+
context "when the YAML parsing fails" do
|
|
170
|
+
it "generates an error message including the file name" do
|
|
171
|
+
allow(YAML).to receive(:safe_load)
|
|
172
|
+
.with("file_content")
|
|
173
|
+
.and_raise(RuntimeError, "could not find expected ':' at line 3 column 6)")
|
|
174
|
+
|
|
175
|
+
expect { environment_loader.send(:setup) }
|
|
176
|
+
.to raise_error(RuntimeError, <<~EOEMSG
|
|
177
|
+
path/to/config/file.yaml:188: failed to load with the following error:
|
|
178
|
+
could not find expected ':' at line 3 column 6)
|
|
179
|
+
EOEMSG
|
|
180
|
+
)
|
|
181
|
+
end
|
|
182
|
+
end
|
|
150
183
|
end
|
|
151
184
|
|
|
152
185
|
describe "#config_file_content" do
|
|
153
|
-
let(:file_path) { "
|
|
186
|
+
let(:file_path) { "path/to/config/file" }
|
|
154
187
|
let(:file_content) do
|
|
155
188
|
<<-YAML_ERB
|
|
156
189
|
---
|
|
@@ -174,9 +207,31 @@ module Jira
|
|
|
174
207
|
end
|
|
175
208
|
|
|
176
209
|
it { expect(environment_loader.send(:config_file_content)).to eq(erb_result) }
|
|
210
|
+
|
|
211
|
+
context "when the ERB evaluation fails" do
|
|
212
|
+
let(:file_content) do
|
|
213
|
+
<<-YAML_ERB
|
|
214
|
+
---
|
|
215
|
+
a_key: <%= 4*4 %>
|
|
216
|
+
another_key: <%= 4*4 %>
|
|
217
|
+
<%
|
|
218
|
+
raise "An error that should be caught and reported!"#{" "}
|
|
219
|
+
%>
|
|
220
|
+
YAML_ERB
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
it "generates an error message including the file name" do
|
|
224
|
+
expect { environment_loader.send(:config_file_content) }
|
|
225
|
+
.to raise_error(RuntimeError, <<~EOEMSG)
|
|
226
|
+
path/to/config/file:5: failed to load with the following error:
|
|
227
|
+
An error that should be caught and reported!
|
|
228
|
+
EOEMSG
|
|
229
|
+
end
|
|
230
|
+
end
|
|
177
231
|
end
|
|
178
232
|
end
|
|
179
233
|
end
|
|
234
|
+
# rubocop:enable Metrics/ClassLength
|
|
180
235
|
end
|
|
181
236
|
end
|
|
182
237
|
end
|
|
@@ -33,27 +33,90 @@ module Jira
|
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
+
# rubocop:disable Naming/VariableNumber, RSpec/IndexedLet
|
|
36
37
|
describe "#act_on_sprints_for_sprint_prefix" do
|
|
37
|
-
def get_sprint(name, attributes)
|
|
38
|
-
instance_double(Sprint, name: name, to_s: name, **attributes
|
|
38
|
+
def get_sprint(name, attributes = {})
|
|
39
|
+
instance_double(Sprint, name: name, to_s: name, **attributes,
|
|
40
|
+
parsed_name: Sprint::Name.parse(name))
|
|
39
41
|
end
|
|
40
42
|
|
|
41
|
-
let(:
|
|
43
|
+
let(:sprint_prefix) do
|
|
44
|
+
instance_double(Sprint::Prefix, name: "Food_Delivery", last_sprint: last_sprint)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
context "when the sprints to create are all posterior to the last sprint from a naming perspective" do
|
|
48
|
+
let(:last_sprint) do
|
|
49
|
+
get_sprint "Food_Delivery_25.2.1", end_date: "2025-02-16 12:45", length_in_days: 10
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
let(:sprint_25_3_1) { get_sprint("Food_Delivery_25.3.1") }
|
|
53
|
+
let(:sprint_25_3_2) { get_sprint("Food_Delivery_25.3.2") }
|
|
54
|
+
let(:sprint_25_3_3) { get_sprint("Food_Delivery_25.3.3") }
|
|
55
|
+
let(:sprint_25_3_4) { get_sprint("Food_Delivery_25.3.4") }
|
|
56
|
+
|
|
57
|
+
before do
|
|
58
|
+
allow(updater).to receive(:create_sprint_for).with(last_sprint,
|
|
59
|
+
"Food_Delivery_25.3.1")
|
|
60
|
+
.and_return(sprint_25_3_1)
|
|
61
|
+
|
|
62
|
+
allow(updater).to receive(:create_sprint_for).with(sprint_25_3_1, "Food_Delivery_25.3.2")
|
|
63
|
+
.and_return(sprint_25_3_2)
|
|
64
|
+
|
|
65
|
+
allow(updater).to receive(:create_sprint_for).with(sprint_25_3_2, "Food_Delivery_25.3.3")
|
|
66
|
+
.and_return(sprint_25_3_3)
|
|
67
|
+
|
|
68
|
+
allow(updater).to receive(:create_sprint_for).with(sprint_25_3_3, "Food_Delivery_25.3.4")
|
|
69
|
+
.and_return(sprint_25_3_4)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it "creates the expected number of sprints with the expected names" do
|
|
73
|
+
expect(sprint_prefix).to receive(:<<).with(sprint_25_3_1)
|
|
74
|
+
expect(sprint_prefix).to receive(:<<).with(sprint_25_3_2)
|
|
75
|
+
expect(sprint_prefix).to receive(:<<).with(sprint_25_3_3)
|
|
76
|
+
expect(sprint_prefix).to receive(:<<).with(sprint_25_3_4)
|
|
77
|
+
|
|
78
|
+
updater.act_on_sprints_for_sprint_prefix(sprint_prefix)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
context "when some sprints to create are anterior to the last sprint from a naming perspective" do
|
|
83
|
+
let(:last_sprint) do
|
|
84
|
+
get_sprint "Food_Delivery_25.3.2", end_date: "2025-02-16 12:45", length_in_days: 10
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
let(:sprint_25_3_3) { get_sprint("Food_Delivery_25.3.3") }
|
|
88
|
+
let(:sprint_25_3_4) { get_sprint("Food_Delivery_25.3.4") }
|
|
89
|
+
|
|
90
|
+
before do
|
|
91
|
+
allow(updater).to receive(:create_sprint_for).with(last_sprint, "Food_Delivery_25.3.3")
|
|
92
|
+
.and_return(sprint_25_3_3)
|
|
93
|
+
|
|
94
|
+
allow(updater).to receive(:create_sprint_for).with(sprint_25_3_3, "Food_Delivery_25.3.4")
|
|
95
|
+
.and_return(sprint_25_3_4)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "only creates the ones posterior to the last sprint" do
|
|
99
|
+
expect(sprint_prefix).to receive(:<<).with(sprint_25_3_3)
|
|
100
|
+
expect(sprint_prefix).to receive(:<<).with(sprint_25_3_4)
|
|
101
|
+
|
|
102
|
+
updater.act_on_sprints_for_sprint_prefix(sprint_prefix)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
42
105
|
|
|
43
|
-
|
|
106
|
+
context "when requested sprints to create are anterior to the last sprint from a naming perspective" do
|
|
107
|
+
let(:last_sprint) do
|
|
108
|
+
get_sprint "Food_Delivery_25.4.1", end_date: "2025-02-16 12:45", length_in_days: 10
|
|
109
|
+
end
|
|
44
110
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
expect(updater).to receive(:create_sprint_for).ordered.with(nil, "Food_Delivery_25.3.2")
|
|
49
|
-
expect(updater).to receive(:create_sprint_for).ordered.with(nil, "Food_Delivery_25.3.3")
|
|
50
|
-
expect(updater).to receive(:create_sprint_for).ordered.with(nil, "Food_Delivery_25.3.4")
|
|
51
|
-
expect(sprint_prefix).to receive(:<<).exactly(4).times
|
|
111
|
+
it "does not create any since they would be anterior to the last sprint" do
|
|
112
|
+
expect(updater).not_to receive(:create_sprint_for)
|
|
113
|
+
expect(sprint_prefix).not_to receive(:<<)
|
|
52
114
|
|
|
53
|
-
|
|
115
|
+
updater.act_on_sprints_for_sprint_prefix(sprint_prefix)
|
|
116
|
+
end
|
|
54
117
|
end
|
|
55
|
-
# rubocop:enable RSpec/MultipleExpectations
|
|
56
118
|
end
|
|
119
|
+
# rubocop:enable Naming/VariableNumber, RSpec/IndexedLet
|
|
57
120
|
end
|
|
58
121
|
end
|
|
59
122
|
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# //wsl.localhost/Ubuntu/home/cbroult/work/ruby/jira-auto-tool/features/ticket_fields_spec.rb
|
|
4
|
+
|
|
5
|
+
require "spec_helper"
|
|
6
|
+
require "jira/auto/tool/ticket"
|
|
7
|
+
|
|
8
|
+
module Jira
|
|
9
|
+
module Auto
|
|
10
|
+
class Tool
|
|
11
|
+
RSpec.describe Jira::Auto::Tool::Ticket do
|
|
12
|
+
let(:tool) { instance_double(Tool) }
|
|
13
|
+
|
|
14
|
+
describe "#ticket_fields" do
|
|
15
|
+
context "when JIRA API V2, jira_ticket responds to #fields" do
|
|
16
|
+
let(:jira_ticket_with_fields) do
|
|
17
|
+
jira_resource_double(JIRA::Resource::Issue, fields: { "example_field" => "value" })
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "returns the fields hash" do
|
|
21
|
+
ticket = described_class.new(tool, jira_ticket_with_fields)
|
|
22
|
+
expect(ticket.ticket_fields).to eq({ "example_field" => "value" })
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
context "when JIRA API V3, jira_ticket does not respond to #fields but responds to #attrs" do
|
|
27
|
+
let(:jira_ticket_with_attrs) do
|
|
28
|
+
jira_resource_double(JIRA::Resource::Issue, attrs: { "fields" => { "example_field" => "value" } })
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
let(:jira_ticket_with_invalid_attrs) do
|
|
32
|
+
jira_resource_double(JIRA::Resource::Issue, attrs: { "invalid" => "data" })
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "returns the fields hash from attrs" do
|
|
36
|
+
ticket = described_class.new(tool, jira_ticket_with_attrs)
|
|
37
|
+
expect(ticket.ticket_fields).to eq({ "example_field" => "value" })
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "raises an error if fields are not found in attrs" do
|
|
41
|
+
ticket = described_class.new(tool, jira_ticket_with_invalid_attrs)
|
|
42
|
+
expect do
|
|
43
|
+
ticket.ticket_fields
|
|
44
|
+
end
|
|
45
|
+
.to raise_error("fields not found in {\"invalid\" => \"data\"} from #{jira_ticket_with_invalid_attrs}!")
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
context "when jira_ticket does not respond to #fields or #attrs" do
|
|
50
|
+
let(:jira_ticket_without_fields_or_attrs) { jira_resource_double(JIRA::Resource::Issue) }
|
|
51
|
+
|
|
52
|
+
it "raises an error indicating attrs are not found" do
|
|
53
|
+
ticket = described_class.new(tool, jira_ticket_without_fields_or_attrs)
|
|
54
|
+
expect do
|
|
55
|
+
ticket.ticket_fields
|
|
56
|
+
end.to raise_error("attrs not found in #{jira_ticket_without_fields_or_attrs}!")
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
data/spec/jira/auto/tool_spec.rb
CHANGED
|
@@ -136,7 +136,7 @@ module Jira
|
|
|
136
136
|
end
|
|
137
137
|
|
|
138
138
|
# TODO: move that to environment_based_value_spec
|
|
139
|
-
RSpec.shared_examples "an overridable environment based value" do |method_name|
|
|
139
|
+
RSpec.shared_examples "an overridable environment based value" do |method_name, holds_a_secret_expectation|
|
|
140
140
|
let(:env_var_name) { method_name.to_s.upcase }
|
|
141
141
|
let(:method_name?) { :"#{method_name}_defined?" }
|
|
142
142
|
let(:config) { Config.new(object_with_overridable_value) }
|
|
@@ -146,6 +146,13 @@ module Jira
|
|
|
146
146
|
allow(config).to receive_messages(value_store: {})
|
|
147
147
|
end
|
|
148
148
|
|
|
149
|
+
context "when dealing with sensitive information" do
|
|
150
|
+
it "defines a predicate informing about the value being a secret or not" do
|
|
151
|
+
expect(object_with_overridable_value.send("#{method_name}_holds_a_secret?"))
|
|
152
|
+
.to eq(holds_a_secret_expectation)
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
149
156
|
context "when the environment variable is set" do
|
|
150
157
|
let(:expected_value) { "#{env_var_name} env_value" }
|
|
151
158
|
|
|
@@ -222,11 +229,11 @@ module Jira
|
|
|
222
229
|
end
|
|
223
230
|
end
|
|
224
231
|
|
|
225
|
-
described_class::ENVIRONMENT_BASED_VALUE_SYMBOLS.each do |method_name|
|
|
226
|
-
describe "environment based values" do
|
|
232
|
+
described_class::ENVIRONMENT_BASED_VALUE_SYMBOLS.each do |method_name, holds_a_secret|
|
|
233
|
+
describe "environment based values - #{method_name} - holds_a_secret = #{holds_a_secret}}" do
|
|
227
234
|
let(:object_with_overridable_value) { tool }
|
|
228
235
|
|
|
229
|
-
it_behaves_like "an overridable environment based value", method_name
|
|
236
|
+
it_behaves_like "an overridable environment based value", method_name, holds_a_secret
|
|
230
237
|
end
|
|
231
238
|
end
|
|
232
239
|
|
|
@@ -426,7 +433,7 @@ module Jira
|
|
|
426
433
|
allow(tool)
|
|
427
434
|
.to receive_messages(project: jira_resource_double(JIRA::Resource::Project, key: "project_key"))
|
|
428
435
|
|
|
429
|
-
allow(query).to receive(:jql).with(expected_jql).and_return([instance_double(JIRA::Resource::Issue)])
|
|
436
|
+
allow(query).to receive(:jql).with(expected_jql, fields: ["*all"]).and_return([instance_double(JIRA::Resource::Issue)])
|
|
430
437
|
end
|
|
431
438
|
|
|
432
439
|
context "without arguments" do
|
data/spec/spec_helper.rb
CHANGED
|
@@ -33,9 +33,9 @@ RSpec.configure do |config|
|
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
config.include(Module.new do
|
|
36
|
-
def jira_resource_double(*
|
|
36
|
+
def jira_resource_double(*)
|
|
37
37
|
# rubocop:disable RSpec/VerifiedDoubles
|
|
38
|
-
double(*
|
|
38
|
+
double(*)
|
|
39
39
|
# rubocop:enable RSpec/VerifiedDoubles
|
|
40
40
|
end
|
|
41
41
|
end)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: jira-auto-tool
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Christophe Broult
|
|
@@ -23,6 +23,20 @@ dependencies:
|
|
|
23
23
|
- - ">="
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
25
|
version: '0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: cgi
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0'
|
|
26
40
|
- !ruby/object:Gem::Dependency
|
|
27
41
|
name: http_logger
|
|
28
42
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -209,12 +223,12 @@ email:
|
|
|
209
223
|
- cbroult@yahoo.com
|
|
210
224
|
executables:
|
|
211
225
|
- jira-auto-tool
|
|
212
|
-
- setup
|
|
213
226
|
extensions: []
|
|
214
227
|
extra_rdoc_files: []
|
|
215
228
|
files:
|
|
216
229
|
- ".rspec"
|
|
217
230
|
- ".rubocop.yml"
|
|
231
|
+
- ".ruby-version"
|
|
218
232
|
- CHANGELOG.md
|
|
219
233
|
- CODE_OF_CONDUCT.md
|
|
220
234
|
- Guardfile
|
|
@@ -223,13 +237,12 @@ files:
|
|
|
223
237
|
- Rakefile
|
|
224
238
|
- bin/jira-auto-tool
|
|
225
239
|
- bin/jira-auto-tool.bat
|
|
226
|
-
- bin/setup
|
|
227
|
-
- bin/setup-dev-win.bat
|
|
228
240
|
- config/examples/jira-auto-tool.env.yaml.erb
|
|
229
241
|
- cucumber.yml
|
|
230
242
|
- documentation/JiraToolClassDiagram.uml
|
|
231
243
|
- documentation/class_diagram.md
|
|
232
244
|
- documentation/principle.md
|
|
245
|
+
- ext/no_wrappers_win.rb
|
|
233
246
|
- features/align_sprint_time_in_dates.feature
|
|
234
247
|
- features/assign_tickets_to_team_sprints.feature
|
|
235
248
|
- features/cache_boards.feature
|
|
@@ -359,6 +372,7 @@ files:
|
|
|
359
372
|
- spec/jira/auto/tool/team_spec.rb
|
|
360
373
|
- spec/jira/auto/tool/team_sprint_prefix_mapper_spec.rb
|
|
361
374
|
- spec/jira/auto/tool/team_sprint_ticket_dispatcher_spec.rb
|
|
375
|
+
- spec/jira/auto/tool/ticket_fields_spec.rb
|
|
362
376
|
- spec/jira/auto/tool/ticket_spec.rb
|
|
363
377
|
- spec/jira/auto/tool/until_date_spec.rb
|
|
364
378
|
- spec/jira/auto/tool_spec.rb
|
|
@@ -379,14 +393,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
379
393
|
requirements:
|
|
380
394
|
- - ">="
|
|
381
395
|
- !ruby/object:Gem::Version
|
|
382
|
-
version: 3.
|
|
396
|
+
version: 3.4.8
|
|
383
397
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
384
398
|
requirements:
|
|
385
399
|
- - ">="
|
|
386
400
|
- !ruby/object:Gem::Version
|
|
387
401
|
version: '0'
|
|
388
402
|
requirements: []
|
|
389
|
-
rubygems_version:
|
|
403
|
+
rubygems_version: 4.0.3
|
|
390
404
|
specification_version: 4
|
|
391
405
|
summary: Automate making adjustments to Jira sprints for multiple teams following
|
|
392
406
|
some naming conventions.
|
data/bin/setup
DELETED
data/bin/setup-dev-win.bat
DELETED