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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 16ad85ccdafa69e73909d4f175e292aea0b13fd3
4
- data.tar.gz: 768b7e7e8bc22e4e0d6e406e0b89df6573ea2046
3
+ metadata.gz: fab7a728ee7f9ddc1d86e930cc73b61dde1aabb8
4
+ data.tar.gz: 3499f338230eb9569a2521091237ef3fe7dd51c4
5
5
  SHA512:
6
- metadata.gz: 15ddba448b7ba2e02991a4e2721e35032074bbe648d527e48da881745e62f1f1809b2dfa1f95f2b756d2dde3c1b7c315af88fb5bd96859e97b606f17e2f8637a
7
- data.tar.gz: f4b2de9c067cc3d0a2ff08522a2c95967d50b4905a55d9efa2ec1d091085c7c121f9d070a8df765b27af71f553d12e0c8527680981f4f0922cae2be9c1210607
6
+ metadata.gz: f0db6f2591d68a924ead6cd71c30016aa2976ccf834be39101ec69cdccfe5f850c466bdd6e3ac0c1fa4a71d5e316df88ac992acdca0c47022cd2c1bbcf31ead2
7
+ data.tar.gz: 19e96e14c94e96f7a6dc3bba1ede47003c55558c7ac9de213f9655725e58b435836eebb51e97724192e774417807a3fdde7dae7e7775cc270bcaf75008097b56
data/Gemfile CHANGED
@@ -7,9 +7,9 @@ group :devel do
7
7
  gem 'geminabox'
8
8
  gem 'json', '~> 2.0'
9
9
  gem 'rake'
10
+ gem 'rspec'
10
11
  gem 'rspec-its'
11
12
  gem 'rspec-mocks'
12
- gem 'rspec'
13
13
  gem 'rubocop'
14
14
  gem 'vcr'
15
15
  gem 'webmock'
@@ -1,14 +1,13 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- released (0.0.1)
4
+ released (0.0.2)
5
5
  ddplugin (~> 1.0)
6
- gems
7
- git
8
- nanoc (~> 4.4)
9
- netrc
10
- octokit
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.10.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
- parallel (1.10.0)
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.45.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.4.2)
102
- faraday (~> 0.8)
103
- multi_json (~> 1.3)
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|
@@ -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
@@ -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'
@@ -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'
@@ -8,6 +8,10 @@ module Released
8
8
  @contents = config.fetch('contents')
9
9
  end
10
10
 
11
+ def to_s
12
+ "file exists (#{@filename})"
13
+ end
14
+
11
15
  def try_achieve
12
16
  File.write(@filename, @contents)
13
17
  end
@@ -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 = Nanoc::Extra::Piper.new(stdout: stdout, stderr: stderr)
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
- "expected the file #{expected_name} to exist"
33
+ "file #{expected_name} does not exist"
37
34
  end
38
35
 
39
36
  private
@@ -53,7 +53,7 @@ module Released
53
53
  end
54
54
 
55
55
  def failure_reason
56
- "expected list of gems to contain “#{@name}”, version #{@version}"
56
+ "list of gems does not contain “#{@name}”, version #{@version}"
57
57
  end
58
58
  end
59
59
  end
@@ -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
- @branch = config.fetch('branch')
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, @branch)
19
+ g.push(@remote, @ref)
16
20
  end
17
21
 
18
22
  def achieved?
19
- there_branch = g.branches["#{@remote}/#{@branch}"]
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
- "HEAD does not exist on #{@remote}/#{@branch}"
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
@@ -11,6 +11,10 @@ module Released
11
11
  @release_notes = config.fetch('release_notes')
12
12
  end
13
13
 
14
+ def to_s
15
+ "GitHub release exists (#{@tag} in #{@repository_name})"
16
+ end
17
+
14
18
  def try_achieve
15
19
  client = Octokit::Client.new(netrc: true)
16
20
  client.create_release(
@@ -23,7 +23,7 @@ module Released
23
23
  def try_achieve
24
24
  stdout = ''
25
25
  stderr = ''
26
- piper = Nanoc::Extra::Piper.new(stdout: stdout, stderr: stderr)
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 = transform(YAML.load_file(@filename))
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 transform(obj)
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 = Nanoc::Extra::Piper.new(stdout: stdout, stderr: stderr)
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
@@ -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 + 5
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
@@ -1,3 +1,3 @@
1
1
  module Released
2
- VERSION = '0.0.1'.freeze
2
+ VERSION = '0.0.2'.freeze
3
3
  end
@@ -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.require_paths = ['lib']
18
+ s.executables = ['released']
19
+ s.require_paths = ['lib']
19
20
 
20
- s.rdoc_options = ['--main', 'README.md']
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('expected the file donkey-0.1.gem to exist') }
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
- # TODO
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
- 'branch' => 'devel',
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 'not pushed' do
38
- it { is_expected.not_to be }
39
- end
40
+ context 'pushing branch' do
41
+ context 'not pushed' do
42
+ it { is_expected.not_to be }
43
+ end
40
44
 
41
- context 'pushed, but not right rev' do
42
- before do
43
- goal.try_achieve
45
+ context 'pushed, but not right rev' do
46
+ before do
47
+ goal.try_achieve
44
48
 
45
- local.chdir { File.write('bye.txt', 'bye now') }
46
- local.add('bye.txt')
47
- local.commit('Add farewell')
48
- local.branch('devel').checkout
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
- it { is_expected.not_to be }
58
+ context 'pushed' do
59
+ before { goal.try_achieve }
60
+ it { is_expected.to be }
61
+ end
52
62
  end
53
63
 
54
- context 'pushed' do
55
- before { goal.try_achieve }
56
- it { is_expected.to be }
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
- example do
64
- expect(remote.branches['devel']).to be_nil
65
- subject
66
- expect(remote.branches['devel'].gcommit.sha).to eql(local.branches['devel'].gcommit.sha)
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
- it { is_expected.to eql('HEAD does not exist on gitlab/devel') }
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.1
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-01 00:00:00.000000000 Z
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: '0'
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: '0'
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: '0'
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: '0'
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.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.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