vump 1.2.0 → 2.0.0.pre.alpha.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/LICENSE +21 -0
- data/README.md +47 -0
- data/VERSION +1 -1
- data/bin/vump +2 -2
- data/lib/vump/cli/cli.rb +100 -0
- data/lib/vump/cli/reporter.rb +116 -0
- data/lib/vump/git/git.rb +42 -0
- data/lib/vump/logger/logger.rb +34 -0
- data/lib/vump/meta.rb +38 -2
- data/lib/vump/modules/base_file_module.rb +39 -0
- data/lib/vump/modules/base_module.rb +28 -0
- data/lib/vump/modules/package_json.rb +24 -0
- data/lib/vump/modules/package_lock_json.rb +9 -0
- data/lib/vump/modules/sheep_a_changelog.rb +29 -0
- data/lib/vump/modules/version_file.rb +21 -0
- data/lib/vump/semver/semver.rb +18 -6
- data/lib/vump/vump.rb +96 -0
- data/vump.gemspec +17 -13
- metadata +118 -19
- data/README.adoc +0 -87
- data/lib/cli.rb +0 -74
- data/lib/vump.rb +0 -69
- data/lib/vump/semver/monkey/keepachangelog.rb +0 -23
- data/lib/vump/semver/version_modules/file_modules/keepachangelog.rb +0 -50
- data/lib/vump/semver/version_modules/file_modules/npm.rb +0 -29
- data/lib/vump/semver/version_modules/file_modules/npm_lock.rb +0 -15
- data/lib/vump/semver/version_modules/file_modules/version_file.rb +0 -26
- data/lib/vump/semver/version_modules/read_write_version_module.rb +0 -45
- data/lib/vump/semver/version_modules/vcs_modules/git.rb +0 -19
- data/lib/vump/version.rb +0 -4
data/README.adoc
DELETED
@@ -1,87 +0,0 @@
|
|
1
|
-
= vump: Semantic version bumper
|
2
|
-
Jaroslav Šmolík <grissius@gmail.com>
|
3
|
-
:semver: https://semver.org/[semver]
|
4
|
-
:git: https://git-scm.com/[git]
|
5
|
-
:rubychangelog: https://rubygems.org/gems/keepachangelog[keepachangelog]
|
6
|
-
|
7
|
-
image:https://travis-ci.org/grissius/vump.svg["Build Status", link="https://travis-ci.org/grissius/vump"]
|
8
|
-
image:https://img.shields.io/gem/v/vump.svg?style=flat[Gem Version, link="https://rubygems.org/gems/vump"]
|
9
|
-
image:https://img.shields.io/badge/yard-docs-blue.svg[Yard Docs, link="http://www.rubydoc.info/github/grissius/vump"]
|
10
|
-
|
11
|
-
CLI tool to easily manage projects using {semver} and automate menial version raising.
|
12
|
-
|
13
|
-
== Introduction
|
14
|
-
|
15
|
-
When working on a project with version management, increasing a version is a mundane, boring task. It might consist of as much as following steps:
|
16
|
-
|
17
|
-
* modify `VERSION` file
|
18
|
-
* modify package file version
|
19
|
-
* update changelog (e.g. if using keepachangelog move unreleased to this version, start new unreleased, update footnote)
|
20
|
-
* create a commit
|
21
|
-
* tag a commit
|
22
|
-
* double check previous steps, because you might have forgotten any of them
|
23
|
-
|
24
|
-
Which is exhausting. If following any standards at all, like {semver}, keepachagnelog etc, it does not require any human input, but to decide which version to increase.
|
25
|
-
|
26
|
-
== Install
|
27
|
-
```
|
28
|
-
gem install vump
|
29
|
-
```
|
30
|
-
=== Requirements
|
31
|
-
|
32
|
-
* ruby >= 2.2
|
33
|
-
|
34
|
-
|
35
|
-
== Usage
|
36
|
-
In root of project directory, choose which version (from {semver}) to bump, and supply it as a sole argument.
|
37
|
-
```
|
38
|
-
vump <major|minor|patch>
|
39
|
-
```
|
40
|
-
|
41
|
-
TIP: You can use any discriminative prefixes such as `maj`, `min`, or even `ma`, `mi` and `p`.
|
42
|
-
|
43
|
-
=== What it does
|
44
|
-
The program loads all modules, each being responsible for a single file it understands.
|
45
|
-
Each module checks if the file exists and if so, it will read the last version.
|
46
|
-
The versions across modules must match and are bumped as desired and written back into files.
|
47
|
-
|
48
|
-
After all file modules are done, {git} module adds all modified files and creates a tagged commit, if {git} is used in the project.
|
49
|
-
|
50
|
-
WARNING: As the interface implies, your project must follow the {semver} specifiaction.
|
51
|
-
|
52
|
-
=== Options
|
53
|
-
`vump --version`:: Print program version
|
54
|
-
`vump --verbose patch`, `vump -v patch`:: Print debug logs
|
55
|
-
`vump --silent patch`, `vump -s patch`:: Print only warning and error logs
|
56
|
-
|
57
|
-
== Current modules
|
58
|
-
|
59
|
-
[WARNING]
|
60
|
-
====
|
61
|
-
Non-trivial modules do not operate on text, but parsed objects, which might result in ugly diffs after first usage.
|
62
|
-
|
63
|
-
If you encounter any fishy :fish: behaviour due to this let me know!
|
64
|
-
====
|
65
|
-
|
66
|
-
VERSION::
|
67
|
-
Find and bump version in `./VERSION` file.
|
68
|
-
+
|
69
|
-
* Expect just verison with whitepsaces around
|
70
|
-
* Write version followed by a newline.
|
71
|
-
|
72
|
-
Npm::
|
73
|
-
Find and bump version in `./package.json` file.
|
74
|
-
+
|
75
|
-
* Parse JSON, modify as object.
|
76
|
-
* Serialize back to JSON, append newline.
|
77
|
-
NpmLock::
|
78
|
-
Find and bump version in `./package-lock.json` file
|
79
|
-
+
|
80
|
-
* Same as Npm.
|
81
|
-
Keepachangelog::
|
82
|
-
Find and bump version in `./CHANGELOG.md` file.
|
83
|
-
+
|
84
|
-
* Parse changelog by {rubychangelog}.
|
85
|
-
* Add changes from `Unreleased` version to new release with current date.
|
86
|
-
* Add empty `Unreleased` version.
|
87
|
-
* Serialize back into markdown.
|
data/lib/cli.rb
DELETED
@@ -1,74 +0,0 @@
|
|
1
|
-
require_relative 'vump/version'
|
2
|
-
require_relative 'vump/meta'
|
3
|
-
require_relative 'vump'
|
4
|
-
require 'optparse'
|
5
|
-
|
6
|
-
# Root module for package Vump
|
7
|
-
module Vump
|
8
|
-
# CLI module for package Vump
|
9
|
-
module CLI
|
10
|
-
# Parse CLI arguemnts
|
11
|
-
#
|
12
|
-
# @param [Array<String>] _ arguments (not used now)
|
13
|
-
# OptionParser parses ARGV
|
14
|
-
# @return [Array<String>, Array<String>] options and args
|
15
|
-
def self.parse_argv(_)
|
16
|
-
options = {}
|
17
|
-
args = OptionParser.new do |opt|
|
18
|
-
opt.on('-h', '--help') { options[:help] = true }
|
19
|
-
opt.on('--version') { options[:version] = true }
|
20
|
-
opt.on('-v', '--verbose') { options[:verbose] = true }
|
21
|
-
opt.on('-s', '--silent') { options[:silent] = true }
|
22
|
-
end.parse!
|
23
|
-
setup(options)
|
24
|
-
[options, args]
|
25
|
-
end
|
26
|
-
|
27
|
-
# Tets if CLI arguments are valid.
|
28
|
-
#
|
29
|
-
# @param [Array<String>] args CLI args
|
30
|
-
# @return true if all valid
|
31
|
-
def self.valid_args(args)
|
32
|
-
if args.length != 1
|
33
|
-
Vump.logger.error "Wrong number of args. Got #{args.length}, expected 1"
|
34
|
-
false
|
35
|
-
elsif !/^(ma|mi|p)/i.match(args.first)
|
36
|
-
Vump.logger.error 'Unknown version to bump. <major|minor|patch>'
|
37
|
-
false
|
38
|
-
else
|
39
|
-
true
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def self.setup(options)
|
44
|
-
Vump.logger.level = Logger::INFO
|
45
|
-
if options[:verbose]
|
46
|
-
Vump.logger.level = Logger::DEBUG
|
47
|
-
elsif options[:silent]
|
48
|
-
Vump.logger.level = Logger::UNKNOWN
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def self.log_meta(options)
|
53
|
-
if options[:version]
|
54
|
-
Vump.logger.info "vump #{Vump::VERSION}"
|
55
|
-
elsif options[:help]
|
56
|
-
Vump.logger.info Vump::SUMMARY
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
# Main CLI command
|
61
|
-
def self.start(argv)
|
62
|
-
options, args = parse_argv(argv)
|
63
|
-
if options[:version] || options[:help]
|
64
|
-
log_meta(options)
|
65
|
-
exit true
|
66
|
-
elsif valid_args(args)
|
67
|
-
exit Vump.orchestrate(args)
|
68
|
-
else
|
69
|
-
Vump.logger.info 'vump <major|minor|patch>'
|
70
|
-
exit false
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
data/lib/vump.rb
DELETED
@@ -1,69 +0,0 @@
|
|
1
|
-
require_relative 'vump/semver/semver'
|
2
|
-
Dir[File.expand_path('vump/semver/version_modules/file_modules/*.rb', __dir__)]
|
3
|
-
.each { |file| require file }
|
4
|
-
Dir[File.expand_path('vump/semver/version_modules/vcs_modules/*.rb', __dir__)]
|
5
|
-
.each { |file| require file }
|
6
|
-
require 'logger'
|
7
|
-
|
8
|
-
# Root package module
|
9
|
-
module Vump
|
10
|
-
@@logger = Logger.new(STDOUT)
|
11
|
-
@@logger.formatter = proc do |severity, _datetime, _progname, msg|
|
12
|
-
"#{severity}: #{msg}\n"
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.logger
|
16
|
-
@@logger
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.bump(what, version)
|
20
|
-
case what
|
21
|
-
when /^ma/i
|
22
|
-
version.bump_major
|
23
|
-
when /^mi/i
|
24
|
-
version.bump_minor
|
25
|
-
when /^p/i
|
26
|
-
version.bump_patch
|
27
|
-
end
|
28
|
-
version
|
29
|
-
end
|
30
|
-
|
31
|
-
def self.modules(base = Dir.pwd)
|
32
|
-
mods_vers = Vump::VersionModules::FileModules
|
33
|
-
.constants
|
34
|
-
.map { |m| Vump::VersionModules::FileModules.const_get(m) }
|
35
|
-
.select { |m| m.is_a? Class }
|
36
|
-
.map { |m| m.new(base) }
|
37
|
-
.map { |m| [m, m.read] }
|
38
|
-
.select { |_m, v| v }
|
39
|
-
# "unzip"
|
40
|
-
mods_vers.empty? ? [[], []] : mods_vers.transpose
|
41
|
-
end
|
42
|
-
|
43
|
-
# Format CLI output
|
44
|
-
#
|
45
|
-
# @param [Array[String]] args CLI args
|
46
|
-
# @return [bool] true if successful
|
47
|
-
def self.orchestrate(args)
|
48
|
-
v_modules, current_versions = modules
|
49
|
-
if current_versions.uniq.length > 1
|
50
|
-
Vump.logger.error 'Different versions detected. Quitting.'
|
51
|
-
return false
|
52
|
-
else
|
53
|
-
new_version = bump(args.first, Vump::Semver.new(current_versions.first))
|
54
|
-
v_modules.each { |m| m.write(new_version.to_s) }
|
55
|
-
Vump::VersionModules::VcsModules::Git.revise(v_modules, new_version)
|
56
|
-
return true
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
# Module containing all worker modules to be executed on bump
|
61
|
-
module VersionModules
|
62
|
-
# All file read/write modules to be exectued
|
63
|
-
module FileModules
|
64
|
-
end
|
65
|
-
# All VCS modules to be exectued
|
66
|
-
module VcsModules
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
require 'keepachangelog'
|
2
|
-
|
3
|
-
# Monkey library patch
|
4
|
-
module Keepachangelog
|
5
|
-
# Monkey library patch
|
6
|
-
class MarkdownPrinter
|
7
|
-
# Add tag prefix
|
8
|
-
def anchor(v, i)
|
9
|
-
from_v = i == v.length - 1 ? first_commit : 'v' + v[i + 1]
|
10
|
-
to_v = Gem::Version.correct?(v[i]) ? 'v' + v[i] : 'HEAD'
|
11
|
-
"[#{v[i]}]: #{options[:url]}/compare/#{from_v}...#{to_v}"
|
12
|
-
end
|
13
|
-
|
14
|
-
# Add newline after empty section
|
15
|
-
def version(header, content)
|
16
|
-
chnages = content['changes']
|
17
|
-
[
|
18
|
-
version_header(header, content['date']),
|
19
|
-
chnages.empty? ? '' : chnages.map { |k, v| section(k, v) }
|
20
|
-
]
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,50 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
require 'date'
|
3
|
-
require 'keepachangelog'
|
4
|
-
require_relative '../read_write_version_module'
|
5
|
-
require_relative '../../monkey/keepachangelog'
|
6
|
-
|
7
|
-
module Vump
|
8
|
-
module VersionModules
|
9
|
-
module FileModules
|
10
|
-
# [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
11
|
-
class KeepAChangeLog < Vump::VersionModules::ReadWriteVersionModule
|
12
|
-
def self.name
|
13
|
-
'CHANGELOG.md'
|
14
|
-
end
|
15
|
-
|
16
|
-
def path
|
17
|
-
@base + '/CHANGELOG.md'
|
18
|
-
end
|
19
|
-
|
20
|
-
def scrape(str)
|
21
|
-
Keepachangelog::MarkdownParser
|
22
|
-
.parse(str)['versions']
|
23
|
-
.keys
|
24
|
-
.reject { |v| v == 'Unreleased' }
|
25
|
-
.first
|
26
|
-
end
|
27
|
-
|
28
|
-
def compose(new_version)
|
29
|
-
content = Keepachangelog::MarkdownParser.parse(@read_contents)
|
30
|
-
content = release_changelog(content, new_version)
|
31
|
-
parser = Keepachangelog::Parser.new
|
32
|
-
parser.parsed_content = content
|
33
|
-
parser.to_md + "\n"
|
34
|
-
end
|
35
|
-
|
36
|
-
def release_changelog(changelog, new_version)
|
37
|
-
versions = changelog['versions']
|
38
|
-
# inherit all from unreleased
|
39
|
-
versions[new_version] = versions['Unreleased']
|
40
|
-
.clone
|
41
|
-
# update date
|
42
|
-
versions[new_version]['date'] = Date.today.to_s
|
43
|
-
# reset unreleased
|
44
|
-
versions['Unreleased']['changes'] = {}
|
45
|
-
changelog
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
require_relative '../read_write_version_module'
|
3
|
-
|
4
|
-
module Vump
|
5
|
-
module VersionModules
|
6
|
-
module FileModules
|
7
|
-
# Npm version module for package.json
|
8
|
-
class Npm < Vump::VersionModules::ReadWriteVersionModule
|
9
|
-
def self.name
|
10
|
-
'package.json'
|
11
|
-
end
|
12
|
-
|
13
|
-
def path
|
14
|
-
@base + '/package.json'
|
15
|
-
end
|
16
|
-
|
17
|
-
def scrape(str)
|
18
|
-
JSON.parse(str)['version']
|
19
|
-
end
|
20
|
-
|
21
|
-
def compose(new_version)
|
22
|
-
json = JSON.parse(@read_contents)
|
23
|
-
json['version'] = new_version
|
24
|
-
JSON.pretty_generate(json) + "\n"
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
require_relative '../read_write_version_module'
|
2
|
-
|
3
|
-
module Vump
|
4
|
-
module VersionModules
|
5
|
-
module FileModules
|
6
|
-
# Module for VERSION file
|
7
|
-
class VersionFile < Vump::VersionModules::ReadWriteVersionModule
|
8
|
-
def self.name
|
9
|
-
'VERSION'
|
10
|
-
end
|
11
|
-
|
12
|
-
def path
|
13
|
-
@base + '/VERSION'
|
14
|
-
end
|
15
|
-
|
16
|
-
def scrape(str)
|
17
|
-
str.strip
|
18
|
-
end
|
19
|
-
|
20
|
-
def compose(new_version)
|
21
|
-
new_version + "\n"
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
module Vump
|
2
|
-
module VersionModules
|
3
|
-
# Read write version module archetype
|
4
|
-
class ReadWriteVersionModule
|
5
|
-
def initialize(base)
|
6
|
-
@base = base
|
7
|
-
end
|
8
|
-
|
9
|
-
def read
|
10
|
-
name = self.class.name
|
11
|
-
if File.file?(path)
|
12
|
-
@read_contents = File.read(path)
|
13
|
-
ver = scrape(@read_contents)
|
14
|
-
Vump.logger.debug("#{name} read `#{ver}` from `#{path}`")
|
15
|
-
else
|
16
|
-
Vump.logger.debug("#{name} could not find `#{path}`")
|
17
|
-
end
|
18
|
-
ver
|
19
|
-
end
|
20
|
-
|
21
|
-
def write(new_version)
|
22
|
-
name = self.class.name
|
23
|
-
File.write(path, compose(new_version))
|
24
|
-
Vump.logger.debug("#{name} bumped to `#{new_version}` in `#{path}`")
|
25
|
-
Vump.logger.info("#{name} successfully bumped!")
|
26
|
-
end
|
27
|
-
|
28
|
-
def self.name
|
29
|
-
raise NotImplementedError
|
30
|
-
end
|
31
|
-
|
32
|
-
def path
|
33
|
-
raise NotImplementedError
|
34
|
-
end
|
35
|
-
|
36
|
-
def scrape(_str)
|
37
|
-
raise NotImplementedError
|
38
|
-
end
|
39
|
-
|
40
|
-
def compose(_new_version)
|
41
|
-
raise NotImplementedError
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
module Vump
|
2
|
-
module VersionModules
|
3
|
-
module VcsModules
|
4
|
-
# Git VCS module
|
5
|
-
class Git
|
6
|
-
def self.revise(modules, release_version)
|
7
|
-
return unless File.exist?(Dir.pwd + '/.git')
|
8
|
-
modules.each { |m| `git add #{m.path}` }
|
9
|
-
msg = "Release #{release_version}"
|
10
|
-
tag = "v#{release_version}"
|
11
|
-
`git commit -m "#{msg}"` unless modules.empty?
|
12
|
-
Vump.logger.info "Git commit \"#{msg}\" created"
|
13
|
-
`git tag "#{tag}"`
|
14
|
-
Vump.logger.info "Git tag \"#{tag}\" created"
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|