jira-auto-tool 0.1.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +17 -7
- data/bin/jira-auto-tool +2 -0
- data/config/examples/jira-auto-tool.env.yaml.erb +28 -0
- data/documentation/JiraToolClassDiagram.uml +44 -0
- data/documentation/class_diagram.md +48 -0
- data/documentation/principle.md +6 -0
- data/features/configure_environment.feature +166 -0
- data/lib/jira/auto/tool/config/options.rb +4 -3
- data/lib/jira/auto/tool/config.rb +6 -2
- data/lib/jira/auto/tool/environment_loader/options.rb +21 -0
- data/lib/jira/auto/tool/environment_loader.rb +115 -0
- data/lib/jira/auto/tool/helpers/environment_based_value.rb +3 -3
- data/lib/jira/auto/tool/version.rb +1 -1
- data/lib/jira/auto/tool.rb +14 -0
- data/spec/jira/auto/tool/common_options_spec.rb +4 -1
- data/spec/jira/auto/tool/environment_loader_spec.rb +180 -0
- data/spec/jira/auto/tool_spec.rb +23 -9
- metadata +9 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 17df99358f86abaa36bf5e36882881e34df34de901441daf121e98b86fbd4ea2
|
4
|
+
data.tar.gz: 9fb2d8b44488861db052fdabab616260ca0b276dfd1f595a39ccff8822a83b0b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7d65dab75a5828d2d2ecc2c533aca864abb0a4f541f662ab4740fcda352805e80482bd6c8aefefc5bd13290a1b2365072732f5813b6365e9928d373ca7f300a7
|
7
|
+
data.tar.gz: a62f5ad58f3cb57756c5c1e9589665553eb802cfa1e8af60629cf27aea3451a0129e4b7a1b808ce28b2db98eb2d5d3da1d44ac8fadb81b49dcabbe176777299b
|
data/README.md
CHANGED
@@ -24,21 +24,30 @@ in such a cloud sandbox. Though, if the sandbox belongs to the target context
|
|
24
24
|
* ... and add to the application's Gemfile by executing:
|
25
25
|
|
26
26
|
```bash
|
27
|
-
bundle add
|
27
|
+
bundle add jira-auto-tool
|
28
28
|
```
|
29
29
|
|
30
30
|
* ... if bundler is not being used to manage dependencies, by executing:
|
31
31
|
|
32
32
|
```bash
|
33
|
-
gem install
|
33
|
+
gem install jira-auto-tool
|
34
34
|
```
|
35
35
|
|
36
36
|
## Setup
|
37
37
|
|
38
|
+
1. Create an example configuration file
|
39
|
+
```bash
|
40
|
+
jira-auto-tool --env-setup
|
41
|
+
```
|
42
|
+
2. Adjust the file to your context.
|
43
|
+
|
44
|
+
**WARNING** - It is highly recommended that the JIRA_API_TOKEN value is set as an environment variable
|
45
|
+
and **NOT** in the generated file.
|
46
|
+
|
38
47
|
While we strive to use convention over configuration as a principle, the following environment variables have to be set
|
39
48
|
in order to use this tool:
|
40
49
|
|
41
|
-
|
50
|
+
Some explanations:
|
42
51
|
|
43
52
|
- `JIRA_USERNAME` - Your Jira account username (e.g., "user@company.com").
|
44
53
|
- `JIRA_API_TOKEN` - Your Jira API authentication token.
|
@@ -63,19 +72,20 @@ See [sprint filtering](./features/sprint_filtering.feature).
|
|
63
72
|
|
64
73
|
## Usage
|
65
74
|
|
66
|
-
* Leverage the [specification by examples](./features)
|
67
75
|
* Use the tool integrated help:
|
68
76
|
```bash
|
69
77
|
jira-auto-tool --help
|
70
78
|
```
|
71
|
-
*
|
79
|
+
* Leverage the [specification by examples](./features) for a detailled understand of the features.
|
80
|
+
* Note that usually the long option names have a short version equivalent to reduce typing.
|
72
81
|
|
73
82
|
Below are a few examples.
|
74
83
|
|
75
84
|
### Add Sprints
|
76
85
|
|
77
|
-
The following is going to
|
78
|
-
|
86
|
+
The following is going to [add sprints](./features/create_sprints_using_existing_ones_as_reference.feature)
|
87
|
+
`sprint_prefix_25.4.3` until `sprint_prefix_25.4.6`
|
88
|
+
to the teams respective sprint prefixes.
|
79
89
|
```bash
|
80
90
|
jira-auto-tool --sprint-add=25.4.3,4
|
81
91
|
```
|
data/bin/jira-auto-tool
CHANGED
@@ -20,6 +20,7 @@ require "jira/auto/tool"
|
|
20
20
|
require "jira/auto/tool/board_controller/options"
|
21
21
|
require "jira/auto/tool/common_options"
|
22
22
|
require "jira/auto/tool/config/options"
|
23
|
+
require "jira/auto/tool/environment_loader/options"
|
23
24
|
require "jira/auto/tool/jira_http_options"
|
24
25
|
require "jira/auto/tool/performer/options"
|
25
26
|
require "jira/auto/tool/project/options"
|
@@ -36,6 +37,7 @@ option_parser = OptionParser.new do |parser|
|
|
36
37
|
Jira::Auto::Tool::JiraHttpOptions.add(tool, parser)
|
37
38
|
Jira::Auto::Tool::BoardController::Options.add(tool, parser)
|
38
39
|
Jira::Auto::Tool::Config::Options.add(tool, parser)
|
40
|
+
Jira::Auto::Tool::EnvironmentLoader::Options.add(tool, parser)
|
39
41
|
Jira::Auto::Tool::Project::Options.add(tool, parser)
|
40
42
|
Jira::Auto::Tool::Performer::Options.add(tool, parser)
|
41
43
|
Jira::Auto::Tool::SprintController::Options.add(tool, parser)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
---
|
2
|
+
<%
|
3
|
+
project_key = "PROJ"
|
4
|
+
sprint_field_name = "Sprint"
|
5
|
+
jira_username = "cbroult@yahoo.com"
|
6
|
+
%>
|
7
|
+
##JIRA_API_TOKEN: WARNING - it is recommended to set the value directly as an environment variable
|
8
|
+
ART_SPRINT_REGEX:
|
9
|
+
DISABLE_COVERAGE: true
|
10
|
+
EXPECTED_START_DATE_FIELD_NAME: Expected Start
|
11
|
+
IMPLEMENTATION_TEAM_FIELD_NAME: "Implementation Team"
|
12
|
+
JAT_RATE_INTERVAL_IN_SECONDS:
|
13
|
+
JAT_RATE_LIMIT_IN_SECONDS:
|
14
|
+
JAT_TICKETS_FOR_TEAM_SPRINT_TICKET_DISPATCHER_JQL: "project = <%= project_key %> AND <%= sprint_field_name %> IS EMPTY"
|
15
|
+
JIRA_BOARD_NAME: "<%= project_key %> - Your board name"
|
16
|
+
JIRA_BOARD_NAME_REGEX: "<%= project_key %>|ART 16|unconventional board name"
|
17
|
+
JIRA_CONTEXT_PATH: /jira
|
18
|
+
JIRA_HTTP_DEBUG:
|
19
|
+
JIRA_PROJECT_KEY: <%= project_key %>
|
20
|
+
JIRA_SITE_URL: http://cbroult.atlassian.net:443/
|
21
|
+
JIRA_SPRINT_FIELD_NAME: "<%= sprint_field_name %>"
|
22
|
+
JIRA_USERNAME: <%= jira_username %>
|
23
|
+
|
24
|
+
<%
|
25
|
+
message = "TODO: set the values specific to your context and remove this part of the file"
|
26
|
+
log.error { message }
|
27
|
+
raise message
|
28
|
+
%>
|
@@ -0,0 +1,44 @@
|
|
1
|
+
classDiagram
|
2
|
+
class Tool {
|
3
|
+
}
|
4
|
+
|
5
|
+
class BoardController {
|
6
|
+
}
|
7
|
+
|
8
|
+
class SprintController {
|
9
|
+
}
|
10
|
+
|
11
|
+
class BoardOptions {
|
12
|
+
+add(tool, parser)$
|
13
|
+
}
|
14
|
+
|
15
|
+
class SprintOptions {
|
16
|
+
+add(tool, parser)$
|
17
|
+
+add_sprint_adding_options(parser, tool)$
|
18
|
+
+add_sprint_listing_options(parser, tool)$
|
19
|
+
+add_sprint_prefix_listing_options(parser, tool)$
|
20
|
+
}
|
21
|
+
|
22
|
+
class UntilDate {
|
23
|
+
}
|
24
|
+
|
25
|
+
class Cache {
|
26
|
+
}
|
27
|
+
|
28
|
+
Tool --> BoardController : has
|
29
|
+
Tool --> SprintController : has
|
30
|
+
BoardController --> BoardOptions : uses
|
31
|
+
SprintController --> SprintOptions : uses
|
32
|
+
BoardController --> Cache : uses
|
33
|
+
SprintOptions --> UntilDate : uses
|
34
|
+
|
35
|
+
%% Namespace structure
|
36
|
+
namespace Jira {
|
37
|
+
namespace Auto {
|
38
|
+
Tool
|
39
|
+
namespace Tool {
|
40
|
+
BoardController
|
41
|
+
SprintController
|
42
|
+
}
|
43
|
+
}
|
44
|
+
}
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# Overall Class Diagram Structure
|
2
|
+
|
3
|
+
```mermaid
|
4
|
+
classDiagram
|
5
|
+
class Tool {
|
6
|
+
}
|
7
|
+
|
8
|
+
class BoardController {
|
9
|
+
}
|
10
|
+
|
11
|
+
class SprintController {
|
12
|
+
}
|
13
|
+
|
14
|
+
class BoardOptions {
|
15
|
+
+add(tool, parser)$
|
16
|
+
}
|
17
|
+
|
18
|
+
class SprintOptions {
|
19
|
+
+add(tool, parser)$
|
20
|
+
+add_sprint_adding_options(parser, tool)$
|
21
|
+
+add_sprint_listing_options(parser, tool)$
|
22
|
+
+add_sprint_prefix_listing_options(parser, tool)$
|
23
|
+
}
|
24
|
+
|
25
|
+
class UntilDate {
|
26
|
+
}
|
27
|
+
|
28
|
+
class Cache {
|
29
|
+
}
|
30
|
+
|
31
|
+
Tool --> BoardController : has
|
32
|
+
Tool --> SprintController : has
|
33
|
+
BoardController --> BoardOptions : uses
|
34
|
+
SprintController --> SprintOptions : uses
|
35
|
+
BoardController --> Cache : uses
|
36
|
+
SprintOptions --> UntilDate : uses
|
37
|
+
|
38
|
+
%% Namespace structure
|
39
|
+
namespace Jira {
|
40
|
+
namespace Auto {
|
41
|
+
Tool
|
42
|
+
namespace Tool {
|
43
|
+
BoardController
|
44
|
+
SprintController
|
45
|
+
}
|
46
|
+
}
|
47
|
+
}
|
48
|
+
```
|
@@ -0,0 +1,166 @@
|
|
1
|
+
@wip
|
2
|
+
Feature: Environment Configuration Management
|
3
|
+
In order to avoid setting environment variables manually
|
4
|
+
As a user of jira-auto-tool
|
5
|
+
I want to be able to configure the tool using a configuration file
|
6
|
+
|
7
|
+
Scenario: Creating the environment configuration file
|
8
|
+
Given a file named "~/.config/jira-auto-tool/jira-auto-tool.env.yaml.erb" does not exist
|
9
|
+
When I successfully run `jira-auto-tool --env-create-file`
|
10
|
+
Then the output should match:
|
11
|
+
"""
|
12
|
+
\s+INFO\s+Jira::Auto::Tool::EnvironmentLoader\s+:\s+Created\s+file\s.+/.config/jira-auto-tool/jira-auto-tool.env.yaml.erb
|
13
|
+
_______________________________________________
|
14
|
+
TODO: Adjust the configuration to your context!
|
15
|
+
"""
|
16
|
+
And a file named "~/.config/jira-auto-tool/jira-auto-tool.env.yaml.erb" should contain exactly:
|
17
|
+
"""
|
18
|
+
---
|
19
|
+
<%
|
20
|
+
project_key = "PROJ"
|
21
|
+
sprint_field_name = "Sprint"
|
22
|
+
jira_username = "cbroult@yahoo.com"
|
23
|
+
%>
|
24
|
+
##JIRA_API_TOKEN: WARNING - it is recommended to set the value directly as an environment variable
|
25
|
+
ART_SPRINT_REGEX:
|
26
|
+
DISABLE_COVERAGE: true
|
27
|
+
EXPECTED_START_DATE_FIELD_NAME: Expected Start
|
28
|
+
IMPLEMENTATION_TEAM_FIELD_NAME: "Implementation Team"
|
29
|
+
JAT_RATE_INTERVAL_IN_SECONDS:
|
30
|
+
JAT_RATE_LIMIT_IN_SECONDS:
|
31
|
+
JAT_TICKETS_FOR_TEAM_SPRINT_TICKET_DISPATCHER_JQL: "project = <%= project_key %> AND <%= sprint_field_name %> IS EMPTY"
|
32
|
+
JIRA_BOARD_NAME: "<%= project_key %> - Your board name"
|
33
|
+
JIRA_BOARD_NAME_REGEX: "<%= project_key %>|ART 16|unconventional board name"
|
34
|
+
JIRA_CONTEXT_PATH: /jira
|
35
|
+
JIRA_HTTP_DEBUG:
|
36
|
+
JIRA_PROJECT_KEY: <%= project_key %>
|
37
|
+
JIRA_SITE_URL: http://cbroult.atlassian.net:443/
|
38
|
+
JIRA_SPRINT_FIELD_NAME: "<%= sprint_field_name %>"
|
39
|
+
JIRA_USERNAME: <%= jira_username %>
|
40
|
+
|
41
|
+
<%
|
42
|
+
message = "TODO: set the values specific to your context and remove this part of the file"
|
43
|
+
log.error { message }
|
44
|
+
raise message
|
45
|
+
%>
|
46
|
+
"""
|
47
|
+
|
48
|
+
|
49
|
+
Scenario: Not overriding an existing environment configuration file
|
50
|
+
Given a file named "~/.config/jira-auto-tool/jira-auto-tool.env.yaml.erb" with:
|
51
|
+
"""
|
52
|
+
---
|
53
|
+
JIRA_TOKEN: 'a dummy token'
|
54
|
+
"""
|
55
|
+
When I run `jira-auto-tool --env-create-file`
|
56
|
+
Then it should fail matching:
|
57
|
+
"""
|
58
|
+
ERROR\s+Jira::Auto::Tool::EnvironmentLoader\s+:\s+Not\s+overriding\s+existing\s+.+/.config/jira-auto-tool/jira-auto-tool.env.yaml.erb
|
59
|
+
______________________________________________
|
60
|
+
Please remove first before running this again!
|
61
|
+
"""
|
62
|
+
|
63
|
+
Scenario: Tool successfully loads the config
|
64
|
+
Given a file named "jira-auto-tool.env.yaml.erb" with:
|
65
|
+
"""
|
66
|
+
---
|
67
|
+
<%
|
68
|
+
jira_username = "user@jira.instance.com"
|
69
|
+
project_key = 'PROJ'
|
70
|
+
sprint_field_name = 'Sprint'
|
71
|
+
%>
|
72
|
+
|
73
|
+
ART_SPRINT_REGEX:
|
74
|
+
EXPECTED_START_DATE_FIELD_NAME: Expected Start
|
75
|
+
IMPLEMENTATION_TEAM_FIELD_NAME: "Implementation Team"
|
76
|
+
JAT_RATE_INTERVAL_IN_SECONDS:
|
77
|
+
JAT_RATE_LIMIT_IN_SECONDS:
|
78
|
+
JAT_TICKETS_FOR_TEAM_SPRINT_TICKET_DISPATCHER_JQL: "project = <%= project_key %> AND <%= sprint_field_name %> IS EMPTY"
|
79
|
+
JIRA_API_TOKEN: "current API TOKEN"
|
80
|
+
JIRA_BOARD_NAME: "Team Board"
|
81
|
+
JIRA_BOARD_NAME_REGEX: "ART 16|unconventional board name"
|
82
|
+
JIRA_CONTEXT_PATH: /jira
|
83
|
+
JIRA_HTTP_DEBUG:
|
84
|
+
JIRA_PROJECT_KEY: <%= project_key %>
|
85
|
+
JIRA_SITE_URL: "<%= 'https://example.atlassian.net' %>"
|
86
|
+
JIRA_SPRINT_FIELD_NAME: "<%= sprint_field_name %>"
|
87
|
+
JIRA_USERNAME: "<%= jira_username %>"
|
88
|
+
"""
|
89
|
+
When I successfully run `jira-auto-tool --env-list`
|
90
|
+
Then the output should contain exactly:
|
91
|
+
"""
|
92
|
+
Using configuration from ./jira-auto-tool.env.yaml.erb
|
93
|
+
+---------------------------------------------------+------------------------------------+
|
94
|
+
| Name | Value |
|
95
|
+
+---------------------------------------------------+------------------------------------+
|
96
|
+
| ART_SPRINT_REGEX | |
|
97
|
+
| EXPECTED_START_DATE_FIELD_NAME | Expected Start |
|
98
|
+
| IMPLEMENTATION_TEAM_FIELD_NAME | Implementation Team |
|
99
|
+
| JAT_RATE_INTERVAL_IN_SECONDS | |
|
100
|
+
| JAT_RATE_LIMIT_IN_SECONDS | |
|
101
|
+
| JAT_TICKETS_FOR_TEAM_SPRINT_TICKET_DISPATCHER_JQL | project = PROJ AND Sprint IS EMPTY |
|
102
|
+
| JIRA_API_TOKEN | current API TOKEN |
|
103
|
+
| JIRA_BOARD_NAME | Team Board |
|
104
|
+
| JIRA_BOARD_NAME_REGEX | ART 16|unconventional board name |
|
105
|
+
| JIRA_CONTEXT_PATH | /jira |
|
106
|
+
| JIRA_HTTP_DEBUG | |
|
107
|
+
| JIRA_PROJECT_KEY | PROJ |
|
108
|
+
| JIRA_SITE_URL | https://example.atlassian.net |
|
109
|
+
| JIRA_SPRINT_FIELD_NAME | Sprint |
|
110
|
+
| JIRA_USERNAME | user@jira.instance.com |
|
111
|
+
+---------------------------------------------------+------------------------------------+
|
112
|
+
"""
|
113
|
+
|
114
|
+
Scenario: Tool looks first for configuration in the current directory
|
115
|
+
Given a file named "./jira-auto-tool.env.yaml.erb" with:
|
116
|
+
"""
|
117
|
+
---
|
118
|
+
JIRA_USERNAME: "current@company.com"
|
119
|
+
JIRA_API_TOKEN: "current-token"
|
120
|
+
JIRA_SITE_URL: "https://current.atlassian.net"
|
121
|
+
"""
|
122
|
+
And a file named "~/.config/jira-auto-tool/jira-auto-tool.env.yaml.erb" with:
|
123
|
+
"""
|
124
|
+
---
|
125
|
+
JIRA_USERNAME: "home@company.com"
|
126
|
+
JIRA_API_TOKEN: "home-token"
|
127
|
+
JIRA_SITE_URL: "https://home.atlassian.net"
|
128
|
+
"""
|
129
|
+
When I successfully run `jira-auto-tool --env-list`
|
130
|
+
Then the output should contain:
|
131
|
+
"""
|
132
|
+
Using configuration from ./jira-auto-tool.env.yaml.erb
|
133
|
+
"""
|
134
|
+
|
135
|
+
Scenario: Tool looks for home directory config folder when no config file in the current directory
|
136
|
+
Given a file named "./jira-auto-tool.env.yaml.erb" does not exist
|
137
|
+
And a file named "~/.config/jira-auto-tool/jira-auto-tool.env.yaml.erb" with:
|
138
|
+
"""
|
139
|
+
JIRA_USERNAME: "home@company.com"
|
140
|
+
JIRA_API_TOKEN: "home-token"
|
141
|
+
JIRA_SITE_URL: "https://home.atlassian.net"
|
142
|
+
"""
|
143
|
+
When I successfully run `jira-auto-tool --env-list`
|
144
|
+
Then the output should match:
|
145
|
+
"""
|
146
|
+
Using configuration from .+/.config/jira-auto-tool/jira-auto-tool.env.yaml.erb
|
147
|
+
"""
|
148
|
+
|
149
|
+
Scenario: Tool uses the existing environment values if no config file found
|
150
|
+
Given the following files should not exist:
|
151
|
+
| ./jira-auto-tool.env.yaml.erb |
|
152
|
+
| ~/.config/jira-auto-tool/jira-auto-tool.env.yaml.erb |
|
153
|
+
And the following environment variables are set:
|
154
|
+
| name | value |
|
155
|
+
| JIRA_API_TOKEN | token-value |
|
156
|
+
When I successfully run `jira-auto-tool --env-list`
|
157
|
+
Then the output should match:
|
158
|
+
"""
|
159
|
+
Only using the environment variables since neither of the following files exist:
|
160
|
+
./jira-auto-tool.env.yaml.erb
|
161
|
+
.+/.config/jira-auto-tool/jira-auto-tool.env.yaml.erb
|
162
|
+
"""
|
163
|
+
And the output should match:
|
164
|
+
"""
|
165
|
+
JIRA_API_TOKEN\s+|token-value\s+
|
166
|
+
"""
|
@@ -5,11 +5,12 @@ module Jira
|
|
5
5
|
class Tool
|
6
6
|
class Config
|
7
7
|
class Options
|
8
|
-
def self.add(_tool,
|
8
|
+
def self.add(_tool, _parser)
|
9
9
|
# parser.section_header "Config"
|
10
|
-
|
10
|
+
|
11
11
|
# parser.on("--config-list") do
|
12
|
-
#
|
12
|
+
# Config.list
|
13
|
+
# TODO: tool.config.list
|
13
14
|
# end
|
14
15
|
end
|
15
16
|
end
|
@@ -32,15 +32,19 @@ module Jira
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def path
|
35
|
-
File.join(dir, "
|
35
|
+
File.join(dir, "#{tool_name}.config.yml")
|
36
36
|
end
|
37
37
|
|
38
38
|
def dir
|
39
|
-
config_dir = File.join(Dir.home, ".config
|
39
|
+
config_dir = File.join(Dir.home, ".config/#{tool_name}")
|
40
40
|
FileUtils.makedirs(config_dir)
|
41
41
|
config_dir
|
42
42
|
end
|
43
43
|
|
44
|
+
def tool_name
|
45
|
+
"jira-auto-tool"
|
46
|
+
end
|
47
|
+
|
44
48
|
private
|
45
49
|
|
46
50
|
def sanitize_key(key)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jira
|
4
|
+
module Auto
|
5
|
+
class Tool
|
6
|
+
class EnvironmentLoader
|
7
|
+
module Options
|
8
|
+
def self.add(tool, parser)
|
9
|
+
parser.section_header "Environment"
|
10
|
+
|
11
|
+
parser.on("--env-list", "List the environment_loader variables used by the tool") do
|
12
|
+
tool.environment.list
|
13
|
+
end
|
14
|
+
|
15
|
+
parser.on("--env-create-file", "Create the environment configuration file") { tool.environment.create_file }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Jira
|
4
|
+
module Auto
|
5
|
+
class Tool
|
6
|
+
class EnvironmentLoader
|
7
|
+
attr_reader :tool
|
8
|
+
|
9
|
+
def initialize(tool, auto_setup: true)
|
10
|
+
@tool = tool
|
11
|
+
|
12
|
+
setup if auto_setup
|
13
|
+
end
|
14
|
+
|
15
|
+
def create_file
|
16
|
+
if File.exist?(file_path)
|
17
|
+
log.error do
|
18
|
+
<<~EOERRORMESSAGE
|
19
|
+
Not overriding existing #{file_path}
|
20
|
+
______________________________________________
|
21
|
+
Please remove first before running this again!
|
22
|
+
EOERRORMESSAGE
|
23
|
+
end
|
24
|
+
|
25
|
+
Kernel.exit 1
|
26
|
+
else
|
27
|
+
FileUtils.cp(example_file_path, file_path)
|
28
|
+
|
29
|
+
log.info do
|
30
|
+
<<~EOMESSAGE
|
31
|
+
Created file #{file_path}
|
32
|
+
_______________________________________________
|
33
|
+
TODO: Adjust the configuration to your context!
|
34
|
+
EOMESSAGE
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def list
|
40
|
+
$stdout.puts <<~EOLIST
|
41
|
+
#{configuration_source_string}
|
42
|
+
#{table}
|
43
|
+
EOLIST
|
44
|
+
end
|
45
|
+
|
46
|
+
def tool_environment
|
47
|
+
Environment.constants.sort.to_h do |constant|
|
48
|
+
constant_as_string = constant.to_s
|
49
|
+
|
50
|
+
[constant_as_string, ENV.fetch(constant_as_string, nil)]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def file_path
|
55
|
+
File.exist?(current_dir_file_path) ? current_dir_file_path : config_dir_file_path
|
56
|
+
end
|
57
|
+
|
58
|
+
def example_file_path
|
59
|
+
File.join(tool.home_dir, "config/examples", file_basename)
|
60
|
+
end
|
61
|
+
|
62
|
+
CURRENT_DIR = "."
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def setup
|
67
|
+
config_values.each { |key, value| ENV[key] = value }
|
68
|
+
end
|
69
|
+
|
70
|
+
def configuration_source_string
|
71
|
+
if File.exist?(file_path)
|
72
|
+
"Using configuration from #{file_path}"
|
73
|
+
else
|
74
|
+
<<~EOENV_ONLY
|
75
|
+
Only using the environment variables since neither of the following files exist:
|
76
|
+
#{current_dir_file_path}
|
77
|
+
#{config_dir_file_path}
|
78
|
+
EOENV_ONLY
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def config_values
|
83
|
+
@config_values ||= YAML.safe_load(config_file_content) || {}
|
84
|
+
end
|
85
|
+
|
86
|
+
def config_file_content
|
87
|
+
@config_file_content ||= File.exist?(file_path) ? ERB.new(File.read(file_path)).result(binding) : ""
|
88
|
+
end
|
89
|
+
|
90
|
+
def table
|
91
|
+
Terminal::Table.new do |t|
|
92
|
+
t.headings = %w[Name Value]
|
93
|
+
t.rows = tool_environment.to_a
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def config
|
98
|
+
tool.config
|
99
|
+
end
|
100
|
+
|
101
|
+
def config_dir_file_path
|
102
|
+
File.join(config.dir, file_basename)
|
103
|
+
end
|
104
|
+
|
105
|
+
def current_dir_file_path
|
106
|
+
File.join(CURRENT_DIR, file_basename)
|
107
|
+
end
|
108
|
+
|
109
|
+
def file_basename
|
110
|
+
"#{config.tool_name}.env.yaml.erb"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -55,10 +55,10 @@ module Jira
|
|
55
55
|
constant_name = method_name.to_s.upcase
|
56
56
|
class_eval <<-EOCONSTANT, __FILE__, __LINE__ + 1
|
57
57
|
# This module and constant will be interpolated as follows:
|
58
|
-
#
|
58
|
+
# class Environment
|
59
59
|
# CONSTANT_NAME = "CONSTANT_NAME"
|
60
60
|
# end
|
61
|
-
|
61
|
+
class Environment
|
62
62
|
#{constant_name} = #{constant_name.inspect}
|
63
63
|
end
|
64
64
|
EOCONSTANT
|
@@ -70,7 +70,7 @@ module Jira
|
|
70
70
|
environment_variable_name = caller_method_name.upcase
|
71
71
|
|
72
72
|
value = ENV.fetch(environment_variable_name) do |name|
|
73
|
-
raise KeyError, "Missing #{name}
|
73
|
+
raise KeyError, "Missing #{name} environment_loader variable!"
|
74
74
|
end
|
75
75
|
|
76
76
|
log.debug { "fetch_corresponding_environment_variable(#{environment_variable_name}) - #{value.inspect}" }
|
data/lib/jira/auto/tool.rb
CHANGED
@@ -8,6 +8,7 @@ require "jira-ruby"
|
|
8
8
|
|
9
9
|
require_relative "tool/config"
|
10
10
|
require_relative "tool/board_controller"
|
11
|
+
require_relative "tool/environment_loader"
|
11
12
|
require_relative "tool/helpers/environment_based_value"
|
12
13
|
require_relative "tool/project"
|
13
14
|
require_relative "tool/rate_limited_jira_client"
|
@@ -23,15 +24,26 @@ require_relative "tool/version"
|
|
23
24
|
|
24
25
|
module Jira
|
25
26
|
module Auto
|
27
|
+
# rubocop:disable Metrics/ClassLength
|
26
28
|
class Tool
|
27
29
|
extend Helpers::EnvironmentBasedValue
|
28
30
|
|
29
31
|
class Error < StandardError; end
|
30
32
|
|
33
|
+
attr_reader :environment
|
34
|
+
|
35
|
+
def initialize
|
36
|
+
@environment = EnvironmentLoader.new(self)
|
37
|
+
end
|
38
|
+
|
31
39
|
def config
|
32
40
|
@config ||= Config.new(self)
|
33
41
|
end
|
34
42
|
|
43
|
+
def home_dir
|
44
|
+
File.expand_path(File.join("..", "..", ".."), __dir__)
|
45
|
+
end
|
46
|
+
|
35
47
|
def board_name
|
36
48
|
jira_board_name
|
37
49
|
end
|
@@ -212,5 +224,7 @@ module Jira
|
|
212
224
|
.create_sprint(self, board.id, attributes)
|
213
225
|
end
|
214
226
|
end
|
227
|
+
|
228
|
+
# rubocop:enable Metrics/ClassLength
|
215
229
|
end
|
216
230
|
end
|
@@ -12,7 +12,10 @@ module Jira
|
|
12
12
|
let(:tool) { Tool.new }
|
13
13
|
let(:parser) { OptionParser.new }
|
14
14
|
|
15
|
-
before
|
15
|
+
before do
|
16
|
+
allow(EnvironmentLoader).to receive_messages(new: instance_double(EnvironmentLoader))
|
17
|
+
described_class.add(tool, parser)
|
18
|
+
end
|
16
19
|
|
17
20
|
context "when using --help" do
|
18
21
|
it do
|
@@ -0,0 +1,180 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rspec"
|
4
|
+
|
5
|
+
module Jira
|
6
|
+
module Auto
|
7
|
+
class Tool
|
8
|
+
class EnvironmentLoader
|
9
|
+
RSpec.describe EnvironmentLoader do
|
10
|
+
let(:environment_loader) { described_class.new(tool, auto_setup: auto_setup) }
|
11
|
+
let(:auto_setup) { false }
|
12
|
+
let(:tool) { instance_double(Tool, config: config) }
|
13
|
+
let(:config) { instance_double(Config, dir: "config_dir", tool_name: "jira-auto-tool") }
|
14
|
+
|
15
|
+
# rubocop:disable RSpec/AnyInstance
|
16
|
+
describe "#initialize" do
|
17
|
+
context "when auto_setup is true" do
|
18
|
+
let(:auto_setup) { true }
|
19
|
+
|
20
|
+
it do
|
21
|
+
expect_any_instance_of(described_class).to receive(:setup)
|
22
|
+
|
23
|
+
environment_loader
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "when auto_setup is false" do
|
28
|
+
let(:auto_setup) { false }
|
29
|
+
|
30
|
+
it do
|
31
|
+
expect_any_instance_of(described_class).not_to receive(:setup)
|
32
|
+
|
33
|
+
environment_loader
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
# rubocop:enable RSpec/AnyInstance
|
38
|
+
|
39
|
+
describe "#file_path" do
|
40
|
+
before do
|
41
|
+
allow(File).to receive(:exist?).with("./jira-auto-tool.env.yaml.erb")
|
42
|
+
.and_return(current_directory_file_exists)
|
43
|
+
end
|
44
|
+
|
45
|
+
context "when file exists in current directory" do
|
46
|
+
let(:current_directory_file_exists) { true }
|
47
|
+
|
48
|
+
it { expect(environment_loader.file_path).to eq("./jira-auto-tool.env.yaml.erb") }
|
49
|
+
end
|
50
|
+
|
51
|
+
context "when file does not exist in current directory" do
|
52
|
+
let(:current_directory_file_exists) { false }
|
53
|
+
|
54
|
+
it { expect(environment_loader.file_path).to eq("config_dir/jira-auto-tool.env.yaml.erb") }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "#tool_environment" do
|
59
|
+
let(:environment_keys) { %i[JIRA_HOST JIRA_USER JIRA_PASSWORD] }
|
60
|
+
|
61
|
+
before do
|
62
|
+
allow(Environment).to receive(:constants).and_return(environment_keys)
|
63
|
+
|
64
|
+
environment_keys.each do |environment_key|
|
65
|
+
allow(ENV).to receive(:fetch).with(environment_key.to_s, nil).and_return("#{environment_key} value")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
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
|
+
)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "#create_file" do
|
79
|
+
let(:logger) { instance_double(Logger) }
|
80
|
+
|
81
|
+
before do
|
82
|
+
allow(environment_loader)
|
83
|
+
.to receive_messages(file_path: "file_path", example_file_path: "example_file_path", log: logger)
|
84
|
+
|
85
|
+
allow(File).to receive(:exist?).with("file_path").and_return(file_path_exists)
|
86
|
+
end
|
87
|
+
|
88
|
+
context "when file does not exist" do
|
89
|
+
let(:file_path_exists) { false }
|
90
|
+
|
91
|
+
it "copies the example config file" do
|
92
|
+
expect(FileUtils).to receive(:cp).with("example_file_path", "file_path")
|
93
|
+
|
94
|
+
expect(logger).to receive(:info) do |&block|
|
95
|
+
expect(block.call).to eq(<<~EOCREATIONMESSAGE)
|
96
|
+
Created file file_path
|
97
|
+
_______________________________________________
|
98
|
+
TODO: Adjust the configuration to your context!
|
99
|
+
EOCREATIONMESSAGE
|
100
|
+
end
|
101
|
+
|
102
|
+
environment_loader.create_file
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context "when file already exists" do
|
107
|
+
let(:file_path_exists) { true }
|
108
|
+
|
109
|
+
it "does not copy the example config file if it already exists" do
|
110
|
+
expect(logger).to receive(:error) do |&block|
|
111
|
+
expect(block.call).to eq(<<~EOEXPECTED_ERROR_MESSAGE)
|
112
|
+
Not overriding existing file_path
|
113
|
+
______________________________________________
|
114
|
+
Please remove first before running this again!
|
115
|
+
EOEXPECTED_ERROR_MESSAGE
|
116
|
+
end
|
117
|
+
|
118
|
+
expect(Kernel).to receive(:exit).with(1)
|
119
|
+
|
120
|
+
environment_loader.create_file
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe "#example_file_path" do
|
126
|
+
before { allow(tool).to receive_messages(home_dir: "<JIRA_AUTO_TOOL_HOME_DIR>") }
|
127
|
+
|
128
|
+
it "returns the path to the example config file" do
|
129
|
+
expect(environment_loader.example_file_path)
|
130
|
+
.to eq("<JIRA_AUTO_TOOL_HOME_DIR>/config/examples/jira-auto-tool.env.yaml.erb")
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
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")
|
137
|
+
allow(environment_loader).to receive_messages(config_file_content: "file_content")
|
138
|
+
|
139
|
+
allow(YAML)
|
140
|
+
.to receive(:safe_load).with("file_content")
|
141
|
+
.and_return({ "a_key" => "a_value", "another_key" => "another_value" })
|
142
|
+
|
143
|
+
expect(ENV).to receive(:[]=).with("a_key", "a_value")
|
144
|
+
expect(ENV).to receive(:[]=).with("another_key", "another_value")
|
145
|
+
|
146
|
+
environment_loader.send(:setup)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
describe "#config_file_content" do
|
151
|
+
let(:file_path) { "file_path" }
|
152
|
+
let(:file_content) do
|
153
|
+
<<-YAML_ERB
|
154
|
+
---
|
155
|
+
a_key: <%= 4*4 %>
|
156
|
+
another_key: another_value
|
157
|
+
YAML_ERB
|
158
|
+
end
|
159
|
+
|
160
|
+
let(:erb_result) do
|
161
|
+
<<-YAML
|
162
|
+
---
|
163
|
+
a_key: 16
|
164
|
+
another_key: another_value
|
165
|
+
YAML
|
166
|
+
end
|
167
|
+
|
168
|
+
before do
|
169
|
+
allow(environment_loader).to receive_messages(file_path: file_path)
|
170
|
+
allow(File).to receive(:exist?).with(file_path).and_return(true)
|
171
|
+
allow(File).to receive(:read).with(file_path).and_return(file_content)
|
172
|
+
end
|
173
|
+
|
174
|
+
it { expect(environment_loader.send(:config_file_content)).to eq(erb_result) }
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
data/spec/jira/auto/tool_spec.rb
CHANGED
@@ -9,6 +9,8 @@ module Jira
|
|
9
9
|
RSpec.describe Tool do
|
10
10
|
let(:tool) { described_class.new }
|
11
11
|
|
12
|
+
before { allow(EnvironmentLoader).to receive_messages(new: instance_double(EnvironmentLoader)) }
|
13
|
+
|
12
14
|
it "has a version number" do
|
13
15
|
expect(Jira::Auto::Tool::VERSION).not_to be_nil
|
14
16
|
end
|
@@ -40,6 +42,14 @@ module Jira
|
|
40
42
|
end
|
41
43
|
end
|
42
44
|
|
45
|
+
describe "#environment_loader" do
|
46
|
+
let(:environment_loader) { instance_double(EnvironmentLoader) }
|
47
|
+
|
48
|
+
before { allow(EnvironmentLoader).to receive_messages(new: environment_loader) }
|
49
|
+
|
50
|
+
it { expect(tool.environment).to eq(environment_loader) }
|
51
|
+
end
|
52
|
+
|
43
53
|
# rubocop:disable RSpec/StubbedMock
|
44
54
|
describe "#create_sprint" do
|
45
55
|
it "creates a future sprint and transitions it to the desired state" do
|
@@ -103,6 +113,10 @@ module Jira
|
|
103
113
|
it { expect(tool.sprint_controller).to be_a(SprintController) }
|
104
114
|
end
|
105
115
|
|
116
|
+
describe "#home_dir" do
|
117
|
+
it { expect(tool.home_dir).to eq(File.expand_path("../../../", __dir__)) }
|
118
|
+
end
|
119
|
+
|
106
120
|
describe "#project" do
|
107
121
|
let(:jira_client) { instance_double(RateLimitedJiraClient, Project: project_query) }
|
108
122
|
let(:jira_project) { instance_double(JIRA::Resource::Project) }
|
@@ -117,7 +131,7 @@ module Jira
|
|
117
131
|
end
|
118
132
|
|
119
133
|
# TODO: move that to environment_based_value_spec
|
120
|
-
RSpec.shared_examples "an overridable
|
134
|
+
RSpec.shared_examples "an overridable environment_loader based value" do |method_name|
|
121
135
|
let(:env_var_name) { method_name.to_s.upcase }
|
122
136
|
let(:method_name?) { :"#{method_name}_defined?" }
|
123
137
|
let(:config) { Config.new(object_with_overridable_value) }
|
@@ -127,7 +141,7 @@ module Jira
|
|
127
141
|
allow(config).to receive_messages(value_store: {})
|
128
142
|
end
|
129
143
|
|
130
|
-
context "when the
|
144
|
+
context "when the environment_loader variable is set" do
|
131
145
|
let(:expected_value) { "#{env_var_name} env_value" }
|
132
146
|
|
133
147
|
before do
|
@@ -142,7 +156,7 @@ module Jira
|
|
142
156
|
.to eq(expected_value)
|
143
157
|
end
|
144
158
|
|
145
|
-
it "fetches its value from the
|
159
|
+
it "fetches its value from the environment_loader" do
|
146
160
|
expect(object_with_overridable_value.send(method_name)).to eq(expected_value)
|
147
161
|
end
|
148
162
|
|
@@ -159,11 +173,11 @@ module Jira
|
|
159
173
|
end
|
160
174
|
end
|
161
175
|
|
162
|
-
context "when the
|
176
|
+
context "when the environment_loader variable is not set" do
|
163
177
|
before do
|
164
178
|
allow(ENV).to receive(:fetch)
|
165
179
|
.with(env_var_name)
|
166
|
-
.and_raise(KeyError.new("Missing #{env_var_name}
|
180
|
+
.and_raise(KeyError.new("Missing #{env_var_name} environment_loader variable!)"))
|
167
181
|
|
168
182
|
allow(ENV).to receive(:key?).with(env_var_name).and_return(false)
|
169
183
|
end
|
@@ -175,9 +189,9 @@ module Jira
|
|
175
189
|
.to eq("DEFAULT_VALUE")
|
176
190
|
end
|
177
191
|
|
178
|
-
it "raises an error if the
|
192
|
+
it "raises an error if the environment_loader variable is not found" do
|
179
193
|
expect { object_with_overridable_value.send(method_name) }
|
180
|
-
.to raise_error(KeyError, /Missing #{env_var_name}
|
194
|
+
.to raise_error(KeyError, /Missing #{env_var_name} environment_loader variable!/)
|
181
195
|
end
|
182
196
|
end
|
183
197
|
|
@@ -218,10 +232,10 @@ module Jira
|
|
218
232
|
jira_site_url jira_username
|
219
233
|
jira_sprint_field_name
|
220
234
|
].each do |method_name|
|
221
|
-
describe "
|
235
|
+
describe "environment_loader based values" do
|
222
236
|
let(:object_with_overridable_value) { tool }
|
223
237
|
|
224
|
-
it_behaves_like "an overridable
|
238
|
+
it_behaves_like "an overridable environment_loader based value", method_name
|
225
239
|
end
|
226
240
|
end
|
227
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:
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christophe Broult
|
@@ -213,10 +213,15 @@ files:
|
|
213
213
|
- bin/jira-auto-tool.bat
|
214
214
|
- bin/setup
|
215
215
|
- bin/setup-dev-win.bat
|
216
|
+
- config/examples/jira-auto-tool.env.yaml.erb
|
216
217
|
- cucumber.yml
|
218
|
+
- documentation/JiraToolClassDiagram.uml
|
219
|
+
- documentation/class_diagram.md
|
220
|
+
- documentation/principle.md
|
217
221
|
- features/align_sprint_time_in_dates.feature
|
218
222
|
- features/assign_tickets_to_team_sprints.feature
|
219
223
|
- features/cache_boards.feature
|
224
|
+
- features/configure_environment.feature
|
220
225
|
- features/control_http_request_rate_limit.feature
|
221
226
|
- features/create_sprints_using_existing_ones_as_reference.feature
|
222
227
|
- features/list_boards.feature
|
@@ -246,6 +251,8 @@ files:
|
|
246
251
|
- lib/jira/auto/tool/common_options.rb
|
247
252
|
- lib/jira/auto/tool/config.rb
|
248
253
|
- lib/jira/auto/tool/config/options.rb
|
254
|
+
- lib/jira/auto/tool/environment_loader.rb
|
255
|
+
- lib/jira/auto/tool/environment_loader/options.rb
|
249
256
|
- lib/jira/auto/tool/fetch_custom_field_options.rb
|
250
257
|
- lib/jira/auto/tool/field.rb
|
251
258
|
- lib/jira/auto/tool/field_controller.rb
|
@@ -299,6 +306,7 @@ files:
|
|
299
306
|
- spec/jira/auto/tool/board_spec.rb
|
300
307
|
- spec/jira/auto/tool/common_options_spec.rb
|
301
308
|
- spec/jira/auto/tool/config_spec.rb
|
309
|
+
- spec/jira/auto/tool/environment_loader_spec.rb
|
302
310
|
- spec/jira/auto/tool/field_controller_spec.rb
|
303
311
|
- spec/jira/auto/tool/field_option_spec.rb
|
304
312
|
- spec/jira/auto/tool/field_spec.rb
|