create_github_release 1.0.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -1
  3. data/.solargraph.yml +23 -0
  4. data/.vscode/launch.json +19 -0
  5. data/.yardopts +1 -0
  6. data/CHANGELOG.md +26 -0
  7. data/README.md +165 -47
  8. data/Rakefile +7 -4
  9. data/create_github_release.gemspec +7 -4
  10. data/exe/create-github-release +5 -1
  11. data/lib/create_github_release/assertion_base.rb +0 -2
  12. data/lib/create_github_release/assertions/bundle_is_up_to_date.rb +1 -1
  13. data/lib/create_github_release/assertions/gh_authenticated.rb +1 -1
  14. data/lib/create_github_release/assertions/gh_command_exists.rb +1 -1
  15. data/lib/create_github_release/assertions/git_command_exists.rb +1 -1
  16. data/lib/create_github_release/assertions/in_git_repo.rb +1 -1
  17. data/lib/create_github_release/assertions/in_repo_root_directory.rb +1 -1
  18. data/lib/create_github_release/assertions/local_and_remote_on_same_commit.rb +1 -1
  19. data/lib/create_github_release/assertions/local_release_branch_does_not_exist.rb +1 -1
  20. data/lib/create_github_release/assertions/no_staged_changes.rb +1 -1
  21. data/lib/create_github_release/assertions/no_uncommitted_changes.rb +1 -1
  22. data/lib/create_github_release/assertions/on_default_branch.rb +1 -1
  23. data/lib/create_github_release/assertions/remote_release_branch_does_not_exist.rb +1 -1
  24. data/lib/create_github_release/assertions/remote_release_tag_does_not_exist.rb +1 -1
  25. data/lib/create_github_release/command_line/options.rb +151 -0
  26. data/lib/create_github_release/command_line/parser.rb +253 -0
  27. data/lib/create_github_release/command_line/validations.rb +293 -0
  28. data/lib/create_github_release/command_line/validator.rb +93 -0
  29. data/lib/create_github_release/command_line.rb +43 -0
  30. data/lib/create_github_release/project.rb +136 -76
  31. data/lib/create_github_release/release_assertions.rb +2 -1
  32. data/lib/create_github_release/release_tasks.rb +2 -1
  33. data/lib/create_github_release/tasks/commit_release.rb +1 -1
  34. data/lib/create_github_release/tasks/create_github_release.rb +1 -1
  35. data/lib/create_github_release/tasks/create_release_branch.rb +1 -1
  36. data/lib/create_github_release/tasks/create_release_pull_request.rb +1 -1
  37. data/lib/create_github_release/tasks/create_release_tag.rb +1 -1
  38. data/lib/create_github_release/tasks/push_release.rb +1 -1
  39. data/lib/create_github_release/tasks/update_changelog.rb +1 -1
  40. data/lib/create_github_release/tasks/update_version.rb +13 -14
  41. data/lib/create_github_release/version.rb +1 -1
  42. data/lib/create_github_release.rb +1 -2
  43. metadata +31 -25
  44. data/lib/create_github_release/command_line_options.rb +0 -367
  45. data/lib/create_github_release/command_line_parser.rb +0 -225
@@ -0,0 +1,151 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'uri'
4
+ require 'forwardable'
5
+
6
+ module CreateGithubRelease
7
+ module CommandLine
8
+ # Stores and validates the command line options
9
+ #
10
+ # @example
11
+ # options = CreateGithubRelease::CommandLine::Options.new
12
+ # options.release_type = 'major'
13
+ # options.valid? #=> true
14
+ # options.errors #=> []
15
+ #
16
+ # @api public
17
+ #
18
+ class Options
19
+ CreateGithubRelease::CommandLine::ALLOWED_OPTIONS.each { |option| attr_accessor option }
20
+
21
+ # @attribute release_type [rw] the type of release to create
22
+ #
23
+ # Must be one of the VALID_RELEASE_TYPES
24
+ #
25
+ # @example
26
+ # options = CreateGithubRelease::CommandLine::Options.new(release_type: 'major')
27
+ # options.release_type #=> 'major'
28
+ # @return [String]
29
+ # @api public
30
+
31
+ # @attribute default_branch [rw] the default branch of the repository
32
+ # @example
33
+ # options = CreateGithubRelease::CommandLine::Options.new(default_branch: 'main')
34
+ # options.default_branch #=> 'main'
35
+ # @return [String]
36
+ # @api public
37
+
38
+ # @attribute release_branch [rw] the branch use to create the release
39
+ # @example
40
+ # options = CreateGithubRelease::CommandLine::Options.new(release_branch: 'release-v1.0.0')
41
+ # options.release_branch #=> 'release-v1.0.0'
42
+ # @return [String]
43
+ # @api public
44
+
45
+ # @attribute remote [rw] the name of the remote to use to access Github
46
+ # @example
47
+ # options = CreateGithubRelease::CommandLine::Options.new(remote: 'origin')
48
+ # options.remote #=> 'origin'
49
+ # @return [String]
50
+ # @api public
51
+
52
+ # @attribute last_release_version [rw] the version of the last release
53
+ # @example
54
+ # options = CreateGithubRelease::CommandLine::Options.new(last_release_version: '0.1.1')
55
+ # options.last_release_version #=> '0.1.1'
56
+ # @return [String]
57
+ # @api public
58
+
59
+ # @attribute next_release_version [rw] the version of the next release
60
+ # @example
61
+ # options = CreateGithubRelease::CommandLine::Options.new(next_release_version: '1.0.0')
62
+ # options.next_release_version #=> '1.0.0'
63
+ # @return [String]
64
+ # @api public
65
+
66
+ # @attribute changelog_path [rw] the path to the changelog file
67
+ # @example
68
+ # options = CreateGithubRelease::CommandLine::Options.new(changelog_path: 'CHANGELOG.md')
69
+ # options.changelog_path #=> 'CHANGELOG.md'
70
+ # @return [String]
71
+ # @api public
72
+
73
+ # @attribute quiet [rw] if `true`, suppresses all output
74
+ # @example
75
+ # options = CreateGithubRelease::CommandLine::Options.new(quiet: true)
76
+ # options.quiet #=> true
77
+ # @return [Boolean]
78
+ # @api public
79
+
80
+ # @attribute verbose [rw] if `true`, enables verbose output
81
+ # @example
82
+ # options = CreateGithubRelease::CommandLine::Options.new(verbose: true)
83
+ # options.verbose #=> true
84
+ # @return [Boolean]
85
+ # @api public
86
+
87
+ # Create a new instance of this class
88
+ #
89
+ # @example No arguments or block given
90
+ # options = CreateGithubRelease::CommandLine::Options.new
91
+ # options.release_type #=> nil
92
+ # options.valid? #=> false
93
+ # options.errors #=> ["--release-type must be given and be one of 'major', 'minor', 'patch'"]
94
+ #
95
+ # @example With keyword arguments
96
+ # config = { release_type: 'major', default_branch: 'main', quiet: true }
97
+ # options = CreateGithubRelease::CommandLine::Options.new(**config)
98
+ # options.release_type #=> 'major'
99
+ # options.default_branch #=> 'main'
100
+ # options.quiet #=> true
101
+ # options.valid? #=> true
102
+ #
103
+ # @example with a configuration block
104
+ # options = CreateGithubRelease::CommandLine::Options.new do |o|
105
+ # o.release_type = 'major'
106
+ # o.default_branch = 'main'
107
+ # o.quiet = true
108
+ # end
109
+ # options.release_type #=> 'major'
110
+ # options.default_branch #=> 'main'
111
+ # options.quiet #=> true
112
+ # options.valid? #=> true
113
+ #
114
+ # @yield [self] an initialization block
115
+ # @yieldparam self [CreateGithubRelease::CommandLine::Options] the instance being initialized
116
+ # @yieldreturn [void] the return value is ignored
117
+ #
118
+ def initialize(**options)
119
+ assert_no_unknown_options(options)
120
+ options.each { |k, v| instance_variable_set("@#{k}", v) }
121
+
122
+ self.quiet ||= false
123
+ self.verbose ||= false
124
+ self.pre ||= false
125
+ @errors = []
126
+
127
+ yield(self) if block_given?
128
+
129
+ @validator = CommandLine::Validator.new(self)
130
+
131
+ valid?
132
+ end
133
+
134
+ extend Forwardable
135
+ def_delegators :@validator, :valid?, :errors
136
+
137
+ private
138
+
139
+ # Raise ArgumentError if options has a key not in ALLOWED_OPTIONS
140
+ # @return [void]
141
+ # @api private
142
+ def assert_no_unknown_options(options)
143
+ unknown_options = options.keys - ALLOWED_OPTIONS
144
+ return if unknown_options.empty?
145
+
146
+ message = "Unknown keywords: #{unknown_options.join(', ')}"
147
+ raise ArgumentError, message
148
+ end
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,253 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'English'
4
+ require 'optparse'
5
+ require 'create_github_release/command_line/options'
6
+
7
+ module CreateGithubRelease
8
+ module CommandLine
9
+ # rubocop:disable Metrics/ClassLength
10
+
11
+ # Parses the options for this script
12
+ #
13
+ # @example Specify the release type
14
+ # options = CommandLineParser.new.parse('major')
15
+ # options.valid? # => true
16
+ # options.release_type # => "major"
17
+ # options.quiet # => false
18
+ #
19
+ # @example Specify the release type and the quiet option
20
+ # parser = CommandLineParser.new
21
+ # args = %w[minor --quiet]
22
+ # options = parser.parse(*args)
23
+ # options.release_type # => "minor"
24
+ # options.quiet # => true
25
+ #
26
+ # @example Show the command line help
27
+ # CommandLineParser.new.parse('--help')
28
+ # parser.parse('--help')
29
+ #
30
+ # @api public
31
+ #
32
+ class Parser
33
+ # Create a new command line parser
34
+ #
35
+ # @example
36
+ # parser = CommandLineParser.new
37
+ #
38
+ def initialize
39
+ @option_parser = OptionParser.new
40
+ define_options
41
+ @options = CreateGithubRelease::CommandLine::Options.new
42
+ end
43
+
44
+ # Parse the command line arguements returning the options
45
+ #
46
+ # @example
47
+ # parser = CommandLineParser.new
48
+ # options = parser.parse(['major'])
49
+ #
50
+ # @param args [Array<String>] the command line arguments
51
+ #
52
+ # @return [CreateGithubRelease::CommandLine::Options] the options
53
+ #
54
+ def parse(*args)
55
+ begin
56
+ option_parser.parse!(remaining_args = args.dup)
57
+ rescue OptionParser::InvalidOption, OptionParser::MissingArgument => e
58
+ report_errors(e.message)
59
+ end
60
+ parse_remaining_args(remaining_args)
61
+ # puts options unless options.quiet
62
+ report_errors(*options.errors) unless options.valid?
63
+ options
64
+ end
65
+
66
+ private
67
+
68
+ # @!attribute [rw] options
69
+ #
70
+ # The options to used for the create-github-release script
71
+ #
72
+ # @example
73
+ # parser = CommandLineParser.new
74
+ # parser.parse(['major'])
75
+ # options = parser.options
76
+ # options.release_type # => 'major'
77
+ #
78
+ # @return [CreateGithubRelease::CommandLine::Options] the options
79
+ #
80
+ # @api private
81
+ #
82
+ attr_reader :options
83
+
84
+ # @!attribute [rw] option_parser
85
+ #
86
+ # The option parser
87
+ #
88
+ # @return [OptionParser] the option parser
89
+ #
90
+ # @api private
91
+ #
92
+ attr_reader :option_parser
93
+
94
+ # Parse non-option arguments (the release type)
95
+ # @return [void]
96
+ # @api private
97
+ def parse_remaining_args(remaining_args)
98
+ options.release_type = remaining_args.shift || nil
99
+ report_errors('Too many args') unless remaining_args.empty?
100
+ end
101
+
102
+ # An error message constructed from the given errors array
103
+ # @return [String]
104
+ # @api private
105
+ def error_message(errors)
106
+ <<~MESSAGE
107
+ #{errors.map { |e| "ERROR: #{e}" }.join("\n")}
108
+
109
+ Use --help for usage
110
+ MESSAGE
111
+ end
112
+
113
+ # Output an error message and useage to stderr and exit
114
+ # @return [void]
115
+ # @api private
116
+ def report_errors(*errors)
117
+ warn error_message(errors)
118
+ exit 1
119
+ end
120
+
121
+ # The command line template as a string
122
+ # @return [String]
123
+ # @api private
124
+ def command_template
125
+ <<~COMMAND
126
+ #{File.basename($PROGRAM_NAME)} --help | RELEASE_TYPE [options]
127
+ COMMAND
128
+ end
129
+
130
+ # Define the options for OptionParser
131
+ # @return [void]
132
+ # @api private
133
+ def define_options
134
+ # @sg-ignore
135
+ option_parser.banner = "Usage:\n#{command_template}"
136
+ option_parser.separator ''
137
+ option_parser.separator "RELEASE_TYPE must be 'major', 'minor', 'patch', 'pre', 'release', or 'first'"
138
+ option_parser.separator ''
139
+ option_parser.separator 'Options:'
140
+ %i[
141
+ define_help_option define_default_branch_option define_release_branch_option define_pre_option
142
+ define_pre_type_option define_remote_option define_last_release_version_option
143
+ define_next_release_version_option define_changelog_path_option define_quiet_option define_verbose_option
144
+ ].each { |m| send(m) }
145
+ end
146
+
147
+ # Define the pre option
148
+ # @return [void]
149
+ # @api private
150
+ def define_pre_option
151
+ option_parser.on('-p', '--pre', 'Create a pre-release') do |pre|
152
+ options.pre = pre
153
+ end
154
+ end
155
+
156
+ # Define the pre-type option
157
+ # @return [void]
158
+ # @api private
159
+ def define_pre_type_option
160
+ description = 'Type of pre-release to create (e.g. alpha, beta, etc.)'
161
+ option_parser.on('-t', '--pre-type=TYPE', description) do |pre_type|
162
+ options.pre_type = pre_type
163
+ end
164
+ end
165
+
166
+ # Define the quiet option
167
+ # @return [void]
168
+ # @api private
169
+ def define_quiet_option
170
+ option_parser.on('-q', '--[no-]quiet', 'Do not show output') do |quiet|
171
+ options.quiet = quiet
172
+ end
173
+ end
174
+
175
+ # Define the verbose option
176
+ # @return [void]
177
+ # @api private
178
+ def define_verbose_option
179
+ option_parser.on('-v', '--[no-]verbose', 'Show extra output') do |verbose|
180
+ options.verbose = verbose
181
+ end
182
+ end
183
+
184
+ # Define the help option
185
+ # @return [void]
186
+ # @api private
187
+ def define_help_option
188
+ option_parser.on_tail('-h', '--help', 'Show this message') do
189
+ puts option_parser
190
+ exit 0
191
+ end
192
+ end
193
+
194
+ # Define the default_branch option which requires a value
195
+ # @return [void]
196
+ # @api private
197
+ def define_default_branch_option
198
+ option_parser.on('--default-branch=BRANCH_NAME', 'Override the default branch') do |name|
199
+ options.default_branch = name
200
+ end
201
+ end
202
+
203
+ # Define the release_branch option which requires a value
204
+ # @return [void]
205
+ # @api private
206
+ def define_release_branch_option
207
+ option_parser.on('--release-branch=BRANCH_NAME', 'Override the release branch to create') do |name|
208
+ options.release_branch = name
209
+ end
210
+ end
211
+
212
+ # Define the remote option which requires a value
213
+ # @return [void]
214
+ # @api private
215
+ def define_remote_option
216
+ option_parser.on('--remote=REMOTE_NAME', "Use this remote name instead of 'origin'") do |name|
217
+ options.remote = name
218
+ end
219
+ end
220
+
221
+ # Define the last_release_version option which requires a value
222
+ # @return [void]
223
+ # @api private
224
+ def define_last_release_version_option
225
+ option_parser.on('--last-release-version=VERSION', 'Use this version instead `semverify current`') do |version|
226
+ options.last_release_version = version
227
+ end
228
+ end
229
+
230
+ # Define the next_release_version option which requires a value
231
+ # @return [void]
232
+ # @api private
233
+ def define_next_release_version_option
234
+ option_parser.on(
235
+ '--next-release-version=VERSION',
236
+ 'Use this version instead `semverify next-RELEASE_TYPE`'
237
+ ) do |version|
238
+ options.next_release_version = version
239
+ end
240
+ end
241
+
242
+ # Define the changelog_path option which requires a value
243
+ # @return [void]
244
+ # @api private
245
+ def define_changelog_path_option
246
+ option_parser.on('--changelog-path=PATH', 'Use this file instead of CHANGELOG.md') do |name|
247
+ options.changelog_path = name
248
+ end
249
+ end
250
+ end
251
+ # rubocop:enable Metrics/ClassLength
252
+ end
253
+ end
@@ -0,0 +1,293 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CreateGithubRelease
4
+ module CommandLine
5
+ # Module containing all option validations
6
+ #
7
+ # All validation classes must inherit from `CreateGithubRelease::Validations::Base`
8
+ # and implement the `#valid?` and `#error` methods.
9
+ #
10
+ # All validation classes must be named `Validate*` and must be defined in the
11
+ # `CreateGithubRelease::Validations` namespace. Classes that follow this convention
12
+ # are automatically run by `CreateGithubRelease::CommandLine::OptionsValidator`.
13
+ #
14
+ # @api private
15
+ #
16
+ module Validations
17
+ # All validation classes inherit this classes initializer and options reader
18
+ # @api public
19
+ class Base
20
+ # Create a new validation object with the given options
21
+ #
22
+ # @example
23
+ # class ValidatePreFlag < Base
24
+ # def validate
25
+ # options.pre == false || %w[major minor patch].include?(options.release_type)
26
+ # end
27
+ # end
28
+ #
29
+ # @param options [CreateGithubRelease::CommandLine::Options] the options to validate
30
+ #
31
+ def initialize(options)
32
+ @options = options
33
+ end
34
+
35
+ private
36
+
37
+ # The options to validate
38
+ # @return [CreateGithubRelease::CommandLine::Options]
39
+ # @api private
40
+ attr_reader :options
41
+
42
+ # Returns `true` if the given version is a valid gem version
43
+ # @return [Boolean]
44
+ # @api private
45
+ def valid_gem_version?(version)
46
+ Gem::Version.new(version)
47
+ true
48
+ rescue ArgumentError
49
+ false
50
+ end
51
+
52
+ # `true` if the given name is a valid git reference
53
+ # @return [Boolean]
54
+ # @api private
55
+ def valid_reference?(name)
56
+ VALID_REF_PATTERN.match?(name)
57
+ end
58
+
59
+ # Returns `true` if the given path is a valid path
60
+ # @param path [String] the path to validate
61
+ # @return [Boolean]
62
+ # @api private
63
+ def valid_path?(path)
64
+ File.expand_path(path)
65
+ true
66
+ rescue ArgumentError
67
+ false
68
+ end
69
+ end
70
+
71
+ # Validate that `pre` is unset or is set with the appropriate release types
72
+ # @api private
73
+ #
74
+ class ValidatePreFlag < Base
75
+ # Returns `true` if valid
76
+ # @return [Boolean]
77
+ # @api private
78
+ def valid?
79
+ options.pre == false || %w[major minor patch].include?(options.release_type)
80
+ end
81
+
82
+ # Called when valid? is `false` to return the error messages
83
+ # @return [String, Array<String>]
84
+ # @api private
85
+ def error
86
+ '--pre can only be given with a release type of major, minor, or patch'
87
+ end
88
+ end
89
+
90
+ # Validate if pre_type is nil or releast_type is 'pre' or the pre flag is set
91
+ # @api private
92
+ #
93
+ class ValidatePreType < Base
94
+ # Returns `true` if valid
95
+ # @return [Boolean]
96
+ # @api private
97
+ def valid?
98
+ options.pre_type.nil? ||
99
+ options.release_type == 'pre' ||
100
+ (%w[major minor patch].include?(options.release_type) && options.pre == true)
101
+ end
102
+
103
+ # Called when valid? is `false` to return the error messages
104
+ # @return [String, Array<String>]
105
+ # @api private
106
+ def error
107
+ if %w[major minor patch pre].include?(options.release_type)
108
+ '--pre must be given when --pre-type is given'
109
+ else
110
+ '--pre-type can only be given with a release type of major, minor, patch, or pre'
111
+ end
112
+ end
113
+ end
114
+
115
+ # Validate that the quiet flag is true or false
116
+ # @api private
117
+ class ValidateQuiet < Base
118
+ # Returns `true` if valid
119
+ # @return [Boolean]
120
+ # @api private
121
+ def valid?
122
+ options.quiet == true || options.quiet == false
123
+ end
124
+
125
+ # Called when valid? is `false` to return the error messages
126
+ # @return [String, Array<String>]
127
+ # @api private
128
+ def error
129
+ 'quiet must be either true or false'
130
+ end
131
+ end
132
+
133
+ # Validate that the verbose flag is true or false
134
+ # @api private
135
+ class ValidateVerbose < Base
136
+ # Returns `true` if the `#verbose` is `true` or `false` and `false` otherwise
137
+ # @return [Boolean]
138
+ # @api private
139
+ def valid?
140
+ options.verbose == true || options.verbose == false
141
+ end
142
+
143
+ # Called when valid? is `false` to return the error messages
144
+ # @return [String, Array<String>]
145
+ # @api private
146
+ def error
147
+ 'verbose must be either true or false'
148
+ end
149
+ end
150
+
151
+ # Validate that either quiet or verbose is given, but not both
152
+ # @api private
153
+ class ValidateOnlyQuietOrVerbose < Base
154
+ # Returns `true` if at most only one of `#quiet` or `#verbose` is `true`
155
+ # @return [Boolean]
156
+ # @api private
157
+ def valid? = !options.quiet || !options.verbose
158
+
159
+ # Called when valid? is `false` to return the error messages
160
+ # @return [String, Array<String>]
161
+ # @api private
162
+ def error = '--quiet and --verbose cannot be used together'
163
+ end
164
+
165
+ # Validates that a release type is given
166
+ # @api private
167
+ class ValidateReleaseTypeGiven < Base
168
+ # Returns `true` if the `#release_type` is not nil
169
+ # @return [Boolean]
170
+ # @api private
171
+ def valid? = !options.release_type.nil?
172
+
173
+ # Called when valid? is `false` to return the error messages
174
+ # @return [String, Array<String>]
175
+ # @api private
176
+ def error
177
+ valid_release_types = "'#{VALID_RELEASE_TYPES.join("', '")}'"
178
+ "RELEASE_TYPE must be given. Must be one of #{valid_release_types}"
179
+ end
180
+ end
181
+
182
+ # Validates that the given release type is valid
183
+ # @api private
184
+ class ValidateReleaseType < Base
185
+ # Returns `true` if the `#release_type` is nil or a valid release type
186
+ # @return [Boolean]
187
+ # @api private
188
+ def valid? = options.release_type.nil? || VALID_RELEASE_TYPES.include?(options.release_type)
189
+
190
+ # Called when valid? is `false` to return the error messages
191
+ # @return [String, Array<String>]
192
+ # @api private
193
+ def error
194
+ valid_release_types = "'#{VALID_RELEASE_TYPES.join("', '")}'"
195
+ "RELEASE_TYPE '#{options.release_type}' is not valid. Must be one of #{valid_release_types}"
196
+ end
197
+ end
198
+
199
+ # Validates the default branch (if given) a valid Git reference
200
+ # @api private
201
+ class ValidateDefaultBranch < Base
202
+ # Returns `true` if the `#default_branch` is nil or is a valid git reference
203
+ # @return [Boolean]
204
+ # @api private
205
+ def valid? = options.default_branch.nil? || valid_reference?(options.default_branch)
206
+
207
+ # Called when valid? is `false` to return the error messages
208
+ # @return [String, Array<String>]
209
+ # @api private
210
+ def error = "--default-branch='#{options.default_branch}' is not valid"
211
+ end
212
+
213
+ # Validates the release branch (if given) a valid Git reference
214
+ # @api private
215
+ class ValidateReleaseBranch < Base
216
+ # Returns `true` if the `#release_branch` is nil or is a valid git reference
217
+ # @return [Boolean]
218
+ # @api private
219
+ def valid? = options.release_branch.nil? || valid_reference?(options.release_branch)
220
+
221
+ # Called when valid? is `false` to return the error messages
222
+ # @return [String, Array<String>]
223
+ # @api private
224
+ def error = "--release-branch='#{options.release_branch}' is not valid"
225
+ end
226
+
227
+ # Validate that the remote (if given) is a valid Git reference
228
+ # @api private
229
+ class ValidateRemote < Base
230
+ # Returns `true` if the `#remote` is nil or is a valid git reference
231
+ # @return [Boolean]
232
+ # @api private
233
+ def valid? = options.remote.nil? || valid_reference?(options.remote)
234
+
235
+ # Called when valid? is `false` to return the error messages
236
+ # @return [String, Array<String>]
237
+ # @api private
238
+ def error = "--remote='#{options.remote}' is not valid"
239
+ end
240
+
241
+ # Validate that the last release version (if given) is a valid gem version
242
+ # @api private
243
+ class ValidateLastReleaseVersion < Base
244
+ # Returns `true` if the `#last_release_version` is nil or is a valid gem version
245
+ # @return [Boolean]
246
+ # @api private
247
+ def valid? = options.last_release_version.nil? || valid_gem_version?(options.last_release_version)
248
+
249
+ # Called when valid? is `false` to return the error messages
250
+ # @return [String, Array<String>]
251
+ # @api private
252
+ def error = "--last-release-version='#{options.last_release_version}' is not valid"
253
+ end
254
+
255
+ # Validate that the next release version (if given) is a valid gem version
256
+ # @api private
257
+ class ValidateNextReleaseVersion < Base
258
+ # Returns `true` if the `#next_release_version` is nil or is a valid gem version
259
+ # @return [Boolean]
260
+ # @api private
261
+ def valid? = options.next_release_version.nil? || valid_gem_version?(options.next_release_version)
262
+
263
+ # Called when valid? is `false` to return the error messages
264
+ # @return [String, Array<String>]
265
+ # @api private
266
+ def error = "--next-release-version='#{options.next_release_version}' is not valid"
267
+ end
268
+
269
+ # Validate that the change log path (if given) is a valid path
270
+ # @api private
271
+ class ValidateChangelogPath < Base
272
+ # Returns `true` if `#changelog_path` is nil or is a valid regular file path
273
+ # @return [Boolean]
274
+ # @api private
275
+ def valid?
276
+ options.changelog_path.nil? ||
277
+ (valid_path?(options.changelog_path) && File.file?(File.expand_path(options.changelog_path)))
278
+ end
279
+
280
+ # Called when valid? is `false` to return the error messages
281
+ # @return [String, Array<String>]
282
+ # @api private
283
+ def error
284
+ if valid_path?(options.changelog_path)
285
+ "The change log path '#{options.changelog_path}' is not a regular file"
286
+ else
287
+ "The change log path '#{options.changelog_path}' is not a valid path"
288
+ end
289
+ end
290
+ end
291
+ end
292
+ end
293
+ end