geet 0.22.0 → 0.24.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.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +34 -0
  3. data/.gitignore +0 -1
  4. data/.ruby-version +1 -0
  5. data/Gemfile +3 -6
  6. data/bin/geet +2 -8
  7. data/bin/tapioca +1 -14
  8. data/geet.gemspec +8 -6
  9. data/lib/geet/commandline/configuration.rb +0 -1
  10. data/lib/geet/commandline/editor.rb +0 -2
  11. data/lib/geet/git/repository.rb +12 -21
  12. data/lib/geet/github/abstract_issue.rb +0 -6
  13. data/lib/geet/github/api_interface.rb +0 -1
  14. data/lib/geet/github/issue.rb +0 -3
  15. data/lib/geet/github/milestone.rb +0 -2
  16. data/lib/geet/github/pr.rb +0 -3
  17. data/lib/geet/github/user.rb +0 -3
  18. data/lib/geet/gitlab/pr.rb +3 -1
  19. data/lib/geet/helpers/json_helper.rb +4 -0
  20. data/lib/geet/helpers/os_helper.rb +29 -8
  21. data/lib/geet/helpers/services_workflow_helper.rb +12 -0
  22. data/lib/geet/helpers/summary_helper.rb +7 -0
  23. data/lib/geet/services/abstract_create_issue.rb +5 -5
  24. data/lib/geet/services/add_upstream_repo.rb +6 -0
  25. data/lib/geet/services/close_milestones.rb +0 -2
  26. data/lib/geet/services/comment_pr.rb +0 -3
  27. data/lib/geet/services/create_gist.rb +0 -4
  28. data/lib/geet/services/create_issue.rb +0 -4
  29. data/lib/geet/services/create_pr.rb +4 -6
  30. data/lib/geet/services/list_issues.rb +0 -3
  31. data/lib/geet/services/merge_pr.rb +0 -2
  32. data/lib/geet/services/open_pr.rb +0 -3
  33. data/lib/geet/services/open_repo.rb +0 -2
  34. data/lib/geet/shared/http_error.rb +8 -2
  35. data/lib/geet/shared/repo_permissions.rb +7 -2
  36. data/lib/geet/shared/selection.rb +3 -2
  37. data/lib/geet/utils/attributes_selection_manager.rb +15 -4
  38. data/lib/geet/utils/git_client.rb +4 -1
  39. data/lib/geet/utils/manual_list_selection.rb +39 -14
  40. data/lib/geet/utils/string_matching_selection.rb +5 -0
  41. data/lib/geet/version.rb +1 -1
  42. data/lib/geet.rb +11 -0
  43. data/sorbet/config +7 -0
  44. data/sorbet/rbi/annotations/.gitattributes +1 -0
  45. data/sorbet/rbi/annotations/rainbow.rbi +269 -0
  46. data/sorbet/rbi/annotations/webmock.rbi +9 -0
  47. data/sorbet/rbi/gems/.gitattributes +1 -0
  48. data/sorbet/rbi/gems/addressable@2.8.7.rbi +1994 -0
  49. data/sorbet/rbi/gems/ast@2.4.2.rbi +585 -0
  50. data/sorbet/rbi/gems/base64@0.3.0.rbi +545 -0
  51. data/sorbet/rbi/gems/benchmark@0.5.0.rbi +637 -0
  52. data/sorbet/rbi/gems/bigdecimal@3.1.8.rbi +9 -0
  53. data/sorbet/rbi/gems/byebug@11.1.3.rbi +37 -0
  54. data/sorbet/rbi/gems/crack@1.0.0.rbi +145 -0
  55. data/sorbet/rbi/gems/diff-lcs@1.6.2.rbi +1134 -0
  56. data/sorbet/rbi/gems/erubi@1.13.1.rbi +155 -0
  57. data/sorbet/rbi/gems/hashdiff@1.1.1.rbi +353 -0
  58. data/sorbet/rbi/gems/json@2.7.2.rbi +1608 -0
  59. data/sorbet/rbi/gems/logger@1.7.0.rbi +963 -0
  60. data/sorbet/rbi/gems/netrc@0.11.0.rbi +159 -0
  61. data/sorbet/rbi/gems/ostruct@0.6.3.rbi +354 -0
  62. data/sorbet/rbi/gems/parallel@1.27.0.rbi +291 -0
  63. data/sorbet/rbi/gems/parseconfig@1.1.2.rbi +9 -0
  64. data/sorbet/rbi/gems/parser@3.3.9.0.rbi +5535 -0
  65. data/sorbet/rbi/gems/pastel@0.8.0.rbi +9 -0
  66. data/sorbet/rbi/gems/prism@1.6.0.rbi +42068 -0
  67. data/sorbet/rbi/gems/public_suffix@6.0.1.rbi +936 -0
  68. data/sorbet/rbi/gems/racc@1.8.1.rbi +154 -0
  69. data/sorbet/rbi/gems/rainbow@3.1.1.rbi +9 -0
  70. data/sorbet/rbi/gems/rake@12.3.3.rbi +3020 -0
  71. data/sorbet/rbi/gems/rbi@0.3.7.rbi +7115 -0
  72. data/sorbet/rbi/gems/rbs@4.0.0.dev.5.rbi +8311 -0
  73. data/sorbet/rbi/gems/regexp_parser@2.11.2.rbi +9 -0
  74. data/sorbet/rbi/gems/require-hooks@0.2.2.rbi +110 -0
  75. data/sorbet/rbi/gems/rexml@3.3.5.rbi +5283 -0
  76. data/sorbet/rbi/gems/rspec-core@3.13.6.rbi +11004 -0
  77. data/sorbet/rbi/gems/rspec-expectations@3.13.5.rbi +8189 -0
  78. data/sorbet/rbi/gems/rspec-mocks@3.13.6.rbi +5350 -0
  79. data/sorbet/rbi/gems/rspec-support@3.13.6.rbi +1627 -0
  80. data/sorbet/rbi/gems/rspec@3.13.2.rbi +83 -0
  81. data/sorbet/rbi/gems/rubocop-ast@1.46.0.rbi +9 -0
  82. data/sorbet/rbi/gems/rubocop@1.35.1.rbi +9 -0
  83. data/sorbet/rbi/gems/ruby-progressbar@1.13.0.rbi +9 -0
  84. data/sorbet/rbi/gems/simple_scripting@0.14.0.rbi +9 -0
  85. data/sorbet/rbi/gems/spoom@1.7.11.rbi +5878 -0
  86. data/sorbet/rbi/gems/strscan@3.1.0.rbi +9 -0
  87. data/sorbet/rbi/gems/tapioca@0.17.10.rbi +3514 -0
  88. data/sorbet/rbi/gems/thor@1.4.0.rbi +4399 -0
  89. data/sorbet/rbi/gems/tsort@0.2.0.rbi +393 -0
  90. data/sorbet/rbi/gems/tty-color@0.6.0.rbi +9 -0
  91. data/sorbet/rbi/gems/tty-cursor@0.7.1.rbi +9 -0
  92. data/sorbet/rbi/gems/tty-prompt@0.23.1.rbi +3307 -0
  93. data/sorbet/rbi/gems/tty-reader@0.9.0.rbi +9 -0
  94. data/sorbet/rbi/gems/tty-screen@0.8.2.rbi +9 -0
  95. data/sorbet/rbi/gems/unicode-display_width@2.5.0.rbi +9 -0
  96. data/sorbet/rbi/gems/vcr@6.1.0.rbi +2830 -0
  97. data/sorbet/rbi/gems/webmock@3.1.1.rbi +1660 -0
  98. data/sorbet/rbi/gems/wisper@2.0.1.rbi +9 -0
  99. data/sorbet/rbi/gems/yard-sorbet@0.9.0.rbi +435 -0
  100. data/sorbet/rbi/gems/yard@0.9.37.rbi +18379 -0
  101. data/sorbet/rbi/gems/zeitwerk@2.7.4.rbi +1196 -0
  102. data/sorbet/rbi/shims/unresolved_gem_constants.rbi +4 -0
  103. data/sorbet/tapioca/config.yml +13 -0
  104. data/sorbet/tapioca/require.rb +4 -0
  105. data/spec/integration/create_pr_spec.rb +157 -147
  106. data/spec/integration/merge_pr_spec.rb +84 -85
  107. data/spec/spec_helper.rb +1 -1
  108. metadata +126 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 51d12d8a213d135faaf048ab5591329373217d1159ef4796e70f8fcfd4504a64
4
- data.tar.gz: 259d6c5267db6d9f8522e33690a6c1cb7455716e43c96cac4ffbee0c22d8fcaf
3
+ metadata.gz: eeb2fbfeebdf5fad15d266e1c4b30fb5554f0418057b5fe279a4395149e9b4a2
4
+ data.tar.gz: 78b4a9f2de093f896d494de393991980e9c619d10ce979a9b9b0941fff39381d
5
5
  SHA512:
6
- metadata.gz: eb69f8b3a197a6ef6646fdea3cfc83510aa0b0a89c739011bc250f136ff4247a9bc33459769499d887cd358a7d3dac75883e08592420ee49884848fea1c77f35
7
- data.tar.gz: 7a327f36d1711c6960dcfe32eac43881b5356f9ba1ba96e8f81fe96647b479e1499391c648b0ad7d1cc330e50ccfb9ca0c08eab0ac353e54e5fb6f4afa7621cb
6
+ metadata.gz: 17409c6c638abc9e27ffbae3af34bec526484c2baf084ddc7adff5beaf91ef3355377cb8bc515afc54fd97b3dc67090a26422891733638cacf3efadd26e4fdf4
7
+ data.tar.gz: f6498c9223f91625dd85117322bef311a74b3bd027b9e4d51cb3e4bdea076418822e9637e56de9a462713eba218aaba33380509d23ddc115f04c7075ec6f3c3f
@@ -0,0 +1,34 @@
1
+ name: CI
2
+
3
+ on: [pull_request]
4
+
5
+ jobs:
6
+ test:
7
+ runs-on: ubuntu-latest
8
+ env:
9
+ GITHUB_API_TOKEN: foo
10
+ GITLAB_API_TOKEN: bar
11
+ strategy:
12
+ matrix:
13
+ ruby-version: [head, 4.0, 3.4, 3.3, 3.2]
14
+ fail-fast: false
15
+ continue-on-error: ${{ endsWith(matrix['ruby-version'], 'head') || matrix['ruby-version'] == 'debug' }}
16
+ steps:
17
+ - uses: actions/checkout@v5
18
+ - uses: ruby/setup-ruby@v1
19
+ with:
20
+ ruby-version: ${{ matrix.ruby-version }}
21
+ bundler-cache: true
22
+ - run: bundle install
23
+ - run: bundle exec rspec
24
+ sorbet:
25
+ runs-on: ubuntu-latest
26
+ steps:
27
+ - uses: actions/checkout@v5
28
+ with:
29
+ fetch-depth: ${{ env.REPO_FETCH_DEPTH }}
30
+ - uses: ruby/setup-ruby@v1
31
+ with:
32
+ bundler-cache: true
33
+ - name: Sorbet
34
+ run: bundle exec srb typecheck
data/.gitignore CHANGED
@@ -1,4 +1,3 @@
1
- /.ruby-version
2
1
  /.ruby-gemset
3
2
  /Gemfile.lock
4
3
  /test_repos
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.4.6
data/Gemfile CHANGED
@@ -4,18 +4,15 @@ source 'https://rubygems.org'
4
4
 
5
5
  gemspec
6
6
 
7
- gem 'sorbet-runtime'
8
-
9
7
  group :development do
10
- gem 'sorbet'
11
8
  gem 'byebug'
12
- gem 'rubocop', '~> 1.35.0', require: :false
9
+ gem 'rubocop', '~> 1.35.0', require: false
13
10
  gem 'spoom', require: false
14
- gem 'tapioca', require: false
11
+ gem 'tapioca', '>= 0.17.10', require: false
15
12
  end
16
13
 
17
14
  group :test do
18
15
  gem 'rspec', '~> 3.13.0'
19
- gem 'vcr', '~> 6.1.0'
16
+ gem 'vcr', '~> 6.4.0'
20
17
  gem 'webmock', '~> 3.1.1'
21
18
  end
data/bin/geet CHANGED
@@ -2,14 +2,8 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require 'simple_scripting/configuration'
5
- require_relative '../lib/geet/commandline/configuration'
6
- require_relative '../lib/geet/commandline/commands'
7
- require_relative '../lib/geet/commandline/editor'
8
- require_relative '../lib/geet/git/repository'
9
- require_relative '../lib/geet/helpers/summary_helper'
10
- require_relative '../lib/geet/shared/selection'
11
- require_relative '../lib/geet/utils/git_client'
12
- Dir[File.join(__dir__, '../lib/geet/services/*.rb')].each { |filename| require filename }
5
+ require 'tmpdir'
6
+ require_relative '../lib/geet'
13
7
 
14
8
  class GeetLauncher
15
9
  include Geet
data/bin/tapioca CHANGED
@@ -8,20 +8,7 @@
8
8
  # this file is here to facilitate running it.
9
9
  #
10
10
 
11
- require "pathname"
12
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
- Pathname.new(__FILE__).realpath)
14
-
15
- bundle_binstub = File.expand_path("../bundle", __FILE__)
16
-
17
- if File.file?(bundle_binstub)
18
- if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
- load(bundle_binstub)
20
- else
21
- abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
- Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
- end
24
- end
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
25
12
 
26
13
  require "rubygems"
27
14
  require "bundler/setup"
data/geet.gemspec CHANGED
@@ -1,24 +1,26 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- $LOAD_PATH << File.expand_path('lib', __dir__)
4
-
5
- require 'geet/version'
3
+ require_relative 'lib/geet/version'
6
4
 
7
5
  Gem::Specification.new do |s|
8
6
  s.name = 'geet'
9
7
  s.version = Geet::VERSION
10
8
  s.platform = Gem::Platform::RUBY
11
- s.required_ruby_version = '>= 2.7.0'
9
+ s.required_ruby_version = '>= 3.2.0'
12
10
  s.authors = ['Saverio Miroddi']
13
- s.date = '2024-08-26'
11
+ s.date = '2026-01-13'
14
12
  s.email = ['saverio.pub2@gmail.com']
15
13
  s.homepage = 'https://github.com/saveriomiroddi/geet'
16
14
  s.summary = 'Commandline interface for performing SCM host operations, eg. create a PR on GitHub'
17
15
  s.description = 'Commandline interface for performing SCM host operations, eg. create a PR on GitHub, with support for multiple hosts.'
18
- s.license = 'GPL-3.0'
16
+ s.license = 'GPL-3.0-only'
19
17
 
18
+ s.add_runtime_dependency 'base64', '~> 0.3.0'
19
+ s.add_runtime_dependency 'ostruct', '~> 0.6.3'
20
20
  s.add_runtime_dependency 'simple_scripting', '~> 0.14.0'
21
+ s.add_runtime_dependency 'sorbet-runtime', '= 0.6.12883'
21
22
  s.add_runtime_dependency 'tty-prompt', '~> 0.23.1'
23
+ s.add_runtime_dependency 'zeitwerk', '~> 2.7'
22
24
 
23
25
  s.add_development_dependency 'rake', '~> 12.3'
24
26
 
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'simple_scripting/argv'
4
- require_relative 'commands'
5
4
 
6
5
  module Geet
7
6
  module Commandline
@@ -2,8 +2,6 @@
2
2
 
3
3
  require 'tempfile'
4
4
 
5
- require_relative '../helpers/os_helper'
6
-
7
5
  module Geet
8
6
  module Commandline
9
7
  class Editor
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../utils/git_client'
4
-
5
3
  module Geet
6
4
  module Git
7
5
  # This class represents, for convenience, both the local and the remote repository, but the
@@ -122,31 +120,24 @@ module Geet
122
120
  def attempt_provider_call(class_name, meth, *args)
123
121
  module_name = provider_name.capitalize
124
122
 
125
- require_provider_modules
126
-
127
123
  full_class_name = "Geet::#{module_name}::#{class_name}"
128
124
 
129
- if Kernel.const_defined?(full_class_name)
130
- klass = Kernel.const_get(full_class_name)
131
-
132
- if !klass.respond_to?(meth)
133
- raise "The functionality invoked (#{class_name}.#{meth}) is not currently supported!"
134
- end
135
-
136
- # Can't use ruby2_keywords, because the method definitions use named keyword arguments.
137
- #
138
- kwargs = args.last.is_a?(Hash) ? args.pop : {}
139
-
140
- klass.send(meth, *args, **kwargs)
141
- else
125
+ # Use const_get directly to trigger Zeitwerk autoloading
126
+ begin
127
+ klass = Object.const_get(full_class_name)
128
+ rescue NameError
142
129
  raise "The class referenced (#{full_class_name}) is not currently supported!"
143
130
  end
144
- end
145
131
 
146
- def require_provider_modules
147
- files_pattern = "#{__dir__}/../#{provider_name}/*.rb"
132
+ if !klass.respond_to?(meth)
133
+ raise "The functionality invoked (#{class_name}.#{meth}) is not currently supported!"
134
+ end
135
+
136
+ # Can't use ruby2_keywords, because the method definitions use named keyword arguments.
137
+ #
138
+ kwargs = args.last.is_a?(Hash) ? args.pop : {}
148
139
 
149
- Dir[files_pattern].each { |filename| require filename }
140
+ klass.send(meth, *args, **kwargs)
150
141
  end
151
142
 
152
143
  # WARNINGS
@@ -2,12 +2,6 @@
2
2
 
3
3
  module Geet
4
4
  module Github
5
- # It seems that autoloading will be deprecated, but it's currently the cleanest solution
6
- # to the legitimate problem of AbstractIssue needing Issue/PR to be loaded (due to :list),
7
- # and viceversa (due to class definition).
8
- autoload :Issue, File.expand_path('issue', __dir__)
9
- autoload :PR, File.expand_path('pr', __dir__)
10
-
11
5
  # For clarity, in this class we keep only the identical logic between the subclasses, but
12
6
  # other methods could be moved in here at some complexity cost.
13
7
  class AbstractIssue
@@ -3,7 +3,6 @@
3
3
  require 'uri'
4
4
  require 'net/http'
5
5
  require 'json'
6
- require_relative '../shared/http_error'
7
6
 
8
7
  module Geet
9
8
  module Github
@@ -2,9 +2,6 @@
2
2
 
3
3
  module Geet
4
4
  module Github
5
- # See AbstractIssue for the circular dependency issue notes.
6
- autoload :AbstractIssue, File.expand_path('abstract_issue', __dir__)
7
-
8
5
  class Issue < Geet::Github::AbstractIssue
9
6
  def self.create(title, description, api_interface, **)
10
7
  api_path = 'issues'
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../helpers/json_helper'
4
-
5
3
  module Geet
6
4
  module Github
7
5
  class Milestone
@@ -2,9 +2,6 @@
2
2
 
3
3
  module Geet
4
4
  module Github
5
- # See AbstractIssue for the circular dependency issue notes.
6
- autoload :AbstractIssue, File.expand_path('abstract_issue', __dir__)
7
-
8
5
  class PR < AbstractIssue
9
6
  # See https://developer.github.com/v3/pulls/#create-a-pull-request
10
7
  #
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../shared/repo_permissions'
4
- require_relative '../shared/http_error'
5
-
6
3
  module Geet
7
4
  module Github
8
5
  class User
@@ -40,7 +40,9 @@ module Geet
40
40
 
41
41
  # See https://docs.gitlab.com/ee/api/merge_requests.html#accept-mr
42
42
  #
43
- def merge
43
+ def merge(merge_method: nil)
44
+ raise ArgumentError, "GitLab does not support the merge_method parameter" if merge_method
45
+
44
46
  api_path = "projects/#{@api_interface.path_with_namespace(encoded: true)}/merge_requests/#{number}/merge"
45
47
 
46
48
  @api_interface.send_request(api_path, http_method: :put)
@@ -1,3 +1,4 @@
1
+ # typed: strict
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require 'time'
@@ -5,10 +6,13 @@ require 'time'
5
6
  module Geet
6
7
  module Helpers
7
8
  module JsonHelper
9
+ extend T::Sig
10
+
8
11
  # Most common Json time format.
9
12
  #
10
13
  # Returns nil if nil is passed.
11
14
  #
15
+ sig { params(timestamp: T.nilable(String)).returns(T.nilable(Date)) }
12
16
  def parse_iso_8601_timestamp(timestamp)
13
17
  Time.iso8601(timestamp).to_date if timestamp
14
18
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
 
3
4
  require 'English'
4
5
  require 'open3'
@@ -7,8 +8,20 @@ require 'shellwords'
7
8
  module Geet
8
9
  module Helpers
9
10
  module OsHelper
11
+ extend T::Sig
12
+
13
+ include Kernel # for Sorbet compatibility
14
+
15
+ sig { params(file_or_url: String).void }
10
16
  def open_file_with_default_application(file_or_url)
11
- open_command = `uname`.strip == 'Darwin' ? "open": "xdg-open"
17
+ open_command = case
18
+ when ENV["WSL_DISTRO_NAME"]
19
+ "wslview"
20
+ when `uname`.strip == 'Darwin'
21
+ "open"
22
+ else
23
+ "xdg-open"
24
+ end
12
25
 
13
26
  command = "#{open_command} #{file_or_url.shellescape}"
14
27
 
@@ -22,12 +35,16 @@ module Geet
22
35
  # On non-interactive runs, the stdout content is returned, stripped of the surrounding
23
36
  # whitespaces.
24
37
  #
25
- # description: optional string, to make the error clearer.
26
- # interactive: set when required; in this case, a different API will be used (`system()`
27
- # instead of `popen3`).
28
- # silent_stderr: don't print the stderr output
29
- # allow_error: don't raise error on failure
30
- #
38
+ sig {
39
+ params(
40
+ command: String,
41
+ description: T.nilable(String), # specify to make the error clearer
42
+ interactive: T::Boolean, # set when required; in this case, a different API will be used (`system()`
43
+ # instead of `popen3`)
44
+ silent_stderr: T::Boolean, # don't print the stderr output
45
+ allow_error: T::Boolean # don't raise error on failure
46
+ ).returns(T.nilable(String))
47
+ }
31
48
  def execute_command(command, description: nil, interactive: false, silent_stderr: false, allow_error: false)
32
49
  description_message = " on #{description}" if description
33
50
 
@@ -38,6 +55,8 @@ module Geet
38
55
  raise "Error#{description_message} (exit status: #{$CHILD_STATUS.exitstatus})"
39
56
  end
40
57
  else
58
+ result = ""
59
+
41
60
  Open3.popen3(command) do |_, stdout, stderr, wait_thread|
42
61
  stdout_content = stdout.read
43
62
  stderr_content = stderr.read
@@ -49,8 +68,10 @@ module Geet
49
68
  raise "Error#{description_message}: #{error_message}"
50
69
  end
51
70
 
52
- stdout_content.strip
71
+ result = stdout_content.strip
53
72
  end
73
+
74
+ result
54
75
  end
55
76
  end
56
77
  end
@@ -1,3 +1,4 @@
1
+ # typed: strict
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require 'English'
@@ -9,10 +10,21 @@ module Geet
9
10
  # Helper for services common workflow, for example, find the merge head.
10
11
  #
11
12
  module ServicesWorkflowHelper
13
+ include Kernel
14
+ extend T::Sig
15
+
16
+ sig { void }
17
+ def initialize
18
+ @repository = T.let(T.unsafe(nil), Git::Repository)
19
+ @git_client = T.let(T.unsafe(nil), Utils::GitClient)
20
+ @out = T.let(T.unsafe(nil), IO)
21
+ end
22
+
12
23
  # Expect to find only one.
13
24
  #
14
25
  # Requires: @out, @repository.
15
26
  #
27
+ sig { returns(T.any(Geet::Github::PR, Geet::Gitlab::PR)) }
16
28
  def checked_find_branch_pr
17
29
  owner = if @repository.upstream?
18
30
  @repository.authenticated_user.username
@@ -1,16 +1,23 @@
1
+ # typed: strict
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module Geet
4
5
  module Helpers
5
6
  module SummaryHelper
7
+ include Kernel
8
+ extend T::Sig
9
+
6
10
  # Split the summary in title and description.
7
11
  # The description is optional, but the title mandatory.
8
12
  #
13
+ sig { params(summary: String).returns([String, String]) }
9
14
  def split_summary(summary)
10
15
  raise "Missing title in summary!" if summary.to_s.strip.empty?
11
16
 
12
17
  title, description = summary.split(/\r|\n/, 2)
13
18
 
19
+ raise "Title missing" if title.nil?
20
+
14
21
  # The title may have a residual newline char; the description may not be present,
15
22
  # or have multiple blank lines.
16
23
  [title.strip, description.to_s.strip]
@@ -1,17 +1,17 @@
1
1
  # frozen_string_literal: true
2
+ # typed: strict
2
3
 
4
+ require 'stringio'
3
5
  require 'tmpdir'
4
6
 
5
- require_relative '../helpers/os_helper'
6
- require_relative '../utils/attributes_selection_manager'
7
- require_relative '../utils/manual_list_selection'
8
- require_relative '../utils/string_matching_selection'
9
-
10
7
  module Geet
11
8
  module Services
12
9
  class AbstractCreateIssue
10
+ extend T::Sig
11
+
13
12
  include Geet::Helpers::OsHelper
14
13
 
14
+ sig { params(repository: T.untyped, out: T.any(IO, StringIO)).void }
15
15
  def initialize(repository, out: $stdout)
16
16
  @repository = repository
17
17
  @out = out
@@ -1,18 +1,23 @@
1
1
  # frozen_string_literal: true
2
+ # typed: strict
2
3
 
3
4
  module Geet
4
5
  module Services
5
6
  # Add the upstream repository to the current repository (configuration).
6
7
  #
7
8
  class AddUpstreamRepo
9
+ extend T::Sig
10
+
8
11
  DEFAULT_GIT_CLIENT = Utils::GitClient.new
9
12
 
13
+ sig { params(repository: T.untyped, out: T.any(IO, StringIO), git_client: T.untyped).void }
10
14
  def initialize(repository, out: $stdout, git_client: DEFAULT_GIT_CLIENT)
11
15
  @repository = repository
12
16
  @out = out
13
17
  @git_client = git_client
14
18
  end
15
19
 
20
+ sig { void }
16
21
  def execute
17
22
  raise "Upstream remote already existing!" if @git_client.remote_defined?(Utils::GitClient::UPSTREAM_NAME)
18
23
 
@@ -31,6 +36,7 @@ module Geet
31
36
 
32
37
  # Use the same protocol as the main repository.
33
38
  #
39
+ sig { params(parent_path: String).returns((String)) }
34
40
  def compose_parent_url(parent_path)
35
41
  protocol, domain, separator, _, suffix = @git_client.remote_components
36
42
 
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../shared/selection'
4
-
5
3
  module Geet
6
4
  module Services
7
5
  class CloseMilestones
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../helpers/os_helper'
4
- require_relative '../helpers/services_workflow_helper'
5
-
6
3
  module Geet
7
4
  module Services
8
5
  # Add a comment to the PR for the current branch.
@@ -1,9 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../helpers/os_helper'
4
- require_relative '../github/api_interface'
5
- require_relative '../github/gist'
6
-
7
3
  module Geet
8
4
  module Services
9
5
  class CreateGist
@@ -1,9 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'abstract_create_issue'
4
- require_relative '../shared/repo_permissions'
5
- require_relative '../shared/selection'
6
-
7
3
  module Geet
8
4
  module Services
9
5
  class CreateIssue < AbstractCreateIssue
@@ -1,12 +1,8 @@
1
1
  # frozen_string_literal: true
2
+ # typed: true
2
3
 
3
4
  require 'io/console' # stdlib
4
5
 
5
- require_relative 'abstract_create_issue'
6
- require_relative '../shared/repo_permissions'
7
- require_relative '../shared/selection'
8
- require_relative 'add_upstream_repo'
9
-
10
6
  module Geet
11
7
  module Services
12
8
  class CreatePr < AbstractCreateIssue
@@ -87,7 +83,9 @@ module Geet
87
83
  selection_manager.select_attributes
88
84
  end
89
85
 
90
- def sync_with_remote_branch
86
+ # `input` is a Sorbet workaround (error 7001).
87
+ #
88
+ def sync_with_remote_branch(input: T.untyped)
91
89
  # Fetching doesn't have a real world case when there isn't a remote branch. It's also not generally
92
90
  # useful when there is a remote branch, however, since a force push is an option, it's important
93
91
  # to be 100% sure of the current diff.
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../utils/attributes_selection_manager'
4
- require_relative '../shared/selection'
5
-
6
3
  module Geet
7
4
  module Services
8
5
  class ListIssues
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../helpers/services_workflow_helper'
4
-
5
3
  module Geet
6
4
  module Services
7
5
  # Merges the PR for the current branch.
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../helpers/os_helper'
4
- require_relative '../helpers/services_workflow_helper'
5
-
6
3
  module Geet
7
4
  module Services
8
5
  # Open in the browser the PR for the current branch.
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../helpers/os_helper'
4
-
5
3
  module Geet
6
4
  module Services
7
5
  # Open in the browser the current repository.
@@ -1,12 +1,18 @@
1
+ # frozen_string_literal: true
2
+ # typed: strict
3
+
1
4
  module Geet
2
5
  module Shared
3
6
  class HttpError < RuntimeError
4
- # Integer.
7
+ extend T::Sig
8
+
9
+ sig { returns(Integer) }
5
10
  attr_reader :code
6
11
 
12
+ sig { params(message: String, code: T.any(Integer, String)).void }
7
13
  def initialize(message, code)
8
14
  super(message)
9
- @code = code.to_i
15
+ @code = T.let(code.to_i, Integer)
10
16
  end
11
17
  end
12
18
  end
@@ -1,24 +1,29 @@
1
1
  # frozen_string_literal: true
2
+ # typed: strict
2
3
 
3
4
  module Geet
4
5
  module Shared
5
6
  module RepoPermissions
7
+ extend T::Sig
8
+
6
9
  PERMISSION_ADMIN = 'admin'
7
10
  PERMISSION_WRITE = 'write'
8
11
  PERMISSION_READ = 'read'
9
12
  PERMISSION_NONE = 'none'
10
13
 
14
+ ALL_PERMISSIONS = T.let(T.unsafe(nil), T::Array[String]) if defined?(T::sig)
11
15
  ALL_PERMISSIONS = [
12
16
  PERMISSION_ADMIN,
13
17
  PERMISSION_WRITE,
14
18
  PERMISSION_READ,
15
19
  PERMISSION_NONE,
16
- ]
20
+ ].freeze
17
21
 
18
22
  # Not worth creating a Permission class at this stage.
19
23
  #
24
+ sig { params(subject_permission: String, object_permission: String).returns(T::Boolean) }
20
25
  def permission_greater_or_equal_to?(subject_permission, object_permission)
21
- ALL_PERMISSIONS.index(subject_permission) <= ALL_PERMISSIONS.index(object_permission)
26
+ T.must(ALL_PERMISSIONS.index(subject_permission)) <= T.must(ALL_PERMISSIONS.index(object_permission))
22
27
  end
23
28
  end
24
29
  end