ci-cache 1.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.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.rspec +1 -0
- data/.travis.yml +14 -0
- data/Gemfile +2 -0
- data/LICENSE +20 -0
- data/README.md +27 -0
- data/Rakefile +1 -0
- data/bin/ci-cache +5 -0
- data/ci-cache.gemspec +23 -0
- data/lib/ci-cache/cli.rb +160 -0
- data/lib/ci-cache/error.rb +3 -0
- data/lib/ci-cache/get.rb +50 -0
- data/lib/ci-cache/set.rb +66 -0
- data/lib/ci-cache/storage.rb +54 -0
- data/lib/ci-cache/version.rb +3 -0
- data/lib/ci-cache.rb +13 -0
- data/spec/cli_spec.rb +52 -0
- data/spec/get_spec.rb +38 -0
- data/spec/set_spec.rb +48 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/storage_spec.rb +46 -0
- metadata +112 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 288ef0fe2be849cb4a5d1fbb0f48ecfae5fc62eb
|
4
|
+
data.tar.gz: 46f0d3a3f1b403bf6f678e48f9e0cdfbc7b808e9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b5ad74c170005c79dd259ff97441d77bbbb85dcda12ee52bf24675daf9478b9effa8fdb7735053c520be586bb5315fcb146ae34f11cfb36d60088bbfb659db07
|
7
|
+
data.tar.gz: 18d7f343646cf8d6bbaa12f239a2690a6ffab84e495d8884812ec24a99b859f982c6587ad0df121b35a60923e49f58796b352da704f4c0cda7c623dc6d85565a
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.travis.yml
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
language: ruby
|
2
|
+
rvm:
|
3
|
+
- 1.9.3
|
4
|
+
- 2.0.0
|
5
|
+
- jruby-19mode
|
6
|
+
- rbx-19mode
|
7
|
+
deploy:
|
8
|
+
provider: rubygems
|
9
|
+
api_key:
|
10
|
+
secure: XMfj0fh0v8byvY67GtTLIeJcxEpmt7WBOTF9fmsEsWv6Wq2ZYeWdlLxgK042FTB7IkFYVF6EsA4zmOFKZkMpypwROj0cwTEeoA/5DjukowVc2KwpRLXMCUBeatRD9U63A8gq3CVrS7t5emo4trxb6lH+x3HIgF5Ef4n8Sj+MWJM=
|
11
|
+
gem: ci-cache
|
12
|
+
on:
|
13
|
+
tags: true
|
14
|
+
repo: johanneswuerbach/ci-cache
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013 Johannes Würbach
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# ci-cache [](https://travis-ci.org/johanneswuerbach/ci-cache)
|
2
|
+
|
3
|
+
Cache files and folders between continues integration builds.
|
4
|
+
|
5
|
+
|
6
|
+
### Examples
|
7
|
+
|
8
|
+
#### Bundler
|
9
|
+
|
10
|
+
```yaml
|
11
|
+
---
|
12
|
+
bundler_args: --without development --path=~/.bundle
|
13
|
+
language: ruby
|
14
|
+
rvm:
|
15
|
+
- 2.0.0
|
16
|
+
env:
|
17
|
+
global:
|
18
|
+
- CI_CACHE_S3_BUCKET="cache-bucket"
|
19
|
+
- CI_CACHE_S3_KEY="cache-aws-key"
|
20
|
+
- CI_CACHE_S3_SECRET="cache-aws-secret"
|
21
|
+
before_install:
|
22
|
+
- gem install ci-cache
|
23
|
+
- ci-cache get --name bundler-cache --output-path ~
|
24
|
+
after_script:
|
25
|
+
- bundle clean
|
26
|
+
- ci-cache set --name bundler-cache --content ~/.bundle --hash-file Gemfile.lock
|
27
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
task(:default) { ruby '-S rspec' }
|
data/bin/ci-cache
ADDED
data/ci-cache.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
$:.unshift File.expand_path("../lib", __FILE__)
|
2
|
+
require "ci-cache/version"
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "ci-cache"
|
6
|
+
s.version = CiCache::VERSION
|
7
|
+
s.author = "Johannes Würbach"
|
8
|
+
s.email = "johannes.wuerbach@googlemail.com"
|
9
|
+
s.homepage = "https://github.com/johanneswuerbach/ci-cache"
|
10
|
+
s.summary = %q{ci cache tool}
|
11
|
+
s.description = %q{cache files in an ephemeral continuous integration environment}
|
12
|
+
s.license = 'MIT'
|
13
|
+
s.files = `git ls-files`.split("\n")
|
14
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
15
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
16
|
+
s.require_path = 'lib'
|
17
|
+
s.required_ruby_version = '>= 1.8.7'
|
18
|
+
|
19
|
+
s.add_runtime_dependency 'aws-sdk'
|
20
|
+
|
21
|
+
s.add_development_dependency 'rspec'
|
22
|
+
s.add_development_dependency 'rake'
|
23
|
+
end
|
data/lib/ci-cache/cli.rb
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
require 'ci-cache/error'
|
2
|
+
require 'optparse'
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
module CiCache
|
6
|
+
class CLI
|
7
|
+
def self.run(argv)
|
8
|
+
new(argv).run
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :options, :argv
|
12
|
+
attr_accessor :fold_count, :command
|
13
|
+
|
14
|
+
VALID_COMMANDS = ['get', 'set']
|
15
|
+
|
16
|
+
def initialize(argv = nil)
|
17
|
+
@argv = argv || ARGV
|
18
|
+
@options = {}
|
19
|
+
self.fold_count = 0
|
20
|
+
end
|
21
|
+
|
22
|
+
def run
|
23
|
+
parse!
|
24
|
+
execute_command
|
25
|
+
rescue Error => error
|
26
|
+
options[:debug] ? raise(error) : die(error.message)
|
27
|
+
end
|
28
|
+
|
29
|
+
def fold(message)
|
30
|
+
self.fold_count += 1
|
31
|
+
print "travis_fold:start:ci-cache.#{fold_count}\r" if options[:fold]
|
32
|
+
puts "\e[33m#{message}\e[0m"
|
33
|
+
yield
|
34
|
+
ensure
|
35
|
+
print "\ntravis_fold:end:ci-cache.#{fold_count}\r" if options[:fold]
|
36
|
+
end
|
37
|
+
|
38
|
+
def name
|
39
|
+
error("No valid name provided") unless options[:name]
|
40
|
+
options[:name]
|
41
|
+
end
|
42
|
+
|
43
|
+
def content
|
44
|
+
error("No valid content provided") unless options[:content]
|
45
|
+
Pathname(options[:content])
|
46
|
+
end
|
47
|
+
|
48
|
+
def hash_file
|
49
|
+
error("No hash file provided") unless options[:hash_file]
|
50
|
+
Pathname(options[:hash_file]).expand_path
|
51
|
+
end
|
52
|
+
|
53
|
+
def output_path
|
54
|
+
error("No output path provided") unless options[:output_path]
|
55
|
+
Pathname(options[:output_path]).expand_path
|
56
|
+
end
|
57
|
+
|
58
|
+
def cache_archive_name
|
59
|
+
"#{name}.tar.gz"
|
60
|
+
end
|
61
|
+
|
62
|
+
def cache_hash_file_name
|
63
|
+
"#{name}.sha2"
|
64
|
+
end
|
65
|
+
|
66
|
+
def tmp_folder
|
67
|
+
Pathname("~").expand_path
|
68
|
+
end
|
69
|
+
|
70
|
+
def archive_path
|
71
|
+
Pathname("#{tmp_folder}/#{cache_archive_name}")
|
72
|
+
end
|
73
|
+
|
74
|
+
def old_hash_file
|
75
|
+
Pathname("#{tmp_folder}/#{cache_hash_file_name}")
|
76
|
+
end
|
77
|
+
|
78
|
+
def log(message)
|
79
|
+
$stderr.puts(message)
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def execute_command
|
85
|
+
if VALID_COMMANDS.include? command
|
86
|
+
send(command)
|
87
|
+
return 0
|
88
|
+
else
|
89
|
+
error "Invalid command."
|
90
|
+
return 1
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def get
|
95
|
+
fold("Getting #{name}") do
|
96
|
+
CiCache::Get.new(self).run
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def set
|
101
|
+
fold("Setting #{name}") do
|
102
|
+
CiCache::Set.new(self).run
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def error(message)
|
107
|
+
raise Error, message
|
108
|
+
end
|
109
|
+
|
110
|
+
def die(message)
|
111
|
+
$stderr.puts(message)
|
112
|
+
exit 1
|
113
|
+
end
|
114
|
+
|
115
|
+
def parse!
|
116
|
+
self.command = argv[0]
|
117
|
+
parser.parse! argv
|
118
|
+
end
|
119
|
+
|
120
|
+
def parser
|
121
|
+
@opt_parser ||= begin
|
122
|
+
options = self.options
|
123
|
+
|
124
|
+
OptionParser.new do |opt|
|
125
|
+
opt.banner = 'Usage: ci-cache COMMAND [OPTIONS]'
|
126
|
+
opt.separator ''
|
127
|
+
opt.separator 'Commands'
|
128
|
+
opt.separator ' get: get files from cache'
|
129
|
+
opt.separator ' set: cache files'
|
130
|
+
opt.separator ''
|
131
|
+
opt.separator 'Options'
|
132
|
+
|
133
|
+
opt.on('--name NAME','archive name') do |name|
|
134
|
+
options[:name] = name
|
135
|
+
end
|
136
|
+
|
137
|
+
opt.on('--content CONTENT','path or file to cache') do |content|
|
138
|
+
options[:content] = content
|
139
|
+
end
|
140
|
+
|
141
|
+
opt.on('--hash-file HASH_FILE', 'file used to check for updates') do |target_path|
|
142
|
+
options[:hash_file] = target_path
|
143
|
+
end
|
144
|
+
|
145
|
+
opt.on('--output-path OUTPUT_PATH', 'path the archive should be extracted to') do |output_path|
|
146
|
+
options[:output_path] = output_path
|
147
|
+
end
|
148
|
+
|
149
|
+
opt.on('--fold', 'fold output on travis') do |fold|
|
150
|
+
options[:fold] = fold
|
151
|
+
end
|
152
|
+
|
153
|
+
opt.on('-h','--help','help') do
|
154
|
+
puts @opt_parser
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
data/lib/ci-cache/get.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
module CiCache
|
2
|
+
class Get
|
3
|
+
|
4
|
+
def initialize(context)
|
5
|
+
@context = context
|
6
|
+
@storage = Storage.new(context)
|
7
|
+
end
|
8
|
+
|
9
|
+
def run
|
10
|
+
download_archive
|
11
|
+
download_hash_file
|
12
|
+
extract_archive
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def download_archive
|
18
|
+
@storage.download(context.cache_archive_name, tmp_folder)
|
19
|
+
end
|
20
|
+
|
21
|
+
def download_hash_file
|
22
|
+
@storage.download(context.cache_hash_file_name, tmp_folder)
|
23
|
+
end
|
24
|
+
|
25
|
+
def extract_archive
|
26
|
+
log "Extract: #{archive_path} ~> #{output_path}"
|
27
|
+
CiCache.shell("tar -C #{output_path} -xf #{archive_path}")
|
28
|
+
end
|
29
|
+
|
30
|
+
def context
|
31
|
+
@context
|
32
|
+
end
|
33
|
+
|
34
|
+
def log(message)
|
35
|
+
context.log(message)
|
36
|
+
end
|
37
|
+
|
38
|
+
def tmp_folder
|
39
|
+
context.tmp_folder
|
40
|
+
end
|
41
|
+
|
42
|
+
def archive_path
|
43
|
+
context.archive_path
|
44
|
+
end
|
45
|
+
|
46
|
+
def output_path
|
47
|
+
context.output_path
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/ci-cache/set.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require "digest"
|
2
|
+
|
3
|
+
module CiCache
|
4
|
+
class Set
|
5
|
+
def initialize(context)
|
6
|
+
@context = context
|
7
|
+
@storage = Storage.new(context)
|
8
|
+
end
|
9
|
+
|
10
|
+
def run
|
11
|
+
if content_has_changed?
|
12
|
+
context.log("Updating cache.")
|
13
|
+
archive_files
|
14
|
+
upload_archive
|
15
|
+
upload_hash_file
|
16
|
+
else
|
17
|
+
context.log("Nothing changed.")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def context
|
24
|
+
@context
|
25
|
+
end
|
26
|
+
|
27
|
+
def archive_files
|
28
|
+
dirname, basename = content.split
|
29
|
+
log "Archive: #{content} ~> #{archive_path}"
|
30
|
+
CiCache.shell("tar -C #{dirname} -cjf #{archive_path} #{basename}")
|
31
|
+
end
|
32
|
+
|
33
|
+
def content_has_changed?
|
34
|
+
new_checksum != old_checksum
|
35
|
+
end
|
36
|
+
|
37
|
+
def new_checksum
|
38
|
+
@_new_checksum ||= Digest::SHA2.file(context.hash_file).hexdigest
|
39
|
+
end
|
40
|
+
|
41
|
+
def old_checksum
|
42
|
+
old_hash_file = context.old_hash_file
|
43
|
+
File.exists?(old_hash_file) ? File.read(old_hash_file) : ""
|
44
|
+
end
|
45
|
+
|
46
|
+
def upload_archive
|
47
|
+
@storage.upload(context.cache_archive_name, context.archive_path)
|
48
|
+
end
|
49
|
+
|
50
|
+
def upload_hash_file
|
51
|
+
@storage.upload(context.cache_hash_file_name, new_checksum)
|
52
|
+
end
|
53
|
+
|
54
|
+
def archive_path
|
55
|
+
context.archive_path
|
56
|
+
end
|
57
|
+
|
58
|
+
def content
|
59
|
+
context.content
|
60
|
+
end
|
61
|
+
|
62
|
+
def log(message)
|
63
|
+
context.log(message)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module CiCache
|
2
|
+
class Storage
|
3
|
+
|
4
|
+
def initialize(context)
|
5
|
+
configure_aws
|
6
|
+
@s3 = AWS::S3.new
|
7
|
+
@context = context
|
8
|
+
end
|
9
|
+
|
10
|
+
def download(name, tmp_folder)
|
11
|
+
target_file = "#{tmp_folder}/#{name}"
|
12
|
+
log "Download: #{name} ~> #{target_file}"
|
13
|
+
object = bucket_object(name)
|
14
|
+
File.open(target_file, 'wb') do |file|
|
15
|
+
object.read do |chunk|
|
16
|
+
file.write(chunk)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
rescue AWS::S3::Errors::AccessDenied => e
|
20
|
+
log "Not found."
|
21
|
+
end
|
22
|
+
|
23
|
+
def upload(name, content)
|
24
|
+
log "Upload: #{name}"
|
25
|
+
object = bucket_object(name)
|
26
|
+
object.write(content)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def log(message)
|
32
|
+
@context.log(message)
|
33
|
+
end
|
34
|
+
|
35
|
+
def bucket_name
|
36
|
+
ENV["CI_CACHE_S3_BUCKET"]
|
37
|
+
end
|
38
|
+
|
39
|
+
def configure_aws
|
40
|
+
AWS.config(
|
41
|
+
access_key_id: ENV["CI_CACHE_S3_KEY"],
|
42
|
+
secret_access_key: ENV["CI_CACHE_S3_SECRET"]
|
43
|
+
)
|
44
|
+
end
|
45
|
+
|
46
|
+
def bucket_object(name)
|
47
|
+
bucket.objects[name]
|
48
|
+
end
|
49
|
+
|
50
|
+
def bucket
|
51
|
+
@s3.buckets[bucket_name]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/ci-cache.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'aws-sdk'
|
2
|
+
|
3
|
+
module CiCache
|
4
|
+
autoload :CLI, 'ci-cache/cli'
|
5
|
+
autoload :Get, 'ci-cache/get'
|
6
|
+
autoload :Set, 'ci-cache/set'
|
7
|
+
autoload :Error, 'ci-cache/error'
|
8
|
+
autoload :Storage, 'ci-cache/storage'
|
9
|
+
|
10
|
+
def self.shell(command)
|
11
|
+
system(command)
|
12
|
+
end
|
13
|
+
end
|
data/spec/cli_spec.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CiCache::CLI do
|
4
|
+
|
5
|
+
describe "::new" do
|
6
|
+
let(:path) { Pathname("~/").expand_path }
|
7
|
+
let(:cli) { CiCache::CLI.new([
|
8
|
+
"set",
|
9
|
+
"--name", "bundle_cache",
|
10
|
+
"--hash-file", "Gemfile",
|
11
|
+
"--content", "~/.bundle_cache"
|
12
|
+
])}
|
13
|
+
subject { cli }
|
14
|
+
before do
|
15
|
+
cli.send(:parse!)
|
16
|
+
end
|
17
|
+
|
18
|
+
its(:cache_archive_name) { should eq("bundle_cache.tar.gz")}
|
19
|
+
its(:cache_hash_file_name) { should eq("bundle_cache.sha2")}
|
20
|
+
its(:tmp_folder) { should eq(path) }
|
21
|
+
its(:archive_path) { should eq(Pathname("#{path}/bundle_cache.tar.gz"))}
|
22
|
+
its(:old_hash_file) { should eq(Pathname("#{path}/bundle_cache.sha2"))}
|
23
|
+
its(:hash_file) { should eq(Pathname("Gemfile").expand_path) }
|
24
|
+
its(:content) { should eq(Pathname("~/.bundle_cache")) }
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "::run" do
|
28
|
+
context "when get is used" do
|
29
|
+
let(:get) { double "get" }
|
30
|
+
subject { CiCache::CLI.run(["get", "--name", "cached"]) }
|
31
|
+
|
32
|
+
it "should execute the get command" do
|
33
|
+
CiCache::Get.should_receive(:new).with(instance_of(CiCache::CLI)).and_return(get)
|
34
|
+
CiCache::CLI.any_instance.should_receive(:fold).and_yield
|
35
|
+
get.should_receive(:run)
|
36
|
+
subject
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "when set is used" do
|
41
|
+
let(:set) { double "set" }
|
42
|
+
subject { CiCache::CLI.run(["set", "--name", "cached"]) }
|
43
|
+
|
44
|
+
it "should execute the set command" do
|
45
|
+
CiCache::Set.should_receive(:new).with(instance_of(CiCache::CLI)).and_return(set)
|
46
|
+
CiCache::CLI.any_instance.should_receive(:fold).and_yield
|
47
|
+
set.should_receive(:run)
|
48
|
+
subject
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/spec/get_spec.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CiCache::Get do
|
4
|
+
describe :run do
|
5
|
+
let(:context) { double "context" }
|
6
|
+
let(:get) { CiCache::Get.new(context) }
|
7
|
+
let(:storage) { double "storage" }
|
8
|
+
subject { get.run }
|
9
|
+
|
10
|
+
before do
|
11
|
+
CiCache.stub(:shell)
|
12
|
+
context.stub(:cache_archive_name).and_return("cache.tar.gz")
|
13
|
+
context.stub(:cache_hash_file_name).and_return("cache.sha2")
|
14
|
+
context.stub(:archive_path).and_return(Pathname("~/cache.tar.gz"))
|
15
|
+
context.stub(:tmp_folder).and_return("~")
|
16
|
+
context.stub(:output_path).and_return("~")
|
17
|
+
context.stub(:log)
|
18
|
+
|
19
|
+
storage.stub(:download)
|
20
|
+
CiCache::Storage.should_receive(:new).and_return(storage)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "downloads the archive" do
|
24
|
+
storage.should_receive(:download).with("cache.tar.gz", "~")
|
25
|
+
subject
|
26
|
+
end
|
27
|
+
|
28
|
+
it "download the hash file" do
|
29
|
+
storage.should_receive(:download).with("cache.sha2", "~")
|
30
|
+
subject
|
31
|
+
end
|
32
|
+
|
33
|
+
it "extracts the archive" do
|
34
|
+
CiCache.should_receive(:shell).with("tar -C ~ -xf ~/cache.tar.gz")
|
35
|
+
subject
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/spec/set_spec.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CiCache::Set do
|
4
|
+
describe :run do
|
5
|
+
let(:context) { double "context" }
|
6
|
+
let(:set) { CiCache::Set.new(context) }
|
7
|
+
let(:storage) { double "storage" }
|
8
|
+
subject { set.run }
|
9
|
+
|
10
|
+
before do
|
11
|
+
CiCache.stub(:shell)
|
12
|
+
context.stub(:cache_archive_name).and_return("cache.tar.gz")
|
13
|
+
context.stub(:cache_hash_file_name).and_return("cache.sha2")
|
14
|
+
context.stub(:hash_file).and_return("Gemfile")
|
15
|
+
context.stub(:archive_path).and_return("~/archive.tar.gz")
|
16
|
+
context.stub(:old_hash_file).and_return("~/cache.sha2")
|
17
|
+
context.stub(:content).and_return(Pathname("~/.bundle_cache"))
|
18
|
+
context.stub(:log)
|
19
|
+
|
20
|
+
storage.stub(:upload)
|
21
|
+
CiCache::Storage.should_receive(:new).and_return(storage)
|
22
|
+
end
|
23
|
+
|
24
|
+
context "when content has changed" do
|
25
|
+
it "archives the folder" do
|
26
|
+
CiCache.should_receive(:shell).with("tar -C ~ -cjf ~/archive.tar.gz .bundle_cache")
|
27
|
+
subject
|
28
|
+
end
|
29
|
+
|
30
|
+
it "uploads the archive" do
|
31
|
+
storage.should_receive(:upload).with("cache.tar.gz", "~/archive.tar.gz")
|
32
|
+
subject
|
33
|
+
end
|
34
|
+
|
35
|
+
it "uploads the hash file" do
|
36
|
+
storage.should_receive(:upload).with("cache.sha2", Digest::SHA2.file("Gemfile").hexdigest)
|
37
|
+
subject
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "when content has not changed" do
|
42
|
+
it "logs a message" do
|
43
|
+
context.should_receive(:log)
|
44
|
+
subject
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'ci-cache'
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe CiCache::Storage do
|
4
|
+
let(:context) { double "context" }
|
5
|
+
let(:storage) { CiCache::Storage.new(context) }
|
6
|
+
let(:object) { double "object" }
|
7
|
+
let(:name) { "file" }
|
8
|
+
|
9
|
+
before do
|
10
|
+
context.stub(:log)
|
11
|
+
end
|
12
|
+
|
13
|
+
describe :download do
|
14
|
+
let(:folder) { "~" }
|
15
|
+
let(:handle) { double "handle" }
|
16
|
+
subject { storage.download(name, folder) }
|
17
|
+
|
18
|
+
context "when the object exists" do
|
19
|
+
it "downloads the object" do
|
20
|
+
storage.should_receive(:bucket_object).and_return(object)
|
21
|
+
object.should_receive(:read).and_yield("chunk")
|
22
|
+
handle.should_receive(:write).with("chunk")
|
23
|
+
File.should_receive(:open).with("~/file", "wb").and_yield(handle)
|
24
|
+
subject
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "when the object doesn't exist" do
|
29
|
+
it "logs an error" do
|
30
|
+
storage.should_receive(:bucket_object).and_raise(AWS::S3::Errors::AccessDenied.new)
|
31
|
+
context.should_receive(:log)
|
32
|
+
subject
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe :upload do
|
38
|
+
subject { storage.upload(name, "content") }
|
39
|
+
|
40
|
+
it "uploads the content" do
|
41
|
+
storage.should_receive(:bucket_object).and_return(object)
|
42
|
+
object.should_receive(:write).with("content")
|
43
|
+
subject
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
metadata
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ci-cache
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Johannes Würbach
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-09-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: aws-sdk
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: cache files in an ephemeral continuous integration environment
|
56
|
+
email: johannes.wuerbach@googlemail.com
|
57
|
+
executables:
|
58
|
+
- ci-cache
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- .gitignore
|
63
|
+
- .rspec
|
64
|
+
- .travis.yml
|
65
|
+
- Gemfile
|
66
|
+
- LICENSE
|
67
|
+
- README.md
|
68
|
+
- Rakefile
|
69
|
+
- bin/ci-cache
|
70
|
+
- ci-cache.gemspec
|
71
|
+
- lib/ci-cache.rb
|
72
|
+
- lib/ci-cache/cli.rb
|
73
|
+
- lib/ci-cache/error.rb
|
74
|
+
- lib/ci-cache/get.rb
|
75
|
+
- lib/ci-cache/set.rb
|
76
|
+
- lib/ci-cache/storage.rb
|
77
|
+
- lib/ci-cache/version.rb
|
78
|
+
- spec/cli_spec.rb
|
79
|
+
- spec/get_spec.rb
|
80
|
+
- spec/set_spec.rb
|
81
|
+
- spec/spec_helper.rb
|
82
|
+
- spec/storage_spec.rb
|
83
|
+
homepage: https://github.com/johanneswuerbach/ci-cache
|
84
|
+
licenses:
|
85
|
+
- MIT
|
86
|
+
metadata: {}
|
87
|
+
post_install_message:
|
88
|
+
rdoc_options: []
|
89
|
+
require_paths:
|
90
|
+
- lib
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: 1.8.7
|
96
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - '>='
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
requirements: []
|
102
|
+
rubyforge_project:
|
103
|
+
rubygems_version: 2.1.3
|
104
|
+
signing_key:
|
105
|
+
specification_version: 4
|
106
|
+
summary: ci cache tool
|
107
|
+
test_files:
|
108
|
+
- spec/cli_spec.rb
|
109
|
+
- spec/get_spec.rb
|
110
|
+
- spec/set_spec.rb
|
111
|
+
- spec/spec_helper.rb
|
112
|
+
- spec/storage_spec.rb
|