tefoji 1.0.7 → 1.0.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 26059a47709ee9c7a4c33054c4da05d66b43e77cd3042497ffa7f7f48ccc2831
4
- data.tar.gz: fe60fc5a310f2147e07c050483bb4a86665ef697396afbf8027ada79a7f25e48
3
+ metadata.gz: 8279bb8ebda1af1e674da5c4d16932b790e69210a5c163563746a80d44aca92b
4
+ data.tar.gz: f17bbc221ed1ec7c4fde90d2e64caddb45078ee0ee2d5cb59e7226d90df14317
5
5
  SHA512:
6
- metadata.gz: 29eb974c65570687064562c4ca3a6acf1b5fdefe3a75a913003fe3ee6bbf930f0bac749821705817e7d6fd8e4e00b51fdc81d937d4ddd62fe5038b291aeef22d
7
- data.tar.gz: f115c57f3ba7c00ee7ae24f581d544da201964cb5a896080f4b2d92f132d0522a350cf340ab43a33eebf4933f3f6f087129f4d88bd4983f6cfc5ca1e84a80935
6
+ metadata.gz: d790551fe749db5eea41ce6889479c3f23e8278ad94744b8be4561d0cceadb33b609949c612224e49bbc21587b8b3cf50501a6eeef1e2d3059c860420e583c15
7
+ data.tar.gz: a0b4bd8875027f141a87f2bc960c43143813500db372e0764df428896fc04f34fd3f5b91d3a4d4ca305e9949b88dd3329f4363a1981905f6b4b7d7fe6c7b9fe9
@@ -3,7 +3,7 @@ module Logging
3
3
  # Another cheap hack to wrap 'logger' above. Called as 'fatal' rather than 'logger.fatal'
4
4
  # directly, does the exit for us so we can be lazy.
5
5
  def fatal(message)
6
- logger.fatal(message)
6
+ @logger.fatal(message)
7
7
  exit 1
8
8
  end
9
9
  end
@@ -48,7 +48,7 @@ module UserFunctions
48
48
  MODULES: 'MODULES',
49
49
  MODULES_INTERNAL: 'FM',
50
50
  OPERATIONS: 'OPS',
51
- PDK: 'PDK',
51
+ PDK: 'CONT',
52
52
  PE_INTERNAL: 'PE',
53
53
  PROJECT_CENTRAL: 'PC',
54
54
  PUPPETDB: 'PDB',
@@ -89,12 +89,12 @@ module UserFunctions
89
89
  CD4PE: 'CD4PE',
90
90
  CODE_MANAGEMENT: 'Dumpling',
91
91
  DUMPLING: 'Dumpling',
92
- FACTER: "Phoenix",
92
+ FACTER: 'Phoenix',
93
93
  INSTALLER: 'Installer and Management',
94
94
  NETWORKING: 'Network Automation',
95
95
  OPERATIONS: 'Operations',
96
96
  PE: 'Dumpling',
97
- PLATFORM_OS: "Phoenix",
97
+ PLATFORM_OS: 'Phoenix',
98
98
  PUPPETDB: 'Dumpling',
99
99
  PUPPETSERVER: 'Dumpling',
100
100
  QE: 'Quality Engineering',
data/lib/tefoji/cli.rb CHANGED
@@ -43,7 +43,7 @@ module Tefoji
43
43
  @user_options = parse_options(argv)
44
44
 
45
45
  if @user_options['--version']
46
- warn "tefoji version #{Gem.loaded_specs['tefoji'].version.to_s}"
46
+ warn "tefoji version #{Gem.loaded_specs['tefoji'].version}"
47
47
  exit 0
48
48
  end
49
49
 
@@ -75,14 +75,15 @@ module Tefoji
75
75
  # Do this so we can inform the user quickly that their credentials didn't work
76
76
  # There may be a better test, but this is the one the original Winston uses
77
77
  def test_authentication
78
- get_username
78
+ get_username(@jira_username)
79
79
  rescue RestClient::Forbidden
80
80
  fatal 'Forbidden: either the authentication is incorrect or ' \
81
81
  'Jira might be requiring a CAPTCHA response from the web interface.'
82
82
  end
83
83
 
84
- def get_username
85
- jira_get("user?username=#{@jira_username}")
84
+ # Get information about user in Jira
85
+ def get_username(username, fail_if_not_found = true)
86
+ jira_get("user?username=#{username}", fail_if_not_found)
86
87
  end
87
88
 
88
89
  # Save authentication YAML to the a file for reuse.
@@ -167,7 +168,7 @@ module Tefoji
167
168
 
168
169
  private
169
170
 
170
- def jira_get(jira_request_path)
171
+ def jira_get(jira_request_path, fail_if_not_found = true)
171
172
  # Jira likes to send complete URLs for responses. Handle
172
173
  # the case where we've received a 'self' query from Jira with
173
174
  # fully formed url
@@ -191,7 +192,9 @@ module Tefoji
191
192
  rescue RestClient::NotFound,
192
193
  SocketError,
193
194
  Errno::ECONNREFUSED => e
194
- fatal "Cannot connect to #{@jira_base_rest_url}: #{e.message}"
195
+ # Return False if not found rather than fail to allow for checking the existence of users.
196
+ fatal "Cannot connect to #{@jira_base_rest_url}: #{e.message}" if fail_if_not_found
197
+ return false
195
198
  end
196
199
 
197
200
  return JSON.parse(response.body)
data/lib/tefoji.rb CHANGED
@@ -74,6 +74,8 @@ module Tefoji
74
74
  resolve_variables(main_template_data['declare'])
75
75
  @logger.debug "Declarations: #{@declarations}"
76
76
 
77
+ check_assignees(main_template_data)
78
+
77
79
  # Process 'before' templates
78
80
  main_template.dig(:includes, :before)&.each do |before|
79
81
  default_epic_saved = @default_target_epic
@@ -641,12 +643,17 @@ module Tefoji
641
643
  def user_function_call(function_definition)
642
644
  @logger.debug "function_definition is: #{function_definition}"
643
645
  function_name = function_definition['name']
644
- if function_definition.key?('arguments')
645
- function_arguments = function_definition['arguments'].map do |a|
646
+ argument = function_definition['argument']
647
+ arguments = function_definition['arguments']
648
+
649
+ if argument.is_a?(Array) || arguments.is_a?(Array)
650
+ arguments = argument || function_definition['arguments']
651
+ function_arguments = arguments.map do |a|
646
652
  expand_right_value(a).value
647
653
  end
648
- elsif function_definition.key?('argument')
649
- function_arguments = [expand_right_value(function_definition['argument']).value]
654
+ elsif argument.is_a?(String) || arguments.is_a?(String)
655
+ argument = function_definition['argument'] || function_definition['arguments']
656
+ function_arguments = [expand_right_value(argument).value]
650
657
  else
651
658
  fatal("No arguments supplied to function \"#{function_name}\"")
652
659
  end
@@ -814,6 +821,124 @@ module Tefoji
814
821
  return true
815
822
  end
816
823
 
824
+ # Iterates through the assignees in a template and checks if they exist on jira. If any assignee in
825
+ # the template does not exist, it will fail, outputting a message saying which users failed and
826
+ # what epics/issues they are associated with.
827
+ # NOTE: This check does not guarantee a user is assignable, so there may be cases when a user passes
828
+ # the check but still fails when being assigned a ticket/epic. If we find a reasonable way to
829
+ # check assignability prior to the epic/issue being created, we should implement it in place of
830
+ # using the get_username method.
831
+ def check_assignees(main_template_data)
832
+ valid_users = []
833
+
834
+ invalid_users_to_features = {}
835
+ main_template_data['features']&.each do |feature|
836
+ next unless feature['assignee']
837
+
838
+ assignee_username = get_username_from_assignee(feature['assignee'])
839
+ next if valid_users.include?(assignee_username)
840
+
841
+ update_user_validity(assignee_username, feature['summary'], valid_users, invalid_users_to_features)
842
+ end
843
+
844
+ if main_template_data.dig('feature', 'assignee')
845
+ assignee_username = get_username_from_assignee(main_template_data['feature']['assignee'])
846
+ unless valid_users.include?(assignee_username)
847
+ update_user_validity(assignee_username, main_template_data['feature']['summary'], valid_users,
848
+ invalid_users_to_features)
849
+ end
850
+ end
851
+
852
+ invalid_users_to_epics = {}
853
+ main_template_data['epics']&.each do |epic|
854
+ next unless epic['assignee']
855
+
856
+ assignee_username = get_username_from_assignee(epic['assignee'])
857
+ next if valid_users.include?(assignee_username)
858
+
859
+ update_user_validity(assignee_username, epic['summary'], valid_users, invalid_users_to_epics)
860
+ end
861
+
862
+ if main_template_data.dig('epic', 'assignee')
863
+ assignee_username = get_username_from_assignee(main_template_data['epic']['assignee'])
864
+ unless valid_users.include?(assignee_username)
865
+ update_user_validity(assignee_username, main_template_data['epic']['summary'], valid_users,
866
+ invalid_users_to_epics)
867
+ end
868
+ end
869
+
870
+ invalid_users_to_issue_defaults = {}
871
+ if main_template_data.dig('issue_defaults', 'assignee')
872
+ assignee_username = get_username_from_assignee(main_template_data['issue_defaults']['assignee'])
873
+ unless valid_users.include?(assignee_username)
874
+ update_user_validity(assignee_username, 'issue_defaults', valid_users, invalid_users_to_issue_defaults)
875
+ end
876
+ end
877
+
878
+ invalid_users_to_issues = {}
879
+ main_template_data['issues'].each do |issue|
880
+ next unless issue['assignee']
881
+
882
+ assignee_username = get_username_from_assignee(issue['assignee'])
883
+ next if valid_users.include?(assignee_username)
884
+
885
+ update_user_validity(assignee_username, issue['summary'], valid_users, invalid_users_to_issues)
886
+ end
887
+ unless invalid_users_to_features.empty? &&
888
+ invalid_users_to_epics.empty? &&
889
+ invalid_users_to_issue_defaults.empty? &&
890
+ invalid_users_to_issues.empty?
891
+ invalid_user_message = "Invalid assignees:\n"
892
+ end
893
+ unless invalid_users_to_features.empty?
894
+ invalid_users_to_features.each do |assignee, feature|
895
+ invalid_user_message += "Assignee #{assignee} associated with features #{feature}\n"
896
+ end
897
+ end
898
+ unless invalid_users_to_epics.empty?
899
+ invalid_users_to_epics.each do |assignee, epic|
900
+ invalid_user_message += "Assignee #{assignee} associated with epics #{epic}\n"
901
+ end
902
+ end
903
+ unless invalid_users_to_issue_defaults.empty?
904
+ invalid_users_to_issue_defaults.each do |assignee, _|
905
+ invalid_user_message += "Assignee #{assignee} associated with issue_defaults\n"
906
+ end
907
+ end
908
+ unless invalid_users_to_issues.empty?
909
+ invalid_users_to_issues.each do |assignee, issues|
910
+ invalid_user_message += "Assignee #{assignee} associated with issues #{issues}\n"
911
+ end
912
+ end
913
+ fatal invalid_user_message if invalid_user_message
914
+ end
915
+
916
+ def get_username_from_assignee(assignee)
917
+ # Assignee is a variable or direct input
918
+ username = expand_string(assignee) if assignee.is_a?(String)
919
+ # Assignee is a function
920
+ if assignee.is_a?(Hash) && assignee.key?('function')
921
+ username = user_function_call(assignee['function'])
922
+ end
923
+
924
+ unless username
925
+ fatal "invalid assignee format for issue: #{issue['short_name']} failed: must be a function or a string"
926
+ end
927
+
928
+ username = username.value unless username.is_a?(String)
929
+ username
930
+ end
931
+
932
+ def update_user_validity(username, issue_name, valid_users, invalid_users)
933
+ if invalid_users.key?(username)
934
+ invalid_users[username] += [issue_name]
935
+ elsif @jira_api.get_username(username, false)
936
+ valid_users << username
937
+ else
938
+ invalid_users[username] = invalid_users.fetch(username, []) + [issue_name]
939
+ end
940
+ end
941
+
817
942
  def logger_initialize(log_location)
818
943
  logger = Logger.new(log_location, progname: 'tefoji', level: @log_level)
819
944
  logger.formatter = proc do |severity, _, script_name, message|
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: 1.0.7
4
+ version: 1.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet Labs
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-08-11 00:00:00.000000000 Z
11
+ date: 2023-02-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry-byebug
@@ -203,7 +203,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
203
203
  - !ruby/object:Gem::Version
204
204
  version: '0'
205
205
  requirements: []
206
- rubygems_version: 3.1.6
206
+ rubygems_version: 3.0.3
207
207
  signing_key:
208
208
  specification_version: 4
209
209
  summary: Generate Jira issues from a YAML specification.