jira-auto-tool 1.2.0 → 1.2.1
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/README.md +47 -9
- data/ext/no_wrappers_win.rb +6 -0
- data/features/configure_environment.feature +48 -8
- 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/version.rb +1 -1
- data/lib/jira/auto/tool.rb +23 -21
- 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_spec.rb +13 -4
- metadata +2 -4
- 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: a991321a0f8768d42b913499a80fd76ff32cbea71f243e651c0097a6e9c1f10a
|
4
|
+
data.tar.gz: 346c3e37814218b13f5b3cb57d74b0431655b9dbca95edf3406f7b1d036252b8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c66c77d800f993de4821e03711585976c1cb021258add0d2ee5cb940d7fa92915d66d1b8754a2a4f245d768bbf19b7e71d791673ac9d30b0cf6bff23bcaadfc8
|
7
|
+
data.tar.gz: 8e3c54c724e47e4267a3ed4c65d23ff723a5c67764fdce38a05aae3ffdbc6a10d35691c4618fabc2b429a8f26af09e3303ac1004ffa0cc6ce94b1f0999b65b4c
|
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:
|
209
|
+
This is meant to fail while loading!
|
210
|
+
"""
|
211
|
+
|
@@ -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
|
data/lib/jira/auto/tool.rb
CHANGED
@@ -139,27 +139,29 @@ 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
|
+
holds_a_secret ||= false
|
164
|
+
define_overridable_environment_based_value(method_name, holds_a_secret)
|
163
165
|
end
|
164
166
|
|
165
167
|
def board_controller
|
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
|
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,13 @@ module Jira
|
|
222
229
|
end
|
223
230
|
end
|
224
231
|
|
225
|
-
described_class::ENVIRONMENT_BASED_VALUE_SYMBOLS.each do |method_name|
|
226
|
-
|
232
|
+
described_class::ENVIRONMENT_BASED_VALUE_SYMBOLS.each do |method_name, holds_a_secret|
|
233
|
+
holds_a_secret ||= false
|
234
|
+
|
235
|
+
describe "environment based values - #{method_name} - holds_a_secret = #{holds_a_secret}}" do
|
227
236
|
let(:object_with_overridable_value) { tool }
|
228
237
|
|
229
|
-
it_behaves_like "an overridable environment based value", method_name
|
238
|
+
it_behaves_like "an overridable environment based value", method_name, holds_a_secret
|
230
239
|
end
|
231
240
|
end
|
232
241
|
|
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.2.
|
4
|
+
version: 1.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christophe Broult
|
@@ -209,7 +209,6 @@ email:
|
|
209
209
|
- cbroult@yahoo.com
|
210
210
|
executables:
|
211
211
|
- jira-auto-tool
|
212
|
-
- setup
|
213
212
|
extensions: []
|
214
213
|
extra_rdoc_files: []
|
215
214
|
files:
|
@@ -223,13 +222,12 @@ files:
|
|
223
222
|
- Rakefile
|
224
223
|
- bin/jira-auto-tool
|
225
224
|
- bin/jira-auto-tool.bat
|
226
|
-
- bin/setup
|
227
|
-
- bin/setup-dev-win.bat
|
228
225
|
- config/examples/jira-auto-tool.env.yaml.erb
|
229
226
|
- cucumber.yml
|
230
227
|
- documentation/JiraToolClassDiagram.uml
|
231
228
|
- documentation/class_diagram.md
|
232
229
|
- documentation/principle.md
|
230
|
+
- ext/no_wrappers_win.rb
|
233
231
|
- features/align_sprint_time_in_dates.feature
|
234
232
|
- features/assign_tickets_to_team_sprints.feature
|
235
233
|
- features/cache_boards.feature
|
data/bin/setup
DELETED
data/bin/setup-dev-win.bat
DELETED