verto 0.1.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 +7 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +53 -0
- data/LICENSE.txt +21 -0
- data/README.md +82 -0
- data/Rakefile +25 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/verto +9 -0
- data/lib/verto/commands/base_command.rb +27 -0
- data/lib/verto/commands/main_command.rb +6 -0
- data/lib/verto/commands/tag_command.rb +88 -0
- data/lib/verto/dsl/file.rb +49 -0
- data/lib/verto/dsl/hook.rb +17 -0
- data/lib/verto/dsl/interpreter.rb +29 -0
- data/lib/verto/dsl/syntax.rb +75 -0
- data/lib/verto/dsl.rb +13 -0
- data/lib/verto/repositories/tag_repository.rb +20 -0
- data/lib/verto/utils/semantic_version.rb +126 -0
- data/lib/verto/utils/system_command_executor.rb +34 -0
- data/lib/verto/utils/tag_filter.rb +13 -0
- data/lib/verto/version.rb +3 -0
- data/lib/verto.rb +56 -0
- data/verto.gemspec +38 -0
- metadata +182 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 57720313b35dae31896c4cc8ed940487c14c6f268269474dcaf7a739eb31f371
|
4
|
+
data.tar.gz: 37b947db3e863ba538e945eff7f02241f862b6d021b43223c9c95d28bf7df144
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e3791c56946d015d4199863331a836d661d159ceed0c817f80c169ee8ea71523a874b31a656be6df2fb7bf7671041ab2430dac4fcc08420292ee76e0fe826997
|
7
|
+
data.tar.gz: dc69546ca9d8427bfe51610fd6444061d3356f840a6836fe81c275ad0bba5abe14592095b92be5bb719392e32de9678ecc9b85785d382084c22f8a2cd92f233a
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
verto (0.1.0)
|
5
|
+
dry-auto_inject (~> 0.6)
|
6
|
+
dry-configurable (~> 0.8)
|
7
|
+
dry-container (~> 0.7)
|
8
|
+
thor (~> 1.0.1)
|
9
|
+
|
10
|
+
GEM
|
11
|
+
remote: https://rubygems.org/
|
12
|
+
specs:
|
13
|
+
byebug (11.1.1)
|
14
|
+
concurrent-ruby (1.1.5)
|
15
|
+
diff-lcs (1.3)
|
16
|
+
dry-auto_inject (0.7.0)
|
17
|
+
dry-container (>= 0.3.4)
|
18
|
+
dry-configurable (0.9.0)
|
19
|
+
concurrent-ruby (~> 1.0)
|
20
|
+
dry-core (~> 0.4, >= 0.4.7)
|
21
|
+
dry-container (0.7.2)
|
22
|
+
concurrent-ruby (~> 1.0)
|
23
|
+
dry-configurable (~> 0.1, >= 0.1.3)
|
24
|
+
dry-core (0.4.9)
|
25
|
+
concurrent-ruby (~> 1.0)
|
26
|
+
rake (10.5.0)
|
27
|
+
rspec (3.9.0)
|
28
|
+
rspec-core (~> 3.9.0)
|
29
|
+
rspec-expectations (~> 3.9.0)
|
30
|
+
rspec-mocks (~> 3.9.0)
|
31
|
+
rspec-core (3.9.1)
|
32
|
+
rspec-support (~> 3.9.1)
|
33
|
+
rspec-expectations (3.9.0)
|
34
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
35
|
+
rspec-support (~> 3.9.0)
|
36
|
+
rspec-mocks (3.9.1)
|
37
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
38
|
+
rspec-support (~> 3.9.0)
|
39
|
+
rspec-support (3.9.2)
|
40
|
+
thor (1.0.1)
|
41
|
+
|
42
|
+
PLATFORMS
|
43
|
+
ruby
|
44
|
+
|
45
|
+
DEPENDENCIES
|
46
|
+
bundler (~> 2.0)
|
47
|
+
byebug
|
48
|
+
rake (~> 10.0)
|
49
|
+
rspec (~> 3.0)
|
50
|
+
verto!
|
51
|
+
|
52
|
+
BUNDLED WITH
|
53
|
+
2.0.2
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2020 Carlos Atkinson
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
# Verto
|
2
|
+
|
3
|
+
Verto is a CLI to generate git tags (following the [Semantic Versioning](https://semver.org/) system)
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Verto is distributed as a ruby gem, to install run:
|
8
|
+
|
9
|
+
```
|
10
|
+
$ gem install verto
|
11
|
+
```
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
Now you can run verto right out of the box without any configuration:
|
16
|
+
|
17
|
+
```
|
18
|
+
verto tag up --patch # Creates a new tag increasing the patch number
|
19
|
+
verto tag up --minor # Creates a new tag increasing the minor number
|
20
|
+
verto tag up --major # Creates a new tag increasing the major number
|
21
|
+
```
|
22
|
+
|
23
|
+
### Verto DSL
|
24
|
+
|
25
|
+
If you need a more specific configuration or want to reflect your development proccess in some way, you can use Verto DSL creating a Vertofile with the configuration.
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
# Vertofile
|
29
|
+
config {
|
30
|
+
pre_release.initial_number = 0
|
31
|
+
project.path = "my/repo/path"
|
32
|
+
}
|
33
|
+
|
34
|
+
before { sh('echo "Creating Tag"') }
|
35
|
+
|
36
|
+
context(branch('master')) {
|
37
|
+
on('before_tag_creation') {
|
38
|
+
versions_changes = "## #{new_version} - #{Time.now.strftime('%d/%m/%Y')}\n"
|
39
|
+
exit unless confirm("Create a new release?\n" \
|
40
|
+
"#{versions_changes}"
|
41
|
+
)
|
42
|
+
|
43
|
+
file('CHANGELOG.md').prepend(versions_changes)
|
44
|
+
git('add CHANGELOG.md')
|
45
|
+
git('commit -m "Updates CHANGELOG"')
|
46
|
+
}
|
47
|
+
|
48
|
+
after_command('tag_up') {
|
49
|
+
git('push --tags')
|
50
|
+
git('push origin master')
|
51
|
+
}
|
52
|
+
}
|
53
|
+
|
54
|
+
context(branch('qa')) {
|
55
|
+
before_command('tag_up') {
|
56
|
+
command_options.add(pre_release: 'rc')
|
57
|
+
}
|
58
|
+
|
59
|
+
after_command('tag_up') {
|
60
|
+
file('releases.log').append(new_version.to_s)
|
61
|
+
}
|
62
|
+
}
|
63
|
+
|
64
|
+
```
|
65
|
+
|
66
|
+
#### Verto Syntax
|
67
|
+
|
68
|
+
...TODO...
|
69
|
+
|
70
|
+
## TODO
|
71
|
+
|
72
|
+
1. Complete README.md description
|
73
|
+
2. Add a configuration to enable, disable or specify the number of tags that a single commit can have(eg: only one release and one pre-release)
|
74
|
+
3. Enable the *sh* dsl output to be show as default
|
75
|
+
|
76
|
+
## Contributing
|
77
|
+
|
78
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/catks/verto.
|
79
|
+
|
80
|
+
## License
|
81
|
+
|
82
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
3
|
+
require_relative "lib/verto"
|
4
|
+
require_relative "spec/helpers/test_repo.rb"
|
5
|
+
|
6
|
+
RSpec::Core::RakeTask.new(:spec)
|
7
|
+
|
8
|
+
task :default => :spec
|
9
|
+
|
10
|
+
desc 'Verto REPL'
|
11
|
+
task :console do
|
12
|
+
exec 'irb -r ./lib/verto -r ./spec/helpers/test_repo.rb'
|
13
|
+
end
|
14
|
+
|
15
|
+
namespace :temp_repo do
|
16
|
+
desc 'Initialize a temp git repo'
|
17
|
+
task :init do
|
18
|
+
TestRepo.new.init!
|
19
|
+
end
|
20
|
+
|
21
|
+
desc 'clear the temp git repo'
|
22
|
+
task :clear do
|
23
|
+
TestRepo.new.clear
|
24
|
+
end
|
25
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "verto"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/exe/verto
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
module Verto
|
2
|
+
class BaseCommand < Thor
|
3
|
+
def self.exit_on_failure?
|
4
|
+
true
|
5
|
+
end
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def command_error!(message)
|
10
|
+
raise Thor::Error, message
|
11
|
+
end
|
12
|
+
|
13
|
+
def options
|
14
|
+
super.merge Verto.config.command_options
|
15
|
+
end
|
16
|
+
|
17
|
+
def call_hooks(moments = [], with_attributes: {})
|
18
|
+
moments_to_call = ([] << moments).flatten
|
19
|
+
|
20
|
+
moments_to_call.each do |moment|
|
21
|
+
Verto.config.hooks
|
22
|
+
.select { |hook| hook.moment == moment.to_sym }
|
23
|
+
.each { |hook| hook.call(with_attributes: with_attributes) }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Verto
|
2
|
+
class TagCommand < BaseCommand
|
3
|
+
desc "up", "Create's a new tag"
|
4
|
+
|
5
|
+
option :major, type: :boolean, default: false
|
6
|
+
option :minor, type: :boolean, default: false
|
7
|
+
option :patch, type: :boolean, default: false
|
8
|
+
option :pre_release, type: :string
|
9
|
+
option :filter, type: :string
|
10
|
+
|
11
|
+
def up
|
12
|
+
call_hooks(%i[before before_tag_up])
|
13
|
+
|
14
|
+
validate_version_option_presence!
|
15
|
+
|
16
|
+
latest_tag = tag_repository.latest(filter: load_filter)
|
17
|
+
|
18
|
+
validate_latest_tag!(latest_tag)
|
19
|
+
|
20
|
+
latest_version = SemanticVersion.new(latest_tag)
|
21
|
+
|
22
|
+
version_up_options = options.select { |key,value| value == true }.keys.map(&:to_sym) & [:major, :minor, :patch]
|
23
|
+
|
24
|
+
new_version = version_up_options.reduce(latest_version) { |version, up_option| version.up(up_option) }
|
25
|
+
|
26
|
+
if options[:pre_release]
|
27
|
+
identifier = pre_release_configured? ? options[:pre_release] : latest_version.pre_release.name
|
28
|
+
new_version = new_version.with_pre_release(identifier)
|
29
|
+
new_version = new_version.up(:pre_release) if new_version.pre_release.name == latest_version.pre_release.name
|
30
|
+
end
|
31
|
+
|
32
|
+
validate_new_version!(new_version, latest_version)
|
33
|
+
call_hooks(:before_tag_creation, with_attributes: { new_version: new_version, latest_version: latest_version } )
|
34
|
+
tag_repository.create!(new_version.to_s)
|
35
|
+
|
36
|
+
call_hooks(:after_tag_up, with_attributes: { new_version: new_version })
|
37
|
+
call_hooks(:after)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
include Verto.import['tag_repository']
|
43
|
+
|
44
|
+
def pre_release_configured?
|
45
|
+
options[:pre_release] != 'pre_release'
|
46
|
+
end
|
47
|
+
|
48
|
+
def validate_latest_tag!(latest_tag)
|
49
|
+
command_error!(
|
50
|
+
<<~TEXT
|
51
|
+
Project doesn't have a previous tag version, create a new tag with git or verto init.
|
52
|
+
eg: `git tag 0.0.1` or `verto init`
|
53
|
+
TEXT
|
54
|
+
) unless latest_tag
|
55
|
+
end
|
56
|
+
|
57
|
+
def validate_new_version!(new_version, latest_version)
|
58
|
+
command_error!(
|
59
|
+
<<~TEXT
|
60
|
+
New version(#{new_version}) can't be equal or lower than latest version(#{latest_version})
|
61
|
+
run up --pre-release with --patch, --minor or --major (eg: verto tag up --pre-release --patch),
|
62
|
+
add filters (eg: verto tag up --pre-release --filter=pre_release_only)
|
63
|
+
or disable tag validation in Vertofile with config.version.validations.new_version_must_be_bigger = false
|
64
|
+
TEXT
|
65
|
+
) if new_version < latest_version
|
66
|
+
end
|
67
|
+
|
68
|
+
def validate_version_option_presence!
|
69
|
+
command_error!(
|
70
|
+
<<~TEXT
|
71
|
+
You must specify the version number to be increased, use the some of the options(eg: --major, --minor, --patch, --pre_release=rc)
|
72
|
+
or configure a Vertofile to specify a default option for current context, eg:
|
73
|
+
|
74
|
+
context('qa') {
|
75
|
+
before_command('tag_up') {
|
76
|
+
command_options.add(pre_release: 'rc')
|
77
|
+
}
|
78
|
+
}
|
79
|
+
TEXT
|
80
|
+
) unless options[:major] || options[:minor] || options[:patch] || options[:pre_release]
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
def load_filter
|
85
|
+
TagFilter.for(options[:filter]) || Regexp.new(options[:filter].to_s)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Verto
|
2
|
+
module DSL
|
3
|
+
class File
|
4
|
+
def initialize(filename, path: Verto.config.project.path)
|
5
|
+
@filename = filename
|
6
|
+
@path = Pathname.new(path)
|
7
|
+
end
|
8
|
+
|
9
|
+
def replace(to_match, to_replace)
|
10
|
+
content = file.read
|
11
|
+
|
12
|
+
file.open('w') do |f|
|
13
|
+
f << content.sub(to_match, to_replace)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def replace_all(to_match, to_replace)
|
18
|
+
content = file.read
|
19
|
+
|
20
|
+
file.open('w') do |f|
|
21
|
+
f << content.gsub(to_match, to_replace)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def append(content)
|
26
|
+
file.open('a') do |f|
|
27
|
+
f << content
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def prepend(content)
|
32
|
+
file_content = file.read
|
33
|
+
|
34
|
+
file.open('w') do |f|
|
35
|
+
f << (content + file_content)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
alias_method :gsub, :replace_all
|
40
|
+
alias_method :sub, :replace
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def file
|
45
|
+
@path.join(@filename)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Verto
|
2
|
+
module DSL
|
3
|
+
class Hook
|
4
|
+
attr_accessor :moment
|
5
|
+
|
6
|
+
def initialize(interpreter: DSL.interpreter, moment: :before, &block)
|
7
|
+
@moment = moment.to_sym
|
8
|
+
@interpreter = interpreter
|
9
|
+
@block = block
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(with_attributes: {})
|
13
|
+
@interpreter.evaluate(attributes: with_attributes, &@block)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Verto
|
2
|
+
module DSL
|
3
|
+
class Interpreter
|
4
|
+
include DSL::Syntax
|
5
|
+
|
6
|
+
def evaluate(vertofile_content=nil, attributes: {}, &block)
|
7
|
+
with_attributes(attributes) do
|
8
|
+
vertofile_content ? instance_eval(vertofile_content) : instance_eval(&block)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def with_attributes(attributes, &block)
|
15
|
+
attributes.each do |key, value|
|
16
|
+
instance_variable_set("@#{key}", value)
|
17
|
+
define_singleton_method(key) { instance_variable_get("@#{key}") }
|
18
|
+
end
|
19
|
+
|
20
|
+
block.call
|
21
|
+
|
22
|
+
attributes.each do |key, value|
|
23
|
+
instance_variable_set("@#{key}", nil)
|
24
|
+
singleton_class.remove_method(key)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Verto
|
2
|
+
module DSL
|
3
|
+
module Syntax
|
4
|
+
def config(&block)
|
5
|
+
Verto.config.instance_eval(&block)
|
6
|
+
end
|
7
|
+
|
8
|
+
def current_branch
|
9
|
+
git('rev-parse --abbrev-ref HEAD').output.chomp.strip
|
10
|
+
end
|
11
|
+
|
12
|
+
def branch(*branch_names)
|
13
|
+
branch_names.map(&:to_s).include? current_branch
|
14
|
+
end
|
15
|
+
|
16
|
+
def context(condition, &block)
|
17
|
+
block.call if condition
|
18
|
+
end
|
19
|
+
|
20
|
+
def git(subcommand)
|
21
|
+
sh("git #{subcommand}")
|
22
|
+
end
|
23
|
+
|
24
|
+
def sh(command)
|
25
|
+
command_executor.run command
|
26
|
+
end
|
27
|
+
|
28
|
+
def command_options
|
29
|
+
Verto.config.command_options
|
30
|
+
end
|
31
|
+
|
32
|
+
def on(moment, &block)
|
33
|
+
Verto.config.hooks << Hook.new(moment: moment, &block)
|
34
|
+
end
|
35
|
+
|
36
|
+
def before(&block)
|
37
|
+
Verto.config.hooks << Hook.new(moment: :before, &block)
|
38
|
+
end
|
39
|
+
|
40
|
+
def after(&block)
|
41
|
+
Verto.config.hooks << Hook.new(moment: :after, &block)
|
42
|
+
end
|
43
|
+
|
44
|
+
def before_command(command_name, &block)
|
45
|
+
Verto.config.hooks << Hook.new(moment: "before_#{command_name}", &block)
|
46
|
+
end
|
47
|
+
|
48
|
+
def after_command(command_name, &block)
|
49
|
+
Verto.config.hooks << Hook.new(moment: "after_#{command_name}", &block)
|
50
|
+
end
|
51
|
+
|
52
|
+
def file(filepath)
|
53
|
+
DSL::File.new(filepath)
|
54
|
+
end
|
55
|
+
|
56
|
+
def env(environment_name)
|
57
|
+
ENV[environment_name]
|
58
|
+
end
|
59
|
+
|
60
|
+
def confirm(text)
|
61
|
+
shell_basic.yes?("#{text} (y/n)")
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def command_executor
|
67
|
+
@command_executor ||= SystemCommandExecutor.new
|
68
|
+
end
|
69
|
+
|
70
|
+
def shell_basic
|
71
|
+
@shell_basic ||= Thor::Shell::Basic.new
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/lib/verto/dsl.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module Verto
|
2
|
+
class TagRepository
|
3
|
+
include Verto.import[executor: 'system_command_executor']
|
4
|
+
|
5
|
+
def latest(filter: nil)
|
6
|
+
all(filter: filter).last
|
7
|
+
end
|
8
|
+
|
9
|
+
def create!(tag)
|
10
|
+
# TODO: Implements tag in other commits
|
11
|
+
executor.run! "git tag #{tag}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def all(filter: nil)
|
15
|
+
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
|
+
|
17
|
+
filter ? results.select { |tag| tag.match?(filter) } : results
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module Verto
|
2
|
+
class SemanticVersion
|
3
|
+
include Comparable
|
4
|
+
|
5
|
+
REGEXP = /(\d+)\.(\d+)\.(\d+)(-?.*)/
|
6
|
+
|
7
|
+
class PreRelease
|
8
|
+
include Comparable
|
9
|
+
|
10
|
+
REGEXP = /-?(.+)\.(\d+)/
|
11
|
+
|
12
|
+
attr_accessor :name, :number
|
13
|
+
|
14
|
+
def self.with(name:, number: Verto.config.pre_release.initial_number)
|
15
|
+
instance = allocate
|
16
|
+
instance.name = name
|
17
|
+
instance.number = number
|
18
|
+
instance
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize(pre_release, initial_number: Verto.config.pre_release.initial_number)
|
22
|
+
name, number = pre_release.match(REGEXP)&.captures
|
23
|
+
|
24
|
+
@initial_number = initial_number
|
25
|
+
return if name.nil? && number.nil?
|
26
|
+
|
27
|
+
@name = name
|
28
|
+
@number = number ? number.to_i : initial_number
|
29
|
+
end
|
30
|
+
|
31
|
+
def up
|
32
|
+
raise BlankPreRelease if blank?
|
33
|
+
|
34
|
+
new_pre_release = self.dup
|
35
|
+
new_pre_release.number = number ? number + 1 : @initial_number
|
36
|
+
new_pre_release
|
37
|
+
end
|
38
|
+
|
39
|
+
def <=>(other)
|
40
|
+
return -1 if present? && other.blank?
|
41
|
+
return 1 if blank? && other.present?
|
42
|
+
to_s <=> other.to_s
|
43
|
+
end
|
44
|
+
|
45
|
+
def blank?
|
46
|
+
name.nil? && number.nil?
|
47
|
+
end
|
48
|
+
|
49
|
+
def present?
|
50
|
+
!blank?
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_s
|
54
|
+
return '' if blank?
|
55
|
+
|
56
|
+
"-#{@name}.#{@number}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
attr_accessor :major, :minor, :patch, :pre_release
|
61
|
+
|
62
|
+
def initialize(version, pre_release_initial_number: Verto.config.pre_release.initial_number)
|
63
|
+
major, minor, patch, pre_release = version.match(REGEXP).captures
|
64
|
+
|
65
|
+
@major = major.to_i
|
66
|
+
@minor = minor.to_i
|
67
|
+
@patch = patch.to_i
|
68
|
+
@pre_release = PreRelease.new(pre_release)
|
69
|
+
|
70
|
+
@pre_release_initial_number = pre_release_initial_number
|
71
|
+
end
|
72
|
+
|
73
|
+
def up(version_type)
|
74
|
+
new_version = self.dup
|
75
|
+
|
76
|
+
case version_type
|
77
|
+
when :major
|
78
|
+
new_version.major += 1
|
79
|
+
new_version.minor = 0
|
80
|
+
new_version.patch = 0
|
81
|
+
new_version.pre_release.number = @pre_release_initial_number if pre_release?
|
82
|
+
when :minor
|
83
|
+
new_version.minor += 1
|
84
|
+
new_version.patch = 0
|
85
|
+
new_version.pre_release.number = @pre_release_initial_number if pre_release?
|
86
|
+
when :patch
|
87
|
+
new_version.patch += 1
|
88
|
+
new_version.pre_release.number = @pre_release_initial_number if pre_release?
|
89
|
+
when :pre_release
|
90
|
+
new_version.pre_release = new_version.pre_release.up
|
91
|
+
end
|
92
|
+
|
93
|
+
new_version
|
94
|
+
end
|
95
|
+
|
96
|
+
def with_pre_release(name)
|
97
|
+
new_version = self.dup
|
98
|
+
|
99
|
+
return new_version if new_version.pre_release? && new_version.pre_release.name == name
|
100
|
+
|
101
|
+
new_version.pre_release = PreRelease.with(name: name)
|
102
|
+
|
103
|
+
new_version
|
104
|
+
end
|
105
|
+
|
106
|
+
def pre_release?
|
107
|
+
pre_release.present?
|
108
|
+
end
|
109
|
+
|
110
|
+
def <=>(other)
|
111
|
+
return 1 if major > other.major
|
112
|
+
return 1 if major == other.major && minor > other.minor
|
113
|
+
return 1 if major == other.major && minor == other.minor && patch > other.patch
|
114
|
+
return 1 if major == other.major && minor == other.minor && patch == other.patch && pre_release > other.pre_release
|
115
|
+
return 0 if major == other.major && minor == other.minor && patch == other.patch && pre_release == other.pre_release
|
116
|
+
|
117
|
+
-1
|
118
|
+
end
|
119
|
+
|
120
|
+
def to_s
|
121
|
+
version = "#{@major}.#{@minor}.#{@patch}"
|
122
|
+
version << @pre_release.to_s if @pre_release
|
123
|
+
version
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
3
|
+
module Verto
|
4
|
+
class SystemCommandExecutor
|
5
|
+
include Verto.import['project.path']
|
6
|
+
|
7
|
+
class Result < Struct.new(:output, :error, :result)
|
8
|
+
def success?
|
9
|
+
@result.success?
|
10
|
+
end
|
11
|
+
|
12
|
+
def error?
|
13
|
+
!success?
|
14
|
+
end
|
15
|
+
end
|
16
|
+
Error = Class.new(StandardError)
|
17
|
+
|
18
|
+
def run(command)
|
19
|
+
Open3.popen3(command, chdir: path.to_s) do |stdin, stdout, stderr, wait_thread|
|
20
|
+
@output = stdout.read
|
21
|
+
@error = stderr.read
|
22
|
+
@result = wait_thread.value
|
23
|
+
end
|
24
|
+
|
25
|
+
Result.new(@output, @error, @result)
|
26
|
+
end
|
27
|
+
|
28
|
+
def run!(command)
|
29
|
+
run(command)
|
30
|
+
|
31
|
+
raise Error, @error unless @error.empty?
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module TagFilter
|
2
|
+
REALEASE_ONLY = /\d+\.\d+\.\d+$/
|
3
|
+
PRE_REALEASE_ONLY = /\d+\.\d+\.\d+-.*\d+/
|
4
|
+
|
5
|
+
FILTERS = {
|
6
|
+
release_only: REALEASE_ONLY,
|
7
|
+
pre_release_only: PRE_REALEASE_ONLY,
|
8
|
+
}
|
9
|
+
|
10
|
+
def self.for(tag_key)
|
11
|
+
FILTERS[tag_key.to_sym] if tag_key
|
12
|
+
end
|
13
|
+
end
|
data/lib/verto.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require "thor"
|
2
|
+
require "dry-container"
|
3
|
+
require "dry-configurable"
|
4
|
+
require "dry-auto_inject"
|
5
|
+
require "pathname"
|
6
|
+
|
7
|
+
require "verto/version"
|
8
|
+
|
9
|
+
module Verto
|
10
|
+
extend Dry::Configurable
|
11
|
+
|
12
|
+
setting :pre_release do
|
13
|
+
setting :initial_number, 1
|
14
|
+
end
|
15
|
+
|
16
|
+
setting :project do
|
17
|
+
setting :path, './'
|
18
|
+
end
|
19
|
+
|
20
|
+
setting :hooks, []
|
21
|
+
setting :command_options, Class.new(Hash) { alias_method :add, :merge! }.new
|
22
|
+
|
23
|
+
def self.root_path
|
24
|
+
Pathname.new File.expand_path(File.dirname(__FILE__) + '/..')
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
def self.container
|
29
|
+
@container ||= Dry::Container.new.tap do |container|
|
30
|
+
container.register('system_command_executor') { SystemCommandExecutor.new }
|
31
|
+
container.register('tag_repository') { TagRepository.new }
|
32
|
+
|
33
|
+
# TODO: Remove project.path from container
|
34
|
+
container.namespace('project') do
|
35
|
+
register('path') { Verto.config.project.path }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.import
|
41
|
+
@import ||= Dry::AutoInject(container)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
require "verto/utils/semantic_version.rb"
|
46
|
+
require "verto/utils/system_command_executor"
|
47
|
+
require "verto/utils/tag_filter"
|
48
|
+
require "verto/dsl"
|
49
|
+
require "verto/dsl/syntax"
|
50
|
+
require "verto/dsl/interpreter"
|
51
|
+
require "verto/dsl/hook"
|
52
|
+
require "verto/dsl/file"
|
53
|
+
require "verto/commands/base_command"
|
54
|
+
require "verto/commands/tag_command"
|
55
|
+
require "verto/commands/main_command"
|
56
|
+
require "verto/repositories/tag_repository"
|
data/verto.gemspec
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
lib = File.expand_path("lib", __dir__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require "verto/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "verto"
|
7
|
+
spec.version = Verto::VERSION
|
8
|
+
spec.authors = ["Carlos Atkinson"]
|
9
|
+
spec.email = ["carlos.atks@gmail.com"]
|
10
|
+
|
11
|
+
spec.summary = %q{Verto helps you to versionate your project}
|
12
|
+
spec.homepage = "https://github.com/catks/verto"
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
|
16
|
+
# spec.metadata["homepage_uri"] = spec.homepage
|
17
|
+
# spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
|
18
|
+
# spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
|
19
|
+
|
20
|
+
# Specify which files should be added to the gem when it is released.
|
21
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
22
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
23
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
24
|
+
end
|
25
|
+
spec.bindir = "exe"
|
26
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
|
+
spec.require_paths = ["lib"]
|
28
|
+
|
29
|
+
spec.add_dependency "thor", "~> 1.0.1"
|
30
|
+
spec.add_dependency "dry-configurable", "~> 0.8"
|
31
|
+
spec.add_dependency "dry-container", "~> 0.7"
|
32
|
+
spec.add_dependency "dry-auto_inject", "~> 0.6"
|
33
|
+
|
34
|
+
spec.add_development_dependency "byebug"
|
35
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
36
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
37
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
38
|
+
end
|
metadata
ADDED
@@ -0,0 +1,182 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: verto
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Carlos Atkinson
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-02-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: thor
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.0.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.0.1
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: dry-configurable
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.8'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.8'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: dry-container
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.7'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.7'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: dry-auto_inject
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0.6'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0.6'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: byebug
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: bundler
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '2.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '2.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rake
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '10.0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '10.0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rspec
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '3.0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '3.0'
|
125
|
+
description:
|
126
|
+
email:
|
127
|
+
- carlos.atks@gmail.com
|
128
|
+
executables:
|
129
|
+
- verto
|
130
|
+
extensions: []
|
131
|
+
extra_rdoc_files: []
|
132
|
+
files:
|
133
|
+
- ".gitignore"
|
134
|
+
- ".rspec"
|
135
|
+
- ".travis.yml"
|
136
|
+
- Gemfile
|
137
|
+
- Gemfile.lock
|
138
|
+
- LICENSE.txt
|
139
|
+
- README.md
|
140
|
+
- Rakefile
|
141
|
+
- bin/console
|
142
|
+
- bin/setup
|
143
|
+
- exe/verto
|
144
|
+
- lib/verto.rb
|
145
|
+
- lib/verto/commands/base_command.rb
|
146
|
+
- lib/verto/commands/main_command.rb
|
147
|
+
- lib/verto/commands/tag_command.rb
|
148
|
+
- lib/verto/dsl.rb
|
149
|
+
- lib/verto/dsl/file.rb
|
150
|
+
- lib/verto/dsl/hook.rb
|
151
|
+
- lib/verto/dsl/interpreter.rb
|
152
|
+
- lib/verto/dsl/syntax.rb
|
153
|
+
- lib/verto/repositories/tag_repository.rb
|
154
|
+
- lib/verto/utils/semantic_version.rb
|
155
|
+
- lib/verto/utils/system_command_executor.rb
|
156
|
+
- lib/verto/utils/tag_filter.rb
|
157
|
+
- lib/verto/version.rb
|
158
|
+
- verto.gemspec
|
159
|
+
homepage: https://github.com/catks/verto
|
160
|
+
licenses:
|
161
|
+
- MIT
|
162
|
+
metadata: {}
|
163
|
+
post_install_message:
|
164
|
+
rdoc_options: []
|
165
|
+
require_paths:
|
166
|
+
- lib
|
167
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
168
|
+
requirements:
|
169
|
+
- - ">="
|
170
|
+
- !ruby/object:Gem::Version
|
171
|
+
version: '0'
|
172
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
173
|
+
requirements:
|
174
|
+
- - ">="
|
175
|
+
- !ruby/object:Gem::Version
|
176
|
+
version: '0'
|
177
|
+
requirements: []
|
178
|
+
rubygems_version: 3.0.3
|
179
|
+
signing_key:
|
180
|
+
specification_version: 4
|
181
|
+
summary: Verto helps you to versionate your project
|
182
|
+
test_files: []
|