geordi 11.1.0 → 11.2.0

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: 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