geordi 12.6.2 → 12.7.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/.github/workflows/test.yml +2 -0
- data/CHANGELOG.md +9 -1
- data/Gemfile +7 -3
- data/Gemfile.lock +7 -3
- data/README.md +15 -1
- data/lib/geordi/capistrano_config.rb +13 -0
- data/lib/geordi/commands/commit.rb +1 -2
- data/lib/geordi/commands/deploy.rb +22 -11
- data/lib/geordi/git.rb +2 -2
- data/lib/geordi/linear_client.rb +23 -12
- data/lib/geordi/util.rb +26 -0
- data/lib/geordi/version.rb +1 -1
- metadata +3 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1abf3be3e77c751d438bf3ee3b95a9552ba675dfce857adf796bc3885ba68804
|
|
4
|
+
data.tar.gz: 5118fa1fd8d510c9f34bcc7931d0e136dbb64d59dc21f557ad323d32647d873d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dc001fe1a1d6fc826e4e0de10a950091f283771f50fcaa801e8d9376ca448b86dafc76ef6bf5612c819724c3c92ea25daea82d8740ec14520aabd654543fe2cd
|
|
7
|
+
data.tar.gz: c74907212b99944097fb569807824475455ec683382fbbad08920b830ef7f41019097f017fd5b0c6800e32c08e3e9f6ba990792afd5305b4e8e71f0ad65d8555
|
data/.github/workflows/test.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,14 @@ This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html
|
|
|
10
10
|
### Breaking changes
|
|
11
11
|
|
|
12
12
|
|
|
13
|
+
## 12.7.0 2026-07-16
|
|
14
|
+
|
|
15
|
+
### Compatible changes
|
|
16
|
+
* `geordi deploy` will now consider actually *deployed* commits for moving Linear issues
|
|
17
|
+
* Support for Ruby 4 added
|
|
18
|
+
* `geordi commit`: No longer add Linear URL to commit message (breaks Linear <-> Gitlab integration)
|
|
19
|
+
|
|
20
|
+
|
|
13
21
|
## 12.6.2 2026-01-30
|
|
14
22
|
|
|
15
23
|
### Compatible changes
|
|
@@ -35,7 +43,7 @@ This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html
|
|
|
35
43
|
## 12.5.0 2025-09-09
|
|
36
44
|
|
|
37
45
|
### Compatible changes
|
|
38
|
-
* `geordi deploy` will now offer to move
|
|
46
|
+
* `geordi deploy` will now offer to move pushed issues to a new state if linear_team_ids are configured.
|
|
39
47
|
|
|
40
48
|
|
|
41
49
|
## 12.4.0 2025-08-29
|
data/Gemfile
CHANGED
|
@@ -3,10 +3,14 @@ source 'http://rubygems.org'
|
|
|
3
3
|
# Specify your gem's dependencies in geordi.gemspec
|
|
4
4
|
gemspec
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
gem '
|
|
6
|
+
# Former standard gems, see https://stdgems.org/
|
|
7
|
+
gem 'logger' # Dependency of aruba
|
|
8
|
+
gem 'abbrev' # Dependency of highline
|
|
9
|
+
gem 'ostruct' # Dependency of pry-byebug
|
|
10
|
+
|
|
11
|
+
gem 'aruba'
|
|
12
|
+
gem 'rake'
|
|
8
13
|
gem 'rspec'
|
|
9
|
-
gem 'abbrev' # Dependency of Highline
|
|
10
14
|
gem 'parallel_tests'
|
|
11
15
|
gem 'launchy'
|
|
12
16
|
gem 'pry-byebug'
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
geordi (12.
|
|
4
|
+
geordi (12.7.0)
|
|
5
5
|
highline
|
|
6
6
|
thor (~> 1)
|
|
7
7
|
|
|
@@ -55,9 +55,11 @@ GEM
|
|
|
55
55
|
highline (2.1.0)
|
|
56
56
|
launchy (2.5.0)
|
|
57
57
|
addressable (~> 2.7)
|
|
58
|
+
logger (1.7.0)
|
|
58
59
|
method_source (1.1.0)
|
|
59
60
|
mini_mime (1.1.5)
|
|
60
61
|
multi_test (1.1.0)
|
|
62
|
+
ostruct (0.6.3)
|
|
61
63
|
parallel (1.19.2)
|
|
62
64
|
parallel_tests (4.7.1)
|
|
63
65
|
parallel
|
|
@@ -91,13 +93,15 @@ PLATFORMS
|
|
|
91
93
|
|
|
92
94
|
DEPENDENCIES
|
|
93
95
|
abbrev
|
|
94
|
-
aruba
|
|
96
|
+
aruba
|
|
95
97
|
cucumber (~> 9)
|
|
96
98
|
geordi!
|
|
97
99
|
launchy
|
|
100
|
+
logger
|
|
101
|
+
ostruct
|
|
98
102
|
parallel_tests
|
|
99
103
|
pry-byebug
|
|
100
|
-
rake
|
|
104
|
+
rake
|
|
101
105
|
rspec
|
|
102
106
|
|
|
103
107
|
BUNDLED WITH
|
data/README.md
CHANGED
|
@@ -170,7 +170,21 @@ Finds available Capistrano stages by their prefix, e.g. `geordi deploy p` will
|
|
|
170
170
|
deploy production, `geordi deploy mak` will deploy a `makandra` stage if there
|
|
171
171
|
is a file config/deploy/makandra.rb.
|
|
172
172
|
|
|
173
|
-
If Linear team ids are configured (see `geordi commit`), will offer to move deployed issues to a new state.
|
|
173
|
+
If Linear team ids are configured (see `geordi commit`), will offer to move deployed issues to a new state.
|
|
174
|
+
Disable this with "skip".
|
|
175
|
+
By default, Geordi will only consider issues it pushes itself during deploy.
|
|
176
|
+
To consider all new commits deployed to the server, add this Capistrano task to your project:
|
|
177
|
+
|
|
178
|
+
namespace :app do
|
|
179
|
+
desc 'Show current revision'
|
|
180
|
+
task :revision do
|
|
181
|
+
on roles :app do
|
|
182
|
+
within current_path do
|
|
183
|
+
info "REVISION: #{capture(:cat, 'REVISION')}"
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
end
|
|
174
188
|
|
|
175
189
|
If your project is running Capistrano 2, Geordi will use `cap deploy:migrations` by default. Skip migrations by passing the -M option: `geordi deploy -M staging`.
|
|
176
190
|
|
|
@@ -51,6 +51,19 @@ module Geordi
|
|
|
51
51
|
'bash --login'
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
+
def self.current_app_revisions(target_stage)
|
|
55
|
+
return ['a76fdd46e5319a202f7daa3f0fbdadb0c6f44408'] if Util.testing?
|
|
56
|
+
output = `cap #{target_stage} app:revision`
|
|
57
|
+
|
|
58
|
+
# git revisions are in SHA-1 format => 40-byte hexadecimal string
|
|
59
|
+
output.scan(/[a-f0-9]{40}/).uniq
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def self.task_defined?(task_name)
|
|
63
|
+
return true if Util.testing?
|
|
64
|
+
`cap -T`.split.include?(task_name)
|
|
65
|
+
end
|
|
66
|
+
|
|
54
67
|
private
|
|
55
68
|
|
|
56
69
|
attr_accessor :deploy_info, :stage
|
|
@@ -22,10 +22,9 @@ def commit(*git_args)
|
|
|
22
22
|
|
|
23
23
|
issue = linear_client.issue_from_branch || linear_client.choose_issue
|
|
24
24
|
title = "[#{issue['identifier']}] #{issue['title']}"
|
|
25
|
-
description = "Issue: #{issue['url']}"
|
|
26
25
|
extra = highline.ask("\nAdd an optional message").strip
|
|
27
26
|
title << ' - ' << extra if extra != ''
|
|
28
|
-
Util.run!(['git', 'commit', '--allow-empty', '-m', title,
|
|
27
|
+
Util.run!(['git', 'commit', '--allow-empty', '-m', title, *git_args])
|
|
29
28
|
|
|
30
29
|
Hint.did_you_know [
|
|
31
30
|
:branch,
|
|
@@ -28,7 +28,21 @@ Finds available Capistrano stages by their prefix, e.g. `geordi deploy p` will
|
|
|
28
28
|
deploy production, `geordi deploy mak` will deploy a `makandra` stage if there
|
|
29
29
|
is a file config/deploy/makandra.rb.
|
|
30
30
|
|
|
31
|
-
If Linear team ids are configured (see `geordi commit`), will offer to move deployed issues to a new state.
|
|
31
|
+
If Linear team ids are configured (see `geordi commit`), will offer to move deployed issues to a new state.
|
|
32
|
+
Disable this with "skip".
|
|
33
|
+
By default, Geordi will only consider issues it pushes itself during deploy.
|
|
34
|
+
To consider all new commits deployed to the server, add this Capistrano task to your project:
|
|
35
|
+
|
|
36
|
+
namespace :app do
|
|
37
|
+
desc 'Show current revision'
|
|
38
|
+
task :revision do
|
|
39
|
+
on roles :app do
|
|
40
|
+
within current_path do
|
|
41
|
+
info "REVISION: \#{capture(:cat, 'REVISION')}"
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
32
46
|
|
|
33
47
|
If your project is running Capistrano 2, Geordi will use `cap deploy:migrations` by default. Skip migrations by passing the -M option: `geordi deploy -M staging`.
|
|
34
48
|
LONGDESC
|
|
@@ -84,12 +98,7 @@ def deploy(target_stage = nil)
|
|
|
84
98
|
|
|
85
99
|
merge_needed = (source_branch != target_branch)
|
|
86
100
|
push_needed = merge_needed || `git cherry -v | wc -l`.strip.to_i > 0
|
|
87
|
-
|
|
88
|
-
if push_needed
|
|
89
|
-
commit_messages = Git.commits_between(source_branch, target_branch)
|
|
90
|
-
linear_issue_ids = LinearClient.extract_issue_ids(commit_messages)
|
|
91
|
-
end
|
|
92
|
-
move_issues = !linear_issue_ids.empty? && target_state && !target_state.empty?
|
|
101
|
+
move_issues = target_state && !target_state.empty?
|
|
93
102
|
|
|
94
103
|
# Checks #####################################################################
|
|
95
104
|
Interaction.note "Checking whether your #{source_branch} branch is ready"
|
|
@@ -117,9 +126,11 @@ def deploy(target_stage = nil)
|
|
|
117
126
|
Interaction.note "From current branch #{source_branch}" if options.current_branch
|
|
118
127
|
|
|
119
128
|
if move_issues
|
|
120
|
-
relevant_commits =
|
|
121
|
-
|
|
122
|
-
|
|
129
|
+
linear_issue_ids, relevant_commits = Util.determine_issues_to_move(source_branch, target_branch, target_stage, linear_client: linear_client)
|
|
130
|
+
if relevant_commits.any?
|
|
131
|
+
Interaction.note("Move these Linear issues to state \"#{target_state}\":")
|
|
132
|
+
puts relevant_commits.uniq.join("\n")
|
|
133
|
+
end
|
|
123
134
|
end
|
|
124
135
|
|
|
125
136
|
# Execute ####################################################################
|
|
@@ -142,7 +153,7 @@ def deploy(target_stage = nil)
|
|
|
142
153
|
|
|
143
154
|
Util.run!(capistrano_call, show_cmd: true)
|
|
144
155
|
|
|
145
|
-
if move_issues
|
|
156
|
+
if move_issues && !linear_issue_ids.empty?
|
|
146
157
|
linear_client.move_issues_to_state(linear_issue_ids, target_state)
|
|
147
158
|
settings.persist_linear_state_after_deploy(target_stage, target_state)
|
|
148
159
|
end
|
data/lib/geordi/git.rb
CHANGED
|
@@ -41,10 +41,10 @@ module Geordi
|
|
|
41
41
|
default_branch || 'master'
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
def commits_between(
|
|
44
|
+
def commits_between(source, target)
|
|
45
45
|
return [ENV['GEORDI_TESTING_GIT_COMMIT']] if Util.testing?
|
|
46
46
|
|
|
47
|
-
commits = `git --no-pager log --pretty=format:%s
|
|
47
|
+
commits = `git --no-pager log --pretty=format:%s #{source}..#{target}`
|
|
48
48
|
|
|
49
49
|
commits&.split("\n")
|
|
50
50
|
end
|
data/lib/geordi/linear_client.rb
CHANGED
|
@@ -25,6 +25,12 @@ module Geordi
|
|
|
25
25
|
found_ids.map { |id| id.delete('[]') } # [W-365] => W-365
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
+
def self.filter_by_issue_ids(list_of_strings, issue_ids)
|
|
29
|
+
list_of_strings.select do |message|
|
|
30
|
+
issue_ids.any? { |id| message.start_with?("[#{id}]") }
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
28
34
|
def initialize
|
|
29
35
|
self.highline = HighLine.new
|
|
30
36
|
self.settings = Settings.new
|
|
@@ -67,16 +73,28 @@ module Geordi
|
|
|
67
73
|
nil
|
|
68
74
|
end
|
|
69
75
|
|
|
76
|
+
def filter_existing_issue_ids(identifiers)
|
|
77
|
+
return identifiers if Util.testing?
|
|
78
|
+
issues = fetch_linear_issues
|
|
79
|
+
identifiers.select { |id| issues.any? { |i| i['identifier'] == id } }
|
|
80
|
+
end
|
|
81
|
+
|
|
70
82
|
def move_issues_to_state(issue_identifiers, state)
|
|
71
83
|
return if Util.testing?
|
|
72
84
|
|
|
73
85
|
issues = fetch_linear_issues # This only retrieves issues for the configured linear team ids
|
|
74
|
-
state_ids_by_team_id = state_ids_by_team_id(state)
|
|
75
86
|
|
|
76
|
-
|
|
77
|
-
|
|
87
|
+
# Only look up states for teams that actually have issues being moved
|
|
88
|
+
# This avoids warning about missing states in teams with no relevant issues.
|
|
89
|
+
relevant_issues = issue_identifiers.filter_map { |id| issues.find { |i| i['identifier'] == id } }
|
|
90
|
+
return if relevant_issues.empty?
|
|
78
91
|
|
|
79
|
-
|
|
92
|
+
relevant_team_ids = relevant_issues.map { |i| i.dig('team', 'id') }.uniq
|
|
93
|
+
|
|
94
|
+
state_ids_by_team_id = state_ids_by_team_id(state, team_ids: relevant_team_ids)
|
|
95
|
+
|
|
96
|
+
relevant_issues.each do |issue|
|
|
97
|
+
next unless (state_id = state_ids_by_team_id[issue.dig('team', 'id')])
|
|
80
98
|
|
|
81
99
|
update_issue_state(issue['id'], state_id)
|
|
82
100
|
end
|
|
@@ -101,12 +119,6 @@ module Geordi
|
|
|
101
119
|
end
|
|
102
120
|
end
|
|
103
121
|
|
|
104
|
-
def filter_by_issue_ids(list_of_strings, issue_ids)
|
|
105
|
-
list_of_strings.select do |message|
|
|
106
|
-
issue_ids.any? { |id| message.start_with?("[#{id}]") }
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
|
|
110
122
|
private
|
|
111
123
|
|
|
112
124
|
attr_accessor :highline, :settings
|
|
@@ -167,10 +179,9 @@ module Geordi
|
|
|
167
179
|
end
|
|
168
180
|
end
|
|
169
181
|
|
|
170
|
-
def state_ids_by_team_id(state_name)
|
|
182
|
+
def state_ids_by_team_id(state_name, team_ids: settings.linear_team_ids)
|
|
171
183
|
result = {}
|
|
172
184
|
|
|
173
|
-
team_ids = settings.linear_team_ids
|
|
174
185
|
filter = {
|
|
175
186
|
"team": {
|
|
176
187
|
"id": {
|
data/lib/geordi/util.rb
CHANGED
|
@@ -220,6 +220,32 @@ module Geordi
|
|
|
220
220
|
%r{(^|\/)spec|_spec\.rb($|:)}.match?(path)
|
|
221
221
|
end
|
|
222
222
|
|
|
223
|
+
def determine_issues_to_move(source_branch, target_branch, target_stage, linear_client: LinearClient.new)
|
|
224
|
+
commit_messages = []
|
|
225
|
+
if CapistranoConfig.task_defined?('app:revision')
|
|
226
|
+
revision = CapistranoConfig.current_app_revisions(target_stage)
|
|
227
|
+
|
|
228
|
+
if revision.empty?
|
|
229
|
+
Interaction.fail 'Could not read a server revision from app:revision output.'
|
|
230
|
+
elsif revision.size > 1
|
|
231
|
+
Interaction.warn 'Currently deployed revision differs on servers.'
|
|
232
|
+
Interaction.confirm_or_cancel('Continue deployment without moving Linear issues?')
|
|
233
|
+
else
|
|
234
|
+
# there is one consistent revision deployed across all target servers => Linear issues can be moved
|
|
235
|
+
commit_messages = Git.commits_between(revision.first, source_branch)
|
|
236
|
+
end
|
|
237
|
+
else
|
|
238
|
+
Interaction.warn 'Missing Capistrano task "app:revision". See `geordi help deploy`.'
|
|
239
|
+
puts 'Without it, Geordi can only consider pushed commits for moving Linear issues.'
|
|
240
|
+
commit_messages = Git.commits_between("origin/#{target_branch}", source_branch)
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
linear_issue_ids = LinearClient.extract_issue_ids(commit_messages)
|
|
244
|
+
linear_issue_ids = linear_client.filter_existing_issue_ids(linear_issue_ids)
|
|
245
|
+
relevant_commits = LinearClient.filter_by_issue_ids(commit_messages, linear_issue_ids)
|
|
246
|
+
[linear_issue_ids, relevant_commits]
|
|
247
|
+
end
|
|
248
|
+
|
|
223
249
|
end
|
|
224
250
|
end
|
|
225
251
|
end
|
data/lib/geordi/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: geordi
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 12.
|
|
4
|
+
version: 12.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Henning Koch
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: thor
|
|
@@ -124,7 +123,6 @@ metadata:
|
|
|
124
123
|
bug_tracker_uri: https://github.com/makandra/geordi/issues
|
|
125
124
|
changelog_uri: https://github.com/makandra/geordi/blob/master/CHANGELOG.md
|
|
126
125
|
rubygems_mfa_required: 'true'
|
|
127
|
-
post_install_message:
|
|
128
126
|
rdoc_options: []
|
|
129
127
|
require_paths:
|
|
130
128
|
- lib
|
|
@@ -139,8 +137,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
139
137
|
- !ruby/object:Gem::Version
|
|
140
138
|
version: '0'
|
|
141
139
|
requirements: []
|
|
142
|
-
rubygems_version:
|
|
143
|
-
signing_key:
|
|
140
|
+
rubygems_version: 4.0.6
|
|
144
141
|
specification_version: 4
|
|
145
142
|
summary: Collection of command line tools we use in our daily work with Ruby, Rails
|
|
146
143
|
and Linux at makandra.
|