bosh-workspace 0.9.6 → 0.9.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9da3815bae98d1612dc8108666ca2a2843d301dd
4
- data.tar.gz: e8592ea8c80c6dcab8c86fa502ed18b8ea390a7f
3
+ metadata.gz: 655a076bbeaf50fdc59837d9c103817bb85dbdf2
4
+ data.tar.gz: dfad167f3135ee92c600d175e465fa0f477cf83b
5
5
  SHA512:
6
- metadata.gz: 0262e9881e357eab8e143a268a8115236b4ae9da9bd3d46d9ca409b0aa75f843dbc1bf7285451e227cd8056f51eea5035c31e3c4a40c52c36cb8f31804393d2a
7
- data.tar.gz: a8b244be56f42052be702bb5f23d9bcc6c6963376517b0d488a1e29e14c41017b504a08c74ac412bd8fee4eedf61c8ae75802b09d38c560d3794f794b59c9d6e
6
+ metadata.gz: c7ab2bc5704fa7b391517397c05d3b222a309acd3977cb6a0bb63b76ab480b03c8520aeea1d5533c52bd37e06327a9f058c62d97de44fa4d0fd0894c072b8524
7
+ data.tar.gz: c28c6c5a73c44e44d9f440554e370d90222f3f6211ea1a662bc777d27cb7568743dde51437b40af844137cd69a13409fc9709e975e703679bd0990c5d5e27e94
data/.gitignore CHANGED
@@ -1,5 +1,6 @@
1
1
  *.gem
2
2
  *.rbc
3
+ *~
3
4
  .bundle
4
5
  .config
5
6
  .yardoc
@@ -18,3 +19,5 @@ tmp
18
19
  *.generated_manifests
19
20
  *.DS_Store
20
21
  /spec/assets/manifests-repo/.releases/*
22
+ .idea
23
+
@@ -1 +1 @@
1
- 2.1.4
1
+ 2.2.3
@@ -3,6 +3,8 @@ cache: bundler
3
3
  sudo: false
4
4
  rvm:
5
5
  - 2.0
6
+ - 2.1
7
+ - 2.2
6
8
  before_script:
7
9
  - wget https://github.com/cloudfoundry-incubator/spiff/releases/download/v1.0.7/spiff_linux_amd64.zip -O /tmp/spiff.zip
8
10
  - unzip /tmp/spiff.zip && mkdir bin && mv spiff bin && chmod +x bin/spiff
data/Gemfile CHANGED
@@ -6,6 +6,7 @@ gemspec
6
6
  group :development do
7
7
  gem "guard-rspec"
8
8
  gem "rubocop"
9
+ gem "pry"
9
10
  end
10
11
 
11
12
  group :test do
data/Guardfile CHANGED
@@ -1,4 +1,6 @@
1
- guard :rspec, cmd: 'rspec', notification: false do
1
+ # workaround for https://github.com/guard/guard-rspec/issues/348
2
+ rspec_results = File.expand_path('rspec_guard_result')
3
+ guard :rspec, cmd: 'bundle exec rspec --fail-fast', notification: false, results_file: rspec_results do
2
4
  watch(%r{^spec/(.+_spec)\.rb$})
3
5
  watch(%r{^lib/bosh/cli/commands/(.+)\.rb$}) { |m| "spec/commands/#{m[1]}_spec.rb" }
4
6
  watch(%r{^lib/bosh/workspace/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
data/README.md CHANGED
@@ -125,6 +125,12 @@ Example `.credentials.yml` file:
125
125
 
126
126
  ## Install Notes
127
127
 
128
+ ### OSX
129
+ cmake isneeded and libssh2 is optionally (only needed when using cloning over ssh)
130
+ ```
131
+ brew install cmake libssh2
132
+ ```
133
+
128
134
  ### Ubuntu
129
135
  cmake and libcurl4-openssl-dev is needed for rugged install
130
136
 
@@ -25,7 +25,7 @@ Gem::Specification.new do |spec|
25
25
  spec.add_runtime_dependency "semi_semantic", "~> 1.1.0"
26
26
  spec.add_runtime_dependency "membrane", "~> 1.1.0"
27
27
  spec.add_runtime_dependency "hashdiff", "~> 0.2.1"
28
- spec.add_runtime_dependency "rugged", "~> 0.23.0b3"
28
+ spec.add_runtime_dependency "rugged", "~> 0.24.0b11"
29
29
 
30
30
  spec.add_development_dependency "bundler", "~> 1.6"
31
31
  spec.add_development_dependency "rspec", "~> 3.3.0"
@@ -84,7 +84,7 @@ module Bosh::Cli::Command
84
84
  unless stemcell.downloaded?
85
85
  err "Stemcell not available offline: #{stemcell.file_name}" if offline?
86
86
  say "Downloading '#{stemcell.name_version.make_green}'"
87
- stemcell_download(stemcell.file_name)
87
+ stemcell_download(stemcell)
88
88
  end
89
89
  say "Uploading '#{stemcell.name_version.make_green}'"
90
90
  stemcell_upload(stemcell.file)
@@ -56,7 +56,7 @@ module Bosh::Workspace
56
56
  when %i(ssh_key)
57
57
  key_file = temp_key_file(credentials[:private_key])
58
58
  Rugged::Credentials::SshKey.new username: user, privatekey: key_file
59
- when %i(plain_text)
59
+ when %i(plaintext)
60
60
  Rugged::Credentials::UserPassword.new(credentials)
61
61
  end
62
62
  end
@@ -1,12 +1,15 @@
1
+ require 'httpclient'
2
+ require 'cli/download_with_progress'
3
+
1
4
  module Bosh::Workspace
2
5
  module StemcellHelper
3
6
  include ProjectDeploymentHelper
4
7
 
5
- def stemcell_download(stemcell_name)
8
+ def stemcell_download(stemcell)
6
9
  Dir.chdir(stemcells_dir) do
7
- say "Downloading stemcell '#{stemcell_name}'"
10
+ say "Downloading stemcell '#{stemcell.name}' version '#{stemcell.version}'"
8
11
  nl
9
- stemcell_cmd.download_public(stemcell_name)
12
+ download_stemcell_from_bosh_io(stemcell)
10
13
  end
11
14
  end
12
15
 
@@ -36,10 +39,38 @@ module Bosh::Workspace
36
39
  end
37
40
  end
38
41
 
42
+ def download_stemcell_from_bosh_io(stemcell)
43
+
44
+ url = "https://bosh.io/d/stemcells/#{stemcell.name}?v=#{stemcell.version}"
45
+
46
+ response = HTTPClient.new.head(url)
47
+
48
+ if response.status == 302
49
+ location = response.header['location'][0]
50
+ response2 = HTTPClient.new.head(location)
51
+
52
+ if response2.status == 200
53
+ size = response2.header['Content-Length'][0]
54
+ else
55
+ say("HTTP #{response2.status} : #{location}".make_red)
56
+ say(" - redirected from: : #{url}".make_red)
57
+ return
58
+ end
59
+ else
60
+ say("HTTP #{response.status} : #{url} (expecting 302 - redirect)".make_red)
61
+ return
62
+ end
63
+
64
+ download_with_progress = Bosh::Cli::DownloadWithProgress.new(location, size.to_i)
65
+ download_with_progress.perform
66
+ end
67
+
39
68
  private
40
69
 
41
70
  def stemcell_cmd
42
71
  @stemcell_cmd ||= Bosh::Cli::Command::Stemcell.new
43
72
  end
73
+
44
74
  end
75
+
45
76
  end
@@ -1,6 +1,7 @@
1
1
  module Bosh::Workspace
2
2
  class ProjectDeployment
3
3
  include Bosh::Cli::Validation
4
+ include Bosh::Exec
4
5
  attr_writer :director_uuid, :stub
5
6
  attr_reader :file
6
7
 
@@ -35,7 +36,7 @@ module Bosh::Workspace
35
36
 
36
37
  def manifest
37
38
  return @manifest unless @manifest.nil?
38
- @manifest = Psych.load(ERB.new(File.read(file)).result)
39
+ @manifest = YAML.load(ERB.new(IO.read(file)).result)
39
40
  validate_stub! unless stub.empty?
40
41
  @manifest = recursive_merge(@manifest, stub) unless stub.empty?
41
42
  @manifest
@@ -43,8 +44,7 @@ module Bosh::Workspace
43
44
 
44
45
  def stub
45
46
  return @stub unless @stub.nil?
46
- stub_file = File.expand_path(File.join(file_dirname, "../stubs", file_basename))
47
- @stub = File.exist?(stub_file) ? Psych.load(File.read(stub_file)) : {}
47
+ @stub = stub_file ? load_stub : {}
48
48
  end
49
49
 
50
50
  %w[name templates releases stemcells meta domain_name].each do |var|
@@ -55,14 +55,46 @@ module Bosh::Workspace
55
55
 
56
56
  private
57
57
 
58
+ def stubs_dir
59
+ File.expand_path(File.join(file_dirname, "../stubs"))
60
+ end
61
+
62
+ def stub_file
63
+ Dir[File.join(stubs_dir, "#{file_basename('.*')}*")].first
64
+ end
65
+
66
+ def executable_stub?
67
+ File.executable?(stub_file)
68
+ end
69
+
70
+ def load_stub
71
+ begin
72
+ YAML.load(executable_stub? ? execute_stub! : IO.read(stub_file))
73
+ rescue Psych::SyntaxError => e
74
+ say "Error loading stub file for deployment #{file} due to invalid YAML"
75
+ err "error: #{e.message}"
76
+ end
77
+ end
78
+
79
+ def execute_stub!
80
+ sh(stub_file, yield: :on_false) do |result|
81
+ execute_stub_failed!(result.command, result.output) if result.failed?
82
+ end.output
83
+ end
84
+
85
+ def execute_stub_failed!(stub, output)
86
+ say("An error occured while executing stub file: #{stub}")
87
+ err("error: '#{output}'")
88
+ end
89
+
58
90
  def validate_stub!
59
91
  return unless stub.keys.any? { |k| !STUB_WHITELIST.include?(k) }
60
92
  offending_keys = stub.keys - STUB_WHITELIST
61
93
  err "Key: '#{offending_keys.first}' not allowed in stub file"
62
94
  end
63
95
 
64
- def file_basename
65
- File.basename(@file)
96
+ def file_basename(filter = '')
97
+ File.basename(@file, filter)
66
98
  end
67
99
 
68
100
  def file_dirname
@@ -76,11 +76,11 @@ module Bosh::Workspace
76
76
  repo_exists? ? open_repo : init_repo
77
77
  end
78
78
 
79
- def fetch_repo(repo = repo)
79
+ def fetch_repo(_repo = repo)
80
80
  return if offline?
81
- repo.fetch('origin', REFSPEC, credentials: @credentials_callback)
82
- commit = repo.references['refs/remotes/origin/HEAD'].resolve.target_id
83
- update_repo_with_ref(repo, commit)
81
+ _repo.fetch('origin', REFSPEC, credentials: @credentials_callback)
82
+ commit = _repo.references['refs/remotes/origin/HEAD'].resolve.target_id
83
+ update_repo_with_ref(_repo, commit)
84
84
  end
85
85
 
86
86
  def repo_exists?(dir = @repo_dir)
@@ -17,6 +17,7 @@ module Bosh::Workspace
17
17
  return if object.is_a? Integer
18
18
  return if object.is_a? Float
19
19
  return if object == "latest"
20
+ return if object.to_s =~ /^\d+$/
20
21
  return if object.to_s =~ /^\d+(\.\d+){1,2}$/
21
22
  raise Membrane::SchemaValidationError.new(
22
23
  "Should match: latest, version.patch.micropatch, version.patch or version. Given: #{object}")
@@ -1,5 +1,5 @@
1
1
  module Bosh
2
2
  module Manifests
3
- VERSION = "0.9.6"
3
+ VERSION = "0.9.7"
4
4
  end
5
5
  end
@@ -0,0 +1,4 @@
1
+ name: foobar
2
+ templates:
3
+ - foo/bar.yml
4
+ meta: {}
@@ -0,0 +1,5 @@
1
+ #!/bin/bash
2
+
3
+ echo 'director_uuid: bar-uuid'
4
+ echo 'name: foobar'
5
+ echo "meta: { 'foo': 'foobar', 'bar': 'foo' }"
@@ -139,7 +139,7 @@ describe Bosh::Cli::Command::Prepare do
139
139
  let(:stemcell_downloaded) { false }
140
140
 
141
141
  it "downloads and uploads the stemcell" do
142
- expect(command).to receive(:stemcell_download).with(stemcell.file_name)
142
+ expect(command).to receive(:stemcell_download).with(stemcell)
143
143
  expect(command).to receive(:stemcell_upload).with(stemcell.file)
144
144
  command.prepare
145
145
  end
@@ -8,7 +8,7 @@ module Bosh::Workspace
8
8
  let(:url) { 'http://foo.com/bar.git' }
9
9
  let(:user) { nil }
10
10
  let(:result) { nil }
11
- let(:allowed_types) { [:plain_text] }
11
+ let(:allowed_types) { [:plaintext] }
12
12
  let(:credentials) do
13
13
  instance_double "Bosh::Workspace::Credentials",
14
14
  :valid? => valid, url_protocols: url_protocols
@@ -38,7 +38,7 @@ module Bosh::Workspace
38
38
 
39
39
  context "with username/password" do
40
40
  let(:result) { { username: user, password: 'barpw' } }
41
- let(:allowed_types) { [:plain_text] }
41
+ let(:allowed_types) { [:plaintext] }
42
42
 
43
43
  it 'returns Rugged user password credentials' do
44
44
  expect(Rugged::Credentials::UserPassword).to receive(:new) do |args|
@@ -23,12 +23,13 @@ describe Bosh::Workspace::StemcellHelper do
23
23
  end
24
24
 
25
25
  describe "#stemcell_download" do
26
- let(:name) { "foo" }
27
- subject { stemcell_helper.stemcell_download(name) }
26
+ let(:stemcell) { instance_double("Bosh::Workspace::Stemcell", :name => "foo", :version => "1") }
27
+
28
+ subject { stemcell_helper.stemcell_download(stemcell) }
28
29
 
29
30
  it "downloads stemcell" do
30
31
  expect(Dir).to receive(:chdir).and_yield
31
- expect(stemcell_cmd).to receive(:download_public).with(name)
32
+ expect(stemcell_helper).to receive(:download_stemcell_from_bosh_io).with(stemcell)
32
33
  subject
33
34
  end
34
35
  end
@@ -1,11 +1,10 @@
1
1
  module Bosh::Workspace
2
2
  describe ProjectDeployment do
3
3
  subject { Bosh::Workspace::ProjectDeployment.new manifest_file }
4
- let(:manifest_content) { ruby_code + manifest.to_yaml }
4
+ let(:manifest_content) { manifest.to_yaml }
5
5
  let(:manifest_file) { get_tmp_file_path(manifest_content, file_name) }
6
6
  let(:file_name) { "foo.yml" }
7
7
  let(:manifest) { :manifest }
8
- let(:ruby_code) { "<% ruby_var=42 %>" }
9
8
 
10
9
  describe ".new" do
11
10
  context "deployment file does not exist" do
@@ -17,13 +16,19 @@ module Bosh::Workspace
17
16
  end
18
17
 
19
18
  describe '#manifest' do
20
- let(:stub_file) { /stubs\/#{file_name}/ }
21
- before do
22
- allow(File).to receive(:exist?).with(manifest_file).and_return(true)
23
- allow(File).to receive(:read).with(manifest_file).and_return(manifest_content)
24
- end
25
-
26
19
  context 'with stub file' do
20
+ let!(:stub_file) do
21
+ path = "../../stubs/#{stub_filename}"
22
+ File.expand_path(path, manifest_file).tap do |file|
23
+ FileUtils.mkdir_p File.dirname(file)
24
+ IO.write(file, stub_content)
25
+ end
26
+ end
27
+
28
+ after { FileUtils.rm(stub_file) }
29
+
30
+ let(:stub_filename) { File.basename(manifest_file) }
31
+
27
32
  let(:manifest) { { 'director_uuid' => 'DIRECTOR_UUID' } }
28
33
  let(:stub_content) do
29
34
  {
@@ -33,11 +38,6 @@ module Bosh::Workspace
33
38
  }.to_yaml
34
39
  end
35
40
 
36
- before do
37
- allow(File).to receive(:exist?).with(stub_file).and_return(true)
38
- allow(File).to receive(:read).with(stub_file).and_return(stub_content)
39
- end
40
-
41
41
  it 'merges stub with manifest' do
42
42
  expect(subject.manifest['director_uuid']).to eq('foo-uuid')
43
43
  end
@@ -51,13 +51,53 @@ module Bosh::Workspace
51
51
  end
52
52
  end
53
53
 
54
- context 'without stub file' do
55
- let(:manifest) { { 'director_uuid' => 'litmus' } }
54
+ context 'with executable stub file' do
55
+ let(:stub_file) { asset_dir("manifests-repo/stubs/foobar.sh") }
56
+ let(:manifest_file) { asset_dir("manifests-repo/deployments/foobar.yml") }
57
+ let(:manifest) do
58
+ {
59
+ 'name' => 'NAME',
60
+ 'director_uuid' => 'DIRECTOR_UUID',
61
+ 'meta' => { 'foo' => 'bar', 'bar' => 'foo' }
62
+ }
63
+ end
56
64
 
57
- before do
58
- allow(File).to receive(:exist?).with(stub_file).and_return(false)
65
+ it 'merges stub output with manifest' do
66
+ expect(subject.manifest['name']).to eq('foobar')
67
+ expect(subject.manifest['director_uuid']).to eq('bar-uuid')
68
+ expect(subject.manifest['meta']).to eq({ 'foo' => 'foobar', 'bar' => 'foo' })
59
69
  end
60
70
 
71
+
72
+ context 'which are invalid' do
73
+ let(:result) { Bosh::Exec::Result.new('foo.sh', 'foo: error:', exit_code) }
74
+
75
+ before do
76
+ expect(subject).to receive(:sh).and_yield(result).and_return(result)
77
+ end
78
+
79
+ context 'non valid yaml returned' do
80
+ let(:exit_code) { 0 }
81
+
82
+ it 'raises an error' do
83
+ expect{ subject.manifest }.to raise_error /mapping values are not allowed/
84
+ end
85
+ end
86
+
87
+ context 'failure during execution' do
88
+ let(:exit_code) { 1 }
89
+
90
+ it 'raises an error' do
91
+ expect{ subject.manifest }.to raise_error /foo: error/
92
+ end
93
+ end
94
+ end
95
+ end
96
+
97
+ context 'without stub file' do
98
+ let(:file_name) { 'bar.yml' }
99
+ let(:manifest) { { 'director_uuid' => 'litmus' } }
100
+
61
101
  it 'reads manifest without errors' do
62
102
  expect(subject.manifest['director_uuid']).to eq('litmus')
63
103
  end
@@ -68,7 +108,7 @@ module Bosh::Workspace
68
108
  context "valid" do
69
109
  it "validates" do
70
110
  allow_any_instance_of(Schemas::ProjectDeployment)
71
- .to receive(:validate).with(manifest)
111
+ .to receive(:validate).with(manifest)
72
112
  expect(subject).to be_valid
73
113
  end
74
114
  end
@@ -76,8 +116,8 @@ module Bosh::Workspace
76
116
  context "invalid" do
77
117
  it "has errors" do
78
118
  allow_any_instance_of(Schemas::ProjectDeployment)
79
- .to receive(:validate).with(manifest)
80
- .and_raise(Membrane::SchemaValidationError.new("foo"))
119
+ .to receive(:validate).with(manifest)
120
+ .and_raise(Membrane::SchemaValidationError.new("foo"))
81
121
  expect(subject).to_not be_valid
82
122
  expect(subject.errors).to include "foo"
83
123
  end
@@ -91,18 +131,18 @@ module Bosh::Workspace
91
131
 
92
132
  describe "attr readers" do
93
133
  let(:manifest) { {
94
- "name" => :name,
95
- "director_uuid" => :director_uuid,
96
- "templates" => :templates,
97
- "releases" => :releases,
98
- "stemcells" => :stemcells,
99
- "meta" => :meta,
100
- "domain_name" => :domain_name,
101
- } }
134
+ "name" => :name,
135
+ "director_uuid" => :director_uuid,
136
+ "templates" => :templates,
137
+ "releases" => :releases,
138
+ "stemcells" => :stemcells,
139
+ "meta" => :meta,
140
+ "domain_name" => :domain_name,
141
+ } }
102
142
 
103
143
  let(:director_uuid) { uuid }
104
144
  %w(name director_uuid templates releases stemcells meta domain_name)
105
- .each do |attr|
145
+ .each do |attr|
106
146
  its(attr.to_sym) { should eq attr.to_sym }
107
147
  end
108
148
  end
@@ -38,6 +38,11 @@ module Bosh::Workspace::Schemas
38
38
  it { expect { subject }.to_not raise_error }
39
39
  end
40
40
 
41
+ context "version string with all digetes without dots" do
42
+ let(:stemcells) { stemcell["version"] = '0000'; [stemcell] }
43
+ it { expect { subject }.to_not raise_error }
44
+ end
45
+
41
46
  context "invalid version" do
42
47
  let(:stemcells) { stemcell["version"] = "foo"; [stemcell] }
43
48
  it { expect { subject }.to raise_error(/version.*should match/i) }
@@ -15,6 +15,8 @@ require "rspec/its"
15
15
  require "tmpdir"
16
16
  require "archive/zip"
17
17
 
18
+ require "pry"
19
+
18
20
  # bosh_cli
19
21
  require "cli"
20
22
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bosh-workspace
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.6
4
+ version: 0.9.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ruben Koster
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-23 00:00:00.000000000 Z
11
+ date: 2015-12-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bosh_cli
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 0.23.0b3
89
+ version: 0.24.0b11
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: 0.23.0b3
96
+ version: 0.24.0b11
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: bundler
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -231,7 +231,9 @@ files:
231
231
  - spec/assets/manifests-repo/.manifests/foo.yml
232
232
  - spec/assets/manifests-repo/deployments/bar.yml
233
233
  - spec/assets/manifests-repo/deployments/foo.yml
234
+ - spec/assets/manifests-repo/deployments/foobar.yml
234
235
  - spec/assets/manifests-repo/stubs/foo.yml
236
+ - spec/assets/manifests-repo/stubs/foobar.sh
235
237
  - spec/assets/manifests-repo/templates/foo/bar.yml
236
238
  - spec/assets/submodule-boshrelease-repo.zip
237
239
  - spec/assets/supermodule-boshrelease-repo.zip
@@ -286,7 +288,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
286
288
  version: '0'
287
289
  requirements: []
288
290
  rubyforge_project:
289
- rubygems_version: 2.4.6
291
+ rubygems_version: 2.4.5.1
290
292
  signing_key:
291
293
  specification_version: 4
292
294
  summary: Manage your bosh workspace
@@ -308,7 +310,9 @@ test_files:
308
310
  - spec/assets/manifests-repo/.manifests/foo.yml
309
311
  - spec/assets/manifests-repo/deployments/bar.yml
310
312
  - spec/assets/manifests-repo/deployments/foo.yml
313
+ - spec/assets/manifests-repo/deployments/foobar.yml
311
314
  - spec/assets/manifests-repo/stubs/foo.yml
315
+ - spec/assets/manifests-repo/stubs/foobar.sh
312
316
  - spec/assets/manifests-repo/templates/foo/bar.yml
313
317
  - spec/assets/submodule-boshrelease-repo.zip
314
318
  - spec/assets/supermodule-boshrelease-repo.zip