released 0.0.1 → 0.0.2
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 +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
|