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 +4 -4
- data/CHANGELOG.md +10 -2
- data/Gemfile.lock +2 -2
- data/README.md +7 -15
- data/lib/geordi/commands/branch.rb +1 -1
- data/lib/geordi/commands/deploy.rb +7 -3
- data/lib/geordi/commands/security_update.rb +10 -25
- data/lib/geordi/gitlinear.rb +26 -33
- data/lib/geordi/interaction.rb +2 -0
- data/lib/geordi/settings.rb +2 -2
- data/lib/geordi/util.rb +13 -1
- data/lib/geordi/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 34d65d80999ddc674119d4be0c198c4aa43e0a7198555aae13f7d0ed529b17a9
|
4
|
+
data.tar.gz: 0e23774900617e49f7ec4a0f49ff41979414aef2cbb1e98ebcf8e32b50094a55
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
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
|
-
|
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:
|
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
|
-
|
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
|
-
|
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
|
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!(
|
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
|
data/lib/geordi/gitlinear.rb
CHANGED
@@ -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
|
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
|
-
|
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
|
-
|
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
|
-
|
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 = "
|
93
|
-
label =
|
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
|
-
|
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
|
-
|
137
|
+
displayName
|
147
138
|
isMe
|
148
139
|
}
|
149
140
|
state {
|
150
|
-
|
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
|
data/lib/geordi/interaction.rb
CHANGED
data/lib/geordi/settings.rb
CHANGED
@@ -62,8 +62,8 @@ module Geordi
|
|
62
62
|
|
63
63
|
if team_ids.empty?
|
64
64
|
Geordi::Interaction.warn 'No team id found.'
|
65
|
-
|
66
|
-
|
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
|
-
|
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
|
data/lib/geordi/version.rb
CHANGED
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.
|
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-
|
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.
|
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
|