egads 2.0.0 → 3.0.0

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.
data/bin/egads CHANGED
@@ -1,5 +1,3 @@
1
1
  #!/usr/bin/env ruby
2
- # TODO: remove this
3
- $: << './lib'
4
2
  require 'egads'
5
3
  Egads::Command.start
@@ -5,8 +5,13 @@ s3:
5
5
  secret_key: mysecret
6
6
  prefix: my_project # Optional prefix for S3 paths
7
7
 
8
+ # Path where seed files are cached
9
+ cache_seeds_to: /var/apps/my_project/seeds
10
+
8
11
  # Path where tarballs are extracted
9
12
  extract_to: /var/apps/my_project/releases
13
+
14
+ # Path where the currently running version is symlinked
10
15
  release_to: /var/apps/my_project/current
11
16
 
12
17
  restart_command: /etc/init.d/rails_services restart
data/lib/egads.rb CHANGED
@@ -2,9 +2,11 @@ require 'yaml'
2
2
  require 'fog'
3
3
  require 'thor'
4
4
  require 'benchmark'
5
+ require 'pathname'
5
6
 
6
7
  module Egads; end
7
8
 
9
+ require 'egads/version'
8
10
  require 'egads/config'
9
11
  require 'egads/s3_tarball'
10
12
  require 'egads/group'
@@ -9,7 +9,7 @@ Capistrano::Configuration.instance.load do
9
9
  namespace :deploy do
10
10
  desc "Deploy"
11
11
  task :default do
12
- deploy.check
12
+ deploy.build
13
13
  deploy.stage
14
14
  deploy.release
15
15
  end
@@ -31,7 +31,15 @@ Capistrano::Configuration.instance.load do
31
31
  run "egads release #{egads_options} #{full_sha}"
32
32
  end
33
33
 
34
- desc "Checks that a deployable tarball is on S3; creates it if missing"
34
+ desc "Builds a deployable tarball and uploads it to S3"
35
+ task :build do
36
+ logger.info "Building tarball for #{full_sha}"
37
+ `bundle exec egads build #{full_sha}`
38
+ abort "Failed to build" if $?.exitstatus != 0
39
+ end
40
+
41
+ # Not used by default. Here for convenience
42
+ desc "Checks that a deployable tarball is on S3; waits for it to exist if missing"
35
43
  task :check do
36
44
  logger.info "Checking tarball for #{full_sha}"
37
45
  logger.info "To build the tarball locally, run `bundle exec egads build #{full_sha}"
data/lib/egads/command.rb CHANGED
@@ -1,5 +1,11 @@
1
1
  module Egads
2
2
  class Command < Thor
3
+
4
+ # Always exit on failure
5
+ def self.exit_on_failure?
6
+ true
7
+ end
8
+
3
9
  require 'egads/local_helpers'
4
10
  require 'egads/command/check'
5
11
  require 'egads/command/build'
@@ -17,5 +23,11 @@ module Egads
17
23
  register(Release, 'release', 'release SHA', '[remote, plumbing] Downloads tarball for SHA from S3 and extracts it to the filesystem')
18
24
  register(Trim, 'trime', 'trim [N]', "[remote, plumbing] Deletes old releases, keeping the N most recent (by mtime)")
19
25
 
26
+ map '--version' => :version
27
+ desc :version, "Prints the version"
28
+ def version
29
+ puts "#{File.basename($0)} #{VERSION}"
30
+ end
31
+
20
32
  end
21
33
  end
@@ -1,53 +1,76 @@
1
1
  module Egads
2
2
  class Build < Group
3
3
  include Thor::Actions
4
- include Egads::LocalHelpers
4
+ include LocalHelpers
5
5
 
6
- desc "[local] Compiles a deployable tarball of the current commit and uploads it to S3"
6
+ desc "[local] Compiles a deployable patch of the current commit and uploads it to S3"
7
7
  class_option :force, type: :boolean, aliases: '-f', default: false, banner: "Build and overwrite existing tarball on S3"
8
+ class_option :seed, type: :boolean, default: false, banner: "Builds and tags a complete tarball for more efficient patches"
8
9
  class_option 'no-upload', type: :boolean, default: false, banner: "Don't upload the tarball to S3"
9
10
  argument :rev, type: :string, default: 'HEAD', desc: 'git revision to build'
10
11
 
12
+ attr_accessor :build_sha
13
+
11
14
  def check_build
12
15
  say_status :rev, "#{rev} parsed to #{sha}"
13
16
 
14
17
  unless should_build?
15
- say_status :done, "Tarball for #{sha} already exists. Pass --force to rebuild."
18
+ say_status :done, "#{build_type} tarball for #{sha} already exists. Pass --force to rebuild."
16
19
  exit 0
17
20
  end
18
21
 
19
- say_status :rev, "#{rev} parsed to #{sha}"
20
22
  exit 1 unless can_build?
23
+ say_status :build, "Making #{build_type} tarball for #{sha}", :yellow
21
24
  end
22
25
 
23
- def make_git_archive
24
- say_status :build, "Making tarball for #{sha}", :yellow
25
- FileUtils.mkdir_p(File.dirname(tarball.local_tar_path))
26
- run_with_code "git archive #{sha} --format=tar > #{tarball.local_tar_path}"
26
+ def run_before_build_hooks
27
+ run_hooks_for(:build, :before)
27
28
  end
28
29
 
29
- def append_revision_file
30
+ def write_revision_file
30
31
  File.open('REVISION', 'w') {|f| f << sha + "\n" }
31
- run_with_code "tar -uf #{tarball.local_tar_path} REVISION"
32
32
  end
33
33
 
34
- def run_after_build_hooks
35
- run_hooks_for(:build,:after)
34
+ def commit_extra_paths
35
+ extra_paths = ["REVISION"]
36
+ extra_paths += Config.build_extra_paths
37
+ run_with_code("git add -f #{extra_paths * ' '} && git commit --no-verify -m 'egads build'")
38
+ # Get the build SHA
39
+ self.build_sha = run_with_code("git rev-parse --verify HEAD").strip
40
+ run_with_code "git reset #{sha}" # Reset to original SHA
41
+
36
42
  end
37
43
 
38
- def append_extra_paths
39
- extra_paths = Config.build_extra_paths
40
- if extra_paths.any?
41
- run_with_code "tar -uf #{tarball.local_tar_path} #{extra_paths * " "}"
44
+ def make_tarball
45
+ if options[:seed]
46
+ # Seed tarball
47
+ run_with_code "git archive #{build_sha} --output #{tarball.local_tar_path}"
48
+ else
49
+ # Patch tarball
50
+ seed_ref = "refs/tags/#{Config.seed_tag}"
51
+ # NB: the seed tarball is named after the parent of seed tag
52
+ seed_parent = run_with_code("git rev-parse --verify #{seed_ref}^").strip
53
+ File.open('egads-seed', 'w') {|f| f << seed_parent + "\n" }
54
+ patch_files = [patch_path, 'egads-seed']
55
+ run_with_code "git diff --binary #{seed_ref} #{build_sha} > #{patch_path}"
56
+ run_with_code "tar -zcf #{tarball.local_tar_path} #{patch_files * ' '}"
57
+ patch_files.each {|f| File.delete(f) }
42
58
  end
59
+
43
60
  end
44
61
 
45
- def gzip_archive
46
- run_with_code "gzip -9f #{tarball.local_tar_path}"
62
+ def run_after_build_hooks
63
+ run_hooks_for(:build, :after)
47
64
  end
48
65
 
49
66
  def upload
50
- invoke(Egads::Upload, [sha]) unless options['no-upload']
67
+ invoke(Egads::Upload, [sha], force: options[:force], seed: options[:seed]) unless options['no-upload']
68
+ end
69
+
70
+ def tag_seed
71
+ if options[:seed]
72
+ run_with_code "git tag -f -a -m 'egads seed' #{Config.seed_tag} #{build_sha} && git push -f origin tag #{Config.seed_tag}"
73
+ end
51
74
  end
52
75
 
53
76
  module BuildHelpers
@@ -60,7 +83,7 @@ module Egads
60
83
  end
61
84
 
62
85
  def sha_is_checked_out?
63
- head = run_with_code("git rev-parse --verify HEAD", capture: true).strip
86
+ head = run_with_code("git rev-parse --verify HEAD").strip
64
87
  short_head = head[0,7]
65
88
  head == sha or error [
66
89
  "Cannot build #{short_sha} because #{short_head} is checked out.",
@@ -76,6 +99,14 @@ module Egads
76
99
  ]
77
100
  end
78
101
 
102
+ def patch_path
103
+ "#{sha}.patch"
104
+ end
105
+
106
+ def build_type
107
+ options[:seed] ? 'seed' : 'patch'
108
+ end
109
+
79
110
  def error(message)
80
111
  lines = Array(message)
81
112
  say_status :error, lines.shift, :red
@@ -83,8 +114,8 @@ module Egads
83
114
 
84
115
  false
85
116
  end
86
-
87
117
  end
88
118
  include BuildHelpers
119
+
89
120
  end
90
121
  end
@@ -3,65 +3,104 @@ module Egads
3
3
  include Thor::Actions
4
4
 
5
5
  desc "[remote, plumbing] Downloads tarball for SHA from S3 and extracts it to the filesystem"
6
- class_option :force, type: :boolean, default: false, banner: "Overwrite existing files"
6
+ class_option :force, type: :boolean, aliases: '-f', default: false, banner: "Overwrite existing files"
7
7
  argument :sha, type: :string, required: true, desc: 'git SHA to download and extract'
8
8
 
9
+ attr_accessor :seed_sha, :seed_path
10
+
9
11
  def setup_environment
10
12
  RemoteConfig.setup_environment
11
13
  end
12
14
 
13
- def download
14
- if should_download?
15
- say_status :download, "Downloading tarball for #{sha}", :yellow
16
- FileUtils.mkdir_p(release_dir)
15
+ def extract
16
+ if should_extract?
17
+ # Download_patch
18
+ do_download(sha, File.join(patch_dir, "#{sha}.tar.gz"), 'patch')
19
+
20
+ do_extract patch_path
21
+
22
+ # Download seed
23
+ self.seed_sha = Pathname.new(patch_dir).join("egads-seed").read.strip
24
+ self.seed_path = File.join(RemoteConfig.seed_dir, "#{seed_sha}.tar.gz")
25
+ do_download(seed_sha, seed_path, 'seed')
26
+
27
+ do_extract seed_path
28
+
29
+ apply_patch
30
+ finish_extraction
31
+ else
32
+ say_status :done, "#{sha} already extracted. Use --force to overwrite"
33
+ end
34
+ end
35
+
36
+ protected
37
+ def apply_patch
38
+ inside patch_dir do
39
+ run_with_code "git apply --whitespace=nowarn < #{sha}.patch"
40
+ end
41
+ end
42
+
43
+ def finish_extraction
44
+ if options[:force]
45
+ say_status :delete, "Removing release dir #{release_dir} if exists", :yellow
46
+ FileUtils.rm_rf(release_dir)
47
+ end
48
+
49
+ say_status :extract, "Moving #{patch_dir} to #{release_dir}"
50
+ File.rename patch_dir, release_dir
51
+ say_status :done, "Extraction complete"
52
+ rescue Errno::ENOTEMPTY
53
+ say_status :error, "#{release_dir} already exists! Did another process create it?", :red
54
+ raise
55
+ end
56
+
57
+ def do_download(sha, path, type='patch')
58
+ if should_download?(path)
59
+ say_status :download, "Downloading #{type} tarball for #{sha}", :yellow
60
+ FileUtils.mkdir_p(File.dirname(path))
61
+ tarball = S3Tarball.new(sha, remote: true, seed: 'seed' == type)
62
+ tmp_path = [path, 'tmp', rand(2**32)] * '.' # Use tmp path for atomicity
17
63
  duration = Benchmark.realtime do
18
- File.open(path, 'w') {|f| f << tarball.contents }
64
+ File.open(tmp_path, 'w') {|f| f << tarball.contents }
19
65
  end
66
+ File.rename(tmp_path, path)
20
67
  size = File.size(path)
21
68
  say_status :done, "Downloaded in %.1f seconds (%.1f KB/s)" % [duration, (size.to_f / 2**10) / duration]
22
69
  else
23
- say_status :done, "Tarball already downloaded. Use --force to overwrite"
70
+ say_status :done, "#{type} tarball already downloaded. Use --force to overwrite"
24
71
  end
25
72
  end
26
73
 
27
- def extract
28
- # Check revision file to see if tarball is already extracted
29
- if should_extract?
74
+ def do_extract(path)
75
+ inside(patch_dir) do
30
76
  # Silence stderr warnings "Ignoring unknown extended header keyword"
31
- # due to BSD/GNU tar.
32
- inside(release_dir) { run_with_code "tar -zxf #{path} 2>/dev/null" }
33
- else
34
- say_status :done, "Tarball already extracted. Use --force to overwrite"
77
+ # due to BSD/GNU tar differences.
78
+ run_with_code "tar -zxf #{path} 2>/dev/null"
35
79
  end
36
80
  end
37
81
 
38
- def mark_as_extracted
39
- FileUtils.touch(extract_flag_path)
40
- end
41
-
42
- protected
82
+ # Directory created upon successful extraction
43
83
  def release_dir
44
84
  RemoteConfig.release_dir(sha)
45
85
  end
46
86
 
47
- def path
48
- File.join(release_dir, "#{sha}.tar.gz")
87
+ # Directory where in-progress extraction occurs
88
+ # Avoids troublesome edge cases where a patch may not not have applied cleanly,
89
+ # or egads crashes during the extraction process
90
+ def patch_dir
91
+ @patch_dir ||= [release_dir, 'extracting', Time.now.strftime("%Y%m%d%H%M%S")] * '.'
49
92
  end
50
93
 
51
- def tarball
52
- @tarball ||= S3Tarball.new(sha, true)
94
+ def patch_path
95
+ File.join(patch_dir, "#{sha}.tar.gz")
53
96
  end
54
97
 
55
- def should_download?
98
+ def should_download?(path)
56
99
  options[:force] || File.zero?(path) || !File.exists?(path)
57
100
  end
58
101
 
59
- def extract_flag_path
60
- File.join(release_dir, '.egads-extract-success')
61
- end
62
-
63
102
  def should_extract?
64
- options[:force] || !File.exists?(extract_flag_path)
103
+ options[:force] || !File.directory?(release_dir)
65
104
  end
66
105
 
67
106
  end
@@ -20,7 +20,7 @@ module Egads
20
20
 
21
21
  def symlink_release
22
22
  return unless should_release?
23
- symlink_directory(dir, release_to)
23
+ atomic_symlink(dir, release_to)
24
24
  end
25
25
 
26
26
  def restart
@@ -28,7 +28,7 @@ module Egads
28
28
 
29
29
  inside release_to do
30
30
  # Restart services
31
- run_with_code(RemoteConfig.restart_command)
31
+ run_with_code(RemoteConfig.restart_command, stream: true)
32
32
  end
33
33
  end
34
34
 
@@ -60,5 +60,18 @@ module Egads
60
60
  @should_release = options[:force] || dir != current_symlink_destination unless defined?(@should_release)
61
61
  @should_release
62
62
  end
63
+
64
+ # Symlinks src to dest, even if dest is an existing directory symlink
65
+ # NB that `ln -f` doesn't work with directories.
66
+ # Use an extra temporary symlink for atomicity (equivalent to `mv -T`)
67
+ def atomic_symlink(src, dest)
68
+ raise ArgumentError.new("#{src} is not a directory") unless File.directory?(src)
69
+ say_status :symlink, "from #{src} to #{dest}"
70
+ tmp = "#{dest}-new-#{rand(2**32)}"
71
+ # Make a temporary symlink
72
+ File.symlink(src, tmp)
73
+ # Atomically rename the symlink, possibly overwriting an existing symlink
74
+ File.rename(tmp, dest)
75
+ end
63
76
  end
64
77
  end
@@ -24,7 +24,7 @@ module Egads
24
24
  return unless should_stage?
25
25
 
26
26
  inside(dir) do
27
- run_with_code("bundle install #{RemoteConfig.bundler_options}") if File.readable?("Gemfile")
27
+ run_with_code("bundle install #{RemoteConfig.bundler_options}", stream: true) if File.readable?("Gemfile")
28
28
  end
29
29
  end
30
30
 
@@ -3,14 +3,25 @@ module Egads
3
3
  include Thor::Actions
4
4
 
5
5
 
6
- desc "[remote, plumbing] Deletes old releases, keeping the N most recent (by mtime)"
6
+ desc "[remote, plumbing] Deletes old releases and seeds, keeping the N most recent (by mtime)"
7
7
  def trim(n=4)
8
+ # Trim old releases
8
9
  inside RemoteConfig.extract_to do
9
- dirs = Dir.glob('*').sort_by{|path| File.mtime(path) }.reverse[n..-1].to_a
10
- dirs.each do |dir|
11
- say_status :trim, "Deleting #{dir}"
12
- FileUtils.rm_rf(dir)
13
- end
10
+ trim_glob('*', n)
11
+ end
12
+
13
+ # Trim seeds
14
+ inside RemoteConfig.seed_dir do
15
+ trim_glob('*.tar.gz', n)
16
+ end
17
+ end
18
+
19
+ protected
20
+ def trim_glob(glob, n)
21
+ paths = Dir.glob(glob).sort_by{|path| File.mtime(path) }.reverse[n..-1].to_a
22
+ paths.each do |path|
23
+ say_status :trim, "Deleting #{path}"
24
+ FileUtils.rm_rf(path)
14
25
  end
15
26
  end
16
27
 
@@ -4,13 +4,16 @@ module Egads
4
4
 
5
5
  desc "[local, plumbing] Uploads a tarball for SHA to S3"
6
6
  argument :sha, type: :string, required: true, desc: 'git SHA to upload'
7
+ class_option :seed, type: :boolean, default: false, banner: "Uploads a seed tarball"
8
+
7
9
 
8
10
  attr_reader :sha
9
11
  def upload
10
12
  @sha = sha
11
13
  size = File.size(path)
14
+ type = options[:seed] ? 'seed' : 'patch'
12
15
 
13
- say_status :upload, "Uploading tarball (%.1f MB)" % (size.to_f / 2**20), :yellow
16
+ say_status :upload, "Uploading #{type} tarball (%.1f MB)" % (size.to_f / 2**20), :yellow
14
17
  duration = Benchmark.realtime do
15
18
  tarball.upload(path)
16
19
  end
@@ -21,11 +24,11 @@ module Egads
21
24
 
22
25
  private
23
26
  def tarball
24
- @tarball ||= S3Tarball.new(sha)
27
+ @tarball ||= S3Tarball.new(sha, seed: options[:seed])
25
28
  end
26
29
 
27
30
  def path
28
- tarball.local_gzipped_path
31
+ tarball.local_tar_path
29
32
  end
30
33
 
31
34
  end
data/lib/egads/config.rb CHANGED
@@ -42,6 +42,10 @@ module Egads
42
42
  def self.build_extra_paths
43
43
  config['build'] && Array(config['build']['extra_paths'])
44
44
  end
45
+
46
+ def self.seed_tag
47
+ config['seed_tag'] || "egads-seed"
48
+ end
45
49
  end
46
50
 
47
51
  # Remote config for the extract command (before data in tarball is available)
@@ -64,6 +68,10 @@ module Egads
64
68
  config['extract_to']
65
69
  end
66
70
 
71
+ def self.seed_dir
72
+ config['cache_seeds_to']
73
+ end
74
+
67
75
  def self.release_dir(sha)
68
76
  File.join(config['extract_to'], sha)
69
77
  end
data/lib/egads/group.rb CHANGED
@@ -1,20 +1,35 @@
1
+ require 'open3'
1
2
  module Egads
2
3
  class CommandError < Thor::Error; end
3
4
 
4
5
  class Group < Thor::Group
5
6
 
7
+ # Always exit on failure
8
+ def self.exit_on_failure?
9
+ true
10
+ end
11
+
6
12
  protected
7
- def run_with_code(command, config={})
8
- result = nil
13
+ def run_with_code(command, options={})
14
+
15
+ say_status :run, "#{command}", options.fetch(:verbose, true)
16
+
17
+ capture = []
9
18
  duration = Benchmark.realtime do
10
- result = run(command, config.merge(capture: true))
11
- end
12
- say_status :done, "Finished in %.1f seconds" % duration
19
+ Open3.popen2e(command) do |_, out, thread|
20
+ out.each do |line|
21
+ puts line if options[:stream]
22
+ capture << line
23
+ end
13
24
 
14
- if $? != 0
15
- raise CommandError.new("`#{command}` failed with exit status #{$?.exitstatus.inspect}")
25
+ unless thread.value == 0
26
+ raise CommandError.new("`#{command}` failed with exit status #{thread.value.exitstatus.inspect}")
27
+ end
28
+ end
16
29
  end
17
- result
30
+ say_status :done, "Finished in %.1f seconds" % duration, options.fetch(:verbose, true)
31
+
32
+ capture.join
18
33
  end
19
34
 
20
35
  # Run command hooks from config file
@@ -22,18 +37,17 @@ module Egads
22
37
  def run_hooks_for(cmd, hook)
23
38
  say_status :hooks, "Running #{cmd} #{hook} hooks"
24
39
  Config.hooks_for(cmd, hook).each do |command|
25
- say run_with_code(command, capture: true)
40
+ run_with_code(command, stream: true)
26
41
  end
27
42
  end
28
43
 
29
- # Symlinks a directory
44
+ # Symlinks a directory (not atomically)
30
45
  # NB that `ln -f` doesn't work with directories.
31
- # This is not atomic.
32
46
  def symlink_directory(src, dest)
33
47
  raise ArgumentError.new("#{src} is not a directory") unless File.directory?(src)
34
48
  say_status :symlink, "from #{src} to #{dest}"
35
49
  FileUtils.rm_rf(dest)
36
- FileUtils.ln_s(src, dest)
50
+ File.symlink(src, dest)
37
51
  end
38
52
 
39
53
  def symlink(src, dest)
@@ -1,5 +1,5 @@
1
1
  module Egads
2
- # Some helper methods for `check` and `upload`
2
+ # Some helper methods for all local commands
3
3
  module LocalHelpers
4
4
  def sha
5
5
  @sha ||= run_with_code("git rev-parse --verify #{rev}").strip
@@ -10,7 +10,7 @@ module Egads
10
10
  end
11
11
 
12
12
  def tarball
13
- @tarball ||= S3Tarball.new(sha)
13
+ @tarball ||= S3Tarball.new(sha, seed: options[:seed])
14
14
  end
15
15
 
16
16
  end
@@ -1,9 +1,10 @@
1
1
  module Egads
2
2
  class S3Tarball
3
- attr_reader :sha, :remote
4
- def initialize(sha, remote = false)
5
- @sha = sha
6
- @remote = remote
3
+ attr_reader :sha, :remote, :seed
4
+ def initialize(sha, options = {})
5
+ @sha = sha
6
+ @remote = options[:remote]
7
+ @seed = options[:seed]
7
8
  end
8
9
 
9
10
  def config
@@ -11,7 +12,11 @@ module Egads
11
12
  end
12
13
 
13
14
  def key
14
- [config.s3_prefix, "#{sha}.tar.gz"].compact * '/'
15
+ [
16
+ config.s3_prefix,
17
+ seed ? 'seeds' : nil,
18
+ "#{sha}.tar.gz"
19
+ ].compact * '/'
15
20
  end
16
21
 
17
22
  def exists?
@@ -19,14 +24,10 @@ module Egads
19
24
  end
20
25
 
21
26
  def local_tar_path
22
- "tmp/#{sha}.tar"
27
+ "tmp/#{sha}.tar.gz"
23
28
  end
24
29
 
25
- def local_gzipped_path
26
- "#{local_tar_path}.gz"
27
- end
28
-
29
- def upload(path=local_gzipped_path)
30
+ def upload(path=local_tar_path)
30
31
  File.open(path) {|f|
31
32
  bucket.files.create(key: key, body: f)
32
33
  }
@@ -42,4 +43,3 @@ module Egads
42
43
  end
43
44
  end
44
45
  end
45
-
data/lib/egads/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Egads
2
- VERSION = '2.0.0'
2
+ VERSION = '3.0.0'
3
3
  end
@@ -5,7 +5,7 @@ describe "Egads::Build" do
5
5
  subject { Egads::Build }
6
6
 
7
7
  it 'should run the correct tasks' do
8
- subject.commands.keys.must_equal %w(check_build make_git_archive append_revision_file run_after_build_hooks append_extra_paths gzip_archive upload)
8
+ subject.commands.keys.must_equal %w(check_build run_before_build_hooks write_revision_file commit_extra_paths make_tarball run_after_build_hooks upload tag_seed)
9
9
  end
10
10
 
11
11
  it 'takes one argument' do
@@ -18,6 +18,9 @@ describe "Egads::Build" do
18
18
  rev.required.must_equal false
19
19
  end
20
20
 
21
+ it "exits on failure" do
22
+ subject.exit_on_failure?.must_equal true
23
+ end
21
24
  end
22
25
 
23
26
  describe "Egags::Build instance" do
@@ -0,0 +1,8 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe "Egads::Command" do
4
+ subject { Egads::Command }
5
+ it 'should exit on failure' do
6
+ subject.exit_on_failure?.must_equal true
7
+ end
8
+ end
@@ -5,6 +5,6 @@ describe "Egads::Extract" do
5
5
  subject { Egads::Extract }
6
6
 
7
7
  it 'should run the correct tasks' do
8
- subject.commands.keys.must_equal %w(setup_environment download extract mark_as_extracted)
8
+ subject.commands.keys.must_equal %w(setup_environment extract)
9
9
  end
10
10
  end
metadata CHANGED
@@ -1,18 +1,20 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: egads
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 3.0.0
5
+ prerelease:
5
6
  platform: ruby
6
7
  authors:
7
8
  - Aaron Suggs
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2013-07-11 00:00:00.000000000 Z
12
+ date: 2013-08-11 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: fog
15
16
  requirement: !ruby/object:Gem::Requirement
17
+ none: false
16
18
  requirements:
17
19
  - - '>='
18
20
  - !ruby/object:Gem::Version
@@ -20,6 +22,7 @@ dependencies:
20
22
  type: :runtime
21
23
  prerelease: false
22
24
  version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
23
26
  requirements:
24
27
  - - '>='
25
28
  - !ruby/object:Gem::Version
@@ -27,6 +30,7 @@ dependencies:
27
30
  - !ruby/object:Gem::Dependency
28
31
  name: thor
29
32
  requirement: !ruby/object:Gem::Requirement
33
+ none: false
30
34
  requirements:
31
35
  - - '>='
32
36
  - !ruby/object:Gem::Version
@@ -34,6 +38,7 @@ dependencies:
34
38
  type: :runtime
35
39
  prerelease: false
36
40
  version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
37
42
  requirements:
38
43
  - - '>='
39
44
  - !ruby/object:Gem::Version
@@ -41,6 +46,7 @@ dependencies:
41
46
  - !ruby/object:Gem::Dependency
42
47
  name: rake
43
48
  requirement: !ruby/object:Gem::Requirement
49
+ none: false
44
50
  requirements:
45
51
  - - '>='
46
52
  - !ruby/object:Gem::Version
@@ -48,6 +54,7 @@ dependencies:
48
54
  type: :development
49
55
  prerelease: false
50
56
  version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
51
58
  requirements:
52
59
  - - '>='
53
60
  - !ruby/object:Gem::Version
@@ -55,6 +62,7 @@ dependencies:
55
62
  - !ruby/object:Gem::Dependency
56
63
  name: minitest
57
64
  requirement: !ruby/object:Gem::Requirement
65
+ none: false
58
66
  requirements:
59
67
  - - '>='
60
68
  - !ruby/object:Gem::Version
@@ -62,6 +70,7 @@ dependencies:
62
70
  type: :development
63
71
  prerelease: false
64
72
  version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
65
74
  requirements:
66
75
  - - '>='
67
76
  - !ruby/object:Gem::Version
@@ -105,6 +114,7 @@ files:
105
114
  - lib/egads/version.rb
106
115
  - spec/egads_build_spec.rb
107
116
  - spec/egads_check_spec.rb
117
+ - spec/egads_command_spec.rb
108
118
  - spec/egads_config_spec.rb
109
119
  - spec/egads_extract_spec.rb
110
120
  - spec/egads_release_spec.rb
@@ -115,31 +125,33 @@ files:
115
125
  - spec/spec_helper.rb
116
126
  homepage: https://github.com/kickstarter/egads
117
127
  licenses: []
118
- metadata: {}
119
128
  post_install_message:
120
129
  rdoc_options:
121
130
  - --charset=UTF-8
122
131
  require_paths:
123
132
  - lib
124
133
  required_ruby_version: !ruby/object:Gem::Requirement
134
+ none: false
125
135
  requirements:
126
136
  - - '>='
127
137
  - !ruby/object:Gem::Version
128
138
  version: '0'
129
139
  required_rubygems_version: !ruby/object:Gem::Requirement
140
+ none: false
130
141
  requirements:
131
142
  - - '>='
132
143
  - !ruby/object:Gem::Version
133
144
  version: '0'
134
145
  requirements: []
135
146
  rubyforge_project:
136
- rubygems_version: 2.0.2
147
+ rubygems_version: 1.8.25
137
148
  signing_key:
138
- specification_version: 4
149
+ specification_version: 3
139
150
  summary: Extensible Git Archive Deploy Strategy
140
151
  test_files:
141
152
  - spec/egads_build_spec.rb
142
153
  - spec/egads_check_spec.rb
154
+ - spec/egads_command_spec.rb
143
155
  - spec/egads_config_spec.rb
144
156
  - spec/egads_extract_spec.rb
145
157
  - spec/egads_release_spec.rb
checksums.yaml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- SHA1:
3
- metadata.gz: 528b9ad77f674b120f2e3d8b64a72e24a4d16f59
4
- data.tar.gz: db4985e423a4d2d265f259c4e457423264ed3dd0
5
- SHA512:
6
- metadata.gz: 14506e0b510f897e04de81aa7805719675a79456d933f1bdf59ae3f0b5e9e5dcaca4fdc2416e1f40d48d2c397213e64b5c3a62b70e87125a9f00018a7a70d958
7
- data.tar.gz: e4c504af004f30c2bdc69f6f8a883a7c66b865f79f77f2a844019078afbc43d47fe9a3c7f95874fcffe8a0e9b2bcca7a2b79e00bde2f8ae1b7cdd21480b25899