geordi 12.4.0 → 12.5.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: 173b8f7db8518c9d6da88feff00ca21cb58bd9d764b5e856ac50487e3499b9e4
4
- data.tar.gz: e739f43a3388d185467e14d3dd1259fe55856dd3acc05018c97d65916b9032b6
3
+ metadata.gz: 2e8dcb193d83d352bffb4f62670c93732de779a9471e51f942a0c20ddf19b89b
4
+ data.tar.gz: 152f889f12fe2cfdeea9b1457bc1b6c9d083169d3400a1189588470fc061f4b2
5
5
  SHA512:
6
- metadata.gz: 2e2d3897e290d2afa0d8916779ff28fbbd72b692c5ff55a43c586364cca86a2b389c7375cb03beb1ddfdd31ee9973a25cfb8e55215bf59398c3ae9bca7e55580
7
- data.tar.gz: 7cbc01ebe625752e6f249d84d58810afad0aec51a669101dcd88bd9026011ab324e8d3ea74682b93c24661bf167ede96217d148509314b35fb5f8b749fd9f55b
6
+ metadata.gz: 04732b8f09ba0f7eba641fe8fa5cbff9ea625f311ce42db3b588345a7565b4631d4e67e81420b3b4f357afc98fff3021a458cdb08a03daf15ea93110512e444d
7
+ data.tar.gz: '02938cfa637e316e97b70666a7615696ccc1d881711c8823954529fc109af32ef16f98f132938ce1e04e49c0f007b1e60563e725669aff040eb504e207b7dc5f'
data/CHANGELOG.md CHANGED
@@ -10,6 +10,12 @@ This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html
10
10
  ### Breaking changes
11
11
 
12
12
 
13
+ ## 12.5.0 2025-09-09
14
+
15
+ ### Compatible changes
16
+ * `geordi deploy` will now offer to move deployed issues to a new state if linear_team_ids are configured.
17
+
18
+
13
19
  ## 12.4.0 2025-08-29
14
20
 
15
21
  ### Compatible changes
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- geordi (12.4.0)
4
+ geordi (12.5.0)
5
5
  highline
6
6
  thor (~> 1)
7
7
 
data/README.md CHANGED
@@ -170,6 +170,8 @@ 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. Disable with "skip".
174
+
173
175
  When your project is running Capistrano 3, deployment will use `cap deploy`
174
176
  instead of `cap deploy:migrations`. You can force using `deploy` by passing the
175
177
  -M option: `geordi deploy -M staging`.
@@ -9,8 +9,22 @@ LONGDESC
9
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
- require 'geordi/gitlinear'
13
- Gitlinear.new.branch(from_master: options.from_master)
12
+ require 'geordi/linear_client'
13
+ require 'geordi/git'
14
+
15
+ issue = LinearClient.new.choose_issue
16
+
17
+ local_branches = Git.local_branch_names
18
+ matching_local_branch = local_branches.find { |branch_name| branch_name == issue['branchName'] }
19
+ matching_local_branch ||= local_branches.find { |branch_name| branch_name.include? issue['identifier'].to_s }
20
+
21
+ if matching_local_branch
22
+ Util.run! ['git', 'checkout', matching_local_branch]
23
+ else
24
+ default_branch = Git.default_branch
25
+ Util.run! ['git', 'checkout', default_branch] if options.from_master
26
+ Util.run! ['git', 'checkout', '-b', issue['branchName']]
27
+ end
14
28
 
15
29
  Hint.did_you_know [
16
30
  :commit,
@@ -9,8 +9,23 @@ stored in `~/.config/geordi/global.yml`.
9
9
  LONGDESC
10
10
 
11
11
  def commit(*git_args)
12
- require 'geordi/gitlinear'
13
- Gitlinear.new.commit(git_args)
12
+ require 'geordi/linear_client'
13
+ require 'geordi/git'
14
+ require 'highline'
15
+
16
+ Interaction.warn <<~WARNING unless Git.staged_changes?
17
+ No staged changes. Will create an empty commit.
18
+ WARNING
19
+
20
+ linear_client = LinearClient.new
21
+ highline = HighLine.new
22
+
23
+ issue = linear_client.issue_from_branch || linear_client.choose_issue
24
+ title = "[#{issue['identifier']}] #{issue['title']}"
25
+ description = "Issue: #{issue['url']}"
26
+ extra = highline.ask("\nAdd an optional message").strip
27
+ title << ' - ' << extra if extra != ''
28
+ Util.run!(['git', 'commit', '--allow-empty', '-m', title, '-m', description, *git_args])
14
29
 
15
30
  Hint.did_you_know [
16
31
  :branch,
@@ -28,6 +28,8 @@ 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. Disable with "skip".
32
+
31
33
  When your project is running Capistrano 3, deployment will use `cap deploy`
32
34
  instead of `cap deploy:migrations`. You can force using `deploy` by passing the
33
35
  -M option: `geordi deploy -M staging`.
@@ -39,6 +41,12 @@ option :current_branch, aliases: '-c', type: :boolean,
39
41
  desc: 'Set DEPLOY_BRANCH to the current branch during deploy'
40
42
 
41
43
  def deploy(target_stage = nil)
44
+ require 'geordi/git'
45
+ require 'geordi/linear_client'
46
+
47
+ settings = Settings.new
48
+ linear_client = LinearClient.new
49
+
42
50
  # Set/Infer default values
43
51
  branch_stage_map = { 'master' => 'staging', 'main' => 'staging', 'production' => 'production' }
44
52
  if target_stage && !Util.deploy_targets.include?(target_stage)
@@ -48,7 +56,7 @@ def deploy(target_stage = nil)
48
56
  end
49
57
 
50
58
  # Ask for required information
51
- target_stage ||= Interaction.prompt 'Deployment stage:', branch_stage_map.fetch(Util.current_branch, 'staging')
59
+ target_stage ||= Interaction.prompt 'Deployment stage:', branch_stage_map.fetch(Git.current_branch, 'staging')
52
60
  capistrano_config = CapistranoConfig.new(target_stage)
53
61
 
54
62
  if options.current_branch
@@ -60,18 +68,25 @@ def deploy(target_stage = nil)
60
68
  set :branch, ENV['DEPLOY_BRANCH'] || 'master'
61
69
  ERROR
62
70
 
63
- source_branch = target_branch = Util.current_branch
71
+ source_branch = target_branch = Git.current_branch
64
72
  else # Normal deploy
65
- source_branch = Interaction.prompt 'Source branch:', Util.current_branch
73
+ source_branch = Interaction.prompt 'Source branch:', Git.current_branch
66
74
 
67
75
  deploy_branch = capistrano_config.branch
68
- deploy_branch ||= Util.git_default_branch
76
+ deploy_branch ||= Git.default_branch
69
77
  target_branch = Interaction.prompt 'Deploy branch:', deploy_branch
70
78
  end
71
79
 
80
+ if settings.linear_integration_set_up?
81
+ config_state = settings.linear_state_after_deploy(target_stage)
82
+ config_state = 'skip' if config_state.empty?
83
+ target_state = Interaction.prompt("Move deployed Linear issues to state:", config_state)
84
+ target_state = '' if target_state.empty? || target_state == 'skip'
85
+ settings.persist_linear_state_after_deploy(target_stage, target_state)
86
+ end
87
+
72
88
  merge_needed = (source_branch != target_branch)
73
89
  push_needed = merge_needed || `git cherry -v | wc -l`.strip.to_i > 0
74
- push_needed = false if Util.testing? # Hard to test
75
90
 
76
91
  Interaction.announce "Checking whether your #{source_branch} branch is ready" ############
77
92
  Util.run!("git checkout #{source_branch}")
@@ -89,13 +104,23 @@ def deploy(target_stage = nil)
89
104
 
90
105
  Interaction.announce 'You are about to:' #################################################
91
106
  Interaction.note "Merge branch #{source_branch} into #{target_branch}" if merge_needed
107
+ linear_issue_ids = []
92
108
  if push_needed
93
- Interaction.note 'Push these commits:' if push_needed
109
+ Interaction.note 'Push these commits:'
94
110
  Util.run!("git --no-pager log origin/#{target_branch}..#{source_branch} --oneline")
111
+
112
+ commit_messages = Git.commits_between(source_branch, target_branch)
113
+ linear_issue_ids = linear_client.extract_issue_ids(commit_messages)
95
114
  end
96
115
  Interaction.note "Deploy to #{target_stage}"
97
116
  Interaction.note "From current branch #{source_branch}" if options.current_branch
98
117
 
118
+ if !linear_issue_ids.empty? && target_state && !target_state.empty?
119
+ relevant_commits = linear_client.filter_by_issue_ids(commit_messages, linear_issue_ids)
120
+ Interaction.note("Move these Linear issues to state \"#{target_state}\":")
121
+ puts relevant_commits.join("\n")
122
+ end
123
+
99
124
  if Interaction.prompt('Go ahead with the deployment?', 'n', /y|yes/)
100
125
  puts
101
126
  git_call = []
@@ -115,6 +140,10 @@ def deploy(target_stage = nil)
115
140
 
116
141
  Util.run!(capistrano_call, show_cmd: true)
117
142
 
143
+ if !linear_issue_ids.empty? && target_state && !target_state.empty?
144
+ linear_client.move_issues_to_state(linear_issue_ids, target_state)
145
+ end
146
+
118
147
  Interaction.success 'Deployment complete.'
119
148
 
120
149
  Hint.did_you_know [
@@ -9,7 +9,9 @@ will tell each step before performing it.
9
9
  LONGDESC
10
10
 
11
11
  def security_update(step = 'prepare')
12
- master = Util.git_default_branch
12
+ require 'geordi/git'
13
+
14
+ master = Git.default_branch
13
15
 
14
16
  case step
15
17
  when 'prepare'
data/lib/geordi/git.rb ADDED
@@ -0,0 +1,53 @@
1
+ module Geordi
2
+ class Git
3
+ class << self
4
+ def local_branch_names
5
+ @local_branch_names ||= begin
6
+ branch_list_string = if Util.testing?
7
+ ENV['GEORDI_TESTING_GIT_BRANCHES'].to_s
8
+ else
9
+ `git branch --format="%(refname:short)"`
10
+ end
11
+
12
+ branch_list_string.strip.split("\n")
13
+ end
14
+ end
15
+
16
+ def current_branch
17
+ if Util.testing?
18
+ default_branch
19
+ else
20
+ `git rev-parse --abbrev-ref HEAD`.strip
21
+ end
22
+ end
23
+
24
+ def staged_changes?
25
+ if Util.testing?
26
+ ENV['GEORDI_TESTING_STAGED_CHANGES'] == 'true'
27
+ else
28
+ statuses = `git status --porcelain`.split("\n")
29
+ statuses.any? { |l| /^[A-Z]/i =~ l }
30
+ end
31
+ end
32
+
33
+ def default_branch
34
+ default_branch = if Util.testing?
35
+ ENV['GEORDI_TESTING_DEFAULT_BRANCH']
36
+ else
37
+ head_symref = `git ls-remote --symref origin HEAD`
38
+ head_symref[%r{\Aref: refs/heads/(\S+)\sHEAD}, 1]
39
+ end
40
+
41
+ default_branch || 'master'
42
+ end
43
+
44
+ def commits_between(source_branch, target_branch)
45
+ return [ENV['GEORDI_TESTING_GIT_COMMIT']] if Util.testing?
46
+
47
+ commits = `git --no-pager log --pretty=format:%s origin/#{target_branch}..#{source_branch}`
48
+
49
+ commits&.split("\n")
50
+ end
51
+ end
52
+ end
53
+ end
@@ -4,7 +4,7 @@ require 'net/http'
4
4
  require 'json'
5
5
 
6
6
  module Geordi
7
- class Gitlinear
7
+ class LinearClient
8
8
  # This require-style is to prevent Ruby from loading files of a different
9
9
  # version of Geordi.
10
10
  require File.expand_path('settings', __dir__)
@@ -16,47 +16,6 @@ module Geordi
16
16
  self.settings = Settings.new
17
17
  end
18
18
 
19
- def commit(git_args)
20
- Interaction.warn <<~WARNING unless Util.staged_changes?
21
- No staged changes. Will create an empty commit.
22
- WARNING
23
-
24
- issue = issue_from_branch || choose_issue
25
- create_commit "[#{issue['identifier']}] #{issue['title']}", "Issue: #{issue['url']}", *git_args
26
- end
27
-
28
- def branch(from_master: false)
29
- issue = choose_issue
30
-
31
- local_branches = local_branch_names
32
- matching_local_branch = local_branches.find { |branch_name| branch_name == issue['branchName'] }
33
- matching_local_branch ||= local_branches.find { |branch_name| branch_name.include? issue['identifier'].to_s }
34
-
35
- if matching_local_branch
36
- Util.run! ['git', 'checkout', matching_local_branch]
37
- else
38
- default_branch = Util.git_default_branch
39
- Util.run! ['git', 'checkout', default_branch] if from_master
40
- Util.run! ['git', 'checkout', '-b', issue['branchName']]
41
- end
42
- end
43
-
44
- private
45
-
46
- attr_accessor :highline, :settings
47
-
48
- def local_branch_names
49
- @local_branch_names ||= begin
50
- branch_list_string = if Util.testing?
51
- ENV['GEORDI_TESTING_GIT_BRANCHES'].to_s
52
- else
53
- `git branch --format="%(refname:short)"`
54
- end
55
-
56
- branch_list_string.strip.split("\n")
57
- end
58
- end
59
-
60
19
  def choose_issue
61
20
  if Util.testing?
62
21
  return dummy_issue_for_testing
@@ -94,23 +53,64 @@ module Geordi
94
53
  nil
95
54
  end
96
55
 
56
+ def move_issues_to_state(issue_identifiers, state)
57
+ return if Util.testing?
58
+
59
+ issues = fetch_linear_issues # This only retrieves issues for the configured linear team ids
60
+ state_ids_by_team_id = state_ids_by_team_id(state)
61
+
62
+ issue_identifiers.each do |identifier|
63
+ issue = issues.find { |i| i['identifier'] == identifier }
64
+
65
+ skip unless issue && (state_id = state_ids_by_team_id[issue.dig('team', 'id')])
66
+
67
+ update_issue_state(issue['id'], state_id)
68
+ end
69
+ end
70
+
97
71
  def issue_from_branch
98
72
  issue = if Util.testing?
99
73
  dummy_issue_for_testing if ENV['GEORDI_TESTING_ISSUE_MATCHES'] == 'true'
100
74
  else
101
- current_branch = Util.current_branch
102
- issue = fetch_linear_issues.find { |issue| issue['branchName'] == current_branch }
75
+ current_branch = Git.current_branch
76
+ fetch_linear_issues.find { |issue| issue['branchName'] == current_branch }
103
77
  end
104
78
 
105
- return unless issue
79
+ if issue
80
+ id = issue['identifier']
81
+ title = issue['title']
82
+
83
+ Interaction.note 'Auto-detected issue from branch name:'
84
+ puts HighLine::BOLD + "[#{id}] #{title}" + HighLine::RESET
85
+
86
+ issue if Interaction.prompt('Use it?', 'y', /y|yes/i)
87
+ end
88
+ end
89
+
90
+ def extract_issue_ids(commit_messages)
91
+ found_ids = []
92
+
93
+ regex = /^\[[A-Z]+\d*-\d+\]/
94
+
95
+ commit_messages&.each do |line|
96
+ line&.scan(regex) do |match|
97
+ found_ids << match
98
+ end
99
+ end
106
100
 
107
- id = issue['identifier']
108
- title = issue['title']
101
+ found_ids.map { |id| id.delete('[]') } # [W-365] => W-365
102
+ end
109
103
 
110
- Interaction.note "Auto-detected issue #{HighLine::BOLD}[#{id}] #{title}#{HighLine::RESET} from branch name."
111
- Interaction.prompt("Use it?", "y", /y|yes/i) ? issue : nil
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
112
108
  end
113
109
 
110
+ private
111
+
112
+ attr_accessor :highline, :settings
113
+
114
114
  def dummy_issue_for_testing
115
115
  settings.linear_api_key
116
116
  ENV['GEORDI_TESTING_NO_LINEAR_ISSUES'] == 'true' ? Geordi::Interaction.fail('No issues to offer.') : {
@@ -123,12 +123,6 @@ module Geordi
123
123
  }
124
124
  end
125
125
 
126
- def create_commit(title, description, *git_args)
127
- extra = highline.ask("\nAdd an optional message").strip
128
- title << ' - ' << extra if extra != ''
129
- Util.run!(['git', 'commit', '--allow-empty', '-m', title, '-m', description, *git_args])
130
- end
131
-
132
126
  def fetch_linear_issues
133
127
  @linear_issues ||= begin
134
128
  team_ids = settings.linear_team_ids
@@ -150,6 +144,7 @@ module Geordi
150
144
  nodes {
151
145
  title
152
146
  identifier
147
+ id
153
148
  url
154
149
  branchName
155
150
  assignee {
@@ -159,7 +154,10 @@ module Geordi
159
154
  state {
160
155
  name
161
156
  position
162
- }
157
+ }
158
+ team {
159
+ id
160
+ }
163
161
  }
164
162
  }
165
163
  }
@@ -169,6 +167,70 @@ module Geordi
169
167
  end
170
168
  end
171
169
 
170
+ def state_ids_by_team_id(state_name)
171
+ result = {}
172
+
173
+ team_ids = settings.linear_team_ids
174
+ filter = {
175
+ "team": {
176
+ "id": {
177
+ "in": team_ids,
178
+ }
179
+ }
180
+ }
181
+ response = query_api(<<~GRAPHQL, filter: filter)
182
+ query workflowStates($filter: WorkflowStateFilter) {
183
+ workflowStates(filter: $filter) {
184
+ nodes {
185
+ id
186
+ name
187
+ team {
188
+ id
189
+ name
190
+ }
191
+ }
192
+ }
193
+ }
194
+ GRAPHQL
195
+
196
+ response = response.dig(*%w[workflowStates nodes])
197
+
198
+ team_ids.each do |team_id|
199
+ found_state = response.find do |item|
200
+ item["team"]["id"] == team_id && item["name"] == state_name
201
+ end
202
+
203
+ if found_state
204
+ result[team_id] = found_state["id"]
205
+ else
206
+ team_identifier = response.find { |item| item.dig('team', 'id') == team_id }&.dig('team', 'name') || team_id
207
+ Interaction.warn("Could not find the state \"#{state_name}\" for team \"#{team_identifier}\". Skipping its issues.")
208
+ end
209
+ end
210
+
211
+ if result.empty?
212
+ Interaction.fail("The issue state #{state_name.inspect} does not exist.")
213
+ end
214
+
215
+ result
216
+ end
217
+
218
+ def update_issue_state(issue_id, state_id)
219
+ query_api(<<~GRAPHQL, nil)
220
+ mutation UpdateIssueState {
221
+ issueUpdate(
222
+ id: "#{issue_id}"
223
+ input: {
224
+ stateId: "#{state_id}"
225
+ }
226
+ )
227
+ {
228
+ success
229
+ }
230
+ }
231
+ GRAPHQL
232
+ end
233
+
172
234
  def query_api(attributes, variables)
173
235
  uri = URI(API_ENDPOINT)
174
236
  loading_message = "Connecting to #{uri.host} ... "
@@ -16,7 +16,7 @@ module Geordi
16
16
  linear_team_ids
17
17
  ].freeze
18
18
 
19
- ALLOWED_LOCAL_SETTINGS = %w[ linear_team_ids irb_flags ].freeze
19
+ ALLOWED_LOCAL_SETTINGS = %w[ linear_team_ids linear_state_after_deploy irb_flags].freeze
20
20
 
21
21
  SETTINGS_WARNED = 'GEORDI_INVALID_SETTINGS_WARNED'
22
22
 
@@ -75,6 +75,32 @@ module Geordi
75
75
  team_ids
76
76
  end
77
77
 
78
+ def linear_integration_set_up?
79
+ team_ids = get_linear_team_ids
80
+ !team_ids.empty?
81
+ end
82
+
83
+ def linear_state_after_deploy(stage)
84
+ config_state = @local_settings['linear_state_after_deploy']
85
+
86
+ if config_state && config_state[stage]
87
+ config_state[stage]
88
+ else
89
+ ''
90
+ end
91
+ end
92
+
93
+ def persist_linear_state_after_deploy(stage, target_state)
94
+ config_state = @local_settings.dig('linear_state_after_deploy', stage)
95
+
96
+ unless target_state.eql?(config_state)
97
+ @local_settings['linear_state_after_deploy'] ||= Hash.new
98
+ @local_settings['linear_state_after_deploy'][stage] = target_state
99
+ save_local_settings
100
+ end
101
+ end
102
+
103
+
78
104
  private
79
105
 
80
106
  def read_settings
@@ -125,6 +151,16 @@ module Geordi
125
151
  end
126
152
  end
127
153
 
154
+ def save_local_settings
155
+ unless Util.testing?
156
+ local_path = LOCAL_SETTINGS_FILE_NAME
157
+
158
+ File.open(local_path, 'w') do |file|
159
+ file.write @local_settings.to_yaml
160
+ end
161
+ end
162
+ end
163
+
128
164
  def inquire_linear_api_key
129
165
  Geordi::Interaction.note 'Create a personal API key here: https://linear.app/makandra/settings/account/security'
130
166
  token = Geordi::Interaction.prompt("Please enter the API key:")
@@ -135,6 +171,13 @@ module Geordi
135
171
  token
136
172
  end
137
173
 
174
+ def get_linear_team_ids
175
+ local_team_ids = normalize_team_ids(@local_settings['linear_team_ids'])
176
+ global_team_ids = normalize_team_ids(@global_settings['linear_team_ids'])
177
+
178
+ local_team_ids | global_team_ids
179
+ end
180
+
138
181
  def normalize_team_ids(team_ids)
139
182
  case team_ids
140
183
  when Array
data/lib/geordi/util.rb CHANGED
@@ -119,22 +119,6 @@ module Geordi
119
119
  end
120
120
  end
121
121
 
122
- def current_branch
123
- if testing?
124
- git_default_branch
125
- else
126
- `git rev-parse --abbrev-ref HEAD`.strip
127
- end
128
- end
129
-
130
- def staged_changes?
131
- if testing?
132
- ENV['GEORDI_TESTING_STAGED_CHANGES'] == 'true'
133
- else
134
- statuses = `git status --porcelain`.split("\n")
135
- statuses.any? { |l| /^[A-Z]/i =~ l }
136
- end
137
- end
138
122
 
139
123
  def deploy_targets
140
124
  Dir['config/deploy/*'].map do |f|
@@ -221,18 +205,6 @@ module Geordi
221
205
  def rspec_path?(path)
222
206
  %r{(^|\/)spec|_spec\.rb($|:)}.match?(path)
223
207
  end
224
-
225
- def git_default_branch
226
- default_branch = if testing?
227
- ENV['GEORDI_TESTING_DEFAULT_BRANCH']
228
- else
229
- head_symref = `git ls-remote --symref origin HEAD`
230
- head_symref[%r{\Aref: refs/heads/(\S+)\sHEAD}, 1]
231
- end
232
-
233
- default_branch || 'master'
234
- end
235
-
236
208
  end
237
209
  end
238
210
  end
@@ -1,3 +1,3 @@
1
1
  module Geordi
2
- VERSION = '12.4.0'.freeze
2
+ VERSION = '12.5.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: 12.4.0
4
+ version: 12.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Henning Koch
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-08-29 00:00:00.000000000 Z
11
+ date: 2025-09-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -102,9 +102,10 @@ files:
102
102
  - lib/geordi/cucumber.rb
103
103
  - lib/geordi/db_cleaner.rb
104
104
  - lib/geordi/dump_loader.rb
105
- - lib/geordi/gitlinear.rb
105
+ - lib/geordi/git.rb
106
106
  - lib/geordi/hint.rb
107
107
  - lib/geordi/interaction.rb
108
+ - lib/geordi/linear_client.rb
108
109
  - lib/geordi/remote.rb
109
110
  - lib/geordi/settings.rb
110
111
  - lib/geordi/util.rb
@@ -123,7 +124,7 @@ metadata:
123
124
  bug_tracker_uri: https://github.com/makandra/geordi/issues
124
125
  changelog_uri: https://github.com/makandra/geordi/blob/master/CHANGELOG.md
125
126
  rubygems_mfa_required: 'true'
126
- post_install_message:
127
+ post_install_message:
127
128
  rdoc_options: []
128
129
  require_paths:
129
130
  - lib
@@ -139,7 +140,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
139
140
  version: '0'
140
141
  requirements: []
141
142
  rubygems_version: 3.1.6
142
- signing_key:
143
+ signing_key:
143
144
  specification_version: 4
144
145
  summary: Collection of command line tools we use in our daily work with Ruby, Rails
145
146
  and Linux at makandra.