tefoji 3.4.2 → 3.5.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/lib/mixins/user_functions.rb +2 -3
- data/lib/tefoji/jira_api.rb +28 -14
- data/lib/tefoji/version.rb +1 -1
- data/lib/tefoji.rb +32 -29
- metadata +5 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fc4b951086f14bcc81ab1aabd55e9598d10178ba5cbfbd61984d89444b2df2b3
|
|
4
|
+
data.tar.gz: a822ad69a634e8e78d763adde8e0606460b290f7b291553216194ddb7c59c23a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4720d892040f8f1be05329d2de1845c1a2255441c9e71cb7211df1b189c4d0d342f31c6611ad52f210fb442a289406250f53c0a7705bbc7c244bd8fe3de3d750
|
|
7
|
+
data.tar.gz: b2e7f33d4e8cd0ee744a3e7d55b8d6d29b5a48887441f54ba0bfdb55789f31167913a963c368fcee9d4458572bd48e7571257e2c853935ac5ed9d52d500a2d05
|
|
@@ -48,6 +48,7 @@ module UserFunctions
|
|
|
48
48
|
MODULES: 'MODULES',
|
|
49
49
|
MODULES_INTERNAL: 'FM',
|
|
50
50
|
OPERATIONS: 'OPS',
|
|
51
|
+
P4DEVOPS: 'P4DEVOPS',
|
|
51
52
|
PDK: 'CONT',
|
|
52
53
|
PE_INTERNAL: 'PE',
|
|
53
54
|
POOLER: 'POOLER',
|
|
@@ -57,7 +58,6 @@ module UserFunctions
|
|
|
57
58
|
PUPPETSERVER: 'SERVER',
|
|
58
59
|
PUPPET_AGENT: 'PA',
|
|
59
60
|
QUALITY_ENGINEERING: 'QENG',
|
|
60
|
-
RELEASE_ENGINEERING: 'RE',
|
|
61
61
|
SLV: 'SLV',
|
|
62
62
|
SUPPORT: 'SUP',
|
|
63
63
|
VANAGON: 'VANAGON',
|
|
@@ -80,8 +80,7 @@ module UserFunctions
|
|
|
80
80
|
CODE_MANAGEMENT: 'Dumpling',
|
|
81
81
|
DUMPLING: 'Dumpling',
|
|
82
82
|
FACTER: 'Phoenix',
|
|
83
|
-
INSTALLER: 'Installer
|
|
84
|
-
NETWORKING: 'Network Automation',
|
|
83
|
+
INSTALLER: 'Installer',
|
|
85
84
|
OPERATIONS: 'Operations',
|
|
86
85
|
PE: 'Dumpling',
|
|
87
86
|
PLATFORM_OS: 'Unicorn',
|
data/lib/tefoji/jira_api.rb
CHANGED
|
@@ -73,21 +73,28 @@ module Tefoji
|
|
|
73
73
|
# HTTP doesn't like linefeeds in the auth string, hence #strict_encode64
|
|
74
74
|
@jira_auth = Base64.strict_encode64(decoded_auth.join(':'))
|
|
75
75
|
@authentication_header = { 'Authorization' => "Basic #{@jira_auth}" }
|
|
76
|
-
end
|
|
77
76
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
77
|
+
# Verify authentication
|
|
78
|
+
return if @jira_mock
|
|
79
|
+
return if get_username(@jira_username)
|
|
80
|
+
|
|
81
|
+
@logger.info "Authentication failed, trying again with username: #{@jira_username}@perforce.com"
|
|
82
|
+
# Reset authentication with @perforce.com added to username
|
|
83
|
+
@jira_username = "#{@jira_username}@perforce.com"
|
|
84
|
+
decoded_auth[0] = @jira_username
|
|
85
|
+
@jira_auth = Base64.strict_encode64(decoded_auth.join(':'))
|
|
86
|
+
@authentication_header = { 'Authorization' => "Basic #{@jira_auth}" }
|
|
87
|
+
# Retry authentication
|
|
88
|
+
fatal 'Authentication failed: Credentials are invalid' unless get_username(@jira_username)
|
|
85
89
|
end
|
|
86
90
|
|
|
87
91
|
# Get information about user in Jira
|
|
88
|
-
def get_username(username
|
|
92
|
+
def get_username(username)
|
|
89
93
|
search_parameters = "user/search?query=#{username}"
|
|
90
|
-
jira_get(search_parameters
|
|
94
|
+
response = jira_get(search_parameters)
|
|
95
|
+
return false if response.empty?
|
|
96
|
+
|
|
97
|
+
response
|
|
91
98
|
end
|
|
92
99
|
|
|
93
100
|
# Get information about user in Jira
|
|
@@ -197,7 +204,7 @@ module Tefoji
|
|
|
197
204
|
account_name = user_name_to_account_name(user_email)
|
|
198
205
|
response = get_username(account_name)
|
|
199
206
|
|
|
200
|
-
fatal "Jira account ID not found for \"#{account_name}\""
|
|
207
|
+
fatal "Jira account ID not found for \"#{account_name}\"" unless response
|
|
201
208
|
account_id = response[0]['accountId']
|
|
202
209
|
|
|
203
210
|
@logger.debug("user account name: \"#{account_name} \" " \
|
|
@@ -241,7 +248,7 @@ module Tefoji
|
|
|
241
248
|
issue_data.key?('type') && issue_data['type'].casecmp?(ISSUE_EPIC)
|
|
242
249
|
end
|
|
243
250
|
|
|
244
|
-
def jira_get(jira_request_path
|
|
251
|
+
def jira_get(jira_request_path)
|
|
245
252
|
# Jira likes to send complete URLs for responses. Handle
|
|
246
253
|
# the case where we've received a 'self' query from Jira with
|
|
247
254
|
# fully formed url
|
|
@@ -265,8 +272,7 @@ module Tefoji
|
|
|
265
272
|
SocketError,
|
|
266
273
|
Errno::ECONNREFUSED => e
|
|
267
274
|
# Return false if not found rather than fail to allow for checking the existence of users.
|
|
268
|
-
fatal "Cannot connect to #{@jira_base_rest_url}: #{e.message}"
|
|
269
|
-
return false
|
|
275
|
+
fatal "Cannot connect to #{@jira_base_rest_url}: #{e.message}"
|
|
270
276
|
end
|
|
271
277
|
return JSON.parse(response.body)
|
|
272
278
|
end
|
|
@@ -433,6 +439,14 @@ module Tefoji
|
|
|
433
439
|
jira_fields['customfield_10020'] = issue_data['sprint'].to_i
|
|
434
440
|
end
|
|
435
441
|
|
|
442
|
+
if issue_data['product']
|
|
443
|
+
jira_fields['customfield_10350'] = { FIELD_VALUE => issue_data['product'] }
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
if issue_data['shirt_size']
|
|
447
|
+
jira_fields['customfield_10078'] = { FIELD_VALUE => issue_data['shirt_size'] }
|
|
448
|
+
end
|
|
449
|
+
|
|
436
450
|
# If a issue has a specified parent issue, prefer that. The parent issue *should* already
|
|
437
451
|
# be linked to the main epic. Otherwise, we need to set it to have an epic_parent. This can
|
|
438
452
|
# either be an epic linked to the main epic or the main epic itself.
|
data/lib/tefoji/version.rb
CHANGED
data/lib/tefoji.rb
CHANGED
|
@@ -75,6 +75,8 @@ module Tefoji
|
|
|
75
75
|
@declarations[k] = DeclaredValue.new(v)
|
|
76
76
|
end
|
|
77
77
|
|
|
78
|
+
standardize_epics(main_template_data)
|
|
79
|
+
|
|
78
80
|
resolve_variables(main_template_data['declare'])
|
|
79
81
|
@logger.debug "Declarations: #{@declarations}"
|
|
80
82
|
|
|
@@ -85,6 +87,7 @@ module Tefoji
|
|
|
85
87
|
main_template.dig(:includes, :before)&.each do |before|
|
|
86
88
|
default_epic_saved = @default_target_epic
|
|
87
89
|
@formats = before.dig(:data, 'formats') if before.dig(:data, 'formats')
|
|
90
|
+
standardize_epics(before[:data])
|
|
88
91
|
process_template(before[:template_name], before[:data], before[:conditional])
|
|
89
92
|
@default_target_epic = default_epic_saved
|
|
90
93
|
end
|
|
@@ -98,6 +101,7 @@ module Tefoji
|
|
|
98
101
|
main_template.dig(:includes, :after)&.each do |after|
|
|
99
102
|
default_epic_saved = @default_target_epic
|
|
100
103
|
@formats = after.dig(:data, 'formats') if after.dig(:data, 'formats')
|
|
104
|
+
standardize_epics(after[:data])
|
|
101
105
|
process_template(after[:template_name], after[:data], after[:conditional])
|
|
102
106
|
@default_target_epic = default_epic_saved
|
|
103
107
|
end
|
|
@@ -118,9 +122,7 @@ module Tefoji
|
|
|
118
122
|
@template_data = template_data
|
|
119
123
|
|
|
120
124
|
if @template_data.key?('epics')
|
|
121
|
-
generate_epics_with_issues
|
|
122
|
-
elsif @template_data.key?('epic')
|
|
123
|
-
generate_epics_with_issues('epic')
|
|
125
|
+
generate_epics_with_issues
|
|
124
126
|
elsif @template_data.key?('issues')
|
|
125
127
|
generate_ordinary_issues
|
|
126
128
|
else
|
|
@@ -272,7 +274,6 @@ module Tefoji
|
|
|
272
274
|
@jira_api.logger = @logger
|
|
273
275
|
|
|
274
276
|
@jira_api.authenticate(@jira_url, @jira_user, @jira_auth_string)
|
|
275
|
-
@jira_api.test_authentication unless @jira_mock
|
|
276
277
|
end
|
|
277
278
|
|
|
278
279
|
# Save Jira auth data
|
|
@@ -281,8 +282,8 @@ module Tefoji
|
|
|
281
282
|
@jira_api.save_authentication(@jira_auth_file)
|
|
282
283
|
end
|
|
283
284
|
|
|
284
|
-
def generate_epics_with_issues
|
|
285
|
-
epics = generate_epics
|
|
285
|
+
def generate_epics_with_issues
|
|
286
|
+
epics = generate_epics
|
|
286
287
|
epics.each do |epic|
|
|
287
288
|
@default_target_epic = epic
|
|
288
289
|
generate_ordinary_issues
|
|
@@ -290,8 +291,8 @@ module Tefoji
|
|
|
290
291
|
end
|
|
291
292
|
|
|
292
293
|
# @return [Array] an array of responses from Jira containing a hash of the epic fields.
|
|
293
|
-
def generate_epics
|
|
294
|
-
epic_to_do_list = [@template_data[
|
|
294
|
+
def generate_epics
|
|
295
|
+
epic_to_do_list = [@template_data['epics']].flatten
|
|
295
296
|
@logger.debug "Generating data: #{@template_data}"
|
|
296
297
|
|
|
297
298
|
epic_to_do_list.map do |epic|
|
|
@@ -848,6 +849,7 @@ module Tefoji
|
|
|
848
849
|
def check_assignees(main_template_data)
|
|
849
850
|
valid_users = []
|
|
850
851
|
invalid_users_to_epics = {}
|
|
852
|
+
|
|
851
853
|
main_template_data['epics']&.each do |epic|
|
|
852
854
|
next unless epic['assignee']
|
|
853
855
|
|
|
@@ -862,18 +864,6 @@ module Tefoji
|
|
|
862
864
|
)
|
|
863
865
|
end
|
|
864
866
|
|
|
865
|
-
if main_template_data.dig('epic', 'assignee')
|
|
866
|
-
assignee_username = get_username_from_assignee(main_template_data['epic']['assignee'])
|
|
867
|
-
unless valid_users.include?(assignee_username)
|
|
868
|
-
update_user_validity(
|
|
869
|
-
assignee_username,
|
|
870
|
-
main_template_data['epic']['summary'],
|
|
871
|
-
valid_users,
|
|
872
|
-
invalid_users_to_epics
|
|
873
|
-
)
|
|
874
|
-
end
|
|
875
|
-
end
|
|
876
|
-
|
|
877
867
|
invalid_users_to_issue_defaults = {}
|
|
878
868
|
if main_template_data.dig('issue_defaults', 'assignee')
|
|
879
869
|
assignee_username = get_username_from_assignee(
|
|
@@ -943,7 +933,7 @@ module Tefoji
|
|
|
943
933
|
def update_user_validity(username, issue_name, valid_users, invalid_users)
|
|
944
934
|
if invalid_users.key?(username)
|
|
945
935
|
invalid_users[username] += [issue_name]
|
|
946
|
-
elsif @jira_api.get_username(username
|
|
936
|
+
elsif @jira_api.get_username(username)
|
|
947
937
|
valid_users << username
|
|
948
938
|
else
|
|
949
939
|
invalid_users[username] = invalid_users.fetch(username, []) + [issue_name]
|
|
@@ -954,6 +944,7 @@ module Tefoji
|
|
|
954
944
|
# in the associated project.
|
|
955
945
|
def check_components(main_template_data)
|
|
956
946
|
invalid_components = Set.new
|
|
947
|
+
|
|
957
948
|
main_template_data['epics']&.each do |epic|
|
|
958
949
|
next unless epic['components']
|
|
959
950
|
|
|
@@ -964,14 +955,6 @@ module Tefoji
|
|
|
964
955
|
end
|
|
965
956
|
end
|
|
966
957
|
|
|
967
|
-
if main_template_data.dig('epic', 'components')
|
|
968
|
-
project = expand_right_value(main_template_data['epic']['project']).value
|
|
969
|
-
update_valid_components(project)
|
|
970
|
-
main_template_data['epic']['components'].each do |component|
|
|
971
|
-
invalid_components.add([project, component]) unless @valid_components[project].include?(component)
|
|
972
|
-
end
|
|
973
|
-
end
|
|
974
|
-
|
|
975
958
|
main_template_data['issues'].each do |issue|
|
|
976
959
|
next unless issue['components']
|
|
977
960
|
|
|
@@ -1013,5 +996,25 @@ module Tefoji
|
|
|
1013
996
|
|
|
1014
997
|
logger
|
|
1015
998
|
end
|
|
999
|
+
|
|
1000
|
+
# Takes template data as input and ensures the format for the epics
|
|
1001
|
+
# field is the 'epics' key with an array as the value.
|
|
1002
|
+
def standardize_epics(template_data)
|
|
1003
|
+
# Determine if epic or epics key exists
|
|
1004
|
+
if template_data['epic']
|
|
1005
|
+
epic_value = 'epic'
|
|
1006
|
+
elsif template_data['epics']
|
|
1007
|
+
epic_value = 'epics'
|
|
1008
|
+
else
|
|
1009
|
+
@logger.debug('No epics found in template, skipping standardize_epics')
|
|
1010
|
+
return
|
|
1011
|
+
end
|
|
1012
|
+
# Convert epic data to array if not currently an array
|
|
1013
|
+
epics_data = template_data[epic_value]
|
|
1014
|
+
epics_data = [template_data[epic_value]] unless epics_data.is_a?(Array)
|
|
1015
|
+
# Set epics data and delete epic data if it exists
|
|
1016
|
+
template_data['epics'] = epics_data
|
|
1017
|
+
template_data.delete('epic') if epic_value == 'epic'
|
|
1018
|
+
end
|
|
1016
1019
|
end
|
|
1017
1020
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: tefoji
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Puppet By Perforce
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2025-10-27 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: debug
|
|
@@ -175,7 +175,7 @@ metadata:
|
|
|
175
175
|
homepage_uri: https://github.com/puppetlabs/tefoji
|
|
176
176
|
source_code_uri: https://github.com/puppetlabs/tefoji
|
|
177
177
|
changelog_uri: https://github.com/puppetlabs/tefoji/blob/main/CHANGELOG.md
|
|
178
|
-
post_install_message:
|
|
178
|
+
post_install_message:
|
|
179
179
|
rdoc_options: []
|
|
180
180
|
require_paths:
|
|
181
181
|
- lib
|
|
@@ -191,7 +191,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
191
191
|
version: '0'
|
|
192
192
|
requirements: []
|
|
193
193
|
rubygems_version: 3.2.33
|
|
194
|
-
signing_key:
|
|
194
|
+
signing_key:
|
|
195
195
|
specification_version: 4
|
|
196
196
|
summary: Generate Jira issues from a YAML specification.
|
|
197
197
|
test_files: []
|