verto 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|