geordi 11.1.0 → 11.2.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: 310a3633bce8944bb4c56987a2d12cf2ed69013ef978e91f48063acba801c634
4
- data.tar.gz: f5e53286619679e6b5c3f0e2439e5c7589ed7c2e2866c0078b51f056658cc3dd
3
+ metadata.gz: 34d65d80999ddc674119d4be0c198c4aa43e0a7198555aae13f7d0ed529b17a9
4
+ data.tar.gz: 0e23774900617e49f7ec4a0f49ff41979414aef2cbb1e98ebcf8e32b50094a55
5
5
  SHA512:
6
- metadata.gz: 692cd04428cdbc217969425a9c3fcc1ea62f95f0a0692aabec218afdb1b804c1e705a181f387c6ba581c5e3dc25acdb5a0485565571c73d7f33d4521629ce300
7
- data.tar.gz: 8f9c32e800de8532265c3b302bfd821c0a24295c55bfac166ddb1390a2a0e93fb15e6028d1a63526ec0fc8268b1a617687152d8a72055c75a0546f45fec292c4
6
+ metadata.gz: 326546035b14d2708c5d1ab4829a4cb51359ff3e8b90a07b6a3245a860d1e121fcfbeea29cacb2a853cbdc7b2a9e6b0ef53219696cabb589c73f4785a732cb74
7
+ data.tar.gz: 3b8c91f822d01b5b4d2a7f825e19d90eca6b92b58d01a7d24e7b87d38ad02faa16a01451a810cefe9fef01c85a695c7f6638cd8ad660db2106a95765a449385f
data/CHANGELOG.md CHANGED
@@ -4,15 +4,23 @@ All notable changes to this project will be documented in this file.
4
4
  This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
5
5
 
6
6
  ## Unreleased
7
+ ### Compatible changes
8
+ ### Breaking changes
9
+
10
+
11
+ ## 11.2.0 2024-11-22
7
12
 
8
13
  ### Compatible changes
14
+ * Add support for default branches other than "master" (e.g. "main"). Will read
15
+ this information from `origin`.
16
+ * `geordi branch` will not fail if it can't determine local branches.
17
+ * Improved Linear issue menu: now includes the issue id, truncates long issue
18
+ titles and puts metadata last
9
19
 
10
- ### Breaking changes
11
20
 
12
21
  ## 11.1.0 2024-11-20
13
22
 
14
23
  ### Compatible changes
15
-
16
24
  * Skip `yarn install` for other package managers:
17
25
  * Before: Check for a `package.json`
18
26
  * After: Check for a `yarn.lock`
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- geordi (11.1.0)
4
+ geordi (11.2.0)
5
5
  thor (~> 1)
6
6
 
7
7
  GEM
@@ -119,4 +119,4 @@ DEPENDENCIES
119
119
  rspec
120
120
 
121
121
  BUNDLED WITH
122
- 2.3.25
122
+ 2.3.26
data/README.md CHANGED
@@ -32,7 +32,7 @@ On the first execution we ask for your Linear API token. It will be
32
32
  stored in `~/.config/geordi/global.yml`.
33
33
 
34
34
  **Options**
35
- - `-m, [--from-master], [--no-from-master]`: Branch from master instead of the current branch
35
+ - `-m, --from-main, [--from-master], [--no-from-master]`: Branch from master instead of the current branch
36
36
 
37
37
 
38
38
  ### `geordi capistrano COMMAND`
@@ -142,7 +142,8 @@ before it does it.** There are different scenarios where this command is handy:
142
142
  be skipped.
143
143
 
144
144
  Calling the command without arguments will infer the target stage from the
145
- current branch and fall back to master/staging.
145
+ current branch and fall back to master/staging. (Will use the actual main branch
146
+ of the repository, e.g. "main" instead of "master".)
146
147
 
147
148
  Finds available Capistrano stages by their prefix, e.g. `geordi deploy p` will
148
149
  deploy production, `geordi deploy mak` will deploy a `makandra` stage if there
@@ -267,29 +268,20 @@ variable like this: `PARALLEL_TEST_PROCESSORS=6 geordi rspec`
267
268
  Support for performing security updates.
268
269
 
269
270
  Preparation for security update: `geordi security-update`. Checks out production
270
- and pulls.
271
+ and pulls, and will tell each step before performing it.
271
272
 
272
- After performing the update: `geordi security-update finish`. Switches branches,
273
- pulls, pushes and deploys as required by our workflow.
274
-
275
- This command tells what it will do before it does it. In detail:
273
+ Part two after performing the update: `geordi security-update finish`. Switches
274
+ branches, pulls, pushes and deploys as required by our workflow. This as well
275
+ will tell each step before performing it. In detail:
276
276
 
277
277
  1. Ask user if tests are green
278
-
279
278
  2. Push production
280
-
281
279
  3. Check out master and pull
282
-
283
280
  4. Merge production and push in master
284
-
285
281
  5. Deploy staging, if there is a staging environment
286
-
287
282
  6. Ask user if deployment log is okay and staging application is still running
288
-
289
283
  7. Deploy other stages
290
-
291
284
  8. Ask user if deployment log is okay and application is still running on all stages
292
-
293
285
  9. Inform user about the next (manual) steps
294
286
 
295
287
 
@@ -6,7 +6,7 @@ On the first execution we ask for your Linear API token. It will be
6
6
  stored in `~/.config/geordi/global.yml`.
7
7
  LONGDESC
8
8
 
9
- option :from_master, aliases: '-m', type: :boolean, desc: 'Branch from master instead of the current branch'
9
+ option :from_master, aliases: %w[-m --from-main], type: :boolean, desc: 'Branch from master instead of the current branch'
10
10
 
11
11
  def branch
12
12
  require 'geordi/gitlinear'
@@ -19,7 +19,8 @@ before it does it.** There are different scenarios where this command is handy:
19
19
  be skipped.
20
20
 
21
21
  Calling the command without arguments will infer the target stage from the
22
- current branch and fall back to master/staging.
22
+ current branch and fall back to master/staging. (Will use the actual main branch
23
+ of the repository, e.g. "main" instead of "master".)
23
24
 
24
25
  Finds available Capistrano stages by their prefix, e.g. `geordi deploy p` will
25
26
  deploy production, `geordi deploy mak` will deploy a `makandra` stage if there
@@ -37,7 +38,7 @@ option :current_branch, aliases: '-c', type: :boolean,
37
38
 
38
39
  def deploy(target_stage = nil)
39
40
  # Set/Infer default values
40
- branch_stage_map = { 'master' => 'staging', 'production' => 'production' }
41
+ branch_stage_map = { 'master' => 'staging', 'main' => 'staging', 'production' => 'production' }
41
42
  if target_stage && !Util.deploy_targets.include?(target_stage)
42
43
  # Target stage autocompletion from available stages
43
44
  target_stage = Util.deploy_targets.find { |t| t.start_with? target_stage }
@@ -58,7 +59,10 @@ def deploy(target_stage = nil)
58
59
  source_branch = target_branch = Util.current_branch
59
60
  else
60
61
  source_branch = Interaction.prompt 'Source branch:', Util.current_branch
61
- target_branch = Interaction.prompt 'Deploy branch:', branch_stage_map.invert.fetch(target_stage, 'master')
62
+
63
+ deploy_branch = 'production' if target_stage == 'production'
64
+ deploy_branch ||= Util.git_default_branch
65
+ target_branch = Interaction.prompt 'Deploy branch:', deploy_branch
62
66
  end
63
67
 
64
68
  merge_needed = (source_branch != target_branch)
@@ -1,33 +1,16 @@
1
1
  desc 'security-update [STEP]', 'Support for performing security updates'
2
2
  long_desc <<-LONGDESC
3
3
  Preparation for security update: `geordi security-update`. Checks out production
4
- and pulls.
4
+ and pulls, and will tell each step before performing it.
5
5
 
6
- After performing the update: `geordi security-update finish`. Switches branches,
7
- pulls, pushes and deploys as required by our workflow.
8
-
9
- This command tells what it will do before it does it. In detail:
10
-
11
- 1. Ask user if tests are green
12
-
13
- 2. Push production
14
-
15
- 3. Check out master and pull
16
-
17
- 4. Merge production and push in master
18
-
19
- 5. Deploy staging, if there is a staging environment
20
-
21
- 6. Ask user if deployment log is okay and staging application is still running
22
-
23
- 7. Deploy other stages
24
-
25
- 8. Ask user if deployment log is okay and application is still running on all stages
26
-
27
- 9. Inform user about the next (manual) steps
6
+ Part two after performing the update: `geordi security-update finish`. Switches
7
+ branches, pulls, pushes and deploys as required by our workflow. This as well
8
+ will tell each step before performing it.
28
9
  LONGDESC
29
10
 
30
11
  def security_update(step = 'prepare')
12
+ master = Util.git_default_branch
13
+
31
14
  case step
32
15
  when 'prepare'
33
16
  Interaction.announce 'Preparing for security update'
@@ -56,11 +39,11 @@ def security_update(step = 'prepare')
56
39
  Interaction.note 'Working directory clean.'
57
40
  Interaction.prompt('Have you successfully run all tests?', 'n', /y|yes/) || Interaction.fail('Please run tests first.')
58
41
 
59
- Interaction.note 'About to: push production, checkout & pull master, merge production, push master.'
42
+ Interaction.note "About to: push production, checkout & pull #{master}, merge production, push #{master}."
60
43
  Interaction.prompt('Continue?', 'n', /y|yes/) || Interaction.fail('Cancelled.')
61
44
 
62
45
  Util.run!('git push', show_cmd: true)
63
- Util.run!('git checkout master', show_cmd: true)
46
+ Util.run!("git checkout #{master}", show_cmd: true)
64
47
  Util.run!('git pull', show_cmd: true)
65
48
  Util.run!('git merge production', show_cmd: true)
66
49
  Util.run!('git push', show_cmd: true)
@@ -106,5 +89,7 @@ def security_update(step = 'prepare')
106
89
  puts
107
90
  Interaction.note 'Now send an email to customer and project lead, informing them about the update.'
108
91
  Interaction.note 'Do not forget to make a joblog on a security budget, if available.'
92
+ else
93
+ Interaction.fail "Unsupported step #{step.inspect}"
109
94
  end
110
95
  end
@@ -31,11 +31,12 @@ module Geordi
31
31
  matching_local_branch = local_branches.find { |branch_name| branch_name == issue['branchName'] }
32
32
  matching_local_branch ||= local_branches.find { |branch_name| branch_name.include? issue['identifier'].to_s }
33
33
 
34
- if matching_local_branch.nil?
35
- Util.run! ['git', 'checkout', 'master'] if from_master
36
- Util.run! ['git', 'checkout', '-b', issue['branchName']]
37
- else
34
+ if matching_local_branch
38
35
  Util.run! ['git', 'checkout', matching_local_branch]
36
+ else
37
+ default_branch = Util.git_default_branch
38
+ Util.run! ['git', 'checkout', default_branch] if from_master
39
+ Util.run! ['git', 'checkout', '-b', issue['branchName']]
39
40
  end
40
41
  end
41
42
 
@@ -51,11 +52,7 @@ module Geordi
51
52
  `git branch --format="%(refname:short)"`
52
53
  end
53
54
 
54
- if branch_list_string.strip.empty?
55
- Interaction.fail 'Could not determine local Git branches.'
56
- end
57
-
58
- branch_list_string.split("\n")
55
+ branch_list_string.strip.split("\n")
59
56
  end
60
57
  end
61
58
 
@@ -64,42 +61,36 @@ module Geordi
64
61
  return dummy_issue_for_testing
65
62
  end
66
63
 
67
- loading_message = 'Connecting to Linear ...'
68
- print(loading_message)
69
64
  issues = fetch_linear_issues
70
- reset_loading_message = "\r#{' ' * (loading_message.length + issues.length)}\r"
71
-
72
65
  if issues.empty?
73
- print reset_loading_message
74
66
  Geordi::Interaction.fail('No issues to offer.')
75
67
  end
68
+ issues.sort_by! { |i| -i.dig('state', 'position') }
76
69
 
77
70
  highline.choose do |menu|
78
- menu.header = 'Choose an issue'
71
+ max_label_length = 60
72
+ menu.header = 'Choose a started issue (ordered by state)'
79
73
 
80
74
  issues.each do |issue|
75
+ id = issue['identifier']
76
+ title = issue['title']
81
77
  state = issue['state']['name']
82
- if issue['assignee']
83
- assignee = issue['assignee']['name']
84
- assignee_is_me = issue['assignee']['isMe']
85
- else
86
- assignee = "unassigned"
87
- assignee_is_me = false
88
- end
89
-
90
- state += HighLine::BOLD if assignee_is_me
78
+ assignee = issue.dig('assignee', 'displayName') || 'unassigned'
91
79
 
92
- label = "(#{assignee}, #{state}) #{issue['title']}"
93
- label = bold(label) if assignee_is_me
80
+ label = "[#{id}] #{title}"
81
+ label = "#{label[0..(max_label_length - 5)]} ..." if label.length > max_label_length
82
+ label = HighLine::BLUE + HighLine::BOLD + label + HighLine::RESET if issue.dig('assignee', 'isMe')
83
+ label = "#{label} (#{assignee} / #{state})"
94
84
 
95
85
  menu.choice(label) { return issue }
96
86
  end
97
87
 
98
88
  menu.hidden('') { Interaction.fail('No issue selected.') }
99
- print reset_loading_message # Once menu is build
100
89
  end
101
90
 
102
- nil # Return nothing
91
+ # Selecting an issue will return that issue. If we ever get here, return
92
+ # nothing
93
+ nil
103
94
  end
104
95
 
105
96
  def dummy_issue_for_testing
@@ -143,11 +134,12 @@ module Geordi
143
134
  url
144
135
  branchName
145
136
  assignee {
146
- name
137
+ displayName
147
138
  isMe
148
139
  }
149
140
  state {
150
- name
141
+ name
142
+ position
151
143
  }
152
144
  }
153
145
  }
@@ -159,7 +151,10 @@ module Geordi
159
151
 
160
152
  def query_api(attributes, variables)
161
153
  uri = URI(API_ENDPOINT)
154
+ loading_message = "Connecting to #{uri.host} ... "
155
+ clear_loading_message = "\r#{' ' * loading_message.length}\r"
162
156
 
157
+ print(loading_message)
163
158
  https = Net::HTTP.new(uri.host, uri.port)
164
159
  https.use_ssl = true
165
160
 
@@ -172,6 +167,7 @@ module Geordi
172
167
  request['Authorization'] = settings.linear_api_key
173
168
 
174
169
  response = https.request(request)
170
+ print clear_loading_message
175
171
 
176
172
  parsed_response = JSON.parse(response.body)[0]
177
173
  if parsed_response.key?('errors')
@@ -181,8 +177,5 @@ module Geordi
181
177
  end
182
178
  end
183
179
 
184
- def bold(string)
185
- HighLine::BOLD + string + HighLine::RESET
186
- end
187
180
  end
188
181
  end
@@ -57,6 +57,8 @@ module Geordi
57
57
  input = default if input.empty? && default
58
58
 
59
59
  agreement_regex ? !!(input =~ agreement_regex) : input
60
+ rescue Interrupt
61
+ fail 'Cancelled.'
60
62
  end
61
63
 
62
64
  end
@@ -62,8 +62,8 @@ module Geordi
62
62
 
63
63
  if team_ids.empty?
64
64
  Geordi::Interaction.warn 'No team id found.'
65
- Interaction.note 'Please open a team in Linear, open the command menu with CTRL + K and choose'
66
- Interaction.note "\"Copy model UUID\". Store that team id in #{LOCAL_SETTINGS_FILE_NAME}:"
65
+ puts 'Please open a team in Linear, open the command menu with CTRL + K and choose'
66
+ puts "\"Copy model UUID\". Store that team id in #{LOCAL_SETTINGS_FILE_NAME}:"
67
67
  puts 'linear_team_ids: abc-123-123-abc, def-456-456-def'
68
68
  exit 1
69
69
  end
data/lib/geordi/util.rb CHANGED
@@ -116,7 +116,7 @@ module Geordi
116
116
 
117
117
  def current_branch
118
118
  if testing?
119
- 'master'
119
+ git_default_branch
120
120
  else
121
121
  `git rev-parse --abbrev-ref HEAD`.strip
122
122
  end
@@ -217,6 +217,18 @@ module Geordi
217
217
  def rspec_path?(path)
218
218
  %r{(^|\/)spec|_spec\.rb($|:)}.match?(path)
219
219
  end
220
+
221
+ def git_default_branch
222
+ default_branch = if testing?
223
+ ENV['GEORDI_TESTING_DEFAULT_BRANCH']
224
+ else
225
+ head_symref = `git ls-remote --symref origin HEAD`
226
+ head_symref[%r{\Aref: refs/heads/(\S+)\sHEAD}, 1]
227
+ end
228
+
229
+ default_branch || 'master'
230
+ end
231
+
220
232
  end
221
233
  end
222
234
  end
@@ -1,3 +1,3 @@
1
1
  module Geordi
2
- VERSION = '11.1.0'.freeze
2
+ VERSION = '11.2.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geordi
3
3
  version: !ruby/object:Gem::Version
4
- version: 11.1.0
4
+ version: 11.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Henning Koch
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-11-20 00:00:00.000000000 Z
11
+ date: 2024-11-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -117,7 +117,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
117
117
  - !ruby/object:Gem::Version
118
118
  version: '0'
119
119
  requirements: []
120
- rubygems_version: 3.4.10
120
+ rubygems_version: 3.2.3
121
121
  signing_key:
122
122
  specification_version: 4
123
123
  summary: Collection of command line tools we use in our daily work with Ruby, Rails