r10k 1.2.4 → 1.3.0rc1
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 +8 -8
- data/{CHANGELOG → CHANGELOG.mkd} +51 -41
- data/doc/dynamic-environments/configuration.mkd +1 -1
- data/doc/dynamic-environments/git-environments.markdown +19 -0
- data/doc/dynamic-environments/usage.mkd +6 -0
- data/lib/r10k/cli/deploy.rb +15 -0
- data/lib/r10k/cli/ext/logging.rb +0 -1
- data/lib/r10k/cli/module/deploy.rb +0 -1
- data/lib/r10k/cli/puppetfile.rb +2 -2
- data/lib/r10k/cli.rb +2 -16
- data/lib/r10k/deployment/environment.rb +9 -79
- data/lib/r10k/deployment/source.rb +15 -89
- data/lib/r10k/deployment.rb +13 -14
- data/lib/r10k/environment/base.rb +42 -0
- data/lib/r10k/environment/git.rb +79 -0
- data/lib/r10k/environment/svn.rb +73 -0
- data/lib/r10k/environment.rb +7 -0
- data/lib/r10k/execution.rb +0 -1
- data/lib/r10k/git/cache.rb +11 -5
- data/lib/r10k/git/repository.rb +1 -8
- data/lib/r10k/git/working_dir.rb +11 -34
- data/lib/r10k/git.rb +0 -1
- data/lib/r10k/instance_cache.rb +32 -0
- data/lib/r10k/keyed_factory.rb +39 -0
- data/lib/r10k/module/forge.rb +2 -3
- data/lib/r10k/module/svn.rb +0 -1
- data/lib/r10k/puppetfile.rb +0 -1
- data/lib/r10k/registry.rb +3 -31
- data/lib/r10k/source/base.rb +60 -0
- data/lib/r10k/source/git.rb +195 -0
- data/lib/r10k/source/svn.rb +140 -0
- data/lib/r10k/source.rb +39 -0
- data/lib/r10k/svn/remote.rb +48 -0
- data/lib/r10k/svn/working_dir.rb +0 -2
- data/lib/r10k/svn.rb +6 -0
- data/lib/r10k/task/deployment.rb +1 -2
- data/lib/r10k/task.rb +0 -2
- data/lib/r10k/task_runner.rb +0 -1
- data/lib/r10k/util/core_ext/hash_ext.rb +19 -0
- data/lib/r10k/util/subprocess.rb +0 -1
- data/lib/r10k/version.rb +1 -1
- data/lib/r10k.rb +1 -0
- data/spec/unit/deployment/environment_spec.rb +16 -15
- data/spec/unit/environment/git_spec.rb +81 -0
- data/spec/unit/environment/svn_spec.rb +76 -0
- data/spec/unit/git/repository_spec.rb +0 -10
- data/spec/unit/git/working_dir_spec.rb +1 -110
- data/spec/unit/{registry_spec.rb → instance_cache_spec.rb} +3 -3
- data/spec/unit/keyed_factory_spec.rb +51 -0
- data/spec/unit/source/git_spec.rb +274 -0
- data/spec/unit/source/svn_spec.rb +102 -0
- data/spec/unit/source_spec.rb +10 -0
- data/spec/unit/svn/remote_spec.rb +21 -0
- data/spec/unit/util/core_ext/hash_ext_spec.rb +63 -0
- metadata +36 -10
- data/lib/r10k/git/alternates.rb +0 -49
- data/spec/unit/git/alternates_spec.rb +0 -90
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'r10k/environment'
|
3
|
+
|
4
|
+
describe R10K::Environment::SVN do
|
5
|
+
|
6
|
+
subject do
|
7
|
+
described_class.new(
|
8
|
+
'myenv',
|
9
|
+
'/some/nonexistent/environmentdir',
|
10
|
+
'svn-dirname',
|
11
|
+
{
|
12
|
+
:remote => 'https://svn-server.site/svn-repo/trunk'
|
13
|
+
}
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:working_dir) { subject.working_dir }
|
18
|
+
|
19
|
+
describe "storing attributes" do
|
20
|
+
it "can return the environment name" do
|
21
|
+
expect(subject.name).to eq 'myenv'
|
22
|
+
end
|
23
|
+
|
24
|
+
it "can return the environment basedir" do
|
25
|
+
expect(subject.basedir).to eq '/some/nonexistent/environmentdir'
|
26
|
+
end
|
27
|
+
|
28
|
+
it "can return the environment dirname" do
|
29
|
+
expect(subject.dirname).to eq 'svn-dirname'
|
30
|
+
end
|
31
|
+
|
32
|
+
it "can return the environment remote" do
|
33
|
+
expect(subject.remote).to eq 'https://svn-server.site/svn-repo/trunk'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "synchronizing the environment" do
|
38
|
+
it "updates all modules when creating a new environment" do
|
39
|
+
allow(working_dir).to receive(:is_svn?).and_return(false)
|
40
|
+
expect(working_dir).to receive(:checkout)
|
41
|
+
expect(subject).to receive(:sync_modules)
|
42
|
+
subject.sync
|
43
|
+
end
|
44
|
+
|
45
|
+
it "does not update all modules when updating an existing environment" do
|
46
|
+
allow(working_dir).to receive(:is_svn?).and_return(true)
|
47
|
+
expect(working_dir).to receive(:update)
|
48
|
+
expect(subject).to_not receive(:sync_modules)
|
49
|
+
subject.sync
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "generating a puppetfile for the environment" do
|
54
|
+
let(:puppetfile) { subject.puppetfile }
|
55
|
+
|
56
|
+
it "creates a puppetfile at the full path to the environment" do
|
57
|
+
expect(puppetfile.basedir).to eq '/some/nonexistent/environmentdir/svn-dirname'
|
58
|
+
end
|
59
|
+
|
60
|
+
it "sets the moduledir to 'modules' relative to the environment path" do
|
61
|
+
expect(puppetfile.moduledir).to eq '/some/nonexistent/environmentdir/svn-dirname/modules'
|
62
|
+
end
|
63
|
+
|
64
|
+
it "sets the puppetfile path to 'Puppetfile' relative to the environment path" do
|
65
|
+
expect(puppetfile.puppetfile_path).to eq '/some/nonexistent/environmentdir/svn-dirname/Puppetfile'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "enumerating modules" do
|
70
|
+
it "loads the Puppetfile and returns modules in that puppetfile" do
|
71
|
+
expect(subject.puppetfile).to receive(:load)
|
72
|
+
expect(subject.puppetfile).to receive(:modules).and_return [:modules]
|
73
|
+
expect(subject.modules).to eq([:modules])
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -21,14 +21,4 @@ describe R10K::Git::Repository do
|
|
21
21
|
})
|
22
22
|
end
|
23
23
|
end
|
24
|
-
|
25
|
-
describe "tags" do
|
26
|
-
let(:tags) { %w[0.1.1 0.1.2 0.1.3 0.1.4 0.2.0 0.3.0 2.0.0] }
|
27
|
-
let(:output) { tags.map {|x| x + "\n"}.join }
|
28
|
-
|
29
|
-
it "returns a list of tags for this repo" do
|
30
|
-
expect(subject).to receive(:git).with(%w[tag -l], anything).and_return(double(:stdout => output))
|
31
|
-
expect(subject.tags).to eq(tags)
|
32
|
-
end
|
33
|
-
end
|
34
24
|
end
|
@@ -2,120 +2,11 @@ require 'spec_helper'
|
|
2
2
|
require 'r10k/git'
|
3
3
|
|
4
4
|
describe R10K::Git::WorkingDir do
|
5
|
-
include_context "fail on execution"
|
6
5
|
|
7
6
|
describe "initializing" do
|
8
7
|
it "generates a new cache for the remote" do
|
9
|
-
wd = described_class.new('master', 'git://github.com/adrienthebo/r10k-fixture-repo', '/
|
8
|
+
wd = described_class.new('master', 'git://github.com/adrienthebo/r10k-fixture-repo', '/tmp')
|
10
9
|
wd.cache.should be_kind_of R10K::Git::Cache
|
11
10
|
end
|
12
|
-
|
13
|
-
it "uses the provided ref as the dirname when no dirname is given" do
|
14
|
-
wd = described_class.new('master', 'git://github.com/adrienthebo/r10k-fixture-repo', '/some/nonexistent/dir')
|
15
|
-
expect(wd.dirname).to eq('master')
|
16
|
-
end
|
17
|
-
|
18
|
-
it "uses an explicit dirname when given" do
|
19
|
-
wd = described_class.new('master', 'git://github.com/adrienthebo/r10k-fixture-repo', '/some/nonexistent/dir', 'mydir')
|
20
|
-
expect(wd.dirname).to eq('mydir')
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
describe "synchronizing the working directory" do
|
25
|
-
subject { described_class.new('master', 'git://github.com/adrienthebo/r10k-fixture-repo', '/some/nonexistent/dir') }
|
26
|
-
it "clones the repository when the repository doesn't exist" do
|
27
|
-
expect(subject).to receive(:cloned?).and_return false
|
28
|
-
expect(subject).to receive(:clone)
|
29
|
-
subject.sync
|
30
|
-
end
|
31
|
-
|
32
|
-
it "updates the repository when the repository already exists" do
|
33
|
-
expect(subject).to receive(:cloned?).and_return true
|
34
|
-
expect(subject).to receive(:update)
|
35
|
-
subject.sync
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
describe "when cloning a new repository" do
|
40
|
-
subject { described_class.new('master', 'git://github.com/adrienthebo/r10k-fixture-repo', '/some/nonexistent/dir') }
|
41
|
-
|
42
|
-
before do
|
43
|
-
allow(subject).to receive(:cloned?).and_return false
|
44
|
-
end
|
45
|
-
|
46
|
-
it "updates the cache before cloning" do
|
47
|
-
expect(subject.cache).to receive(:sync)
|
48
|
-
allow(subject).to receive(:git)
|
49
|
-
allow(subject).to receive(:checkout)
|
50
|
-
subject.sync
|
51
|
-
end
|
52
|
-
|
53
|
-
it "clones the repository and uses the cache git dir as an object reference" do
|
54
|
-
allow(subject.cache).to receive(:sync)
|
55
|
-
expect(subject).to receive(:git).with(['clone', '--reference', subject.cache.git_dir,
|
56
|
-
'git://github.com/adrienthebo/r10k-fixture-repo',
|
57
|
-
'/some/nonexistent/dir/master'])
|
58
|
-
expect(subject).to receive(:git).with(['remote', 'add', 'cache', subject.cache.git_dir],
|
59
|
-
an_instance_of(Hash))
|
60
|
-
|
61
|
-
expect(subject).to receive(:git).with(['fetch', 'cache'], an_instance_of(Hash))
|
62
|
-
allow(subject).to receive(:checkout)
|
63
|
-
subject.sync
|
64
|
-
end
|
65
|
-
|
66
|
-
it 'checks out the specific ref after the clone' do
|
67
|
-
allow(subject.cache).to receive(:sync)
|
68
|
-
allow(subject).to receive(:git)
|
69
|
-
expect(subject).to receive(:checkout)
|
70
|
-
subject.sync
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
describe "updating an existing repository" do
|
75
|
-
subject { described_class.new('master', 'git://github.com/adrienthebo/r10k-fixture-repo', '/some/nonexistent/dir') }
|
76
|
-
|
77
|
-
before do
|
78
|
-
allow(subject).to receive(:cloned?).and_return true
|
79
|
-
end
|
80
|
-
|
81
|
-
it "updates the remotes when they are out of sync" do
|
82
|
-
allow(subject).to receive(:ref_needs_fetch?).and_return false
|
83
|
-
allow(subject).to receive(:needs_checkout?).and_return false
|
84
|
-
|
85
|
-
expect(subject).to receive(:update_remotes?).and_return true
|
86
|
-
expect(subject).to receive(:update_remotes)
|
87
|
-
|
88
|
-
subject.sync
|
89
|
-
end
|
90
|
-
|
91
|
-
it "updates the cache when the ref requires an update" do
|
92
|
-
allow(subject).to receive(:update_remotes?).and_return false
|
93
|
-
|
94
|
-
expect(subject).to receive(:ref_needs_fetch?).and_return true
|
95
|
-
expect(subject).to receive(:fetch_from_cache)
|
96
|
-
expect(subject).to receive(:checkout).with(an_instance_of(R10K::Git::Ref))
|
97
|
-
|
98
|
-
subject.sync
|
99
|
-
end
|
100
|
-
|
101
|
-
it "checks out the ref when the wrong commit is checked out" do
|
102
|
-
allow(subject).to receive(:update_remotes?).and_return false
|
103
|
-
allow(subject).to receive(:ref_needs_fetch?).and_return false
|
104
|
-
|
105
|
-
expect(subject).to receive(:needs_checkout?).and_return true
|
106
|
-
expect(subject).to receive(:checkout).with(an_instance_of(R10K::Git::Ref))
|
107
|
-
|
108
|
-
subject.sync
|
109
|
-
end
|
110
|
-
|
111
|
-
it "doesn't update the repo when everything is in sync" do
|
112
|
-
allow(subject).to receive(:update_remotes?).and_return false
|
113
|
-
allow(subject).to receive(:ref_needs_fetch?).and_return false
|
114
|
-
allow(subject).to receive(:needs_checkout?).and_return false
|
115
|
-
|
116
|
-
expect(subject).to_not receive(:checkout)
|
117
|
-
|
118
|
-
subject.sync
|
119
|
-
end
|
120
11
|
end
|
121
12
|
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
require 'r10k/
|
3
|
+
require 'r10k/instance_cache'
|
4
4
|
|
5
|
-
describe R10K::
|
5
|
+
describe R10K::InstanceCache do
|
6
6
|
|
7
|
-
describe "setting up a new
|
7
|
+
describe "setting up a new instance cache" do
|
8
8
|
let(:klass) do
|
9
9
|
dubs = double('test class')
|
10
10
|
allow(dubs).to receive(:new) { |*args| args }
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'r10k/keyed_factory'
|
3
|
+
|
4
|
+
describe R10K::KeyedFactory do
|
5
|
+
|
6
|
+
let(:registered) { Class.new }
|
7
|
+
|
8
|
+
describe "registering implementations" do
|
9
|
+
it "can register new implementations" do
|
10
|
+
subject.register(:klass, registered)
|
11
|
+
expect(subject.retrieve(:klass)).to eq registered
|
12
|
+
end
|
13
|
+
|
14
|
+
it "raises an error when a duplicate implementation is registered" do
|
15
|
+
subject.register(:klass, registered)
|
16
|
+
|
17
|
+
expect {
|
18
|
+
subject.register(:klass, registered)
|
19
|
+
}.to raise_error(R10K::KeyedFactory::DuplicateImplementationError)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "can register classes with nil as a key" do
|
23
|
+
subject.register(nil, registered)
|
24
|
+
expect(subject.retrieve(nil)).to eq registered
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "generating instances" do
|
29
|
+
before do
|
30
|
+
subject.register(:klass, registered)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "generates an instance with the associated class" do
|
34
|
+
instance = subject.generate(:klass)
|
35
|
+
expect(instance).to be_a_kind_of registered
|
36
|
+
end
|
37
|
+
|
38
|
+
it "can generate a class with nil as a key" do
|
39
|
+
other = Class.new
|
40
|
+
subject.register(nil, other)
|
41
|
+
instance = subject.generate(nil)
|
42
|
+
expect(instance).to be_a_kind_of other
|
43
|
+
end
|
44
|
+
|
45
|
+
it "raises an error if no implementation was registered with the given key" do
|
46
|
+
expect {
|
47
|
+
subject.generate(:foo)
|
48
|
+
}.to raise_error(R10K::KeyedFactory::UnknownImplementationError)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,274 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'r10k/source'
|
3
|
+
|
4
|
+
describe R10K::Source::Git do
|
5
|
+
|
6
|
+
subject do
|
7
|
+
described_class.new('mysource', '/some/nonexistent/dir',
|
8
|
+
{:remote => 'https://git-server/repo.git'})
|
9
|
+
end
|
10
|
+
|
11
|
+
it "stores the name" do
|
12
|
+
expect(subject.name).to eq 'mysource'
|
13
|
+
end
|
14
|
+
|
15
|
+
it "stores the basedir" do
|
16
|
+
expect(subject.basedir).to eq '/some/nonexistent/dir'
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "preloading" do
|
20
|
+
it "fetches the git cache" do
|
21
|
+
expect(subject.cache).to receive(:sync)
|
22
|
+
subject.preload!
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "lazily generating environments" do
|
27
|
+
it "returns an empty list of environments when the cache has not been created" do
|
28
|
+
allow(subject.cache).to receive(:cached?).and_return false
|
29
|
+
expect(subject.environments).to be_empty
|
30
|
+
end
|
31
|
+
|
32
|
+
it "generates environments when the cache is present and environments have not been loaded" do
|
33
|
+
allow(subject.cache).to receive(:cached?).and_return true
|
34
|
+
allow(subject).to receive(:generate_environments).and_return %w[hi]
|
35
|
+
expect(subject.environments).to have(1).items
|
36
|
+
end
|
37
|
+
|
38
|
+
it "doesn't recreate environments if they have already been loaded" do
|
39
|
+
allow(subject.cache).to receive(:cached?).and_return true
|
40
|
+
allow(subject).to receive(:generate_environments).once.and_return %w[hi]
|
41
|
+
expect(subject.environments).to have(1).items
|
42
|
+
expect(subject.environments).to have(1).items
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "eagerly generating environments" do
|
47
|
+
before do
|
48
|
+
allow(subject.cache).to receive(:branches).and_return %w[master]
|
49
|
+
end
|
50
|
+
|
51
|
+
let(:master_env) { subject.generate_environments.first }
|
52
|
+
|
53
|
+
it "creates an environment for each branch" do
|
54
|
+
expect(subject.generate_environments).to have(1).items
|
55
|
+
end
|
56
|
+
|
57
|
+
it "copies the source remote to the environment" do
|
58
|
+
expect(master_env.remote).to eq subject.remote
|
59
|
+
end
|
60
|
+
|
61
|
+
it "uses the branch name as the directory by default" do
|
62
|
+
expect(master_env.dirname).to eq 'master'
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe R10K::Source::Git, "handling invalid branch names" do
|
68
|
+
%w[correct_and_warn correct].each do |setting|
|
69
|
+
describe "when invalid is #{setting}" do
|
70
|
+
subject do
|
71
|
+
described_class.new('/some/nonexistent/dir', 'mysource', {
|
72
|
+
:remote => 'https://git-server/repo.git',
|
73
|
+
:invalid_branches => setting
|
74
|
+
})
|
75
|
+
end
|
76
|
+
|
77
|
+
before do
|
78
|
+
allow(subject.cache).to receive(:branches).and_return ['master', 'invalid-branch']
|
79
|
+
end
|
80
|
+
|
81
|
+
it "creates an environment for each branch" do
|
82
|
+
expect(subject.generate_environments).to have(2).items
|
83
|
+
end
|
84
|
+
|
85
|
+
it "removes invalid characters from branch names" do
|
86
|
+
invalid_env = subject.generate_environments.last
|
87
|
+
expect(invalid_env.dirname).to eq 'invalid_branch'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "when invalid is 'error'" do
|
93
|
+
subject do
|
94
|
+
described_class.new('/some/nonexistent/dir', 'mysource', {
|
95
|
+
:remote => 'https://git-server/repo.git',
|
96
|
+
:invalid_branches => 'error',
|
97
|
+
})
|
98
|
+
end
|
99
|
+
|
100
|
+
before do
|
101
|
+
allow(subject.cache).to receive(:branches).and_return ['master', 'invalid-branch']
|
102
|
+
end
|
103
|
+
|
104
|
+
it "only creates an environment for valid branches" do
|
105
|
+
expect(subject.generate_environments).to have(1).items
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# Since prefixing is an immutable property of a source, it's easier to create
|
111
|
+
# a new context and duplicate stubs in a single location rather than packing a
|
112
|
+
# single test with all the stubs that entirely recreate the source.
|
113
|
+
describe R10K::Source::Git, 'when prefixing is enabled' do
|
114
|
+
subject do
|
115
|
+
described_class.new(
|
116
|
+
'prefixed',
|
117
|
+
'/some/nonexistent/dir',
|
118
|
+
{
|
119
|
+
:prefix => true,
|
120
|
+
:remote => 'https://git-server/repo.git',
|
121
|
+
})
|
122
|
+
end
|
123
|
+
|
124
|
+
describe "generating prefixed environments" do
|
125
|
+
before do
|
126
|
+
allow(subject.cache).to receive(:cached?).and_return true
|
127
|
+
allow(subject.cache).to receive(:branches).and_return %w[master other]
|
128
|
+
end
|
129
|
+
|
130
|
+
let(:environments) { subject.environments }
|
131
|
+
|
132
|
+
it "creates an environment for each branch" do
|
133
|
+
expect(subject.environments).to have(2).items
|
134
|
+
end
|
135
|
+
|
136
|
+
it "prefixes the source name to environments when prefixing is enabled" do
|
137
|
+
expect(environments[0].dirname).to eq 'prefixed_master'
|
138
|
+
expect(environments[1].dirname).to eq 'prefixed_other'
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe R10K::Source::Git, 'registering as a source' do
|
144
|
+
it "registers with the :git key" do
|
145
|
+
expect(R10K::Source.retrieve(:git)).to eq described_class
|
146
|
+
end
|
147
|
+
|
148
|
+
it "registers with the nil key" do
|
149
|
+
expect(R10K::Source.retrieve(nil)).to eq described_class
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
describe R10K::Source::Git::BranchName do
|
154
|
+
describe "prefixing" do
|
155
|
+
it "uses the branch name as the dirname when prefixing is off" do
|
156
|
+
bn = described_class.new('mybranch', {:prefix => false, :sourcename => 'foo'})
|
157
|
+
expect(bn.dirname).to eq 'mybranch'
|
158
|
+
end
|
159
|
+
|
160
|
+
it "prepends the source name when prefixing is on" do
|
161
|
+
bn = described_class.new('mybranch', {:prefix => true, :sourcename => 'foo'})
|
162
|
+
expect(bn.dirname).to eq 'foo_mybranch'
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
describe "determining the validate behavior with :invalid" do
|
167
|
+
[
|
168
|
+
['correct_and_warn', {:validate => true, :correct => true}],
|
169
|
+
['correct', {:validate => false, :correct => true}],
|
170
|
+
['error', {:validate => true, :correct => false}],
|
171
|
+
].each do |(setting, outcome)|
|
172
|
+
it "treats #{setting} as #{outcome.inspect}" do
|
173
|
+
bn = described_class.new('mybranch', {:invalid => setting})
|
174
|
+
expect(bn.validate?).to eq outcome[:validate]
|
175
|
+
expect(bn.correct?).to eq outcome[:correct]
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
describe "determining if a branch is a valid environment name" do
|
181
|
+
invalid_cases = [
|
182
|
+
'hyphenated-branch',
|
183
|
+
'dotted.branch',
|
184
|
+
'slashed/branch',
|
185
|
+
'at@branch',
|
186
|
+
'http://branch'
|
187
|
+
]
|
188
|
+
|
189
|
+
valid_cases = [
|
190
|
+
'my_branchname',
|
191
|
+
'my_issue_346',
|
192
|
+
]
|
193
|
+
|
194
|
+
describe "and validate is false" do
|
195
|
+
invalid_cases.each do |branch|
|
196
|
+
it "is valid if the branch is #{branch}" do
|
197
|
+
bn = described_class.new(branch, {:validate => false})
|
198
|
+
expect(bn).to be_valid
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
valid_cases.each do |branch|
|
203
|
+
it "is valid if the branch is #{branch}" do
|
204
|
+
bn = described_class.new(branch, {:validate => false})
|
205
|
+
expect(bn).to be_valid
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
describe "and validate is true" do
|
211
|
+
invalid_cases.each do |branch|
|
212
|
+
it "is invalid if the branch is #{branch}" do
|
213
|
+
bn = described_class.new(branch, {:validate => true})
|
214
|
+
expect(bn).to_not be_valid
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
valid_cases.each do |branch|
|
219
|
+
it "is valid if the branch is #{branch}" do
|
220
|
+
bn = described_class.new(branch, {:validate => true})
|
221
|
+
expect(bn).to be_valid
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
describe "correcting branch names" do
|
229
|
+
invalid_cases = [
|
230
|
+
'hyphenated-branch',
|
231
|
+
'dotted.branch',
|
232
|
+
'slashed/branch',
|
233
|
+
'at@branch',
|
234
|
+
'http://branch'
|
235
|
+
]
|
236
|
+
|
237
|
+
valid_cases = [
|
238
|
+
'my_branchname',
|
239
|
+
'my_issue_346',
|
240
|
+
]
|
241
|
+
|
242
|
+
describe "and correct is false" do
|
243
|
+
invalid_cases.each do |branch|
|
244
|
+
it "doesn't modify #{branch}" do
|
245
|
+
bn = described_class.new(branch.dup, {:correct => false})
|
246
|
+
expect(bn.dirname).to eq branch
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
valid_cases.each do |branch|
|
251
|
+
it "doesn't modify #{branch}" do
|
252
|
+
bn = described_class.new(branch.dup, {:correct => false})
|
253
|
+
expect(bn.dirname).to eq branch
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
describe "and correct is true" do
|
259
|
+
invalid_cases.each do |branch|
|
260
|
+
it "replaces invalid characters in #{branch} with underscores" do
|
261
|
+
bn = described_class.new(branch.dup, {:correct => true})
|
262
|
+
expect(bn.dirname).to eq branch.gsub(/\W/, '_')
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
valid_cases.each do |branch|
|
267
|
+
it "doesn't modify #{branch}" do
|
268
|
+
bn = described_class.new(branch.dup, {:correct => true})
|
269
|
+
expect(bn.dirname).to eq branch
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'r10k/source'
|
3
|
+
|
4
|
+
describe R10K::Source::SVN do
|
5
|
+
|
6
|
+
subject do
|
7
|
+
described_class.new('mysource', '/some/nonexistent/dir',
|
8
|
+
{:remote => 'https://svn-server.site/repo'})
|
9
|
+
end
|
10
|
+
|
11
|
+
it "stores the name" do
|
12
|
+
expect(subject.name).to eq 'mysource'
|
13
|
+
end
|
14
|
+
|
15
|
+
it "stores the basedir" do
|
16
|
+
expect(subject.basedir).to eq '/some/nonexistent/dir'
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
describe "lazily generating environments" do
|
21
|
+
it "generates environments when they have not been loaded" do
|
22
|
+
expect(subject).to receive(:generate_environments).and_return %w[hi]
|
23
|
+
expect(subject.environments).to eq %w[hi]
|
24
|
+
end
|
25
|
+
|
26
|
+
it "doesn't recreate environments if they have already been loaded" do
|
27
|
+
expect(subject).to receive(:generate_environments).once.and_return %w[hi]
|
28
|
+
subject.environments
|
29
|
+
subject.environments
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "eagerly generating environments" do
|
34
|
+
before do
|
35
|
+
allow(subject.svn_remote).to receive(:branches).and_return %w[apache dns robobutler]
|
36
|
+
end
|
37
|
+
|
38
|
+
let(:environments) { subject.generate_environments }
|
39
|
+
|
40
|
+
it "creates an environment for each branch and the trunk" do
|
41
|
+
expect(environments[0].name).to eq 'production'
|
42
|
+
expect(environments[1].name).to eq 'apache'
|
43
|
+
expect(environments[2].name).to eq 'dns'
|
44
|
+
expect(environments[3].name).to eq 'robobutler'
|
45
|
+
end
|
46
|
+
|
47
|
+
it "maps trunk to production" do
|
48
|
+
expect(environments[0].remote).to eq 'https://svn-server.site/repo/trunk'
|
49
|
+
end
|
50
|
+
|
51
|
+
it "sets the remote for branch environments to subdirectories of the branches/ directory" do
|
52
|
+
expect(environments[1].remote).to eq 'https://svn-server.site/repo/branches/apache'
|
53
|
+
expect(environments[2].remote).to eq 'https://svn-server.site/repo/branches/dns'
|
54
|
+
expect(environments[3].remote).to eq 'https://svn-server.site/repo/branches/robobutler'
|
55
|
+
end
|
56
|
+
|
57
|
+
it "uses the branch name as the directory by default" do
|
58
|
+
expect(environments[0].dirname).to eq 'production'
|
59
|
+
expect(environments[1].dirname).to eq 'apache'
|
60
|
+
expect(environments[2].dirname).to eq 'dns'
|
61
|
+
expect(environments[3].dirname).to eq 'robobutler'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe R10K::Source::SVN, 'when prefixing is enabled' do
|
67
|
+
subject do
|
68
|
+
described_class.new(
|
69
|
+
'mysource',
|
70
|
+
'/some/nonexistent/dir',
|
71
|
+
{
|
72
|
+
:remote => 'https://svn-server.site/repo',
|
73
|
+
:prefix => true
|
74
|
+
}
|
75
|
+
)
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "generating prefixed environments" do
|
79
|
+
before do
|
80
|
+
allow(subject.svn_remote).to receive(:branches).and_return %w[apache dns robobutler]
|
81
|
+
end
|
82
|
+
|
83
|
+
let(:environments) { subject.generate_environments }
|
84
|
+
|
85
|
+
it "creates an environment for each branch and the trunk" do
|
86
|
+
expect(environments).to have(4).items
|
87
|
+
end
|
88
|
+
|
89
|
+
it "prefixes the source name to environments" do
|
90
|
+
expect(environments[0].dirname).to eq 'mysource_production'
|
91
|
+
expect(environments[1].dirname).to eq 'mysource_apache'
|
92
|
+
expect(environments[2].dirname).to eq 'mysource_dns'
|
93
|
+
expect(environments[3].dirname).to eq 'mysource_robobutler'
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe R10K::Source::SVN, 'registering as a source' do
|
99
|
+
it "registers with the :svn key" do
|
100
|
+
expect(R10K::Source.retrieve(:svn)).to eq described_class
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'r10k/source'
|
3
|
+
|
4
|
+
describe R10K::Source do
|
5
|
+
it "implementds methods for a keyed factory" do
|
6
|
+
expect(described_class).to respond_to :register
|
7
|
+
expect(described_class).to respond_to :retrieve
|
8
|
+
expect(described_class).to respond_to :generate
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'r10k'
|
2
|
+
require 'r10k/svn'
|
3
|
+
|
4
|
+
describe R10K::SVN::Remote do
|
5
|
+
subject { described_class.new('https://svn-server.site/repo') }
|
6
|
+
|
7
|
+
it "generates the trunk URL by appending '/trunk' to the base URL" do
|
8
|
+
expect(subject.trunk).to eq 'https://svn-server.site/repo/trunk'
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "retrieving branches" do
|
12
|
+
let(:branches) do
|
13
|
+
%[apache/\ndns/\nrobobutler/\nstaging/\n]
|
14
|
+
end
|
15
|
+
|
16
|
+
it "enumerates the /branches directory of the base URL" do
|
17
|
+
allow(subject).to receive(:svn).with(['ls', 'https://svn-server.site/repo/branches']).and_return(branches)
|
18
|
+
expect(subject.branches).to eq(%w[apache dns robobutler staging])
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|