r10k 3.5.2 → 3.6.0

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
  SHA256:
3
- metadata.gz: c2fbe395273c7e4fa08a3cb6fa552c05d4745c6c3f8add19b7fe7bb63c03b2d4
4
- data.tar.gz: 7e59bb47f25fcac554075de51a4b37d55de612cdb43079a1212adf4d3c84707a
3
+ metadata.gz: 4e54158e0a651c799246229971ba62ad36bd40a670ca84e61479aa5280306c8a
4
+ data.tar.gz: 153cc105ce9276d79e2501dc99accb398bba8fec423fbf0726a1b183993a2748
5
5
  SHA512:
6
- metadata.gz: 7925d5b8d45bcb502ce11a4d190048f3bcf03310ee42a9128a5ff66e72425a48269a35fba1177905a895175a096b45441fb2f0090e174ecd2bbd86217d5ed641
7
- data.tar.gz: 796889d0936244967388973e0903e9011cc11b11a8fcb6b91bc083f13e8fb4e1400b96f79337f778576d04c917e3cc170b1094e124f3a05a8174b1de82d28824
6
+ metadata.gz: 264ea2591c062d460edab02b8edf7a59c9ebc08ebea27ee2b103e43bdf71c936b797094014d66b776573196d4a9e86dfc9f0fd345626f27d7e25c8170ebaa83a
7
+ data.tar.gz: 224e40f3f13466ab2ea3296bc3741b10d591ea65c97ba60b3dd81078f70149770c07c46ac1464a44fd59af0d20dbc8bbf1a5e3990e5d7921cc05403772d99640
@@ -1 +1,4 @@
1
- Please add all notable changes to the "Unreleased" section of the CHANGELOG.
1
+ Please add all notable changes to the "Unreleased" section of the CHANGELOG in the format:
2
+ ```
3
+ - (JIRA ticket) Summary of changes. [Issue or PR #](link to issue or PR)
4
+ ```
@@ -2,7 +2,15 @@ CHANGELOG
2
2
  =========
3
3
 
4
4
  Unreleased
5
- ----
5
+ ----------
6
+
7
+ 3.6.0
8
+ -----
9
+
10
+ - Add filter_command configuration option for git repositories. (Thanks to [mhumpula](https://github.com/mhumpula) for the feature.) [#823](https://github.com/puppetlabs/r10k/pull/823)
11
+ - Increase default pool_size to 4, allowing modules to be downloaded on 4 threads concurrently. [#1038](https://github.com/puppetlabs/r10k/issues/1038)
12
+ - Ensure that modules that share a cachedir download serially, to avoid cache corruption. [#1058](https://github.com/puppetlabs/r10k/issues/1058)
13
+ - Don't purge root when using `puppetfile install`. [#1084](https://github.com/puppetlabs/r10k/issues/1084)
6
14
 
7
15
  3.5.2
8
16
  -----
@@ -175,6 +183,11 @@ Ruby >= 2.3 official and documented.
175
183
  - Unable to parse Puppetfile
176
184
  - Various perfomance improvements
177
185
 
186
+ 2.6.9
187
+ ----
188
+
189
+ - Don't purge root when using `puppetfile install`. [#1084](https://github.com/puppetlabs/r10k/issues/1084)
190
+
178
191
  2.6.8
179
192
  ----
180
193
 
data/README.mkd CHANGED
@@ -98,6 +98,14 @@ When localizing the strings found in R10k, follow the prescribed
98
98
  The workflow describes the rake tasks provided to generate the .po files for
99
99
  each locale.
100
100
 
101
+ Releasing
102
+ ---------
103
+ To release a new version of the r10k gem, ensure the [changelog](CHANGELOG.mkd) is up to date and open a pull request updating the [version file](lib/r10k/version.rb). When the PR is merged, a new release of the gem will be triggered.
104
+
105
+ By default, a patch (Z) release will be triggered. To release a new major (X) or minor (Y) version, include `#major` or `#minor` (respectively) in your commit message to trigger the appropriate release.
106
+
107
+ NOTE: This currently only works for the default branch. If you would like to release from a different branch, please contact the [CODEOWNERS](CODEOWNERS).
108
+
101
109
  Getting help
102
110
  ------------
103
111
 
@@ -113,6 +121,7 @@ Please see the CHANGELOG for a listing of the (very awesome) contributors.
113
121
 
114
122
  ## Maintenance
115
123
 
116
- See [MAINTAINERS](MAINTAINERS) (json file)
124
+ See [CODEOWNERS](CODEOWNERS) for active repo maintainers.
125
+
126
+ Open [issues](https://github.com/puppetlabs/r10k/issues) directly in the r10k repo.
117
127
 
118
- Tickets: File at https://tickets.puppet.com/browse/RK
@@ -19,6 +19,7 @@ variables:
19
19
  CONTAINER_BUILD_PATH: .
20
20
  LINT_IGNORES:
21
21
  DOCKER_BUILDKIT: 1
22
+ BUILD_OPTIONS: --build-arg alpine_version=3.9
22
23
 
23
24
  workspace:
24
25
  clean: resources
@@ -53,7 +54,7 @@ steps:
53
54
 
54
55
  - powershell: |
55
56
  . "$(bundle show pupperware)/ci/build.ps1"
56
- Build-Container -Name $ENV:CONTAINER_NAME -Namespace $ENV:NAMESPACE -PathOrUri $ENV:CONTAINER_BUILD_PATH
57
+ Build-Container -Name $ENV:CONTAINER_NAME -Namespace $ENV:NAMESPACE -PathOrUri $ENV:CONTAINER_BUILD_PATH -AdditionalOptions ($ENV:BUILD_OPTIONS -split ' ')
57
58
  displayName: Build $(CONTAINER_NAME) Container
58
59
  timeoutInMinutes: 5
59
60
  name: build_container
@@ -76,9 +76,9 @@ The proxy server being used will be logged at the "debug" level when r10k runs.
76
76
  ### pool_size
77
77
 
78
78
  The pool_size setting is a number to determine how many threads should be spawn
79
- while updating modules. The default value is 1, which means the default behaviour
80
- is to update modules in a serial manner. Increasing this number should bring
81
- some performance gains.
79
+ while updating modules. The default value is 4, which means modules will be updated
80
+ in parallel. If this causes issues, change this setting to 1 to cause modules to be
81
+ updated serially.
82
82
 
83
83
  ### git
84
84
 
@@ -411,6 +411,29 @@ sources:
411
411
  - 'dev'
412
412
  ```
413
413
 
414
+ ### filter_command
415
+
416
+ You can filter out any branch based on the result of the command specified as
417
+ 'filter_command'. Currently it only works with git repository. Non zero return
418
+ status of the command results in a branch beeing removed. The command is passed
419
+ additional environment variables
420
+
421
+ * GIT_DIR – path to the cached git repository
422
+ * R10K_BRANCH – branch which is being filtered
423
+ * R10K_NAME – source name from r10k configuration
424
+
425
+ This can be used for example for filtering out the branches with invalid gpg signature of their latest commit
426
+
427
+ ```yaml
428
+ ---
429
+ sources:
430
+ mysource:
431
+ basedir: '/etc/puppet/environments'
432
+ filter_command: 'git verify-commit $R10K_BRANCH 2> /dev/null'
433
+ ```
434
+
435
+ Beware that if the production branch of manifests is filtered out, you will end up with empty environment.
436
+
414
437
  Examples
415
438
  --------
416
439
 
@@ -6,6 +6,7 @@ build_date := $(shell date -u +%FT%T)
6
6
  hadolint_available := $(shell hadolint --help > /dev/null 2>&1; echo $$?)
7
7
  hadolint_command := hadolint
8
8
  hadolint_container := hadolint/hadolint:latest
9
+ alpine_version := 3.9
9
10
  export BUNDLE_PATH = $(PWD)/.bundle/gems
10
11
  export BUNDLE_BIN = $(PWD)/.bundle/bin
11
12
  export GEMFILE = $(PWD)/Gemfile
@@ -48,9 +49,10 @@ else
48
49
  endif
49
50
 
50
51
  build: prep
52
+ docker pull alpine:$(alpine_version)
51
53
  docker build \
52
54
  ${DOCKER_BUILD_FLAGS} \
53
- --pull \
55
+ --build-arg alpine_version=$(alpine_version) \
54
56
  --build-arg vcs_ref=$(vcs_ref) \
55
57
  --build-arg build_date=$(build_date) \
56
58
  --build-arg version=$(VERSION) \
@@ -1,4 +1,5 @@
1
- FROM alpine:3.9 as build
1
+ ARG alpine_version=3.9
2
+ FROM alpine:${alpine_version} as build
2
3
 
3
4
  # hadolint ignore=DL3018
4
5
  RUN apk add --no-cache ruby git && \
@@ -8,7 +9,7 @@ COPY . /workspace
8
9
  RUN gem build r10k.gemspec && \
9
10
  mv r10k*.gem r10k.gem
10
11
 
11
- FROM alpine:3.9
12
+ FROM alpine:${alpine_version}
12
13
 
13
14
  ARG vcs_ref
14
15
  ARG build_date
@@ -1,4 +1,5 @@
1
- FROM alpine:3.9
1
+ ARG alpine_version=3.9
2
+ FROM alpine:${alpine_version}
2
3
 
3
4
  ARG vcs_ref
4
5
  ARG build_date
@@ -0,0 +1,68 @@
1
+ require 'git_utils'
2
+ require 'r10k_utils'
3
+ require 'master_manipulator'
4
+ test_name 'Verify the same remote can be used in more than one object'
5
+
6
+ env_path = on(master, puppet('config print environmentpath')).stdout.rstrip
7
+ r10k_fqp = get_r10k_fqp(master)
8
+ git_environments_path = '/root/environments'
9
+ git_repo_path = '/git_repos'
10
+ git_repo_name = 'environments'
11
+ git_control_remote = File.join(git_repo_path, "#{git_repo_name}.git")
12
+ code_dir = "#{env_path}/production"
13
+
14
+ last_commit = git_last_commit(master, git_environments_path)
15
+ git_provider = ENV['GIT_PROVIDER']
16
+ r10k_config_path = get_r10k_config_file_path(master)
17
+ r10k_config_bak_path = "#{r10k_config_path}.bak"
18
+ #In-line files
19
+ r10k_conf = <<-CONF
20
+ cachedir: '/var/cache/r10k'
21
+ git:
22
+ provider: '#{git_provider}'
23
+ sources:
24
+ control:
25
+ basedir: "#{env_path}"
26
+ remote: "#{git_control_remote}"
27
+ CONF
28
+
29
+ # Install the same module in two different places
30
+ puppetfile = <<-EOS
31
+ mod 'prod_apache',
32
+ :git => 'git://github.com/puppetlabs/puppetlabs-apache.git',
33
+ :branch => 'master'
34
+
35
+ mod 'test_apache',
36
+ :git => 'git://github.com/puppetlabs/puppetlabs-apache.git',
37
+ :branch => 'master'
38
+ EOS
39
+
40
+ teardown do
41
+ step 'Restore Original "r10k" Config'
42
+ on(master, "mv #{r10k_config_bak_path} #{r10k_config_path}")
43
+
44
+ clean_up_r10k(master, last_commit, git_environments_path)
45
+ end
46
+
47
+ step 'Stub the forge'
48
+ stub_forge_on(master)
49
+
50
+ step 'Backup Current "r10k" Config'
51
+ on(master, "mv #{r10k_config_path} #{r10k_config_bak_path}")
52
+
53
+ step 'Update the "r10k" Config'
54
+ create_remote_file(master, r10k_config_path, r10k_conf)
55
+
56
+ step 'Ask r10k to deploy'
57
+ on(master, "#{r10k_fqp} deploy environment -p")
58
+
59
+ step 'Add puppetfile with repeated remote'
60
+ create_remote_file(master, "#{git_environments_path}/Puppetfile", puppetfile)
61
+ git_add_commit_push(master, 'production', 'add Puppetfile', git_environments_path)
62
+
63
+ step 'Deploy r10k'
64
+ on(master, "#{r10k_fqp} deploy environment -p")
65
+
66
+ step 'Verify module was installed in both places'
67
+ on(master, "test -d #{code_dir}/modules/prod_apache")
68
+ on(master, "test -d #{code_dir}/modules/test_apache")
@@ -99,10 +99,8 @@ class R10K::Git::Cache
99
99
 
100
100
  alias cached? exist?
101
101
 
102
- private
103
-
104
102
  # Reformat the remote name into something that can be used as a directory
105
103
  def sanitized_dirname
106
- @remote.gsub(/[^@\w\.-]/, '-')
104
+ @sanitized_dirname ||= @remote.gsub(/[^@\w\.-]/, '-')
107
105
  end
108
106
  end
@@ -12,6 +12,10 @@ class R10K::Git::StatefulRepository
12
12
  # @api private
13
13
  attr_reader :repo
14
14
 
15
+ # @!attribute [r] cache
16
+ # @api private
17
+ attr_reader :cache
18
+
15
19
  extend Forwardable
16
20
  def_delegators :@repo, :head, :tracked_paths
17
21
 
@@ -99,6 +99,14 @@ class R10K::Module::Base
99
99
  raise NotImplementedError
100
100
  end
101
101
 
102
+ # Return the module's cachedir. Subclasses that implement a cache
103
+ # will override this to return a real directory location.
104
+ #
105
+ # @return [String, :none]
106
+ def cachedir
107
+ :none
108
+ end
109
+
102
110
  private
103
111
 
104
112
  def parse_title(title)
@@ -57,6 +57,10 @@ class R10K::Module::Git < R10K::Module::Base
57
57
  @repo.status(version)
58
58
  end
59
59
 
60
+ def cachedir
61
+ @repo.cache.sanitized_dirname
62
+ end
63
+
60
64
  private
61
65
 
62
66
  def validate_ref(desired, default)
@@ -10,7 +10,7 @@ class Puppetfile
10
10
 
11
11
  include R10K::Settings::Mixin
12
12
 
13
- def_setting_attr :pool_size, 1
13
+ def_setting_attr :pool_size, 4
14
14
 
15
15
  include R10K::Logging
16
16
 
@@ -42,6 +42,11 @@ class Puppetfile
42
42
  # @return [Boolean] Overwrite any locally made changes
43
43
  attr_accessor :force
44
44
 
45
+ # @!attribute [r] modules_by_vcs_cachedir
46
+ # @api private Only exposed for testing purposes
47
+ # @return [Hash{:none, String => Array<R10K::Module>}]
48
+ attr_reader :modules_by_vcs_cachedir
49
+
45
50
  # @param [String] basedir
46
51
  # @param [String] moduledir The directory to install the modules, default to #{basedir}/modules
47
52
  # @param [String] puppetfile_path The path to the Puppetfile, default to #{basedir}/Puppetfile
@@ -58,6 +63,7 @@ class Puppetfile
58
63
 
59
64
  @modules = []
60
65
  @managed_content = {}
66
+ @modules_by_vcs_cachedir = {}
61
67
  @forge = 'forgeapi.puppetlabs.com'
62
68
 
63
69
  @loaded = false
@@ -137,6 +143,9 @@ class Puppetfile
137
143
  mod.origin = 'Puppetfile'
138
144
 
139
145
  @managed_content[install_path] << mod.name
146
+ cachedir = mod.cachedir
147
+ @modules_by_vcs_cachedir[cachedir] ||= []
148
+ @modules_by_vcs_cachedir[cachedir] << mod
140
149
  @modules << mod
141
150
  end
142
151
 
@@ -145,7 +154,9 @@ class Puppetfile
145
154
  def managed_directories
146
155
  self.load unless @loaded
147
156
 
148
- @managed_content.keys
157
+ dirs = @managed_content.keys
158
+ dirs.delete(real_basedir)
159
+ dirs
149
160
  end
150
161
 
151
162
  # Returns an array of the full paths to all the content being managed.
@@ -212,15 +223,22 @@ class Puppetfile
212
223
  def modules_queue(visitor)
213
224
  Queue.new.tap do |queue|
214
225
  visitor.visit(:puppetfile, self) do
215
- modules.each { |mod| queue << mod }
226
+ modules_by_cachedir = modules_by_vcs_cachedir.clone
227
+ modules_without_vcs_cachedir = modules_by_cachedir.delete(:none) || []
228
+
229
+ modules_without_vcs_cachedir.each {|mod| queue << Array(mod) }
230
+ modules_by_cachedir.values.each {|mods| queue << mods }
216
231
  end
217
232
  end
218
233
  end
234
+ public :modules_queue
219
235
 
220
236
  def visitor_thread(visitor, mods_queue)
221
237
  Thread.new do
222
238
  begin
223
- while mod = mods_queue.pop(true) do mod.accept(visitor) end
239
+ while mods = mods_queue.pop(true) do
240
+ mods.each {|mod| mod.accept(visitor) }
241
+ end
224
242
  rescue ThreadError => e
225
243
  logger.debug _("Module thread %{id} exiting: %{message}") % {message: e.message, id: Thread.current.object_id}
226
244
  Thread.exit
@@ -248,8 +266,6 @@ class Puppetfile
248
266
  end
249
267
 
250
268
  def validate_install_path(path, modname)
251
- real_basedir = Pathname.new(basedir).cleanpath.to_s
252
-
253
269
  unless /^#{Regexp.escape(real_basedir)}.*/ =~ path
254
270
  raise R10K::Error.new("Puppetfile cannot manage content '#{modname}' outside of containing environment: #{path} is not within #{real_basedir}")
255
271
  end
@@ -257,6 +273,10 @@ class Puppetfile
257
273
  true
258
274
  end
259
275
 
276
+ def real_basedir
277
+ Pathname.new(basedir).cleanpath.to_s
278
+ end
279
+
260
280
  class DSL
261
281
  # A barebones implementation of the Puppetfile DSL
262
282
  #
@@ -160,7 +160,7 @@ module R10K
160
160
 
161
161
  Definition.new(:pool_size, {
162
162
  :desc => "The amount of threads used to concurrently install modules. The default value is 1: install one module at a time.",
163
- :default => 1,
163
+ :default => 4,
164
164
  :validate => lambda do |value|
165
165
  if !value.is_a?(Integer)
166
166
  raise ArgumentError, "The pool_size setting should be an integer, not a #{value.class}"
@@ -41,6 +41,10 @@ class R10K::Source::Git < R10K::Source::Base
41
41
  # that will be deployed as environments.
42
42
  attr_reader :ignore_branch_prefixes
43
43
 
44
+ # @!attribute [r] filter_command
45
+ # @return [String] Command to run to filter branches
46
+ attr_reader :filter_command
47
+
44
48
  # Initialize the given source.
45
49
  #
46
50
  # @param name [String] The identifier for this source.
@@ -61,6 +65,7 @@ class R10K::Source::Git < R10K::Source::Base
61
65
  @remote = options[:remote]
62
66
  @invalid_branches = (options[:invalid_branches] || 'correct_and_warn')
63
67
  @ignore_branch_prefixes = options[:ignore_branch_prefixes]
68
+ @filter_command = options[:filter_command]
64
69
 
65
70
  @cache = R10K::Git.cache.generate(@remote)
66
71
  end
@@ -115,7 +120,7 @@ class R10K::Source::Git < R10K::Source::Base
115
120
  environments.map {|env| env.dirname }
116
121
  end
117
122
 
118
- def filter_branches(branches, ignore_prefixes)
123
+ def filter_branches_by_regexp(branches, ignore_prefixes)
119
124
  filter = Regexp.new("^#{Regexp.union(ignore_prefixes)}")
120
125
  branches = branches.reject do |branch|
121
126
  result = filter.match(branch)
@@ -127,14 +132,29 @@ class R10K::Source::Git < R10K::Source::Base
127
132
  branches
128
133
  end
129
134
 
135
+ def filter_branches_by_command(branches, command)
136
+ branches.select do |branch|
137
+ result = system({'GIT_DIR' => @cache.git_dir.to_s, 'R10K_BRANCH' => branch, 'R10K_NAME' => @name.to_s}, command)
138
+ unless result
139
+ logger.warn _("Branch `%{name}:%{branch}` filtered out by filter_command %{cmd}") % {name: @name, branch: branch, cmd: command}
140
+ end
141
+ result
142
+ end
143
+ end
144
+
130
145
  private
131
146
 
132
147
  def branch_names
133
148
  opts = {:prefix => @prefix, :invalid => @invalid_branches, :source => @name}
134
149
  branches = @cache.branches
135
150
  if @ignore_branch_prefixes && !@ignore_branch_prefixes.empty?
136
- branches = filter_branches(branches, @ignore_branch_prefixes)
151
+ branches = filter_branches_by_regexp(branches, @ignore_branch_prefixes)
152
+ end
153
+
154
+ if @filter_command && !@filter_command.empty?
155
+ branches = filter_branches_by_command(branches, @filter_command)
137
156
  end
157
+
138
158
  branches.map do |branch|
139
159
  R10K::Environment::Name.new(branch, opts)
140
160
  end
@@ -2,5 +2,5 @@ module R10K
2
2
  # When updating to a new major (X) or minor (Y) version, include `#major` or
3
3
  # `#minor` (respectively) in your commit message to trigger the appropriate
4
4
  # release. Otherwise, a new patch (Z) version will be released.
5
- VERSION = '3.5.2'
5
+ VERSION = '3.6.0'
6
6
  end
@@ -6,11 +6,11 @@
6
6
  #, fuzzy
7
7
  msgid ""
8
8
  msgstr ""
9
- "Project-Id-Version: r10k 3.4.1-20-g8fe925b\n"
9
+ "Project-Id-Version: r10k 3.4.1-57-g2eb088a\n"
10
10
  "\n"
11
11
  "Report-Msgid-Bugs-To: docs@puppetlabs.com\n"
12
- "POT-Creation-Date: 2020-04-28 18:41+0000\n"
13
- "PO-Revision-Date: 2020-04-28 18:41+0000\n"
12
+ "POT-Creation-Date: 2020-07-22 16:41+0000\n"
13
+ "PO-Revision-Date: 2020-07-22 16:41+0000\n"
14
14
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
15
15
  "Language-Team: LANGUAGE <LL@li.org>\n"
16
16
  "Language: \n"
@@ -442,26 +442,30 @@ msgid ""
442
442
  "Returned: %{data}"
443
443
  msgstr ""
444
444
 
445
- #: ../lib/r10k/source/git.rb:72
445
+ #: ../lib/r10k/source/git.rb:77
446
446
  msgid "Fetching '%{remote}' to determine current branches."
447
447
  msgstr ""
448
448
 
449
- #: ../lib/r10k/source/git.rb:75
449
+ #: ../lib/r10k/source/git.rb:80
450
450
  msgid "Unable to determine current branches for Git source '%{name}' (%{basedir})"
451
451
  msgstr ""
452
452
 
453
- #: ../lib/r10k/source/git.rb:100
453
+ #: ../lib/r10k/source/git.rb:105
454
454
  msgid "Environment %{env_name} contained non-word characters, correcting name to %{corrected_env_name}"
455
455
  msgstr ""
456
456
 
457
- #: ../lib/r10k/source/git.rb:104
457
+ #: ../lib/r10k/source/git.rb:109
458
458
  msgid "Environment %{env_name} contained non-word characters, ignoring it."
459
459
  msgstr ""
460
460
 
461
- #: ../lib/r10k/source/git.rb:123 ../lib/r10k/source/svn.rb:113
461
+ #: ../lib/r10k/source/git.rb:128 ../lib/r10k/source/svn.rb:113
462
462
  msgid "Branch %{branch} filtered out by ignore_branch_prefixes %{ibp}"
463
463
  msgstr ""
464
464
 
465
+ #: ../lib/r10k/source/git.rb:139
466
+ msgid "Branch `%{name}:%{branch}` filtered out by filter_command %{cmd}"
467
+ msgstr ""
468
+
465
469
  #: ../lib/r10k/source/yaml.rb:10
466
470
  msgid "Couldn't open environments file %{file}: %{err}"
467
471
  msgstr ""
@@ -70,8 +70,8 @@ describe R10K::Action::Deploy::Module do
70
70
 
71
71
  before do
72
72
  allow(subject).to receive(:visit_environment).and_wrap_original do |original, environment, &block|
73
- expect(environment.puppetfile).to receive(:modules).and_return(
74
- [R10K::Module::Local.new(environment.name, '/fakedir', [], environment)]
73
+ expect(environment.puppetfile).to receive(:modules_by_vcs_cachedir).and_return(
74
+ {none: [R10K::Module::Local.new(environment.name, '/fakedir', [], environment)]}
75
75
  )
76
76
  original.call(environment, &block)
77
77
  end
@@ -27,6 +27,7 @@ describe R10K::Action::Puppetfile::Install do
27
27
  before do
28
28
  allow(puppetfile).to receive(:purge!)
29
29
  allow(puppetfile).to receive(:modules).and_return(modules)
30
+ allow(puppetfile).to receive(:modules_by_vcs_cachedir).and_return({none: modules})
30
31
  end
31
32
 
32
33
  it "syncs each module in the Puppetfile" do
@@ -127,6 +127,25 @@ describe R10K::Puppetfile do
127
127
 
128
128
  expect { subject.add_module('puppet/test_module', module_opts) }.to raise_error(R10K::Error, /cannot manage content.*is not within/i).and not_change { subject.modules }
129
129
  end
130
+
131
+ it "groups modules by vcs cache location" do
132
+ module_opts = { install_path: File.join(subject.basedir, 'vendor') }
133
+ opts1 = module_opts.merge(git: 'git@example.com:puppet/test_module.git')
134
+ opts2 = module_opts.merge(git: 'git@example.com:puppet/test_module_c.git')
135
+ sanitized_name1 = "git@example.com-puppet-test_module.git"
136
+ sanitized_name2 = "git@example.com-puppet-test_module_c.git"
137
+
138
+ subject.add_module('puppet/test_module_a', opts1)
139
+ subject.add_module('puppet/test_module_b', opts1)
140
+ subject.add_module('puppet/test_module_c', opts2)
141
+ subject.add_module('puppet/test_module_d', '1.2.3')
142
+
143
+ mods_by_cachedir = subject.modules_by_vcs_cachedir
144
+
145
+ expect(mods_by_cachedir[:none].length).to be 1
146
+ expect(mods_by_cachedir[sanitized_name1].length).to be 2
147
+ expect(mods_by_cachedir[sanitized_name2].length).to be 1
148
+ end
130
149
  end
131
150
 
132
151
  describe "#purge_exclusions" do
@@ -154,6 +173,26 @@ describe R10K::Puppetfile do
154
173
  end
155
174
  end
156
175
 
176
+ describe '#managed_directories' do
177
+ it 'returns an array of paths that can be purged' do
178
+ allow(R10K::Module).to receive(:new).with('puppet/test_module', subject.moduledir, '1.2.3', anything).and_call_original
179
+
180
+ subject.add_module('puppet/test_module', '1.2.3')
181
+ expect(subject.managed_directories).to match_array(["/some/nonexistent/basedir/modules"])
182
+ end
183
+
184
+ context 'with a module with install_path == \'\'' do
185
+ it 'basedir isn\'t in the list of paths to purge' do
186
+ module_opts = { install_path: '', git: 'git@example.com:puppet/test_module.git' }
187
+
188
+ allow(R10K::Module).to receive(:new).with('puppet/test_module', subject.basedir, module_opts, anything).and_call_original
189
+
190
+ subject.add_module('puppet/test_module', module_opts)
191
+ expect(subject.managed_directories).to be_empty
192
+ end
193
+ end
194
+ end
195
+
157
196
  describe "evaluating a Puppetfile" do
158
197
  def expect_wrapped_error(orig, pf_path, wrapped_error)
159
198
  expect(orig).to be_a_kind_of(R10K::Error)
@@ -268,7 +307,7 @@ describe R10K::Puppetfile do
268
307
  mod2 = spy('module')
269
308
  expect(mod2).to receive(:accept).with(visitor)
270
309
 
271
- expect(subject).to receive(:modules).and_return([mod1, mod2])
310
+ expect(subject).to receive(:modules_by_vcs_cachedir).and_return({none: [mod1, mod2]})
272
311
  subject.accept(visitor)
273
312
  end
274
313
 
@@ -289,12 +328,38 @@ describe R10K::Puppetfile do
289
328
  mod2 = spy('module')
290
329
  expect(mod2).to receive(:accept).with(visitor)
291
330
 
292
- expect(subject).to receive(:modules).and_return([mod1, mod2])
331
+ expect(subject).to receive(:modules_by_vcs_cachedir).and_return({none: [mod1, mod2]})
293
332
 
294
333
  expect(Thread).to receive(:new).exactly(pool_size).and_call_original
295
334
  expect(Queue).to receive(:new).and_call_original
296
335
 
297
336
  subject.accept(visitor)
298
337
  end
338
+
339
+ it "Creates queues of modules grouped by cachedir" do
340
+ visitor = spy('visitor')
341
+ expect(visitor).to receive(:visit) do |type, other, &block|
342
+ expect(type).to eq :puppetfile
343
+ expect(other).to eq subject
344
+ block.call
345
+ end
346
+
347
+ mod1 = spy('module1')
348
+ mod2 = spy('module2')
349
+ mod3 = spy('module3')
350
+ mod4 = spy('module4')
351
+ mod5 = spy('module5')
352
+ mod6 = spy('module6')
353
+
354
+ expect(subject).to receive(:modules_by_vcs_cachedir)
355
+ .and_return({:none => [mod1, mod2],
356
+ "foo-cachedir" => [mod3, mod4],
357
+ "bar-cachedir" => [mod5, mod6]})
358
+
359
+ queue = subject.modules_queue(visitor)
360
+ expect(queue.length).to be 4
361
+ queue_array = 4.times.map { queue.pop }
362
+ expect(queue_array).to match_array([[mod1], [mod2], [mod3, mod4], [mod5, mod6]])
363
+ end
299
364
  end
300
365
  end
@@ -93,9 +93,45 @@ describe R10K::Source::Git do
93
93
  let(:ignore_prefixes) { ['dev', 'test'] }
94
94
 
95
95
  it "filters branches" do
96
- expect(subject.filter_branches(branches, ignore_prefixes)).to eq(['master', 'production', 'not_dev_test_me'])
96
+ expect(subject.filter_branches_by_regexp(branches, ignore_prefixes)).to eq(['master', 'production', 'not_dev_test_me'])
97
97
  end
98
98
  end
99
+
100
+ describe "filtering branches with command" do
101
+ let(:branches) { ['master', 'development', 'production'] }
102
+ let(:filter_command) { 'sh -c "[ $R10K_BRANCH != development ]"' }
103
+
104
+ it "filters branches" do
105
+ expect(subject.filter_branches_by_command(branches, filter_command)).to eq(['master', 'production'])
106
+ end
107
+ end
108
+
109
+ describe "generate_environments respects filter_command setting" do
110
+ before do
111
+ allow(subject.cache).to receive(:branches).and_return ['master', 'development', 'production']
112
+ subject.instance_variable_set(:@filter_command, '[ $R10K_BRANCH != master ]')
113
+ end
114
+
115
+ let(:environments) { subject.generate_environments }
116
+
117
+ it "creates an environment for each branch not filtered by filter_command" do
118
+ expect(subject.generate_environments.size).to eq(2)
119
+ end
120
+ end
121
+
122
+ describe "generate_environments respects filter_command setting and name" do
123
+ before do
124
+ allow(subject.cache).to receive(:branches).and_return ['master', 'development', 'production']
125
+ subject.instance_variable_set(:@filter_command, '[ $R10K_NAME = mysource ]')
126
+ end
127
+
128
+ let(:environments) { subject.generate_environments }
129
+
130
+ it "creates an environment for each branch not filtered by filter_command" do
131
+ expect(subject.generate_environments.size).to eq(3)
132
+ end
133
+ end
134
+
99
135
  end
100
136
 
101
137
  describe R10K::Source::Git, "handling invalid branch names" do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: r10k
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.5.2
4
+ version: 3.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adrien Thebo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-21 00:00:00.000000000 Z
11
+ date: 2020-10-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colored2
@@ -282,6 +282,7 @@ files:
282
282
  - integration/tests/command_line/negative/neg_invalid_cmd_line_arg.rb
283
283
  - integration/tests/git_source/HTTP_proxy_and_git_source.rb
284
284
  - integration/tests/git_source/git_source_git.rb
285
+ - integration/tests/git_source/git_source_repeated_remote.rb
285
286
  - integration/tests/git_source/git_source_ssh.rb
286
287
  - integration/tests/git_source/git_source_submodule.rb
287
288
  - integration/tests/git_source/negative/neg_git_broken_remote.rb