gem-release 1.0.0 → 2.0.0.dev.1
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 +4 -4
- data/Gemfile +13 -0
- data/Gemfile.lock +72 -0
- data/{lib/gem_release/templates/LICENSE → MIT-LICENSE.md} +3 -2
- data/README.md +646 -0
- data/README.md.erb +159 -0
- data/TODO.txt +194 -0
- data/lib/gem/release.rb +13 -0
- data/lib/gem/release/cmds.rb +16 -0
- data/lib/gem/release/cmds/base.rb +101 -0
- data/lib/gem/release/cmds/bootstrap.rb +222 -0
- data/lib/gem/release/cmds/bump.rb +165 -0
- data/lib/gem/release/cmds/gemspec.rb +85 -0
- data/lib/gem/release/cmds/release.rb +100 -0
- data/lib/gem/release/cmds/runner.rb +52 -0
- data/lib/gem/release/cmds/tag.rb +93 -0
- data/lib/gem/release/config.rb +42 -0
- data/lib/gem/release/config/env.rb +49 -0
- data/lib/gem/release/config/files.rb +35 -0
- data/lib/gem/release/context.rb +76 -0
- data/lib/gem/release/context/gem.rb +28 -0
- data/lib/gem/release/context/gemspec.rb +41 -0
- data/lib/gem/release/context/paths.rb +87 -0
- data/lib/gem/release/context/system.rb +36 -0
- data/lib/gem/release/data.rb +60 -0
- data/lib/gem/release/files/template.rb +61 -0
- data/lib/gem/release/files/template/context.rb +30 -0
- data/lib/gem/release/files/templates.rb +59 -0
- data/lib/gem/release/files/templates/group.rb +47 -0
- data/lib/gem/release/files/version.rb +68 -0
- data/lib/gem/release/helper.rb +45 -0
- data/lib/gem/release/helper/hash.rb +35 -0
- data/lib/gem/release/helper/string.rb +43 -0
- data/lib/gem/release/support/gem_command.rb +67 -0
- data/lib/gem/release/support/registry.rb +59 -0
- data/lib/gem/release/templates/.gitignore +8 -0
- data/lib/gem/release/templates/Gemfile +3 -0
- data/lib/gem/release/templates/gemspec +19 -0
- data/lib/gem/release/templates/licenses/mit.md +21 -0
- data/lib/gem/release/templates/licenses/mpl-2.md +373 -0
- data/lib/gem/release/templates/main.rb +1 -0
- data/lib/gem/release/templates/rspec/.rspec +3 -0
- data/lib/gem/release/templates/rspec/spec/spec_helper.rb +4 -0
- data/lib/gem/release/templates/travis/.travis.yml +1 -0
- data/lib/gem/release/templates/version.rb +1 -0
- data/lib/gem/release/version.rb +5 -0
- data/lib/gem/release/version/number.rb +102 -0
- data/lib/rubygems/commands/bootstrap_command.rb +4 -93
- data/lib/rubygems/commands/bump_command.rb +4 -110
- data/lib/rubygems/commands/gemspec_command.rb +5 -29
- data/lib/rubygems/commands/release_command.rb +4 -70
- data/lib/rubygems/commands/tag_command.rb +5 -46
- data/lib/rubygems_plugin.rb +8 -2
- metadata +56 -83
- data/lib/core_ext/hash/symbolize_keys.rb +0 -13
- data/lib/core_ext/kernel/silence.rb +0 -18
- data/lib/core_ext/string/camelize.rb +0 -5
- data/lib/gem_release.rb +0 -10
- data/lib/gem_release/command_options.rb +0 -31
- data/lib/gem_release/configuration.rb +0 -33
- data/lib/gem_release/gemspec_template.rb +0 -35
- data/lib/gem_release/helpers.rb +0 -104
- data/lib/gem_release/template.rb +0 -52
- data/lib/gem_release/templates/Gemfile +0 -3
- data/lib/gem_release/templates/README.md +0 -1
- data/lib/gem_release/templates/Rakefile +0 -10
- data/lib/gem_release/templates/gemspec +0 -18
- data/lib/gem_release/templates/gitignore +0 -25
- data/lib/gem_release/templates/test/test_helper.rb +0 -2
- data/lib/gem_release/templates/version.rb +0 -12
- data/lib/gem_release/version.rb +0 -3
- data/lib/gem_release/version_file.rb +0 -115
- data/lib/gem_release/version_template.rb +0 -14
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'gem/release/cmds/base'
|
2
|
+
require 'rubygems/commands/build_command'
|
3
|
+
require 'rubygems/commands/push_command'
|
4
|
+
|
5
|
+
module Gem
|
6
|
+
module Release
|
7
|
+
module Cmds
|
8
|
+
class Release < Base
|
9
|
+
summary 'Releases one or all gems in this directory.'
|
10
|
+
|
11
|
+
description <<~str
|
12
|
+
Builds one or many gems from the given gemspec(s), pushes them to rubygems.org
|
13
|
+
(or another, compatible host), and removes the left over gem file.
|
14
|
+
|
15
|
+
Optionally invoke `gem tag`.
|
16
|
+
|
17
|
+
If no argument is given the first gemspec's name is assumed as the gem name.
|
18
|
+
If one or many arguments are given then these will be used. If `--recurse` is
|
19
|
+
given then all gem names from all gemspecs in this directory or any of its
|
20
|
+
subdirectories will be used.
|
21
|
+
str
|
22
|
+
|
23
|
+
arg :gem_name, 'name of the gem (optional, will use the first gemspec, or all gemspecs if --recurse is given)'
|
24
|
+
|
25
|
+
DESCR = {
|
26
|
+
host: 'Push to a compatible host other than rubygems.org',
|
27
|
+
key: 'Use the API key from ~/.gem/credentials',
|
28
|
+
tag: 'Shortcut for running the `gem tag` command',
|
29
|
+
recurse: 'Recurse into directories that contain gemspec files'
|
30
|
+
}
|
31
|
+
|
32
|
+
opt '-h', '--host HOST', DESCR[:host] do |value|
|
33
|
+
opts[:host] = value
|
34
|
+
end
|
35
|
+
|
36
|
+
opt '-k', '--key KEY', DESCR[:key] do |value|
|
37
|
+
opts[:key] = value
|
38
|
+
end
|
39
|
+
|
40
|
+
opt '-t', '--tag', DESCR[:tag] do |value|
|
41
|
+
opts[:tag] = value
|
42
|
+
end
|
43
|
+
|
44
|
+
opt '--recurse', DESCR[:recurse] do |value|
|
45
|
+
opts[:recurse] = value
|
46
|
+
end
|
47
|
+
|
48
|
+
MSGS = {
|
49
|
+
release: 'Releasing %s with version %s',
|
50
|
+
build: 'Building %s',
|
51
|
+
push: 'Pushing %s',
|
52
|
+
cleanup: 'Deleting left over gem file %s'
|
53
|
+
}
|
54
|
+
|
55
|
+
CMDS = {
|
56
|
+
cleanup: 'rm -f %s'
|
57
|
+
}
|
58
|
+
|
59
|
+
def run
|
60
|
+
in_gem_dirs do
|
61
|
+
release
|
62
|
+
end
|
63
|
+
tag if opts[:tag]
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def release
|
69
|
+
announce :release, gem.name, gem.version
|
70
|
+
build
|
71
|
+
push
|
72
|
+
ensure
|
73
|
+
cleanup
|
74
|
+
end
|
75
|
+
|
76
|
+
def tag
|
77
|
+
Tag.new(context, args, opts).run
|
78
|
+
end
|
79
|
+
|
80
|
+
def build
|
81
|
+
gem_cmd :build, gem.spec_filename
|
82
|
+
end
|
83
|
+
|
84
|
+
def push
|
85
|
+
gem_cmd :push, gem.filename, *push_args
|
86
|
+
end
|
87
|
+
|
88
|
+
def push_args
|
89
|
+
args = [:key, :host].map { |opt| ["--#{opt}", opts[opt]] if opts[opt] }
|
90
|
+
args << "--quiet" if quiet?
|
91
|
+
args.compact.flatten
|
92
|
+
end
|
93
|
+
|
94
|
+
def cleanup
|
95
|
+
cmd :cleanup, gem.filename
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'gem/release/context'
|
2
|
+
|
3
|
+
module Gem
|
4
|
+
module Release
|
5
|
+
module Cmds
|
6
|
+
class Runner < Struct.new(:context, :name, :args, :opts)
|
7
|
+
def run
|
8
|
+
run_cmd
|
9
|
+
success
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def run_cmd
|
15
|
+
const.new(context.class.new, args, opts).run
|
16
|
+
end
|
17
|
+
|
18
|
+
def const
|
19
|
+
Base[name]
|
20
|
+
end
|
21
|
+
|
22
|
+
def opts
|
23
|
+
except(super, :args, :build_args)
|
24
|
+
end
|
25
|
+
|
26
|
+
def args
|
27
|
+
super.select { |arg| arg.is_a?(String) && arg[0] != '-' }
|
28
|
+
end
|
29
|
+
|
30
|
+
def success
|
31
|
+
context.announce "All is good, thanks my friend." unless quiet?
|
32
|
+
end
|
33
|
+
|
34
|
+
def quiet?
|
35
|
+
opts[:quiet] || opts[:silent]
|
36
|
+
end
|
37
|
+
|
38
|
+
def opts
|
39
|
+
@opts ||= config.merge(super)
|
40
|
+
end
|
41
|
+
|
42
|
+
def config
|
43
|
+
context.config.for(name.to_sym)
|
44
|
+
end
|
45
|
+
|
46
|
+
def except(hash, *keys)
|
47
|
+
hash.reject { |key, _| keys.include?(key) }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'gem/release/cmds/base'
|
2
|
+
|
3
|
+
module Gem
|
4
|
+
module Release
|
5
|
+
module Cmds
|
6
|
+
class Tag < Base
|
7
|
+
summary "Tags the HEAD commit with the gem's current version."
|
8
|
+
|
9
|
+
description <<~str
|
10
|
+
Creates an annotated tag for the current HEAD commit, using the gem's
|
11
|
+
current version.
|
12
|
+
|
13
|
+
Optionally pushes the tag to the origin repository.
|
14
|
+
|
15
|
+
If one or many arguments are given then gemspecs with the same names
|
16
|
+
will be searched, and the working directory changed to their respective
|
17
|
+
directories. If `--recurse` is given then the directories all gem names from
|
18
|
+
all gemspecs in this directory or any of its subdirectories will be used.
|
19
|
+
This assumes that these directories are separate git repositories.
|
20
|
+
|
21
|
+
The tag name will be `v[version]`. For example, if the current version is
|
22
|
+
`1.0.0`, then The tag is created using the command `git tag -am "tag v1.0.0"
|
23
|
+
v1.0.0`.
|
24
|
+
str
|
25
|
+
|
26
|
+
DEFAULTS = {
|
27
|
+
push: true,
|
28
|
+
remote: 'origin'
|
29
|
+
}
|
30
|
+
|
31
|
+
DESCR = {
|
32
|
+
push: 'Push tag to the remote git repository',
|
33
|
+
remote: 'Git remote to push to (defaults to origin)',
|
34
|
+
}
|
35
|
+
|
36
|
+
opt '-p', '--[no]-push', DESCR[:push] do
|
37
|
+
opts[:push] = true
|
38
|
+
end
|
39
|
+
|
40
|
+
opt '--remote REMOTE', DESCR[:remote] do |value|
|
41
|
+
opts[:remote] = value
|
42
|
+
end
|
43
|
+
|
44
|
+
MSGS = {
|
45
|
+
tag: 'Tagging %s as version %s',
|
46
|
+
git_tag: 'Creating git tag %s',
|
47
|
+
git_push: 'Pushing tags to the %s git repository',
|
48
|
+
no_remote: 'Cannot push to missing git remote %s',
|
49
|
+
}
|
50
|
+
|
51
|
+
CMDS = {
|
52
|
+
git_tag: 'git tag -am "tag %s" %s',
|
53
|
+
git_push: 'git push --tags %s'
|
54
|
+
}
|
55
|
+
|
56
|
+
def run
|
57
|
+
in_gem_dirs do
|
58
|
+
announce :tag, gem.name, gem.version
|
59
|
+
validate
|
60
|
+
tag
|
61
|
+
push if opts[:push]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def validate
|
68
|
+
abort :no_remote, remote if push? && !git_remotes.include?(remote)
|
69
|
+
end
|
70
|
+
|
71
|
+
def tag
|
72
|
+
cmd :git_tag, tag_name, tag_name
|
73
|
+
end
|
74
|
+
|
75
|
+
def push
|
76
|
+
cmd :git_push, remote
|
77
|
+
end
|
78
|
+
|
79
|
+
def tag_name
|
80
|
+
"v#{gem.version}"
|
81
|
+
end
|
82
|
+
|
83
|
+
def push?
|
84
|
+
opts[:push] || opts[:push_commit]
|
85
|
+
end
|
86
|
+
|
87
|
+
def remote
|
88
|
+
opts[:remote]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'gem/release/config/env'
|
2
|
+
require 'gem/release/config/files'
|
3
|
+
require 'gem/release/helper/hash'
|
4
|
+
|
5
|
+
module Gem
|
6
|
+
module Release
|
7
|
+
class Config
|
8
|
+
include Helper::Hash
|
9
|
+
|
10
|
+
attr_reader :opts
|
11
|
+
|
12
|
+
SOURCES = [Env, Files]
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@opts = load
|
16
|
+
end
|
17
|
+
|
18
|
+
def [](key)
|
19
|
+
opts[key]
|
20
|
+
end
|
21
|
+
|
22
|
+
def for(key)
|
23
|
+
common.merge(self[key] || {})
|
24
|
+
end
|
25
|
+
|
26
|
+
def common
|
27
|
+
opts.reject { |_, value| value.is_a?(Hash) }
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def load
|
33
|
+
opts = sources.map(&:load)
|
34
|
+
opts.inject { |one, other| deep_merge(one, other) }
|
35
|
+
end
|
36
|
+
|
37
|
+
def sources
|
38
|
+
SOURCES.map(&:new)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'gem/release/helper/hash'
|
2
|
+
|
3
|
+
module Gem
|
4
|
+
module Release
|
5
|
+
class Config
|
6
|
+
class Env
|
7
|
+
include Helper::Hash
|
8
|
+
|
9
|
+
PREFIX = 'GEM_RELEASE_'
|
10
|
+
TRUE = /^(true|yes|on)$/
|
11
|
+
FALSE = /^(false|no|off)$/
|
12
|
+
|
13
|
+
def load
|
14
|
+
opts = vars.map { |key, value| to_hash(keys_for(key), cast(value)) }
|
15
|
+
opts = opts.inject { |one, other| deep_merge(one, other) }
|
16
|
+
opts || {}
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def vars
|
22
|
+
ENV.select { |key, _| key.start_with?(PREFIX) }
|
23
|
+
end
|
24
|
+
|
25
|
+
def keys_for(key)
|
26
|
+
key.sub(PREFIX, '').split('_').map(&:downcase).map(&:to_sym)
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_hash(keys, value)
|
30
|
+
keys = keys.reverse
|
31
|
+
keys.inject(keys.shift => value) { |value, key| { key => value } }
|
32
|
+
end
|
33
|
+
|
34
|
+
def cast(value)
|
35
|
+
case value
|
36
|
+
when TRUE
|
37
|
+
true
|
38
|
+
when FALSE
|
39
|
+
false
|
40
|
+
when ''
|
41
|
+
false
|
42
|
+
else
|
43
|
+
value
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'gem/release/helper/hash'
|
3
|
+
|
4
|
+
module Gem
|
5
|
+
module Release
|
6
|
+
class Config
|
7
|
+
class Files
|
8
|
+
include Helper::Hash
|
9
|
+
|
10
|
+
PATHS = %w(
|
11
|
+
./.gem_release/config.yml
|
12
|
+
./.gem_release.yml
|
13
|
+
~/.gem_release/config.yml
|
14
|
+
~/.gem_release.yml
|
15
|
+
)
|
16
|
+
|
17
|
+
def load
|
18
|
+
return {} unless path
|
19
|
+
symbolize_keys(YAML.load_file(path) || {})
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def path
|
25
|
+
@path ||= paths.first
|
26
|
+
end
|
27
|
+
|
28
|
+
def paths
|
29
|
+
paths = PATHS.map { |path| File.expand_path(path) }
|
30
|
+
paths.select { |path| File.exists?(path) }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'gem/release/context/gem'
|
2
|
+
require 'gem/release/context/paths'
|
3
|
+
require 'gem/release/context/system'
|
4
|
+
|
5
|
+
module Gem
|
6
|
+
module Release
|
7
|
+
class Context
|
8
|
+
class << self
|
9
|
+
attr_accessor :last
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_accessor :config, :gem, :system
|
13
|
+
|
14
|
+
COLORS = {
|
15
|
+
red: "\e[31m",
|
16
|
+
green: "\e[32m",
|
17
|
+
yellow: "\e[33m",
|
18
|
+
blue: "\e[34m",
|
19
|
+
gray: "\e[37m",
|
20
|
+
reset: "\e[0m"
|
21
|
+
}
|
22
|
+
|
23
|
+
def initialize(name = nil)
|
24
|
+
@config = Config.new
|
25
|
+
@gem = Gem.new(name || File.basename(Dir.pwd))
|
26
|
+
@system = System.new
|
27
|
+
end
|
28
|
+
|
29
|
+
def announce(str)
|
30
|
+
puts colored(:green, with_spacing(str, true))
|
31
|
+
end
|
32
|
+
|
33
|
+
def info(str)
|
34
|
+
puts colored(:blue, with_spacing(str, true))
|
35
|
+
end
|
36
|
+
|
37
|
+
def notice(str)
|
38
|
+
puts colored(:gray, with_spacing(str, false))
|
39
|
+
end
|
40
|
+
|
41
|
+
def warn(str)
|
42
|
+
puts colored(:yellow, with_spacing(str, false))
|
43
|
+
end
|
44
|
+
|
45
|
+
def error(str)
|
46
|
+
puts colored(:red, with_spacing(str, true))
|
47
|
+
end
|
48
|
+
|
49
|
+
def abort(str)
|
50
|
+
error(str)
|
51
|
+
exit 1
|
52
|
+
end
|
53
|
+
|
54
|
+
def in_dirs(args, opts, &block)
|
55
|
+
Paths::ByNames.new(args, opts).in_dirs(&block)
|
56
|
+
end
|
57
|
+
|
58
|
+
def in_gem_dirs(args, opts, &block)
|
59
|
+
Paths::ByGemspecs.new(args, opts).in_dirs(&block)
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def colored(color, str)
|
65
|
+
[COLORS[color], str, COLORS[:reset]].join
|
66
|
+
end
|
67
|
+
|
68
|
+
def with_spacing(str, space)
|
69
|
+
space = false if self.class.last.nil?
|
70
|
+
str = "\n#{str}" if space && !self.class.last
|
71
|
+
self.class.last = space
|
72
|
+
str
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|