geordi 11.0.0 → 11.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +17 -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/commands/yarn_install.rb +1 -1
- 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 +2 -2
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,14 +4,29 @@ 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
|
|
21
|
+
## 11.1.0 2024-11-20
|
22
|
+
|
23
|
+
### Compatible changes
|
24
|
+
* Skip `yarn install` for other package managers:
|
25
|
+
* Before: Check for a `package.json`
|
26
|
+
* After: Check for a `yarn.lock`
|
12
27
|
|
13
28
|
|
14
|
-
## 11.0.0
|
29
|
+
## 11.0.0 2024-11-13
|
15
30
|
|
16
31
|
### Compatible changes
|
17
32
|
* `geordi unit` now supports `parallel_tests`, binstubs and `bundle exec`
|
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
|
@@ -1,7 +1,7 @@
|
|
1
1
|
desc 'yarn-install', 'Runs yarn install if required', hide: true
|
2
2
|
|
3
3
|
def yarn_install
|
4
|
-
if File.exist?('
|
4
|
+
if File.exist?('yarn.lock') && !system('yarn check --integrity > /dev/null 2>&1')
|
5
5
|
Interaction.announce 'Yarn install'
|
6
6
|
Util.run!('yarn install')
|
7
7
|
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
|