cl-magic 0.3.9 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 42235afcff8b801982ca721b3217756dad15a401063e59310900dd595c05a4e2
4
- data.tar.gz: a49e3798271b7cef9f8e82d9b0a6e9846e9a56a1de1d4d75d91ed81e2291d237
3
+ metadata.gz: '08b4655abcd92a0d5e3a779fdc7e0e09231c7cb15d073e06878c085227ef3f9d'
4
+ data.tar.gz: 63999d535d6ad18d22b8cff1e259b9b054bbf7faf75939e54c9819885ca24feb
5
5
  SHA512:
6
- metadata.gz: 5319a3c52cc59b51c2a6a0e8469cc7085e6485765c335ba44bf6709937c8eb7d12b4b410c78ebb71b283faabd466d647b9109399b20ea9e72ffc4d5fdfa6b252
7
- data.tar.gz: 5f016f4f25736f492b0985fe4ebe5cfb0f33597cf8a365d240743f7635c8142db1726c6c17ffac9a4f6a34946e6864e8a0eabda6b8ef89dd5068f6f14161dc06
6
+ metadata.gz: 4157d207e824e2d0a309790187873d3b6b02c41bd892fc3436e359cc1f4639044576129d1a8d36ac9a0faee8afa6dc2366db506f93401bf4165e93766435f3d7
7
+ data.tar.gz: 0bce3b21105e81dd1bc1d5656e941ceec30814bb01e19c16a7a5ee57eba98403093d7359eb9e113bd60b0850a87764b1241a08febe1881dcde74c303fb9d35be
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cl-magic (0.3.9)
4
+ cl-magic (0.4.0)
5
5
  activesupport
6
6
  optparse-subcommand
7
7
  pastel
data/lib/cl/magic/cl-auth CHANGED
@@ -61,6 +61,18 @@ def aws_okta(options)
61
61
  # cmd = "aws-okta add" # old
62
62
  # do work
63
63
  if is_tty
64
+
65
+ # ensure we are logged in
66
+ begin
67
+ TTY::Command.new(:printer => :null).run("aws-okta exec #{options[:aws_profile]} -- env")
68
+ rescue TTY::Command::ExitError => e
69
+ if e.message.include? "Failed to authenticate"
70
+ @logger.info "authenticate first with: aws-okta add"
71
+ else
72
+ raise
73
+ end
74
+ end
75
+
64
76
  puts
65
77
  @logger.info "now export into your environment with"
66
78
  puts
data/lib/cl/magic/cl-dk CHANGED
@@ -41,7 +41,11 @@ end
41
41
 
42
42
  def get_repo_basename()
43
43
  command = "cd #{@working_dir} && basename $(git remote get-url origin 2> /dev/null) .git"
44
- return TTY::Command.new(:printer => :null).run(command).out.gsub('.git', '').strip.chomp
44
+ repo_basename = TTY::Command.new(:printer => :null).run(command).out.gsub('.git', '').strip.chomp
45
+ if repo_basename==".git" or repo_basename==""
46
+ return File.basename(@working_dir)
47
+ end
48
+ return repo_basename
45
49
  end
46
50
 
47
51
  def get_world_settings_filepath()
@@ -106,37 +110,35 @@ def print_dk_help(dk_parts_hash, dk_make_hash, args)
106
110
  has_dk_commands = dk_parts_hash.keys.any?
107
111
 
108
112
  if no_args or asked_for_help
109
- if has_dk_commands
110
- puts ""
111
- puts "Usage: dk [DK_PARTS] [COMPOSE_OPTIONS] COMPOSE_COMMAND"
112
- puts ""
113
- puts "Run docker compose while munging yamls in sophisticated ways."
114
- puts ""
115
- if get_repo_basename
116
- puts "PROJ INFO"
117
- puts " - Repo basename: #{get_repo_basename}"
118
- puts " - World filepath: #{get_world_project_path()}"
119
- puts ""
120
- end
121
- puts "PROJ PARTS"
122
- dk_parts_hash.keys.each do |key|
123
- print_dk_help_line(key, dk_parts_hash[key].fetch('help'))
124
- end
125
- puts ""
126
- puts "YML TOKENS"
127
- puts " - <dk-remove> removes section of yaml"
128
- puts " - <dk-replace> replaces values in a yaml array"
129
- puts " - <dk-world-path> absolute filepath to world directory"
130
- puts " - <dk-project-path> absolute filepath to world/project directory"
131
- puts " - <dk-working-path> absolute filepath to location dk command was run from"
132
- puts ""
133
- puts "ADDITIONAL TURNKEY COMMANDS"
134
- puts " - dk set-world sets the location of the world directory"
135
- puts " - dk make turnkey commands for a project"
136
- puts " - dk set-parts save parts so they are automatically applied to commands"
113
+ puts ""
114
+ puts "Usage: dk [DK_PARTS] [COMPOSE_OPTIONS] COMPOSE_COMMAND"
115
+ puts ""
116
+ puts "Run docker compose while munging yamls in sophisticated ways."
117
+ puts ""
118
+ if get_repo_basename
119
+ puts "PROJ INFO"
120
+ puts " - Repo basename: #{get_repo_basename}"
121
+ puts " - World filepath: #{get_world_project_path()}"
137
122
  puts ""
138
- puts "-------------------------"
139
123
  end
124
+ puts "PROJ PARTS"
125
+ dk_parts_hash.keys.each do |key|
126
+ print_dk_help_line(key, dk_parts_hash[key].fetch('help'))
127
+ end
128
+ puts ""
129
+ puts "YML TOKENS"
130
+ puts " - <dk-remove> removes section of yaml"
131
+ puts " - <dk-replace> replaces values in a yaml array"
132
+ puts " - <dk-world-path> absolute filepath to world directory"
133
+ puts " - <dk-project-path> absolute filepath to world/project directory"
134
+ puts " - <dk-working-path> absolute filepath to location dk command was run from"
135
+ puts ""
136
+ puts "ADDITIONAL TURNKEY COMMANDS"
137
+ puts " - dk set-world sets the location of the world directory"
138
+ puts " - dk make turnkey commands for a project"
139
+ puts " - dk set-parts save parts so they are automatically applied to commands"
140
+ puts ""
141
+ puts "-------------------------"
140
142
  end
141
143
  end
142
144
 
@@ -12,8 +12,6 @@ require 'cl/magic/common/jira.rb'
12
12
  require 'net/http'
13
13
  require 'json'
14
14
 
15
- require 'byebug'
16
-
17
15
  @logger = get_logger()
18
16
  @cl_cmd_name = File.basename(__FILE__).split('-').join(' ')
19
17
 
@@ -27,7 +25,7 @@ def do_work(options)
27
25
 
28
26
  puts ""
29
27
  @logger.wait "fetch epics"
30
- epic_ids = jira.get_epic_ids(options[:project], options[:epic_wildcard])
28
+ epic_ids, epics = jira.get_epic_ids(options[:project], options[:epic_wildcard])
31
29
  @logger.success "#{epic_ids.count} epics"
32
30
 
33
31
  puts ""
@@ -44,8 +42,8 @@ def do_work(options)
44
42
  @logger.wait "saving file"
45
43
  output_filepath = File.join(@working_dir, options[:output_filename])
46
44
  File.open(output_filepath, 'w') do |file|
47
- issues.each do |issue|
48
- file.puts(issue.to_json)
45
+ issues.each do |o|
46
+ file.puts(o.to_json)
49
47
  end
50
48
  end
51
49
 
@@ -122,7 +120,8 @@ write_history("""#{@cl_cmd_name} \\
122
120
  --base-uri=#{options[:base_uri]} \\
123
121
  --username=#{options[:username]} \\
124
122
  --project=#{options[:project]} \\
125
- --epic-wildcard=#{options[:epic_wildcard]}
123
+ --epic-wildcard=#{options[:epic_wildcard]} \\
124
+ --token
126
125
  """)
127
126
 
128
127
  do_work(options)
@@ -13,8 +13,6 @@ require 'cl/magic/common/jira.rb'
13
13
  require 'net/http'
14
14
  require 'json'
15
15
 
16
- require 'byebug'
17
-
18
16
  @logger = get_logger()
19
17
  @cl_cmd_name = File.basename(__FILE__).split('-').join(' ')
20
18
 
@@ -28,70 +26,50 @@ def get_issues_from_datafile(options)
28
26
  File.foreach(filepath) do |line|
29
27
  issue = JSON.parse(line)
30
28
  issuetype = issue["fields"]["issuetype"]["name"]
29
+ labels = issue["fields"]["labels"]
31
30
 
32
- # filter if needed
33
- issues << issue unless options[:exclude_issuetypes].include?(issuetype)
31
+ has_excluded_labels = (labels & options[:exclude_labels]).any?
32
+ is_excluded_issuetype = options[:exclude_issuetypes].include?(issuetype.downcase)
33
+ issues << issue unless has_excluded_labels or is_excluded_issuetype
34
34
  end
35
35
  return issues
36
36
  end
37
37
 
38
- def oldest_issue_date(issues)
39
- return issues.collect {|i| Date.parse(i["fields"]["created"])}.sort.first
40
- end
38
+ def in_range_issue_stats(issues, start_date, end_date, options)
41
39
 
42
- def do_work(options)
43
- issues = get_issues_from_datafile(options)
44
- oldest_date = oldest_issue_date(issues)
45
- iter_date_range(oldest_date) do |start_date, end_date|
46
- stat_hashes = issues_to_stat_hashes(issues, start_date, end_date, options)
47
- counts = print_stats(stat_hashes, start_date, end_date)
48
- puts counts # print each time range
40
+ def in_range_logs(start_date, end_date, issue)
41
+ return issue["status_changelogs"].select do |log|
42
+ (start_date..end_date).cover?(Date.parse(log["created"]))
43
+ end
49
44
  end
50
- end
51
45
 
52
- def iter_date_range(start_date)
53
- current_date = start_date.beginning_of_week
54
- while current_date < 1.week.ago.end_of_week
55
- yield current_date, current_date.end_of_week
56
- current_date += 2.weeks # increment
57
- end
58
- end
46
+ # in-range
47
+ in_range_issues = issues.select do |issue|
59
48
 
60
- def issues_to_stat_hashes(issues, start_date, end_date, options)
49
+ # issue created date?
50
+ issue_in_range = Date.parse(issue["fields"]["created"]) < end_date
61
51
 
62
- # parse dates for changelogs
63
- issues.each do |issue|
64
- issue["status_changelogs"].each do |l|
65
- date_string = l["created"]
66
- l["created"] = Date.parse(date_string) unless date_string.class == Date
67
- end
52
+ # logs created date?
53
+ logs_in_range = in_range_logs(start_date, end_date, issue).any?
54
+
55
+ # select if
56
+ (logs_in_range or issue_in_range)
68
57
  end
69
58
 
70
- # collect stat hashes
71
- return issues.collect do |issue|
59
+ # stat hashes
60
+ return in_range_issues.collect do |issue|
72
61
 
73
- # skip if issue is out of range
74
- issue_created = Date.parse(issue["fields"]["created"])
75
- if issue_created > end_date
76
- nil
77
- else
78
- # get in-range status change
79
- status_changelog = nil
80
- status_changelog = issue["status_changelogs"]
81
- .select { |l| l["created"] > end_date }
82
- .sort_by { |l| l["created"] }.last if start_date && end_date
83
-
84
- # exclude issue types
85
- if status_changelog and options[:exclude_issuetypes].include?(status_changelog["toString"])
86
- nil
87
- else
88
- # yield stat hash
89
- {
90
- issuetype: issue["fields"]["issuetype"]["name"],
91
- status: status_changelog ? status_changelog["toString"] : issue["fields"]["status"]["name"]
92
- }
93
- end
94
- end
62
+ # most recent in-range log?
63
+ changelog = in_range_logs(start_date, end_date, issue)
64
+ .sort_by { |l| Date.parse(l["created"]) }.last
65
+
66
+ # yield stat hash
67
+ status = changelog ? changelog["toString"] : issue["fields"]["status"]["name"]
68
+ {
69
+ key: issue["key"],
70
+ issuetype: issue["fields"]["issuetype"]["name"],
71
+ status: status
72
+ }
95
73
  end.compact
96
74
  end
97
75
 
@@ -99,37 +77,70 @@ def print_stats(stat_hashes, start_date, end_date)
99
77
  counts = {
100
78
  start_date: start_date.strftime("%m-%d-%Y"),
101
79
  end_date: end_date.strftime("%m-%d-%Y"),
80
+ total: 0,
102
81
  total_todo: 0,
103
82
  total_done: 0,
104
- total: stat_hashes ? stat_hashes.count : 0
83
+ by_type: {}
105
84
  }
106
- return counts unless stat_hashes.any?
107
- stat_hashes.each do |stat|
108
85
 
86
+ stat_hashes.each do |stat|
109
87
  issuetype = stat[:issuetype]
110
88
  status = stat[:status]
111
89
 
112
- # count all
113
- increment(counts, "status_#{issuetype.downcase.underscore}")
114
-
115
90
  # count by status
116
91
  case status
117
- when "Ready","Rework","In Progress","In QA","Ready For Code Review","In Code Review"
92
+ when "To Do","Ready","Rework","In Progress","In QA","Ready For Code Review","In Code Review"
93
+ increment_type(counts, issuetype, :to_do)
118
94
  increment(counts, :total_todo)
119
95
  when "Ready to Deploy","Closed"
96
+ increment_type(counts, issuetype, :done)
120
97
  increment(counts, :total_done)
121
- # else
122
- # raise "invalid ticket status: #{status}"
98
+ else
99
+ # if status != "Won't Do"
100
+ # debugger
101
+ # end
123
102
  end
103
+
104
+ # count totals
105
+ unless status=="Won't Do"
106
+ increment(counts, :total)
107
+ increment_type(counts, issuetype, :total)
108
+ end
109
+
124
110
  end
125
111
  return counts
126
112
  end
127
113
 
114
+ def oldest_issue_date(issues)
115
+ return issues.collect {|i| Date.parse(i["fields"]["created"])}.sort.first.beginning_of_day
116
+ end
117
+
118
+ def increment_type(hash, type, status_category)
119
+ type = type.downcase.underscore
120
+ hash[:by_type][type] = {} unless hash[:by_type].key?(type)
121
+ hash[:by_type][type][status_category] ||= 0
122
+ hash[:by_type][type][status_category] += 1
123
+ end
124
+
128
125
  def increment(hash, key)
129
- if hash.key? key
130
- hash[key] += 1
131
- else
132
- hash[key] = 1
126
+ hash[key] ||= 0
127
+ hash[key] += 1
128
+ end
129
+
130
+ def iter_date_range(start_date)
131
+ while start_date < Date.today.end_of_week
132
+ yield start_date.beginning_of_week.beginning_of_day, start_date.end_of_week.end_of_day
133
+ start_date += 1.weeks # increment
134
+ end
135
+ end
136
+
137
+ def do_work(options)
138
+ issues = get_issues_from_datafile(options)
139
+ oldest_date = oldest_issue_date(issues).beginning_of_week
140
+ iter_date_range(oldest_date) do |start_date, end_date|
141
+ stat_hashes = in_range_issue_stats(issues, start_date, end_date, options)
142
+ counts = print_stats(stat_hashes, start_date, end_date)
143
+ puts counts # print each time range
133
144
  end
134
145
  end
135
146
 
@@ -160,6 +171,10 @@ global = OptionParser.new do |g|
160
171
  options[:exclude_issuetypes] = v.split(',')
161
172
  options[:exclude_issuetypes] << "Won't Do"
162
173
  end
174
+
175
+ g.on("-l", "--exclude-labels CSV", "comma separated list of labels that will cause a ticket to be excluded") do |v|
176
+ options[:exclude_labels] = v.split(',')
177
+ end
163
178
  end
164
179
 
165
180
  #
@@ -171,10 +186,14 @@ global.parse(ARGV)
171
186
 
172
187
  # prompt for missing options
173
188
  ask_and_store_option(options, :data_filepath, "data_filepath: ")
189
+ options[:exclude_issuetypes] = [] if options[:exclude_issuetypes].nil?
190
+ options[:exclude_labels] = [] if options[:exclude_labels].nil?
174
191
 
175
192
  # display full command
176
193
  write_history("""#{@cl_cmd_name} \\
177
- --data-filepath=#{options[:data_filepath]}
194
+ --data-filepath=#{options[:data_filepath]} \\
195
+ --exclude-issuetypes=#{options[:exclude_issuetypes].join(',')} \\
196
+ --exclude-labels=#{options[:exclude_labels].join(',')}
178
197
  """)
179
198
 
180
199
  do_work(options)
data/lib/cl/magic/cl-poll CHANGED
@@ -17,10 +17,10 @@ require 'cl/magic/common/kubectl.rb'
17
17
  # Features
18
18
  #
19
19
 
20
- def do_work(options)
20
+ def do_work(options, remaining_options)
21
21
  while true
22
- tty_command = TTY::Command.new(printer: :null)
23
- out, err = tty_command.run(ARGV.join(' '))
22
+ tty_command = TTY::Command.new(printer: :null, pty: options[:pty])
23
+ out, err = tty_command.run("cd #{@working_dir} && #{remaining_options.join(' ')}")
24
24
  puts out
25
25
  puts
26
26
  sleep(1)
@@ -31,7 +31,9 @@ end
31
31
  # Options
32
32
  #
33
33
 
34
- options = {}
34
+ options = {
35
+ pty: true
36
+ }
35
37
  global_banner = <<DOC
36
38
 
37
39
  A sandbox to try things
@@ -43,10 +45,23 @@ DOC
43
45
  global = OptionParser.new do |g|
44
46
  g.banner = global_banner
45
47
  add_help_and_verbose(g)
48
+
49
+ g.on("--no-pty", "disable pseudo terminal") do |v|
50
+ options[:pty] = v
51
+ end
46
52
  end
47
53
 
48
54
  #
49
55
  # Run
50
56
  #
51
57
 
52
- do_work(options)
58
+ remaining_options = []
59
+ global.order! do |option|
60
+ remaining_options << option
61
+ end
62
+
63
+ global.parse(ARGV)
64
+
65
+ @working_dir = ENV['CL_WORKING_DIR'] # passed through cl-magic to here
66
+
67
+ do_work(options, remaining_options)
@@ -1,4 +1,3 @@
1
- require 'byebug'
2
1
 
3
2
  class Jira
4
3
 
@@ -16,7 +15,9 @@ class Jira
16
15
  def get_epic_ids(project, epic_wildcard)
17
16
  jql_query = "project = \"#{project}\" AND issuetype = Epic AND text ~ \"#{epic_wildcard}\""
18
17
  results = run_jql_query(jql_query)
19
- return results.select{|h| h['fields']['summary'].start_with? epic_wildcard}.map {|h| h['id']}
18
+ epics = results.select{|h| h['fields']['summary'].start_with? epic_wildcard}
19
+ epic_ids = epics.map {|h| h['id']}
20
+ return epic_ids, epics
20
21
  end
21
22
 
22
23
  def get_issues(project, epic_ids)
@@ -153,7 +154,7 @@ def collect_status_changelogs(jira, issues, options)
153
154
  # append them to issue
154
155
  status_logs.each do |status_log|
155
156
  issue["status_changelogs"] << status_log
156
- end if status_logs.count > 0
157
+ end
157
158
  end
158
159
 
159
160
  final_issue_hashes << issue # save
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Cl
4
4
  module Magic
5
- VERSION = "0.3.9"
5
+ VERSION = "0.4.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cl-magic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.9
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Don Najd
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-03 00:00:00.000000000 Z
11
+ date: 2023-07-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake