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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f848715468127f8c2d342bdd77fd68f78b2e9684c67d506c0761e6982ce325d2
4
- data.tar.gz: 3c578b782fce257b587e09c0261fe60c8fcb59293b6419e097b8f9fdd52e1bd4
3
+ metadata.gz: a991321a0f8768d42b913499a80fd76ff32cbea71f243e651c0097a6e9c1f10a
4
+ data.tar.gz: 346c3e37814218b13f5b3cb57d74b0431655b9dbca95edf3406f7b1d036252b8
5
5
  SHA512:
6
- metadata.gz: 98c0d515b13ecf5f7f145eec5729435c7378d7325dae29bd250822461badcd47081a58ace1450b51c5b68eeb59d3552ff3905ae968c3e41fdc082c7af3141f37
7
- data.tar.gz: 94871345d52b7809ad2267bf12f0d62114d0d10b1032fc93856a2fd78fef6c5c6308951fa6804e073ea3a0df046d81f3c648a6caadcacaac091ec1a98babe2b9
6
+ metadata.gz: c66c77d800f993de4821e03711585976c1cb021258add0d2ee5cb940d7fa92915d66d1b8754a2a4f245d768bbf19b7e71d791673ac9d30b0cf6bff23bcaadfc8
7
+ data.tar.gz: 8e3c54c724e47e4267a3ed4c65d23ff723a5c67764fdce38a05aae3ffdbc6a10d35691c4618fabc2b429a8f26af09e3303ac1004ffa0cc6ce94b1f0999b65b4c
data/README.md CHANGED
@@ -4,15 +4,33 @@
4
4
  ![Main Workflow - all branches](https://github.com/cbroult/jira-auto-tool/actions/workflows/main.yml/badge.svg?label=Ruby%20-%20all%20branches)
5
5
 
6
6
  ****
7
- The purpose of this tool it support managing the sprints of multiple teams so it is easier to adjust to changes.
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
- <!-- Generated using jekyll-toc -->
13
-
14
- * TOC
15
- {:toc}
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 te `JIRA_API_TOKEN` that should
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
- To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
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
 
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Disable wrappers only on Windows
4
+ puts "Disabling wrappers for Windows installation"
5
+ RubyGems.configuration.wrappers = false
6
+ exit 0
@@ -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 | current 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+|token-value\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
- And the board only has the following sprints:
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, ENV.fetch(constant_as_string, nil)]
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
- last_sprint = create_sprint_for(last_sprint, parsed_new_name.to_s)
25
-
26
- sprint_prefix << last_sprint
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
@@ -3,7 +3,7 @@
3
3
  module Jira
4
4
  module Auto
5
5
  class Tool
6
- VERSION = "1.2.0"
6
+ VERSION = "1.2.1"
7
7
  end
8
8
  end
9
9
  end
@@ -139,27 +139,29 @@ module Jira
139
139
  jira_base_url + url
140
140
  end
141
141
 
142
- ENVIRONMENT_BASED_VALUE_SYMBOLS = %i[
143
- art_sprint_regex
144
- expected_start_date_field_name
145
- implementation_team_field_name
146
- jat_rate_interval_in_seconds
147
- jat_rate_limit_implementation
148
- jat_rate_limit_per_interval
149
- jat_tickets_for_team_sprint_ticket_dispatcher_jql
150
- jira_api_token
151
- jira_board_name
152
- jira_board_name_regex
153
- jira_context_path
154
- jira_http_debug
155
- jira_project_key
156
- jira_site_url
157
- jira_sprint_field_name
158
- jira_username
159
- ].freeze
160
-
161
- ENVIRONMENT_BASED_VALUE_SYMBOLS.each do |method_name|
162
- define_overridable_environment_based_value(method_name)
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
@@ -29,7 +29,7 @@ end
29
29
  def amend_commit_to_include_gemfile_lock_changes
30
30
  puts "Amending commit to include Gemfile.lock update..."
31
31
  system("git add .")
32
- system(%(git commit --amend --no-edit))
32
+ system("git commit --amend --no-edit")
33
33
  end
34
34
 
35
35
  namespace :version do
@@ -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[JIRA_HOST JIRA_USER JIRA_PASSWORD] }
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).to eq(
71
- "JIRA_HOST" => "JIRA_HOST value",
72
- "JIRA_USER" => "JIRA_USER value",
73
- "JIRA_PASSWORD" => "JIRA_PASSWORD value"
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
- it "sets up the value according to the configuration file content" do
136
- allow(environment_loader).to receive_messages(file_path: "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) { "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(:last_sprint) { get_sprint "Food_Delivery_25.2.1", end_date: "2025-02-16 12:45", length_in_days: 10 }
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
- let(:sprint_prefix) { instance_double(Sprint::Prefix, name: "Food_Delivery", last_sprint: last_sprint) }
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
- # rubocop:disable RSpec/MultipleExpectations
46
- it "creates the expected number of sprints with the expected names" do
47
- expect(updater).to receive(:create_sprint_for).ordered.with(last_sprint, "Food_Delivery_25.3.1")
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
- updater.act_on_sprints_for_sprint_prefix(sprint_prefix)
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
@@ -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
- describe "environment based values" do
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.0
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
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
- set -vx
5
-
6
- bundle install
7
-
8
- # Do any other automated setup that you need to do here
@@ -1,3 +0,0 @@
1
-
2
-
3
- choco install act-cli