egads 2.0.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/egads +0 -2
- data/example/egads_remote.yml +5 -0
- data/lib/egads.rb +2 -0
- data/lib/egads/capistrano.rb +10 -2
- data/lib/egads/command.rb +12 -0
- data/lib/egads/command/build.rb +52 -21
- data/lib/egads/command/extract.rb +68 -29
- data/lib/egads/command/release.rb +15 -2
- data/lib/egads/command/stage.rb +1 -1
- data/lib/egads/command/trim.rb +17 -6
- data/lib/egads/command/upload.rb +6 -3
- data/lib/egads/config.rb +8 -0
- data/lib/egads/group.rb +26 -12
- data/lib/egads/local_helpers.rb +2 -2
- data/lib/egads/s3_tarball.rb +12 -12
- data/lib/egads/version.rb +1 -1
- data/spec/egads_build_spec.rb +4 -1
- data/spec/egads_command_spec.rb +8 -0
- data/spec/egads_extract_spec.rb +1 -1
- metadata +17 -5
- checksums.yaml +0 -7
data/bin/egads
CHANGED
data/example/egads_remote.yml
CHANGED
@@ -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
data/lib/egads/capistrano.rb
CHANGED
@@ -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.
|
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 "
|
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
|
data/lib/egads/command/build.rb
CHANGED
@@ -1,53 +1,76 @@
|
|
1
1
|
module Egads
|
2
2
|
class Build < Group
|
3
3
|
include Thor::Actions
|
4
|
-
include
|
4
|
+
include LocalHelpers
|
5
5
|
|
6
|
-
desc "[local] Compiles a deployable
|
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, "
|
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
|
24
|
-
|
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
|
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
|
35
|
-
|
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
|
39
|
-
|
40
|
-
|
41
|
-
run_with_code "
|
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
|
46
|
-
|
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"
|
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
|
14
|
-
if
|
15
|
-
|
16
|
-
|
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(
|
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, "
|
70
|
+
say_status :done, "#{type} tarball already downloaded. Use --force to overwrite"
|
24
71
|
end
|
25
72
|
end
|
26
73
|
|
27
|
-
def
|
28
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
48
|
-
|
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
|
52
|
-
|
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.
|
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
|
-
|
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
|
data/lib/egads/command/stage.rb
CHANGED
@@ -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
|
|
data/lib/egads/command/trim.rb
CHANGED
@@ -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
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
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
|
|
data/lib/egads/command/upload.rb
CHANGED
@@ -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.
|
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,
|
8
|
-
|
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
|
-
|
11
|
-
|
12
|
-
|
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
|
-
|
15
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
50
|
+
File.symlink(src, dest)
|
37
51
|
end
|
38
52
|
|
39
53
|
def symlink(src, dest)
|
data/lib/egads/local_helpers.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Egads
|
2
|
-
# Some helper methods for
|
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
|
data/lib/egads/s3_tarball.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
module Egads
|
2
2
|
class S3Tarball
|
3
|
-
attr_reader :sha, :remote
|
4
|
-
def initialize(sha,
|
5
|
-
@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
|
-
[
|
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
|
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
data/spec/egads_build_spec.rb
CHANGED
@@ -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
|
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
|
data/spec/egads_extract_spec.rb
CHANGED
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:
|
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-
|
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:
|
147
|
+
rubygems_version: 1.8.25
|
137
148
|
signing_key:
|
138
|
-
specification_version:
|
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
|