verto 0.9.0 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +54 -0
  3. data/.rubocop.yml +23 -0
  4. data/.rubocop_todo.yml +50 -0
  5. data/.ruby-version +1 -1
  6. data/CHANGELOG.md +22 -0
  7. data/Gemfile +3 -1
  8. data/Gemfile.lock +79 -29
  9. data/README.md +75 -65
  10. data/Rakefile +7 -5
  11. data/VERTO_SYNTAX.md +350 -0
  12. data/Vertofile +5 -19
  13. data/bin/console +5 -8
  14. data/djin.yml +50 -0
  15. data/exe/verto +8 -4
  16. data/lib/verto/commands/base_command.rb +7 -2
  17. data/lib/verto/commands/main_command.rb +10 -6
  18. data/lib/verto/commands/tag_command.rb +65 -26
  19. data/lib/verto/dsl/built_in_hooks.rb +7 -1
  20. data/lib/verto/dsl/file.rb +4 -2
  21. data/lib/verto/dsl/hook.rb +2 -0
  22. data/lib/verto/dsl/interpreter.rb +8 -7
  23. data/lib/verto/dsl/syntax.rb +27 -6
  24. data/lib/verto/dsl/update_changelog/filtered_by.rb +45 -0
  25. data/lib/verto/dsl/update_changelog/with_commit_messages.rb +30 -0
  26. data/lib/verto/dsl/update_changelog/with_merged_pull_requests.rb +19 -0
  27. data/lib/verto/dsl/update_changelog.rb +85 -0
  28. data/lib/verto/dsl.rb +2 -0
  29. data/lib/verto/repositories/tag_repository.rb +6 -0
  30. data/lib/verto/utils/cli_helpers.rb +37 -0
  31. data/lib/verto/utils/command_options.rb +4 -2
  32. data/lib/verto/utils/semantic_version.rb +2 -0
  33. data/lib/verto/utils/strict_hash.rb +9 -0
  34. data/lib/verto/utils/system_command_executor.rb +4 -2
  35. data/lib/verto/utils/tag_filter.rb +7 -5
  36. data/lib/verto/utils/template.rb +2 -0
  37. data/lib/verto/utils/templates/Vertofile +26 -28
  38. data/lib/verto/version.rb +3 -1
  39. data/lib/verto.rb +62 -25
  40. data/verto.gemspec +33 -25
  41. metadata +113 -19
  42. data/.travis.yml +0 -13
@@ -1,6 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ # rubocop:disable Metrics/ClassLength
1
4
  module Verto
2
5
  class TagCommand < BaseCommand
3
- desc "up", "Create's a new tag"
6
+ desc 'init', "Create's the first tag"
7
+
8
+ def init
9
+ load_config_hooks!
10
+
11
+ error_message = 'This repository already has tags'
12
+ raise Verto::ExitError, error_message if tag_repository.any?
13
+
14
+ create_git_tag('0.1.0')
15
+ end
16
+
17
+ desc 'up', "Create's a new tag"
4
18
 
5
19
  option :major, type: :boolean, default: false
6
20
  option :minor, type: :boolean, default: false
@@ -13,7 +27,7 @@ module Verto
13
27
  def up
14
28
  load_config_hooks!
15
29
 
16
- call_hooks(%i[before before_tag_up], with_attributes: { command_options: options} )
30
+ call_hooks(%i[before before_tag_up], with_attributes: { command_options: options })
17
31
 
18
32
  validate_version_option_presence!
19
33
 
@@ -27,11 +41,9 @@ module Verto
27
41
 
28
42
  validate_new_version!(new_version, latest_version)
29
43
 
30
- call_hooks(:before_tag_creation, with_attributes: { new_version: new_version } )
44
+ call_hooks(:before_tag_creation, with_attributes: { new_version: new_version })
31
45
 
32
- stderr.puts "Creating Tag #{version_prefix}#{new_version}..."
33
- tag_repository.create!("#{version_prefix}#{new_version}")
34
- stderr.puts "Tag #{version_prefix}#{new_version} Created!"
46
+ create_git_tag(new_version)
35
47
 
36
48
  call_hooks(:after_tag_up, with_attributes: { new_version: new_version })
37
49
  call_hooks(:after)
@@ -42,7 +54,7 @@ module Verto
42
54
  include Verto.import['tag_repository']
43
55
 
44
56
  def up_version(version, options)
45
- up_options = options.select { |_, value| value == true }.keys.map(&:to_sym) & [:major, :minor, :patch]
57
+ up_options = options.select { |_, value| value == true }.keys.map(&:to_sym) & %i[major minor patch]
46
58
  up_option = up_options.min
47
59
 
48
60
  new_version = version.up(up_option)
@@ -50,53 +62,65 @@ module Verto
50
62
  if options[:pre_release]
51
63
  identifier = pre_release_configured? ? options[:pre_release] : version.pre_release.name || default_identifier
52
64
  new_version = new_version.with_pre_release(identifier)
53
- new_version = new_version.up(:pre_release) if new_version.pre_release.name == version.pre_release.name && new_version == version
65
+ if new_version.pre_release.name == version.pre_release.name && new_version == version
66
+ new_version = new_version.up(:pre_release)
67
+ end
54
68
  end
55
69
 
56
- if options[:release]
57
- new_version = new_version.release_version
58
- end
70
+ new_version = new_version.release_version if options[:release]
59
71
 
60
72
  new_version
61
73
  end
62
74
 
75
+ def create_git_tag(version)
76
+ stderr.puts "Creating Tag #{version_prefix}#{version}..."
77
+ tag_repository.create!("#{version_prefix}#{version}")
78
+ stderr.puts "Tag #{version_prefix}#{version} Created!"
79
+ end
80
+
63
81
  def pre_release_configured?
64
82
  options[:pre_release] != 'pre_release'
65
83
  end
66
84
 
67
85
  def validate_latest_tag!(latest_tag)
86
+ return if latest_tag
87
+
68
88
  command_error!(
69
89
  <<~TEXT
70
90
  Project doesn't have a previous tag version, create a new tag with git.
71
91
  eg: `git tag #{version_prefix}0.1.0`
72
92
  TEXT
73
- ) unless latest_tag
93
+ )
74
94
  end
75
95
 
76
96
  def validate_new_version!(new_version, latest_version)
97
+ return unless new_version < latest_version && Verto.config.version.validations.new_version_must_be_bigger
98
+
77
99
  command_error!(
78
100
  <<~TEXT
79
- New version(#{new_version}) can't be equal or lower than latest version(#{latest_version})
80
- run up --pre-release with --patch, --minor or --major (eg: verto tag up --patch --pre-release=rc),
81
- add filters (eg: verto tag up --pre-release --filter=pre_release_only)
82
- or disable tag validation in Vertofile with config.version.validations.new_version_must_be_bigger = false
101
+ New version(#{new_version}) can't be equal or lower than latest version(#{latest_version})
102
+ run up --pre-release with --patch, --minor or --major (eg: verto tag up --patch --pre-release=rc),
103
+ add filters (eg: verto tag up --pre-release --filter=pre_release_only)
104
+ or disable tag validation in Vertofile with config.version.validations.new_version_must_be_bigger = false
83
105
  TEXT
84
- ) if new_version < latest_version && Verto.config.version.validations.new_version_must_be_bigger
106
+ )
85
107
  end
86
108
 
87
109
  def validate_version_option_presence!
110
+ return if options[:major] || options[:minor] || options[:patch] || options[:pre_release] || options[:release]
111
+
88
112
  command_error!(
89
113
  <<~TEXT
90
- You must specify the version number to be increased, use the some of the options(eg: --major, --minor, --patch, --pre_release=rc)
91
- or configure a Vertofile to specify a default option for current context, eg:
114
+ You must specify the version number to be increased, use the some of the options(eg: --major, --minor, --patch, --pre_release=rc)
115
+ or configure a Vertofile to specify a default option for current context, eg:
92
116
 
93
- context('qa') {
94
- before_command('tag_up') {
95
- command_options.add(pre_release: 'rc')
117
+ context('qa') {
118
+ before_command('tag_up') {
119
+ command_options.add(pre_release: 'rc')
120
+ }
96
121
  }
97
- }
98
122
  TEXT
99
- ) unless options[:major] || options[:minor] || options[:patch] || options[:pre_release] || options[:release]
123
+ )
100
124
  end
101
125
 
102
126
  def load_filter
@@ -108,8 +132,22 @@ module Verto
108
132
  end
109
133
 
110
134
  def load_config_hooks!
111
- Verto.config.hooks.prepend Verto::DSL::BuiltInHooks::GitPullCurrentBranch if Verto.config.git.pull_before_tag_creation
112
- Verto.config.hooks << Verto::DSL::BuiltInHooks::GitPushCurrentBranch if Verto.config.git.push_after_tag_creation
135
+ enabled_hooks = ->(_, v) { v }
136
+
137
+ config_hooks[:before].select(&enabled_hooks).each_key { |hook| Verto.config.hooks.prepend(hook) }
138
+ config_hooks[:after].select(&enabled_hooks).each_key { |hook| Verto.config.hooks << hook }
139
+ end
140
+
141
+ def config_hooks
142
+ @config_hooks ||= {
143
+ before: {
144
+ Verto::DSL::BuiltInHooks::GitPullCurrentBranch => Verto.config.git.pull_before_tag_creation,
145
+ Verto::DSL::BuiltInHooks::GitFetch => Verto.config.git.fetch_before_tag_creation
146
+ },
147
+ after: {
148
+ Verto::DSL::BuiltInHooks::GitPushCurrentBranch => Verto.config.git.push_after_tag_creation
149
+ }
150
+ }
113
151
  end
114
152
 
115
153
  def default_identifier
@@ -117,3 +155,4 @@ module Verto
117
155
  end
118
156
  end
119
157
  end
158
+ # rubocop:enable Metrics/ClassLength
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Verto
2
4
  module DSL
3
5
  module BuiltInHooks
@@ -5,8 +7,12 @@ module Verto
5
7
  git!("pull origin #{current_branch}")
6
8
  end
7
9
 
10
+ GitFetch = DSL::Hook.new(moment: :before) do
11
+ git!('fetch')
12
+ end
13
+
8
14
  GitPushTags = DSL::Hook.new(moment: :after) do
9
- git!("push --tags")
15
+ git!('push --tags')
10
16
  end
11
17
 
12
18
  GitPushCurrentBranchCommits = DSL::Hook.new(moment: :after) do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Verto
2
4
  module DSL
3
5
  class File
@@ -36,8 +38,8 @@ module Verto
36
38
  end
37
39
  end
38
40
 
39
- alias_method :gsub, :replace_all
40
- alias_method :sub, :replace
41
+ alias gsub replace_all
42
+ alias sub replace
41
43
 
42
44
  private
43
45
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Verto
2
4
  module DSL
3
5
  class Hook
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Verto
2
4
  module DSL
3
5
  class Interpreter
@@ -6,15 +8,14 @@ module Verto
6
8
  # TODO: Wrap stacktrace
7
9
  Error = Class.new(Verto::ExitError)
8
10
 
9
- def evaluate(vertofile_content=nil, attributes: {}, &block)
11
+ def evaluate(vertofile_content = nil, attributes: {}, &block)
10
12
  with_attributes(attributes) do
11
- vertofile_content ? instance_eval(vertofile_content) : instance_eval(&block)
13
+ vertofile_content ? instance_eval(vertofile_content) : instance_eval(&block)
12
14
  end
15
+ rescue StandardError => e
16
+ raise e if e.is_a?(Verto::ExitError)
13
17
 
14
- rescue StandardError => error
15
- raise error if error.is_a?(Verto::ExitError)
16
-
17
- raise Error, error.message
18
+ raise Error, e.message
18
19
  end
19
20
 
20
21
  private
@@ -27,7 +28,7 @@ module Verto
27
28
 
28
29
  block.call
29
30
 
30
- attributes.each do |key, value|
31
+ attributes.each do |key, _value|
31
32
  instance_variable_set("@#{key}", nil)
32
33
  singleton_class.remove_method(key)
33
34
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Verto
2
4
  module DSL
3
5
  module Syntax
@@ -100,6 +102,28 @@ module Verto
100
102
  Verto.config.hooks << Hook.new(moment: 'before_tag_creation', &block)
101
103
  end
102
104
 
105
+ # Start the flow to Update the CHANGELOG file
106
+ # @param :with [Symbol] The strategy to search commit messages
107
+ # Options include:
108
+ # :merged_pull_requests_with_bracketed_labels -> Uses all PR merged commits after the last tag if they have the [***] pattern
109
+ # :commits_with_bracketed_labels -> Uses all commits after the last tag if they have the [***] pattern (Exclude merge commits)
110
+ # :merged_pull_requests_messages -> Uses all merged commit after the last tag
111
+ # :commit_messages -> Uses all commits after the last tag (Exclude merge commits)
112
+ # @param :confirmation [Boolean] Adds a confirmation step before updating the CHANGELOG
113
+ # @param filename [String] The CHANGELOG filename
114
+ # @param message_pattern [Regexp] A regexp pattern to filter commit messages
115
+ def update_changelog(with: :merged_pull_requests_with_bracketed_labels, confirmation: true, filename: 'CHANGELOG.md')
116
+ permitted_moments = %w[before_tag_creation after_tag_up]
117
+ unless permitted_moments.include? Verto.current_moment.to_s
118
+ raise ExitError, 'update_changelog is only supported in before_tag_creation or after_command_tag_up'
119
+ end
120
+
121
+ UpdateChangelog.new.call(with: with,
122
+ new_version: new_version,
123
+ confirmation: confirmation,
124
+ filename: filename)
125
+ end
126
+
103
127
  def file(filepath)
104
128
  DSL::File.new(filepath)
105
129
  end
@@ -108,8 +132,9 @@ module Verto
108
132
  ENV[environment_name]
109
133
  end
110
134
 
135
+ # TODO: Use delegator
111
136
  def confirm(text)
112
- shell_basic.yes?("#{text} (y/n)")
137
+ CliHelpers.confirm(text)
113
138
  end
114
139
 
115
140
  def error(text)
@@ -128,16 +153,12 @@ module Verto
128
153
  @executors ||= {
129
154
  from_config: Verto::SystemCommandExecutor.new,
130
155
  true => Verto::SystemCommandExecutor.new(stdout: $stdout, stderr: $stderr),
131
- false => Verto::SystemCommandExecutor.new(stdout: nil, stderr: nil),
156
+ false => Verto::SystemCommandExecutor.new(stdout: nil, stderr: nil)
132
157
  }
133
158
 
134
159
  @executors[output]
135
160
  end
136
161
 
137
- def shell_basic
138
- @shell_basic ||= Thor::Shell::Basic.new
139
- end
140
-
141
162
  def stderr
142
163
  Verto.stderr
143
164
  end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Verto
4
+ module DSL
5
+ class UpdateChangelog
6
+ module FilteredBy
7
+ def self.included(klass)
8
+ klass.extend(ClassMethods)
9
+ end
10
+
11
+ module ClassMethods
12
+ def filtered_by(filter)
13
+ Proxy.new(self, filter)
14
+ end
15
+ end
16
+
17
+ class Proxy
18
+ def initialize(filter_class, final_filter)
19
+ @filter_class = filter_class
20
+ @final_filter = final_filter
21
+ end
22
+
23
+ def new
24
+ filter_object
25
+
26
+ self
27
+ end
28
+
29
+ def call(*args)
30
+ filter_object
31
+ .call(*args)
32
+ .select { |message| @final_filter.match?(message) }
33
+ end
34
+
35
+ private
36
+
37
+ # Lazy evaluete object to load Verto dependencies only at the last
38
+ def filter_object
39
+ @filter_object ||= @filter_class.new
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Verto
4
+ module DSL
5
+ class UpdateChangelog
6
+ class WithCommitMessages
7
+ include Verto.import[executor: 'system_command_executor_without_output', tag_repository: 'tag_repository']
8
+ include FilteredBy
9
+
10
+ def call(message_pattern = /.+/)
11
+ executor.run(
12
+ "git log --no-merges --pretty=format:%s #{commit_range}"
13
+ ).output.split("\n").map(&:strip).select { |message| message_pattern.match? message }
14
+ end
15
+
16
+ private
17
+
18
+ def commit_range
19
+ return unless latest_tag
20
+
21
+ "HEAD ^#{latest_tag}"
22
+ end
23
+
24
+ def latest_tag
25
+ tag_repository.latest
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Verto
4
+ module DSL
5
+ class UpdateChangelog
6
+ class WithMergedPullRequests
7
+ include Verto.import[executor: 'system_command_executor_without_output']
8
+ include FilteredBy
9
+
10
+ def call(message_pattern = /.+/)
11
+ # FIXME: Format the command
12
+ executor.run(
13
+ %q(git log --oneline --decorate | grep -B 100 -m 1 "tag:" | grep "pull request" | awk '{print $1}' | xargs -r git show --format='%b' | grep -v Approved | grep -v "^$") # rubocop:disable Layout/LineLength
14
+ ).output.split("\n").map(&:strip).select { |pr_message| message_pattern.match? pr_message }
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Verto
4
+ module DSL
5
+ class UpdateChangelog
6
+ include Verto.import[:cli_helpers, :stdout, changelog_format: 'changelog.format']
7
+
8
+ InvalidChangelogSource = Class.new(Verto::ExitError)
9
+
10
+ BRACKETED_LABELS_REGEXP = /^[[:space:]]*\[.*\]/.freeze
11
+
12
+ SOURCES = StrictHash.new(
13
+ {
14
+ merged_pull_requests_with_bracketed_labels: WithMergedPullRequests.filtered_by(BRACKETED_LABELS_REGEXP),
15
+ commits_with_bracketed_labels: WithCommitMessages.filtered_by(BRACKETED_LABELS_REGEXP),
16
+ merged_pull_requests_messages: WithMergedPullRequests,
17
+ commit_messages: WithCommitMessages
18
+ },
19
+ default_proc: ->(hash, _) { raise InvalidChangelogSource, "Invalid CHANGELOG Source, avaliable options: '#{hash.keys.join(',')}'" }
20
+ )
21
+
22
+ def call(new_version:, confirmation: true, filename: 'CHANGELOG.md', with: :merged_pull_requests_with_bracketed_labels, message_pattern: nil)
23
+ verify_file_presence!(filename)
24
+
25
+ changelog_changes = format_changes(new_version, version_changes(with, message_pattern))
26
+
27
+ if confirmation
28
+ stdout.puts separator
29
+ stdout.puts changelog_changes
30
+ stdout.puts separator
31
+ changelog_changes = select_changelog_text(changelog_changes)
32
+ end
33
+
34
+ update_file(filename, changelog_changes)
35
+ end
36
+
37
+ private
38
+
39
+ # TODO: Refactor
40
+ def select_changelog_text(changelog_changes) # rubocop:disable Metrics/MethodLength
41
+ choices = [
42
+ { key: 'y', name: 'Create a new Release CHANGELOG', value: :yes },
43
+ { key: 'n', name: 'Cancel the Release CHANGELOG', value: :no },
44
+ { key: 'e', name: 'Edit the Release CHANGELOG before continuing', value: :edit }
45
+ ]
46
+ case cli_helpers.select_options('Create new Release?', choices)
47
+ when :no
48
+ exit
49
+ when :edit
50
+ cli_helpers.edit_text(changelog_changes)
51
+ else
52
+ changelog_changes
53
+ end
54
+ end
55
+
56
+ def verify_file_presence!(filename)
57
+ return if Verto.project_path.join(filename).exist?
58
+
59
+ raise Verto::ExitError, "changelog file '#{filename}' doesnt exist"
60
+ end
61
+
62
+ def version_changes(with, message_pattern)
63
+ SOURCES[with.to_sym].new.call(*args_if_any(message_pattern))
64
+ end
65
+
66
+ def update_file(filename, changelog_changes)
67
+ DSL::File.new(filename).prepend(changelog_changes)
68
+ end
69
+
70
+ def format_changes(new_version, version_changes)
71
+ changes = Mustache.render(changelog_format,
72
+ { new_version: new_version, version_changes: version_changes })
73
+ "#{changes}\n"
74
+ end
75
+
76
+ def separator
77
+ '---------------------------'
78
+ end
79
+
80
+ def args_if_any(arg)
81
+ [arg].compact
82
+ end
83
+ end
84
+ end
85
+ end
data/lib/verto/dsl.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Verto
2
4
  module DSL
3
5
  def self.load_file(filepath)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Verto
2
4
  class TagRepository
3
5
  include Verto.import[executor: 'system_command_executor_without_output']
@@ -11,6 +13,10 @@ module Verto
11
13
  executor.run! "git tag #{tag}"
12
14
  end
13
15
 
16
+ def any?
17
+ all.any?
18
+ end
19
+
14
20
  def all(filter: nil)
15
21
  results = executor.run("git tag | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+(-.+\.[0-9]+)*' | sed 's/\([0-9]\.[0-9]\.[0-9]$\)/\1-zzzzzzzzzz/' | sort -V | sed 's/-zzzzzzzzzz//' | cat").output.split
16
22
 
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Verto
4
+ module CliHelpers
5
+ class << self
6
+ def confirm(text)
7
+ shell_basic.yes?("#{text} (y/n)")
8
+ end
9
+
10
+ def select_options(question, choices)
11
+ tty_prompt.expand(question, choices)
12
+ end
13
+
14
+ def edit_text(text)
15
+ tempfile = "/tmp/verto-changelog-edit-#{SecureRandom.hex}"
16
+
17
+ TTY::Editor.open(tempfile, text: text)
18
+
19
+ edited_text = File.read(tempfile)
20
+
21
+ File.delete(tempfile)
22
+
23
+ edited_text
24
+ end
25
+
26
+ private
27
+
28
+ def shell_basic
29
+ @shell_basic ||= Thor::Shell::Basic.new
30
+ end
31
+
32
+ def tty_prompt
33
+ @tty_prompt = TTY::Prompt.new
34
+ end
35
+ end
36
+ end
37
+ end
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Verto
2
4
  class CommandOptions < Thor::CoreExt::HashWithIndifferentAccess
3
- alias_method :add, :merge!
5
+ alias add merge!
4
6
 
5
7
  def except(*keys)
6
- self.reject { |key, v| keys.include?(key) }
8
+ reject { |key, _v| keys.include?(key) }
7
9
  end
8
10
  end
9
11
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Verto
2
4
  class SemanticVersion < Vseries::SemanticVersion
3
5
  DEFAULT_PRE_RELEASE_INITIAL_NUMBER = Verto.config.pre_release.initial_number
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class StrictHash < Hash
4
+ def initialize(hash, default_proc: nil)
5
+ super()
6
+ self.default_proc = default_proc if default_proc
7
+ merge!(hash)
8
+ end
9
+ end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'open3'
2
4
 
3
5
  module Verto
4
6
  class SystemCommandExecutor
5
7
  include Verto.import['project.path', 'stdout', 'stderr']
6
8
 
7
- class Result < Struct.new(:output, :error, :result)
9
+ Result = Struct.new(:output, :error, :result) do
8
10
  def success?
9
11
  result.success?
10
12
  end
@@ -16,7 +18,7 @@ module Verto
16
18
  Error = Class.new(StandardError)
17
19
 
18
20
  def run(command)
19
- stderr.puts running_log(command, path) if stderr
21
+ stderr&.puts running_log(command, path)
20
22
 
21
23
  Open3.popen3(command, chdir: path.to_s) do |_, stdout, stderr, wait_thread|
22
24
  @output = stdout.read
@@ -1,12 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module TagFilter
2
- REALEASE_ONLY = /\d+\.\d+\.\d+$/
3
- PRE_REALEASE_ONLY = /\d+\.\d+\.\d+-.*\d+/
4
+ RELEASE_ONLY = /\d+\.\d+\.\d+$/.freeze
5
+ PRE_RELEASE_ONLY = /\d+\.\d+\.\d+-.*\d+/.freeze
4
6
 
5
7
  FILTERS = {
6
- release_only: REALEASE_ONLY,
7
- pre_release_only: PRE_REALEASE_ONLY,
8
+ release_only: RELEASE_ONLY,
9
+ pre_release_only: PRE_RELEASE_ONLY,
8
10
  all: nil
9
- }
11
+ }.freeze
10
12
 
11
13
  def self.for(tag_key)
12
14
  FILTERS[tag_key.to_sym] if tag_key
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Verto
2
4
  class Template
3
5
  def self.render(template_name, to:)