released 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/Gemfile.lock +12 -26
- data/README.md +9 -0
- data/Rakefile +1 -1
- data/bin/released +16 -0
- data/lib/released.rb +1 -1
- data/lib/released/goals.rb +1 -0
- data/lib/released/goals/file_exists.rb +4 -0
- data/lib/released/goals/gem_built.rb +2 -5
- data/lib/released/goals/gem_pushed.rb +1 -1
- data/lib/released/goals/git_ref_pushed.rb +27 -10
- data/lib/released/goals/git_tag_exists.rb +48 -0
- data/lib/released/goals/github_release_exists.rb +4 -0
- data/lib/released/goals/shell.rb +5 -1
- data/lib/released/pipeline_reader.rb +18 -11
- data/lib/released/piper.rb +46 -0
- data/lib/released/runner.rb +10 -3
- data/lib/released/version.rb +1 -1
- data/released.gemspec +9 -11
- data/spec/released/goals/gem_built_spec.rb +13 -1
- data/spec/released/goals/gem_pushed_spec.rb +5 -1
- data/spec/released/goals/git_ref_pushed_spec.rb +82 -20
- data/spec/released/goals/git_tag_exists_spec.rb +122 -0
- data/spec/released/pipeline_reader_spec.rb +16 -1
- metadata +26 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fab7a728ee7f9ddc1d86e930cc73b61dde1aabb8
|
4
|
+
data.tar.gz: 3499f338230eb9569a2521091237ef3fe7dd51c4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f0db6f2591d68a924ead6cd71c30016aa2976ccf834be39101ec69cdccfe5f850c466bdd6e3ac0c1fa4a71d5e316df88ac992acdca0c47022cd2c1bbcf31ead2
|
7
|
+
data.tar.gz: 19e96e14c94e96f7a6dc3bba1ede47003c55558c7ac9de213f9655725e58b435836eebb51e97724192e774417807a3fdde7dae7e7775cc270bcaf75008097b56
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
released (0.0.
|
4
|
+
released (0.0.2)
|
5
5
|
ddplugin (~> 1.0)
|
6
|
-
gems
|
7
|
-
git
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
twitter
|
6
|
+
gems (~> 0.8)
|
7
|
+
git (~> 1.3)
|
8
|
+
netrc (~> 0.11)
|
9
|
+
octokit (~> 4.6)
|
10
|
+
twitter (~> 4.8)
|
12
11
|
|
13
12
|
GEM
|
14
13
|
remote: https://rubygems.org/
|
@@ -17,15 +16,11 @@ GEM
|
|
17
16
|
public_suffix (~> 2.0, >= 2.0.2)
|
18
17
|
ast (2.3.0)
|
19
18
|
builder (3.2.2)
|
20
|
-
colored (1.2)
|
21
|
-
concurrent-ruby (1.0.2)
|
22
19
|
crack (0.4.3)
|
23
20
|
safe_yaml (~> 1.0.0)
|
24
|
-
cri (2.7.0)
|
25
|
-
colored (~> 1.2)
|
26
21
|
ddplugin (1.0.0)
|
27
22
|
diff-lcs (1.2.5)
|
28
|
-
faraday (0.
|
23
|
+
faraday (0.9.2)
|
29
24
|
multipart-post (>= 1.2, < 3)
|
30
25
|
fuubar (2.2.0)
|
31
26
|
rspec-core (~> 3.0)
|
@@ -38,24 +33,16 @@ GEM
|
|
38
33
|
sinatra (>= 1.2.7)
|
39
34
|
gems (0.8.3)
|
40
35
|
git (1.3.0)
|
41
|
-
hamster (3.0.0)
|
42
|
-
concurrent-ruby (~> 1.0)
|
43
36
|
hashdiff (0.3.1)
|
44
37
|
httpclient (2.8.2.4)
|
45
38
|
json (2.0.2)
|
46
39
|
multi_json (1.12.1)
|
47
40
|
multipart-post (2.0.0)
|
48
|
-
nanoc (4.4.2)
|
49
|
-
cri (~> 2.3)
|
50
|
-
hamster (~> 3.0)
|
51
|
-
parallel (~> 1.9)
|
52
|
-
ref (~> 2.0)
|
53
41
|
nesty (1.0.2)
|
54
42
|
netrc (0.11.0)
|
55
43
|
octokit (4.6.2)
|
56
44
|
sawyer (~> 0.8.0, >= 0.5.3)
|
57
|
-
|
58
|
-
parser (2.3.2.0)
|
45
|
+
parser (2.3.3.1)
|
59
46
|
ast (~> 2.2)
|
60
47
|
powerpack (0.1.1)
|
61
48
|
public_suffix (2.0.4)
|
@@ -64,7 +51,6 @@ GEM
|
|
64
51
|
rack
|
65
52
|
rainbow (2.1.0)
|
66
53
|
rake (11.3.0)
|
67
|
-
ref (2.0.0)
|
68
54
|
rspec (3.5.0)
|
69
55
|
rspec-core (~> 3.5.0)
|
70
56
|
rspec-expectations (~> 3.5.0)
|
@@ -81,7 +67,7 @@ GEM
|
|
81
67
|
diff-lcs (>= 1.2.0, < 2.0)
|
82
68
|
rspec-support (~> 3.5.0)
|
83
69
|
rspec-support (3.5.0)
|
84
|
-
rubocop (0.
|
70
|
+
rubocop (0.46.0)
|
85
71
|
parser (>= 2.3.1.1, < 3.0)
|
86
72
|
powerpack (~> 0.1)
|
87
73
|
rainbow (>= 1.99.1, < 3.0)
|
@@ -98,9 +84,9 @@ GEM
|
|
98
84
|
rack-protection (~> 1.4)
|
99
85
|
tilt (>= 1.3, < 3)
|
100
86
|
tilt (2.0.5)
|
101
|
-
twitter (4.
|
102
|
-
faraday (~> 0.8)
|
103
|
-
multi_json (~> 1.
|
87
|
+
twitter (4.8.1)
|
88
|
+
faraday (~> 0.8, < 0.10)
|
89
|
+
multi_json (~> 1.0)
|
104
90
|
simple_oauth (~> 0.2)
|
105
91
|
unicode-display_width (1.1.1)
|
106
92
|
vcr (3.0.3)
|
data/README.md
CHANGED
@@ -113,8 +113,17 @@ Strings in `pipeline.yaml` will be replaced according the following rules:
|
|
113
113
|
|
114
114
|
* Strings starting with `sh!` will be replaced with the output of the shell command following the exclamation mark. For example, `version: sh!echo -n 0.1.2` will become `version: 0.1.2`.
|
115
115
|
|
116
|
+
* Strings starting with `var!` will be replaced with the value of the named variable. See below for details on how to set variables. For example, `version: var!version` will become `version: 0.1.2`, if the `version` variable is set to `0.1.2`.
|
117
|
+
|
116
118
|
* Strings starting with `-----BEGIN PGP MESSAGE-----` will be replaced with their content passed through `gpg --decrypt`.
|
117
119
|
|
120
|
+
The pipeline file can contain a `vars` section, which defines variables. The keys are variable names, and the value are the variable values. For example, the following defines a variable `version` with the contents of `Released::VERSION`, defined in `lib/released/version.rb`:
|
121
|
+
|
122
|
+
```yaml
|
123
|
+
vars:
|
124
|
+
version: sh!ruby -r./lib/released/version -e 'print Released::VERSION'
|
125
|
+
```
|
126
|
+
|
118
127
|
## Defining custom goal types
|
119
128
|
|
120
129
|
To define a custom goal type, subclass `Released::Goal` and give it an identifier:
|
data/Rakefile
CHANGED
@@ -3,7 +3,7 @@ require 'rspec/core/rake_task'
|
|
3
3
|
|
4
4
|
RuboCop::RakeTask.new(:rubocop) do |task|
|
5
5
|
task.options = %w(--display-cop-names --format simple)
|
6
|
-
task.patterns = ['bin/*', 'lib/**/*.rb', 'spec/**/*.rb']
|
6
|
+
task.patterns = ['bin/*', 'lib/**/*.rb', 'spec/**/*.rb', 'Gemfile', 'Rakefile', '*.gemspec']
|
7
7
|
end
|
8
8
|
|
9
9
|
RSpec::Core::RakeTask.new(:spec) do |t|
|
data/bin/released
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'released'
|
4
|
+
require 'yaml'
|
5
|
+
|
6
|
+
opts, args = ARGV.partition { |a| a.start_with?('-') }
|
7
|
+
|
8
|
+
if args.size != 1
|
9
|
+
$stderr.puts "usage: #{$PROGRAM_NAME} [options] filename"
|
10
|
+
exit 1
|
11
|
+
end
|
12
|
+
|
13
|
+
dry_run = opts.include?('--dry-run')
|
14
|
+
|
15
|
+
goals = Released::PipelineReader.new(args[0]).read
|
16
|
+
Released::Runner.new(goals, dry_run: dry_run).run
|
data/lib/released.rb
CHANGED
@@ -8,10 +8,10 @@ require 'shellwords'
|
|
8
8
|
require 'uri'
|
9
9
|
|
10
10
|
require 'ddplugin'
|
11
|
-
require 'nanoc'
|
12
11
|
|
13
12
|
require_relative 'released/version'
|
14
13
|
require_relative 'released/goal'
|
15
14
|
require_relative 'released/runner'
|
15
|
+
require_relative 'released/piper'
|
16
16
|
require_relative 'released/pipeline_reader'
|
17
17
|
require_relative 'released/goals'
|
data/lib/released/goals.rb
CHANGED
@@ -7,5 +7,6 @@ require_relative 'goals/file_exists'
|
|
7
7
|
require_relative 'goals/gem_built'
|
8
8
|
require_relative 'goals/gem_pushed'
|
9
9
|
require_relative 'goals/git_ref_pushed'
|
10
|
+
require_relative 'goals/git_tag_exists'
|
10
11
|
require_relative 'goals/github_release_exists'
|
11
12
|
require_relative 'goals/shell'
|
@@ -13,12 +13,9 @@ module Released
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def try_achieve
|
16
|
-
# TODO: remove
|
17
|
-
Dir['*.gem'].each { |f| FileUtils.rm_f(f) }
|
18
|
-
|
19
16
|
stdout = ''
|
20
17
|
stderr = ''
|
21
|
-
piper =
|
18
|
+
piper = Released::Piper.new(stdout: stdout, stderr: stderr)
|
22
19
|
|
23
20
|
begin
|
24
21
|
gemspec_file_path = "#{@name}.gemspec"
|
@@ -33,7 +30,7 @@ module Released
|
|
33
30
|
end
|
34
31
|
|
35
32
|
def failure_reason
|
36
|
-
"
|
33
|
+
"file #{expected_name} does not exist"
|
37
34
|
end
|
38
35
|
|
39
36
|
private
|
@@ -8,25 +8,27 @@ module Released
|
|
8
8
|
def initialize(config)
|
9
9
|
@working_dir = config.fetch('working_dir')
|
10
10
|
@remote = config.fetch('remote')
|
11
|
-
@
|
11
|
+
@ref = config.fetch('ref')
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_s
|
15
|
+
"Git ref pushed (#{@remote}/#{@ref})"
|
12
16
|
end
|
13
17
|
|
14
18
|
def try_achieve
|
15
|
-
g.push(@remote, @
|
19
|
+
g.push(@remote, @ref)
|
16
20
|
end
|
17
21
|
|
18
22
|
def achieved?
|
19
|
-
|
20
|
-
return false if there_branch.nil?
|
21
|
-
there = there_branch.gcommit.sha
|
22
|
-
|
23
|
-
here = g.object('HEAD').sha
|
24
|
-
|
25
|
-
here == there
|
23
|
+
local_sha == remote_sha
|
26
24
|
end
|
27
25
|
|
28
26
|
def failure_reason
|
29
|
-
|
27
|
+
if remote_sha
|
28
|
+
"ref #{@ref} (#{abbr local_sha}) is not the same as #{@remote}/#{@ref} (#{abbr remote_sha})"
|
29
|
+
else
|
30
|
+
"ref #{@ref} (#{abbr local_sha}) does not exist on remote #{@remote}"
|
31
|
+
end
|
30
32
|
end
|
31
33
|
|
32
34
|
private
|
@@ -34,6 +36,21 @@ module Released
|
|
34
36
|
def g
|
35
37
|
@_g ||= Git.open(@working_dir)
|
36
38
|
end
|
39
|
+
|
40
|
+
def abbr(sha)
|
41
|
+
sha && sha[0..7]
|
42
|
+
end
|
43
|
+
|
44
|
+
def remote_sha
|
45
|
+
remote_url = g.remote(@remote).url
|
46
|
+
res = Git.ls_remote(remote_url)
|
47
|
+
ref = res['branches'].merge(res['tags']).find { |name, _data| name == @ref }
|
48
|
+
ref ? ref[1][:sha] : nil
|
49
|
+
end
|
50
|
+
|
51
|
+
def local_sha
|
52
|
+
g.object(@ref).sha
|
53
|
+
end
|
37
54
|
end
|
38
55
|
end
|
39
56
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'git'
|
2
|
+
|
3
|
+
module Released
|
4
|
+
module Goals
|
5
|
+
class GitTagExists < Released::Goal
|
6
|
+
identifier :git_tag_exists
|
7
|
+
|
8
|
+
def initialize(config)
|
9
|
+
@working_dir = config.fetch('working_dir')
|
10
|
+
@name = config.fetch('name')
|
11
|
+
@ref = config.fetch('ref')
|
12
|
+
end
|
13
|
+
|
14
|
+
# git tag --sign --annotate 2.7.1 --message 'Version 2.7.1'
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
"Git tag exists (#{@name}, ref #{@ref})"
|
18
|
+
end
|
19
|
+
|
20
|
+
def try_achieve
|
21
|
+
g.add_tag(@name, @ref)
|
22
|
+
end
|
23
|
+
|
24
|
+
def achieved?
|
25
|
+
g.tags.any? { |t| t.name == @name && t.sha == ref_sha }
|
26
|
+
end
|
27
|
+
|
28
|
+
def failure_reason
|
29
|
+
tag_with_name = g.tags.find { |t| t.name == @name }
|
30
|
+
if tag_with_name
|
31
|
+
"tag named #{@name} points to different rev"
|
32
|
+
else
|
33
|
+
"no tag named #{@name} exists"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def g
|
40
|
+
@_g ||= Git.open(@working_dir)
|
41
|
+
end
|
42
|
+
|
43
|
+
def ref_sha
|
44
|
+
g.object(@ref).sha
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/released/goals/shell.rb
CHANGED
@@ -23,7 +23,7 @@ module Released
|
|
23
23
|
def try_achieve
|
24
24
|
stdout = ''
|
25
25
|
stderr = ''
|
26
|
-
piper =
|
26
|
+
piper = Released::Piper.new(stdout: stdout, stderr: stderr)
|
27
27
|
|
28
28
|
begin
|
29
29
|
piper.run(@command, [])
|
@@ -35,6 +35,10 @@ module Released
|
|
35
35
|
def achieved?
|
36
36
|
false
|
37
37
|
end
|
38
|
+
|
39
|
+
def failure_reason
|
40
|
+
'command not executed'
|
41
|
+
end
|
38
42
|
end
|
39
43
|
end
|
40
44
|
end
|
@@ -5,7 +5,7 @@ module Released
|
|
5
5
|
end
|
6
6
|
|
7
7
|
def read
|
8
|
-
yaml =
|
8
|
+
yaml = transform_root(YAML.load_file(@filename))
|
9
9
|
|
10
10
|
goals = []
|
11
11
|
|
@@ -22,37 +22,44 @@ module Released
|
|
22
22
|
|
23
23
|
private
|
24
24
|
|
25
|
-
def
|
25
|
+
def transform_root(obj)
|
26
|
+
vars = transform(obj['vars'], {})
|
27
|
+
{ 'goals' => transform(obj['goals'], vars) }
|
28
|
+
end
|
29
|
+
|
30
|
+
def transform(obj, vars)
|
26
31
|
case obj
|
27
32
|
when Hash
|
28
|
-
transform_hash(obj)
|
33
|
+
transform_hash(obj, vars)
|
29
34
|
when Array
|
30
|
-
transform_array(obj)
|
35
|
+
transform_array(obj, vars)
|
31
36
|
when String
|
32
|
-
transform_string(obj)
|
37
|
+
transform_string(obj, vars)
|
33
38
|
else
|
34
39
|
obj
|
35
40
|
end
|
36
41
|
end
|
37
42
|
|
38
|
-
def transform_hash(hash)
|
43
|
+
def transform_hash(hash, vars)
|
39
44
|
hash.each_with_object({}) do |(key, value), memo|
|
40
|
-
memo[key] = transform(value)
|
45
|
+
memo[key] = transform(value, vars)
|
41
46
|
end
|
42
47
|
end
|
43
48
|
|
44
|
-
def transform_array(array)
|
49
|
+
def transform_array(array, vars)
|
45
50
|
array.map do |elem|
|
46
|
-
transform(elem)
|
51
|
+
transform(elem, vars)
|
47
52
|
end
|
48
53
|
end
|
49
54
|
|
50
|
-
def transform_string(string)
|
55
|
+
def transform_string(string, vars)
|
51
56
|
case string
|
52
57
|
when /\Aenv!(.*)/
|
53
58
|
ENV.fetch(Regexp.last_match(1))
|
54
59
|
when /\Ash!(.*)/
|
55
60
|
`#{Regexp.last_match(1)}`
|
61
|
+
when /\Avar!(.*)/
|
62
|
+
vars[Regexp.last_match(1)]
|
56
63
|
when /\A-----BEGIN PGP MESSAGE-----/
|
57
64
|
decrypt(string)
|
58
65
|
else
|
@@ -64,7 +71,7 @@ module Released
|
|
64
71
|
stdout = ''
|
65
72
|
stderr = ''
|
66
73
|
|
67
|
-
piper =
|
74
|
+
piper = Released::Piper.new(stdout: stdout, stderr: stderr)
|
68
75
|
piper.run(['gpg', '--decrypt', '--no-tty'], string)
|
69
76
|
|
70
77
|
stdout
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
3
|
+
module Released
|
4
|
+
class Piper
|
5
|
+
class Error < StandardError
|
6
|
+
def initialize(command, exit_code)
|
7
|
+
@command = command
|
8
|
+
@exit_code = exit_code
|
9
|
+
end
|
10
|
+
|
11
|
+
def message
|
12
|
+
"command exited with a nonzero status code #{@exit_code} (command: #{@command.join(' ')})"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# @param [IO] stdout
|
17
|
+
# @param [IO] stderr
|
18
|
+
def initialize(stdout: $stdout, stderr: $stderr)
|
19
|
+
@stdout = stdout
|
20
|
+
@stderr = stderr
|
21
|
+
end
|
22
|
+
|
23
|
+
# @param [Array<String>] cmd
|
24
|
+
#
|
25
|
+
# @param [String, nil] input
|
26
|
+
def run(cmd, input)
|
27
|
+
Open3.popen3(*cmd) do |stdin, stdout, stderr, wait_thr|
|
28
|
+
stdout_thread = Thread.new { @stdout << stdout.read }
|
29
|
+
stderr_thread = Thread.new { @stderr << stderr.read }
|
30
|
+
|
31
|
+
if input
|
32
|
+
stdin << input
|
33
|
+
end
|
34
|
+
stdin.close
|
35
|
+
|
36
|
+
stdout_thread.join
|
37
|
+
stderr_thread.join
|
38
|
+
|
39
|
+
exit_status = wait_thr.value
|
40
|
+
unless exit_status.success?
|
41
|
+
raise Error.new(cmd, exit_status.to_i)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/released/runner.rb
CHANGED
@@ -55,10 +55,15 @@ module Released
|
|
55
55
|
private
|
56
56
|
|
57
57
|
def print_goals
|
58
|
+
# Create space
|
59
|
+
@goals.each { puts }
|
60
|
+
@tui.move_up(@goals.size)
|
61
|
+
|
58
62
|
@goals.each do |goal|
|
59
63
|
left.times { $stdout << '. ' }
|
60
64
|
|
61
65
|
@tui.move_to_left
|
66
|
+
$stdout << ' '
|
62
67
|
$stdout << goal
|
63
68
|
$stdout << ' '
|
64
69
|
|
@@ -92,7 +97,7 @@ module Released
|
|
92
97
|
end
|
93
98
|
|
94
99
|
def left
|
95
|
-
@_left ||= @goals.map { |g| g.to_s.size }.max +
|
100
|
+
@_left ||= @goals.map { |g| g.to_s.size }.max + 8
|
96
101
|
end
|
97
102
|
|
98
103
|
def assess_all
|
@@ -136,7 +141,7 @@ module Released
|
|
136
141
|
if goal.achieved?
|
137
142
|
write_state(idx, left, 'ok (already achieved)')
|
138
143
|
else
|
139
|
-
write_state(idx, left, 'pending')
|
144
|
+
write_state(idx, left, 'pending: ' + goal.failure_reason)
|
140
145
|
end
|
141
146
|
next
|
142
147
|
end
|
@@ -162,7 +167,9 @@ module Released
|
|
162
167
|
write_state(idx, left, 'ok (newly achieved)')
|
163
168
|
next
|
164
169
|
else
|
165
|
-
write_state(idx, left, 'failed')
|
170
|
+
write_state(idx, left, 'failed: ' + goal.failure_reason)
|
171
|
+
puts
|
172
|
+
puts 'Failed!'
|
166
173
|
exit 1 # FIXME: eww
|
167
174
|
end
|
168
175
|
end
|
data/lib/released/version.rb
CHANGED
data/released.gemspec
CHANGED
@@ -13,24 +13,22 @@ Gem::Specification.new do |s|
|
|
13
13
|
|
14
14
|
s.files =
|
15
15
|
Dir['[A-Z]*'] +
|
16
|
-
Dir['{lib,spec}/**/*'] +
|
16
|
+
Dir['{bin,lib,spec}/**/*'] +
|
17
17
|
Dir['*.gemspec']
|
18
|
-
s.
|
18
|
+
s.executables = ['released']
|
19
|
+
s.require_paths = ['lib']
|
19
20
|
|
20
|
-
s.rdoc_options
|
21
|
+
s.rdoc_options = ['--main', 'README.md']
|
21
22
|
|
22
23
|
s.required_ruby_version = '>= 2.3.0'
|
23
24
|
|
24
25
|
# Dependencies for goals
|
25
26
|
# TODO: Move into plugins
|
26
|
-
s.add_runtime_dependency('git')
|
27
|
-
s.add_runtime_dependency('twitter')
|
28
|
-
s.add_runtime_dependency('gems')
|
29
|
-
s.add_runtime_dependency('netrc')
|
30
|
-
s.add_runtime_dependency('octokit')
|
31
|
-
|
32
|
-
# TODO: Remove this (copy piper?)
|
33
|
-
s.add_runtime_dependency('nanoc', '~> 4.4')
|
27
|
+
s.add_runtime_dependency('git', '~> 1.3')
|
28
|
+
s.add_runtime_dependency('twitter', '~> 4.8')
|
29
|
+
s.add_runtime_dependency('gems', '~> 0.8')
|
30
|
+
s.add_runtime_dependency('netrc', '~> 0.11')
|
31
|
+
s.add_runtime_dependency('octokit', '~> 4.6')
|
34
32
|
|
35
33
|
s.add_runtime_dependency('ddplugin', '~> 1.0')
|
36
34
|
|
@@ -54,11 +54,23 @@ describe Released::Goals::GemBuilt do
|
|
54
54
|
it 'builds the gem' do
|
55
55
|
expect { subject }.to change { File.file?('donkey-0.1.gem') }.from(false).to(true)
|
56
56
|
end
|
57
|
+
|
58
|
+
context 'other gems already exist' do
|
59
|
+
before { File.write('foo-1.0.gem', 'stuff') }
|
60
|
+
|
61
|
+
it 'builds the gem' do
|
62
|
+
expect { subject }.to change { File.file?('donkey-0.1.gem') }.from(false).to(true)
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'does not remove other gems' do
|
66
|
+
expect { subject }.not_to change { File.file?('foo-1.0.gem') }
|
67
|
+
end
|
68
|
+
end
|
57
69
|
end
|
58
70
|
end
|
59
71
|
|
60
72
|
describe '#failure_reason' do
|
61
73
|
subject { goal.failure_reason }
|
62
|
-
it { is_expected.to eql('
|
74
|
+
it { is_expected.to eql('file donkey-0.1.gem does not exist') }
|
63
75
|
end
|
64
76
|
end
|
@@ -144,6 +144,10 @@ describe Released::Goals::GemPushed, stdio: true do
|
|
144
144
|
end
|
145
145
|
|
146
146
|
describe '#failure_reason' do
|
147
|
-
|
147
|
+
subject { goal.failure_reason }
|
148
|
+
|
149
|
+
let(:authorization) { incorrect_authorization } # irrelevant
|
150
|
+
|
151
|
+
it { is_expected.to eql('list of gems does not contain “nanoc”, version 4.4.2') }
|
148
152
|
end
|
149
153
|
end
|
@@ -7,10 +7,12 @@ describe Released::Goals::GitRefPushed do
|
|
7
7
|
{
|
8
8
|
'working_dir' => 'local',
|
9
9
|
'remote' => 'gitlab',
|
10
|
-
'
|
10
|
+
'ref' => config_ref,
|
11
11
|
}
|
12
12
|
end
|
13
13
|
|
14
|
+
let(:config_ref) { 'devel' }
|
15
|
+
|
14
16
|
let!(:local) do
|
15
17
|
Git.init('local').tap do |g|
|
16
18
|
g.config('user.name', 'Testy McTestface')
|
@@ -20,6 +22,7 @@ describe Released::Goals::GitRefPushed do
|
|
20
22
|
g.add('hello.txt')
|
21
23
|
g.commit('Add greeting')
|
22
24
|
g.branch('devel').checkout
|
25
|
+
g.add_tag('1.2.4')
|
23
26
|
end
|
24
27
|
end
|
25
28
|
|
@@ -34,41 +37,100 @@ describe Released::Goals::GitRefPushed do
|
|
34
37
|
describe '#achieved?' do
|
35
38
|
subject { goal.achieved? }
|
36
39
|
|
37
|
-
context '
|
38
|
-
|
39
|
-
|
40
|
+
context 'pushing branch' do
|
41
|
+
context 'not pushed' do
|
42
|
+
it { is_expected.not_to be }
|
43
|
+
end
|
40
44
|
|
41
|
-
|
42
|
-
|
43
|
-
|
45
|
+
context 'pushed, but not right rev' do
|
46
|
+
before do
|
47
|
+
goal.try_achieve
|
44
48
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
+
local.chdir { File.write('bye.txt', 'bye now') }
|
50
|
+
local.add('bye.txt')
|
51
|
+
local.commit('Add farewell')
|
52
|
+
local.branch('devel').checkout
|
53
|
+
end
|
54
|
+
|
55
|
+
it { is_expected.not_to be }
|
49
56
|
end
|
50
57
|
|
51
|
-
|
58
|
+
context 'pushed' do
|
59
|
+
before { goal.try_achieve }
|
60
|
+
it { is_expected.to be }
|
61
|
+
end
|
52
62
|
end
|
53
63
|
|
54
|
-
context '
|
55
|
-
|
56
|
-
|
64
|
+
context 'pushing tag' do
|
65
|
+
let(:config_ref) { '1.2.4' }
|
66
|
+
|
67
|
+
context 'not pushed' do
|
68
|
+
it { is_expected.not_to be }
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'pushed, but not right rev' do
|
72
|
+
before do
|
73
|
+
goal.try_achieve
|
74
|
+
|
75
|
+
local.chdir { File.write('bye.txt', 'bye now') }
|
76
|
+
local.add('bye.txt')
|
77
|
+
local.commit('Add farewell')
|
78
|
+
local.delete_tag('1.2.4')
|
79
|
+
local.add_tag('1.2.4')
|
80
|
+
end
|
81
|
+
|
82
|
+
it { is_expected.not_to be }
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'pushed' do
|
86
|
+
before { goal.try_achieve }
|
87
|
+
it { is_expected.to be }
|
88
|
+
end
|
57
89
|
end
|
58
90
|
end
|
59
91
|
|
60
92
|
describe '#try_achieve' do
|
61
93
|
subject { goal.try_achieve }
|
62
94
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
95
|
+
context 'pushing branch' do
|
96
|
+
let(:config_ref) { 'devel' }
|
97
|
+
|
98
|
+
example do
|
99
|
+
expect(remote.branches['devel']).to be_nil
|
100
|
+
subject
|
101
|
+
expect(remote.branches['devel'].gcommit.sha).to eql(local.branches['devel'].gcommit.sha)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
context 'pushing tag' do
|
106
|
+
let(:config_ref) { '1.2.4' }
|
107
|
+
|
108
|
+
example do
|
109
|
+
expect(remote.tags).to be_empty
|
110
|
+
subject
|
111
|
+
expect(remote.tag('1.2.4').sha).to eql(local.tag('1.2.4').sha)
|
112
|
+
end
|
67
113
|
end
|
68
114
|
end
|
69
115
|
|
70
116
|
describe '#failure_reason' do
|
71
117
|
subject { goal.failure_reason }
|
72
|
-
|
118
|
+
|
119
|
+
context 'pushed, but not right rev' do
|
120
|
+
before do
|
121
|
+
goal.try_achieve
|
122
|
+
|
123
|
+
local.chdir { File.write('bye.txt', 'bye now') }
|
124
|
+
local.add('bye.txt')
|
125
|
+
local.commit('Add farewell')
|
126
|
+
local.branch('devel').checkout
|
127
|
+
end
|
128
|
+
|
129
|
+
it { is_expected.to match(%r{ref devel \(.{8}\) is not the same as gitlab/devel \(.{8}\)}) }
|
130
|
+
end
|
131
|
+
|
132
|
+
context 'not pushed' do
|
133
|
+
it { is_expected.to match(/ref devel \(.{8}\) does not exist on remote gitlab/) }
|
134
|
+
end
|
73
135
|
end
|
74
136
|
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
describe Released::Goals::GitTagExists do
|
2
|
+
subject(:goal) do
|
3
|
+
described_class.new(config)
|
4
|
+
end
|
5
|
+
|
6
|
+
let(:config) do
|
7
|
+
{
|
8
|
+
'working_dir' => 'local',
|
9
|
+
'name' => '1.3',
|
10
|
+
'ref' => config_ref,
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:config_ref) { 'HEAD' }
|
15
|
+
|
16
|
+
let!(:local) do
|
17
|
+
Git.init('local').tap do |g|
|
18
|
+
g.config('user.name', 'Testy McTestface')
|
19
|
+
g.config('user.email', 'testface@example.com')
|
20
|
+
|
21
|
+
g.chdir { File.write('hello.txt', 'hi there') }
|
22
|
+
g.add('hello.txt')
|
23
|
+
g.commit('Add greeting')
|
24
|
+
g.branch('devel').checkout
|
25
|
+
g.add_tag('sweet')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#achieved?' do
|
30
|
+
subject { goal.achieved? }
|
31
|
+
|
32
|
+
context 'not tagged' do
|
33
|
+
it { is_expected.not_to be }
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'tagged, but wrong rev' do
|
37
|
+
before do
|
38
|
+
local.add_tag('1.3')
|
39
|
+
|
40
|
+
local.chdir { File.write('bye.txt', 'bye now') }
|
41
|
+
local.add('bye.txt')
|
42
|
+
local.commit('Add farewell')
|
43
|
+
end
|
44
|
+
|
45
|
+
it { is_expected.not_to be }
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'tagged' do
|
49
|
+
before do
|
50
|
+
local.add_tag('1.3')
|
51
|
+
end
|
52
|
+
|
53
|
+
it { is_expected.to be }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '#try_achieve' do
|
58
|
+
subject { goal.try_achieve }
|
59
|
+
|
60
|
+
let(:created_tag) { local.tags.find { |t| t.name == '1.3' } }
|
61
|
+
|
62
|
+
context 'referencing HEAD' do
|
63
|
+
let(:config_ref) { 'HEAD' }
|
64
|
+
|
65
|
+
example do
|
66
|
+
expect(created_tag).to be_nil
|
67
|
+
subject
|
68
|
+
expect(local.tag('1.3').sha).to eql(local.object('HEAD').sha)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'referencing branch' do
|
73
|
+
let(:config_ref) { 'devel' }
|
74
|
+
|
75
|
+
example do
|
76
|
+
expect(created_tag).to be_nil
|
77
|
+
subject
|
78
|
+
expect(local.tag('1.3').sha).to eql(local.object('HEAD').sha)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'referencing sha' do
|
83
|
+
let(:config_ref) { local.object('devel').sha }
|
84
|
+
|
85
|
+
example do
|
86
|
+
expect(created_tag).to be_nil
|
87
|
+
subject
|
88
|
+
expect(local.tag('1.3').sha).to eql(local.object('HEAD').sha)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'referencing tag' do
|
93
|
+
let(:config_ref) { local.object('sweet').sha }
|
94
|
+
|
95
|
+
example do
|
96
|
+
expect(created_tag).to be_nil
|
97
|
+
subject
|
98
|
+
expect(local.tag('1.3').sha).to eql(local.object('HEAD').sha)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe '#failure_reason' do
|
104
|
+
subject { goal.failure_reason }
|
105
|
+
|
106
|
+
context 'not tagged' do
|
107
|
+
it { is_expected.to eql('no tag named 1.3 exists') }
|
108
|
+
end
|
109
|
+
|
110
|
+
context 'tagged, but wrong rev' do
|
111
|
+
before do
|
112
|
+
local.add_tag('1.3')
|
113
|
+
|
114
|
+
local.chdir { File.write('bye.txt', 'bye now') }
|
115
|
+
local.add('bye.txt')
|
116
|
+
local.commit('Add farewell')
|
117
|
+
end
|
118
|
+
|
119
|
+
it { is_expected.to eql('tag named 1.3 points to different rev') }
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -8,7 +8,9 @@ describe Released::PipelineReader do
|
|
8
8
|
end
|
9
9
|
|
10
10
|
describe '#transform' do
|
11
|
-
subject { pipeline_reader.send(:transform, obj) }
|
11
|
+
subject { pipeline_reader.send(:transform, obj, vars) }
|
12
|
+
|
13
|
+
let(:vars) { {} }
|
12
14
|
|
13
15
|
context 'with array' do
|
14
16
|
let(:obj) { %w(hello env!FAVORITE_GEM_AUTHOR) }
|
@@ -36,6 +38,19 @@ describe Released::PipelineReader do
|
|
36
38
|
it { is_expected.to eql('hello') }
|
37
39
|
end
|
38
40
|
|
41
|
+
context 'var! string' do
|
42
|
+
let(:obj) { 'var!version' }
|
43
|
+
|
44
|
+
context 'var does not exist' do
|
45
|
+
# TODO
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'var exists' do
|
49
|
+
let(:vars) { { 'version' => '1.2.4' } }
|
50
|
+
it { is_expected.to eql('1.2.4') }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
39
54
|
context 'encrypted string' do
|
40
55
|
# TODO
|
41
56
|
end
|
metadata
CHANGED
@@ -1,99 +1,85 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: released
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Denis Defreyne
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-12-
|
11
|
+
date: 2016-12-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: git
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '1.3'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '1.3'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: twitter
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '4.8'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '4.8'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: gems
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
47
|
+
version: '0.8'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
54
|
+
version: '0.8'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: netrc
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
61
|
+
version: '0.11'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
68
|
+
version: '0.11'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: octokit
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - ">="
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
76
|
-
type: :runtime
|
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: nanoc
|
85
71
|
requirement: !ruby/object:Gem::Requirement
|
86
72
|
requirements:
|
87
73
|
- - "~>"
|
88
74
|
- !ruby/object:Gem::Version
|
89
|
-
version: '4.
|
75
|
+
version: '4.6'
|
90
76
|
type: :runtime
|
91
77
|
prerelease: false
|
92
78
|
version_requirements: !ruby/object:Gem::Requirement
|
93
79
|
requirements:
|
94
80
|
- - "~>"
|
95
81
|
- !ruby/object:Gem::Version
|
96
|
-
version: '4.
|
82
|
+
version: '4.6'
|
97
83
|
- !ruby/object:Gem::Dependency
|
98
84
|
name: ddplugin
|
99
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -130,7 +116,8 @@ dependencies:
|
|
130
116
|
version: '2.0'
|
131
117
|
description: ''
|
132
118
|
email: denis.defreyne@stoneship.org
|
133
|
-
executables:
|
119
|
+
executables:
|
120
|
+
- released
|
134
121
|
extensions: []
|
135
122
|
extra_rdoc_files: []
|
136
123
|
files:
|
@@ -138,6 +125,7 @@ files:
|
|
138
125
|
- Gemfile.lock
|
139
126
|
- README.md
|
140
127
|
- Rakefile
|
128
|
+
- bin/released
|
141
129
|
- lib/released.rb
|
142
130
|
- lib/released/goal.rb
|
143
131
|
- lib/released/goals.rb
|
@@ -145,15 +133,18 @@ files:
|
|
145
133
|
- lib/released/goals/gem_built.rb
|
146
134
|
- lib/released/goals/gem_pushed.rb
|
147
135
|
- lib/released/goals/git_ref_pushed.rb
|
136
|
+
- lib/released/goals/git_tag_exists.rb
|
148
137
|
- lib/released/goals/github_release_exists.rb
|
149
138
|
- lib/released/goals/shell.rb
|
150
139
|
- lib/released/pipeline_reader.rb
|
140
|
+
- lib/released/piper.rb
|
151
141
|
- lib/released/runner.rb
|
152
142
|
- lib/released/version.rb
|
153
143
|
- released.gemspec
|
154
144
|
- spec/released/goals/gem_built_spec.rb
|
155
145
|
- spec/released/goals/gem_pushed_spec.rb
|
156
146
|
- spec/released/goals/git_ref_pushed_spec.rb
|
147
|
+
- spec/released/goals/git_tag_exists_spec.rb
|
157
148
|
- spec/released/pipeline_reader_spec.rb
|
158
149
|
- spec/spec_helper.rb
|
159
150
|
homepage: https://github.com/ddfreyne/released
|