buildpack-packager 2.3.4
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 +14 -0
- data/.rspec +2 -0
- data/Gemfile +5 -0
- data/LICENSE +176 -0
- data/README.md +180 -0
- data/Rakefile +6 -0
- data/bin/buildpack-packager +79 -0
- data/buildpack-packager.gemspec +33 -0
- data/doc/disconnected_environments.md +50 -0
- data/lib/buildpack/manifest_dependency.rb +14 -0
- data/lib/buildpack/manifest_validator.rb +88 -0
- data/lib/buildpack/packager.rb +55 -0
- data/lib/buildpack/packager/default_versions_presenter.rb +38 -0
- data/lib/buildpack/packager/dependencies_presenter.rb +41 -0
- data/lib/buildpack/packager/manifest_schema.yml +67 -0
- data/lib/buildpack/packager/package.rb +139 -0
- data/lib/buildpack/packager/table_presentation.rb +21 -0
- data/lib/buildpack/packager/version.rb +5 -0
- data/lib/buildpack/packager/zip_file_excluder.rb +31 -0
- data/lib/kwalify/parser/yaml-patcher.rb +70 -0
- data/spec/buildpack/packager_spec.rb +7 -0
- data/spec/fixtures/buildpack-with-uri-credentials/VERSION +1 -0
- data/spec/fixtures/buildpack-with-uri-credentials/manifest.yml +36 -0
- data/spec/fixtures/buildpack-without-uri-credentials/VERSION +1 -0
- data/spec/fixtures/buildpack-without-uri-credentials/manifest.yml +36 -0
- data/spec/fixtures/manifests/manifest_invalid-md6.yml +18 -0
- data/spec/fixtures/manifests/manifest_invalid-md6_and_defaults.yml +21 -0
- data/spec/fixtures/manifests/manifest_valid.yml +19 -0
- data/spec/helpers/cache_directory_helpers.rb +15 -0
- data/spec/helpers/fake_binary_hosting_helpers.rb +21 -0
- data/spec/helpers/file_system_helpers.rb +35 -0
- data/spec/integration/bin/buildpack_packager/download_caching_spec.rb +85 -0
- data/spec/integration/bin/buildpack_packager_spec.rb +378 -0
- data/spec/integration/buildpack/directory_name_spec.rb +89 -0
- data/spec/integration/buildpack/packager_spec.rb +454 -0
- data/spec/integration/default_versions_spec.rb +170 -0
- data/spec/integration/output_spec.rb +70 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/unit/buildpack/packager/zip_file_excluder_spec.rb +68 -0
- data/spec/unit/manifest_dependency_spec.rb +41 -0
- data/spec/unit/manifest_validator_spec.rb +35 -0
- data/spec/unit/packager/package_spec.rb +196 -0
- metadata +235 -0
@@ -0,0 +1,170 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
describe 'Buildpack packager default_versions validation' do
|
5
|
+
let(:flags) { '--uncached' }
|
6
|
+
let(:buildpack_dir) { Dir.mktmpdir }
|
7
|
+
let(:cache_dir) { Dir.mktmpdir }
|
8
|
+
let(:base_manifest_contents) { <<-BASE
|
9
|
+
language: python
|
10
|
+
url_to_dependency_map: []
|
11
|
+
exclude_files: []
|
12
|
+
BASE
|
13
|
+
}
|
14
|
+
|
15
|
+
before do
|
16
|
+
Dir.chdir(buildpack_dir) do
|
17
|
+
File.write('manifest.yml', manifest)
|
18
|
+
File.write('VERSION', '1.7.8')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
after do
|
23
|
+
FileUtils.rm_rf(buildpack_dir)
|
24
|
+
FileUtils.rm_rf(cache_dir)
|
25
|
+
end
|
26
|
+
|
27
|
+
shared_examples_for "general output that helps with the error is produced" do
|
28
|
+
it "outputs a link to the Cloud Foundry custom buildpacks page" do
|
29
|
+
output, status = run_packager_binary(buildpack_dir, flags)
|
30
|
+
expect(output).to include("For more information, see https://docs.cloudfoundry.org/buildpacks/custom.html#specifying-default-versions")
|
31
|
+
end
|
32
|
+
|
33
|
+
it "states the buildpack manifest is malformed" do
|
34
|
+
output, status = run_packager_binary(buildpack_dir, flags)
|
35
|
+
expect(output).to include("The buildpack manifest is malformed:")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'defaults and dependencies are in agreement' do
|
40
|
+
let(:manifest) {<<-MANIFEST
|
41
|
+
#{base_manifest_contents}
|
42
|
+
default_versions:
|
43
|
+
- name: python
|
44
|
+
version: 3.3.5
|
45
|
+
dependencies:
|
46
|
+
- name: python
|
47
|
+
version: 3.3.5
|
48
|
+
uri: http://example.com/
|
49
|
+
md5: 68901bbf8a04e71e0b30aa19c3946b21
|
50
|
+
cf_stacks:
|
51
|
+
- cflinuxfs2
|
52
|
+
MANIFEST
|
53
|
+
}
|
54
|
+
|
55
|
+
it 'emits no errors' do
|
56
|
+
_, status = run_packager_binary(buildpack_dir, flags)
|
57
|
+
|
58
|
+
expect(status).to be_success
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'multiple default versions for a dependency' do
|
63
|
+
let(:manifest) {<<-MANIFEST
|
64
|
+
#{base_manifest_contents}
|
65
|
+
default_versions:
|
66
|
+
- name: python
|
67
|
+
version: 3.3.5
|
68
|
+
- name: python
|
69
|
+
version: 3.3.2
|
70
|
+
- name: ruby
|
71
|
+
version: 4.3.5
|
72
|
+
- name: ruby
|
73
|
+
version: 4.3.2
|
74
|
+
dependencies:
|
75
|
+
- name: python
|
76
|
+
uri: https://a.org
|
77
|
+
version: 3.3.5
|
78
|
+
md5: 3a2
|
79
|
+
cf_stacks: [cflinuxfs2]
|
80
|
+
- name: python
|
81
|
+
uri: https://a.org
|
82
|
+
version: 3.3.2
|
83
|
+
md5: 3a2
|
84
|
+
cf_stacks: [cflinuxfs2]
|
85
|
+
- name: ruby
|
86
|
+
uri: https://a.org
|
87
|
+
version: 4.3.5
|
88
|
+
md5: 3a2
|
89
|
+
cf_stacks: [cflinuxfs2]
|
90
|
+
- name: ruby
|
91
|
+
uri: https://a.org
|
92
|
+
version: 4.3.2
|
93
|
+
md5: 3a2
|
94
|
+
cf_stacks: [cflinuxfs2]
|
95
|
+
MANIFEST
|
96
|
+
}
|
97
|
+
|
98
|
+
it_behaves_like "general output that helps with the error is produced"
|
99
|
+
|
100
|
+
it 'fails and errors stating the context' do
|
101
|
+
output, status = run_packager_binary(buildpack_dir, flags)
|
102
|
+
|
103
|
+
expect(output).to include("python had more " +
|
104
|
+
"than one 'default_versions' entry in the buildpack manifest.")
|
105
|
+
expect(output).to include("ruby had more " +
|
106
|
+
"than one 'default_versions' entry in the buildpack manifest.")
|
107
|
+
expect(status).to_not be_success
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'no dependency with name found for default in manifest' do
|
112
|
+
let(:manifest) {<<-MANIFEST
|
113
|
+
#{base_manifest_contents}
|
114
|
+
default_versions:
|
115
|
+
- name: python
|
116
|
+
version: 3.3.5
|
117
|
+
- name: ruby
|
118
|
+
version: 4.3.5
|
119
|
+
dependencies: []
|
120
|
+
MANIFEST
|
121
|
+
}
|
122
|
+
|
123
|
+
it_behaves_like "general output that helps with the error is produced"
|
124
|
+
|
125
|
+
it 'fails and errors stating the context' do
|
126
|
+
output, status = run_packager_binary(buildpack_dir, flags)
|
127
|
+
|
128
|
+
expect(output).to include("a 'default_versions' entry for python 3.3.5 was specified by the buildpack manifest, " +
|
129
|
+
"but no 'dependencies' entry for python 3.3.5 was found in the buildpack manifest.")
|
130
|
+
expect(output).to include("a 'default_versions' entry for ruby 4.3.5 was specified by the buildpack manifest, " +
|
131
|
+
"but no 'dependencies' entry for ruby 4.3.5 was found in the buildpack manifest.")
|
132
|
+
expect(status).to_not be_success
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
context 'no dependency with version found for default in manifest' do
|
137
|
+
let(:manifest) {<<-MANIFEST
|
138
|
+
#{base_manifest_contents}
|
139
|
+
default_versions:
|
140
|
+
- name: ruby
|
141
|
+
version: 1.1.1
|
142
|
+
- name: python
|
143
|
+
version: 3.3.5
|
144
|
+
dependencies:
|
145
|
+
- name: ruby
|
146
|
+
uri: https://a.org
|
147
|
+
version: 9.9.9
|
148
|
+
md5: 3a2
|
149
|
+
cf_stacks: [cflinuxfs2]
|
150
|
+
- name: python
|
151
|
+
uri: https://a.org
|
152
|
+
version: 9.9.9
|
153
|
+
md5: 3a2
|
154
|
+
cf_stacks: [cflinuxfs2]
|
155
|
+
MANIFEST
|
156
|
+
}
|
157
|
+
|
158
|
+
it_behaves_like "general output that helps with the error is produced"
|
159
|
+
|
160
|
+
it 'fails and errors stating the context' do
|
161
|
+
output, status = run_packager_binary(buildpack_dir, flags)
|
162
|
+
|
163
|
+
expect(output).to include("a 'default_versions' entry for python 3.3.5 was specified by the buildpack manifest, " +
|
164
|
+
"but no 'dependencies' entry for python 3.3.5 was found in the buildpack manifest.")
|
165
|
+
expect(output).to include("a 'default_versions' entry for ruby 1.1.1 was specified by the buildpack manifest, " +
|
166
|
+
"but no 'dependencies' entry for ruby 1.1.1 was found in the buildpack manifest.")
|
167
|
+
expect(status).to_not be_success
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
describe 'Buildpack packager output' do
|
5
|
+
let(:buildpack_type) { '--uncached' }
|
6
|
+
let(:fixture_name) { 'buildpack-without-uri-credentials' }
|
7
|
+
let(:buildpack_fixture) { File.join(File.dirname(__FILE__), '..', 'fixtures', fixture_name) }
|
8
|
+
let(:tmpdir) { Dir.mktmpdir }
|
9
|
+
|
10
|
+
before do
|
11
|
+
FileUtils.rm_rf(tmpdir)
|
12
|
+
end
|
13
|
+
|
14
|
+
def buildpack_packager_execute(buildpack_dir, home_dir)
|
15
|
+
Dir.chdir(buildpack_dir) do
|
16
|
+
`HOME=#{home_dir} buildpack-packager #{buildpack_type}`
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
subject { buildpack_packager_execute(buildpack_fixture, tmpdir) }
|
21
|
+
|
22
|
+
context 'building the uncached buildpack' do
|
23
|
+
it 'outputs the type of buildpack created, where and its human readable size' do
|
24
|
+
expect(subject).to include("Uncached buildpack created and saved as")
|
25
|
+
expect(subject).to include("spec/fixtures/#{fixture_name}/go_buildpack-v1.7.8.zip")
|
26
|
+
expect(subject).to match(/with a size of 4\.0K$/)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'building the cached buildpack' do
|
31
|
+
let(:buildpack_type) { '--cached' }
|
32
|
+
|
33
|
+
it 'outputs the dependencies downloaded, their versions, and download source url' do
|
34
|
+
expect(subject).to include("Downloading go version 1.6.3 from: https://buildpacks.cloudfoundry.org/concourse-binaries/go/go1.6.3.linux-amd64.tar.gz")
|
35
|
+
expect(subject).to include("Using go version 1.6.3 with size")
|
36
|
+
expect(subject).to include("go version 1.6.3 matches the manifest provided md5 checksum of 5f7bf9d61d2b0dd75c9e2cd7a87272cc")
|
37
|
+
|
38
|
+
expect(subject).to include("Downloading godep version v74 from: https://pivotal-buildpacks.s3.amazonaws.com/concourse-binaries/godep/godep-v74-linux-x64.tgz")
|
39
|
+
expect(subject).to include("Using godep version v74 with size 2.8M")
|
40
|
+
expect(subject).to include("godep version v74 matches the manifest provided md5 checksum of 70220eee9f9e654e0b85887f696b6add")
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'outputs the type of buildpack created, where and its human readable size' do
|
44
|
+
expect(subject).to include("Cached buildpack created and saved as")
|
45
|
+
expect(subject).to include("spec/fixtures/#{fixture_name}/go_buildpack-cached-v1.7.8.zip")
|
46
|
+
expect(subject).to match(/with a size of 68M$/)
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'with a buildpack packager dependency cache intact' do
|
50
|
+
before { buildpack_packager_execute(buildpack_fixture, tmpdir) }
|
51
|
+
|
52
|
+
it 'outputs the dependencies downloaded, their versions, and cache location' do
|
53
|
+
expect(subject).to include("Using go version 1.6.3 from local cache at: #{tmpdir}/.buildpack-packager/cache/https___buildpacks.cloudfoundry.org_concourse-binaries_go_go1.6.3.linux-amd64.tar.gz with size")
|
54
|
+
expect(subject).to include("go version 1.6.3 matches the manifest provided md5 checksum of 5f7bf9d61d2b0dd75c9e2cd7a87272cc")
|
55
|
+
|
56
|
+
expect(subject).to include("Using godep version v74 from local cache at: #{tmpdir}/.buildpack-packager/cache/https___pivotal-buildpacks.s3.amazonaws.com_concourse-binaries_godep_godep-v74-linux-x64.tgz with size")
|
57
|
+
expect(subject).to include("godep version v74 matches the manifest provided md5 checksum of 70220eee9f9e654e0b85887f696b6add")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'with auth credentials in the dependency uri' do
|
62
|
+
let(:fixture_name) { 'buildpack-with-uri-credentials' }
|
63
|
+
|
64
|
+
it 'outputs the dependencies download source url without the credentials' do
|
65
|
+
expect(subject).to include('Downloading go version 1.6.3 from: https://-redacted-:-redacted-@buildpacks.cloudfoundry.org/concourse-binaries/go/go1.6.3.linux-amd64.tar.gz')
|
66
|
+
expect(subject).to include('Downloading godep version v74 from: https://-redacted-:-redacted-@buildpacks.cloudfoundry.org/concourse-binaries/godep/godep-v74-linux-x64.tgz')
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
$LOAD_PATH << File.expand_path('../../lib', __FILE__)
|
2
|
+
$LOAD_PATH << File.expand_path('../../spec/helpers', __FILE__)
|
3
|
+
require 'buildpack/packager'
|
4
|
+
require 'file_system_helpers'
|
5
|
+
require 'cache_directory_helpers'
|
6
|
+
require 'fake_binary_hosting_helpers'
|
7
|
+
|
8
|
+
RSpec.configure do |config|
|
9
|
+
config.include FileSystemHelpers
|
10
|
+
config.include CacheDirectoryHelpers
|
11
|
+
config.include FakeBinaryHostingHelpers
|
12
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'buildpack/packager/zip_file_excluder'
|
2
|
+
require 'spec_helper'
|
3
|
+
require 'tmpdir'
|
4
|
+
require 'securerandom'
|
5
|
+
|
6
|
+
module Buildpack
|
7
|
+
module Packager
|
8
|
+
describe ZipFileExcluder do
|
9
|
+
describe '#generate_exclusions_from_manifest' do
|
10
|
+
let(:excluder) { ZipFileExcluder.new }
|
11
|
+
let(:file1) { SecureRandom.uuid }
|
12
|
+
let(:file2) { SecureRandom.uuid }
|
13
|
+
let(:dir) { "#{SecureRandom.uuid}/" }
|
14
|
+
let(:excluded_files) { [file1, file2] }
|
15
|
+
subject do
|
16
|
+
excluder.generate_manifest_exclusions excluded_files
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'does not include directories' do
|
20
|
+
it do
|
21
|
+
is_expected.to eq "-x #{file1} -x \\*/#{file1} -x #{file2} -x \\*/#{file2}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'includes directories' do
|
26
|
+
let(:excluded_files) { [file1, dir] }
|
27
|
+
it do
|
28
|
+
is_expected.to eq "-x #{file1} -x \\*/#{file1} -x #{dir}\\* -x \\*/#{dir}\\*"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'uses short flags to support zip 2.3.*, see [#107948062]' do
|
33
|
+
is_expected.to include('-x')
|
34
|
+
is_expected.to_not include('--exclude')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '#generate_exclusions_from_git_files' do
|
40
|
+
let(:excluder) { ZipFileExcluder.new }
|
41
|
+
|
42
|
+
context 'git files exist' do
|
43
|
+
let (:files) { ['.gitignore', '.git/', '.gitmodules', 'lib/.git'] }
|
44
|
+
|
45
|
+
it 'returns an exclusion string with all the git files' do
|
46
|
+
Dir.mktmpdir do |dir|
|
47
|
+
Dir.mkdir "#{dir}/lib"
|
48
|
+
|
49
|
+
files.each do |gitfilename|
|
50
|
+
if gitfilename =~ /.*\/$/
|
51
|
+
Dir.mkdir "#{dir}/#{gitfilename}"
|
52
|
+
else
|
53
|
+
File.new "#{dir}/#{gitfilename}", 'w'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
git_exclusions = excluder.generate_exclusions_from_git_files dir
|
58
|
+
|
59
|
+
expect(git_exclusions).to include '-x .gitignore -x \\*/.gitignore'
|
60
|
+
expect(git_exclusions).to include '-x lib/.git -x \\*/lib/.git'
|
61
|
+
expect(git_exclusions).to include '-x .gitmodules -x \\*/.gitmodules'
|
62
|
+
expect(git_exclusions).to include '-x .git/\\* -x \\*/.git/\\*'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'buildpack/manifest_dependency'
|
3
|
+
|
4
|
+
describe Buildpack::ManifestDependency do
|
5
|
+
describe '#==' do
|
6
|
+
context 'two objects with the same name and same version' do
|
7
|
+
let(:first_dependency) { described_class.new('name', 'version') }
|
8
|
+
let(:second_dependency) { described_class.new('name', 'version') }
|
9
|
+
|
10
|
+
it 'returns true' do
|
11
|
+
expect(first_dependency == second_dependency).to be true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
context 'two objects with the same name only' do
|
15
|
+
let(:first_dependency) { described_class.new('name', 'version 11111111') }
|
16
|
+
let(:second_dependency) { described_class.new('name', 'version 22222222') }
|
17
|
+
|
18
|
+
it 'returns false' do
|
19
|
+
expect(first_dependency == second_dependency).to be false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'two objects with the same version only' do
|
24
|
+
let(:first_dependency) { described_class.new('name 111', 'version') }
|
25
|
+
let(:second_dependency) { described_class.new('name 222', 'version') }
|
26
|
+
|
27
|
+
it 'returns false' do
|
28
|
+
expect(first_dependency == second_dependency).to be false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'two objects with different names and different versions' do
|
33
|
+
let(:first_dependency) { described_class.new('name 111111', 'version 11111111') }
|
34
|
+
let(:second_dependency) { described_class.new('name 222222', 'version 22222222') }
|
35
|
+
|
36
|
+
it 'returns false' do
|
37
|
+
expect(first_dependency == second_dependency).to be false
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'buildpack/manifest_validator'
|
3
|
+
|
4
|
+
describe Buildpack::ManifestValidator do
|
5
|
+
let(:manifest_path) { "#{File.dirname(__FILE__)}/../fixtures/manifests/#{manifest_file_name}" }
|
6
|
+
let(:validator) { Buildpack::ManifestValidator.new(manifest_path) }
|
7
|
+
|
8
|
+
context 'with a valid manifest' do
|
9
|
+
let(:manifest_file_name) { 'manifest_valid.yml' }
|
10
|
+
|
11
|
+
it 'reports valid manifests correctly' do
|
12
|
+
expect(validator.valid?).to be(true)
|
13
|
+
expect(validator.errors).to be_empty
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'with a manifest with an invalid md5 key' do
|
18
|
+
let(:manifest_file_name) { 'manifest_invalid-md6.yml' }
|
19
|
+
|
20
|
+
it 'reports invalid manifests correctly' do
|
21
|
+
expect(validator.valid?).to be(false)
|
22
|
+
expect(validator.errors[:manifest_parser_errors]).not_to be_empty
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'and incorrect defaults' do
|
26
|
+
let(:manifest_file_name) { 'manifest_invalid-md6_and_defaults.yml' }
|
27
|
+
|
28
|
+
it 'reports manifest parser errors only' do
|
29
|
+
expect(validator).to_not receive(:validate_default_versions)
|
30
|
+
expect(validator.valid?).to be(false)
|
31
|
+
expect(validator.errors[:manifest_parser_errors]).not_to be_empty
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,196 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'tmpdir'
|
3
|
+
|
4
|
+
module Buildpack
|
5
|
+
module Packager
|
6
|
+
describe Package do
|
7
|
+
let(:packager) { Buildpack::Packager::Package.new(options) }
|
8
|
+
let(:manifest_path) { 'manifest.yml' }
|
9
|
+
let(:dependency) { double(:dependency) }
|
10
|
+
let(:mode) { :uncached }
|
11
|
+
let(:local_cache_dir) { nil }
|
12
|
+
let(:force_download) { false }
|
13
|
+
let(:options) do
|
14
|
+
{
|
15
|
+
root_dir: 'root_dir',
|
16
|
+
mode: mode,
|
17
|
+
cache_dir: local_cache_dir,
|
18
|
+
manifest_path: manifest_path,
|
19
|
+
force_download: force_download
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
let(:manifest) do
|
24
|
+
{
|
25
|
+
language: 'fake_language',
|
26
|
+
dependencies: [dependency],
|
27
|
+
exclude_files: ['.DS_Store', '.gitignore']
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
before do
|
32
|
+
allow(YAML).to receive(:load_file).and_return(manifest)
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#copy_buildpack_to_temp_dir' do
|
36
|
+
context 'with full manifest specified' do
|
37
|
+
let(:manifest_path) { 'manifest-including-unsupported.yml' }
|
38
|
+
|
39
|
+
before do
|
40
|
+
allow(FileUtils).to receive(:mv)
|
41
|
+
allow(FileUtils).to receive(:cp_r)
|
42
|
+
allow(FileUtils).to receive(:cp)
|
43
|
+
allow(FileUtils).to receive(:rm)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'replaces the default manifest with the full manifest' do
|
47
|
+
expect(FileUtils).to receive(:cp).with('manifest-including-unsupported.yml', File.join('hello_dir', 'manifest.yml'))
|
48
|
+
packager.copy_buildpack_to_temp_dir('hello_dir')
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe '#build_dependencies' do
|
54
|
+
let(:mode) { :cached }
|
55
|
+
|
56
|
+
before do
|
57
|
+
allow(FileUtils).to receive(:mkdir_p)
|
58
|
+
allow(packager).to receive(:download_dependencies)
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'when cache_dir is provided' do
|
62
|
+
let(:local_cache_dir) { 'local_cache_dir' }
|
63
|
+
|
64
|
+
it 'creates the provided cache dir' do
|
65
|
+
expect(FileUtils).to receive(:mkdir_p).with(local_cache_dir)
|
66
|
+
packager.build_dependencies('hello_dir')
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'creates the dependency dir' do
|
70
|
+
expect(FileUtils).to receive(:mkdir_p).with(File.join('hello_dir', 'dependencies'))
|
71
|
+
packager.build_dependencies('hello_dir')
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'calls download_dependencies with right arguments' do
|
75
|
+
expect(packager).to receive(:download_dependencies).with([dependency], local_cache_dir, File.join('hello_dir', 'dependencies'))
|
76
|
+
packager.build_dependencies('hello_dir')
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'when cache_dir is NOT provided' do
|
81
|
+
it 'creates the default cache dir' do
|
82
|
+
expect(FileUtils).to receive(:mkdir_p).with(File.join(ENV['HOME'], '.buildpack-packager', 'cache'))
|
83
|
+
packager.build_dependencies('hello_dir')
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe '#download_dependencies' do
|
89
|
+
let(:local_cache_dir) { 'local_cache_dir' }
|
90
|
+
let(:dependency_dir) { File.join('hello_dir', 'dependencies') }
|
91
|
+
let(:url_with_parameters) { 'http://some.cdn/with?parameters=true&secondParameter=present' }
|
92
|
+
|
93
|
+
before do
|
94
|
+
allow(dependency).to receive(:[])
|
95
|
+
allow(dependency).to receive(:[]).with('uri').and_return('file:///fake_uri.tgz')
|
96
|
+
allow(packager).to receive(:ensure_correct_dependency_checksum)
|
97
|
+
allow(FileUtils).to receive(:cp)
|
98
|
+
allow(packager).to receive(:download_file)
|
99
|
+
end
|
100
|
+
|
101
|
+
context 'before dependency has been cached locally' do
|
102
|
+
before do
|
103
|
+
allow(File).to receive(:exist?).and_return(false)
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'downloads the dependency to the local cache' do
|
107
|
+
expanded_local_file_location = File.expand_path(File.join('local_cache_dir', 'file____fake_uri.tgz'))
|
108
|
+
expect(packager).to receive(:download_file).with('file:///fake_uri.tgz', expanded_local_file_location)
|
109
|
+
packager.download_dependencies([dependency], local_cache_dir, dependency_dir)
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'copies the dependency from the local cache to the dependency_dir' do
|
113
|
+
expanded_local_file_location = File.expand_path(File.join('local_cache_dir', 'file____fake_uri.tgz'))
|
114
|
+
expect(FileUtils).to receive(:cp).with(expanded_local_file_location, dependency_dir)
|
115
|
+
packager.download_dependencies([dependency], local_cache_dir, dependency_dir)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context 'after dependency has been cached locally' do
|
120
|
+
before do
|
121
|
+
allow(File).to receive(:exist?).and_return(true)
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'does not re-download the dependency' do
|
125
|
+
expect(packager).not_to receive(:download_file)
|
126
|
+
packager.download_dependencies([dependency], local_cache_dir, dependency_dir)
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'copies the dependency from the local cache to the dependency_dir' do
|
130
|
+
expanded_local_file_location = File.expand_path(File.join('local_cache_dir', 'file____fake_uri.tgz'))
|
131
|
+
expect(FileUtils).to receive(:cp).with(expanded_local_file_location, dependency_dir)
|
132
|
+
packager.download_dependencies([dependency], local_cache_dir, dependency_dir)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
context 'with :force_download option active and a locally cached dependency' do
|
137
|
+
let(:force_download) { true }
|
138
|
+
|
139
|
+
before do
|
140
|
+
allow(File).to receive(:exist?).and_return(true)
|
141
|
+
end
|
142
|
+
|
143
|
+
it 're-downloads the dependency anyway' do
|
144
|
+
expect(packager).to receive(:download_file)
|
145
|
+
packager.download_dependencies([dependency], local_cache_dir, dependency_dir)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'translates ? and & characters in the url to underscores' do
|
150
|
+
package = Package.new
|
151
|
+
expect(package.send(:uri_cache_path, url_with_parameters)).to eq("http___some.cdn_with_parameters=true_secondParameter=present")
|
152
|
+
end
|
153
|
+
|
154
|
+
context 'url has login and password authentication credentials' do
|
155
|
+
let(:url_with_credentials) { 'http://log!i213:pas!9sword@some.cdn/with' }
|
156
|
+
|
157
|
+
it 'redacts the credentials in the resulting file path' do
|
158
|
+
package = Package.new
|
159
|
+
expect(package.send(:uri_without_credentials, url_with_credentials)).to eq("http://-redacted-:-redacted-@some.cdn/with")
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
context 'url has a login authentication credential' do
|
164
|
+
let(:url_with_credentials) { 'http://log!i213@some.cdn/with' }
|
165
|
+
|
166
|
+
it 'redacts the credential in the resulting file path' do
|
167
|
+
package = Package.new
|
168
|
+
expect(package.send(:uri_without_credentials, url_with_credentials)).to eq("http://-redacted-@some.cdn/with")
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
describe '#build_zip_file' do
|
174
|
+
before do
|
175
|
+
allow(packager).to receive(:buildpack_version).and_return('1.0.0')
|
176
|
+
allow(FileUtils).to receive(:rm_rf)
|
177
|
+
allow(packager).to receive(:zip_files)
|
178
|
+
allow(packager).to receive(:zip_file_path)
|
179
|
+
.and_return(File.join('root_dir', 'fake_language_buildpack-v1.0.0.zip'))
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'removes the file at the zip file path' do
|
183
|
+
zip_file_path = File.join('root_dir', 'fake_language_buildpack-v1.0.0.zip')
|
184
|
+
expect(FileUtils).to receive(:rm_rf).with(zip_file_path)
|
185
|
+
packager.build_zip_file('hello_dir')
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'zips up the temp directory to the zip file path without the excluded files' do
|
189
|
+
zip_file_path = File.join('root_dir', 'fake_language_buildpack-v1.0.0.zip')
|
190
|
+
expect(packager).to receive(:zip_files).with('hello_dir', zip_file_path, ['.DS_Store', '.gitignore'])
|
191
|
+
packager.build_zip_file('hello_dir')
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|