packaging 0.88.77

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +17 -0
  3. data/README-Solaris.md +117 -0
  4. data/README.md +977 -0
  5. data/lib/packaging.rb +32 -0
  6. data/lib/packaging/archive.rb +126 -0
  7. data/lib/packaging/artifactory.rb +651 -0
  8. data/lib/packaging/artifactory/extensions.rb +94 -0
  9. data/lib/packaging/config.rb +492 -0
  10. data/lib/packaging/config/params.rb +387 -0
  11. data/lib/packaging/config/validations.rb +13 -0
  12. data/lib/packaging/deb.rb +28 -0
  13. data/lib/packaging/deb/repo.rb +264 -0
  14. data/lib/packaging/gem.rb +70 -0
  15. data/lib/packaging/metrics.rb +15 -0
  16. data/lib/packaging/nuget.rb +39 -0
  17. data/lib/packaging/paths.rb +376 -0
  18. data/lib/packaging/platforms.rb +507 -0
  19. data/lib/packaging/repo.rb +155 -0
  20. data/lib/packaging/retrieve.rb +75 -0
  21. data/lib/packaging/rpm.rb +5 -0
  22. data/lib/packaging/rpm/repo.rb +254 -0
  23. data/lib/packaging/sign.rb +8 -0
  24. data/lib/packaging/sign/deb.rb +9 -0
  25. data/lib/packaging/sign/dmg.rb +41 -0
  26. data/lib/packaging/sign/ips.rb +57 -0
  27. data/lib/packaging/sign/msi.rb +124 -0
  28. data/lib/packaging/sign/rpm.rb +115 -0
  29. data/lib/packaging/tar.rb +163 -0
  30. data/lib/packaging/util.rb +146 -0
  31. data/lib/packaging/util/date.rb +20 -0
  32. data/lib/packaging/util/execution.rb +85 -0
  33. data/lib/packaging/util/file.rb +125 -0
  34. data/lib/packaging/util/git.rb +174 -0
  35. data/lib/packaging/util/git_tags.rb +73 -0
  36. data/lib/packaging/util/gpg.rb +66 -0
  37. data/lib/packaging/util/jenkins.rb +95 -0
  38. data/lib/packaging/util/misc.rb +69 -0
  39. data/lib/packaging/util/net.rb +410 -0
  40. data/lib/packaging/util/os.rb +17 -0
  41. data/lib/packaging/util/platform.rb +40 -0
  42. data/lib/packaging/util/rake_utils.rb +112 -0
  43. data/lib/packaging/util/serialization.rb +19 -0
  44. data/lib/packaging/util/ship.rb +300 -0
  45. data/lib/packaging/util/tool.rb +41 -0
  46. data/lib/packaging/util/version.rb +334 -0
  47. data/spec/fixtures/config/ext/build_defaults.yaml +2 -0
  48. data/spec/fixtures/config/ext/project_data.yaml +2 -0
  49. data/spec/fixtures/configs/components/test_file.json +1 -0
  50. data/spec/fixtures/configs/components/test_file_2.json +0 -0
  51. data/spec/fixtures/configs/components/test_file_not_tagged.json +1 -0
  52. data/spec/fixtures/configs/components/test_file_wrong_ext.txt +0 -0
  53. data/spec/fixtures/configs/components/test_file_wrong_ext.wrong +0 -0
  54. data/spec/fixtures/util/pre_tasks.yaml +4 -0
  55. data/spec/lib/packaging/artifactory_spec.rb +221 -0
  56. data/spec/lib/packaging/config_spec.rb +576 -0
  57. data/spec/lib/packaging/deb/repo_spec.rb +157 -0
  58. data/spec/lib/packaging/deb_spec.rb +52 -0
  59. data/spec/lib/packaging/gem_spec.rb +86 -0
  60. data/spec/lib/packaging/paths_spec.rb +418 -0
  61. data/spec/lib/packaging/platforms_spec.rb +178 -0
  62. data/spec/lib/packaging/repo_spec.rb +135 -0
  63. data/spec/lib/packaging/retrieve_spec.rb +100 -0
  64. data/spec/lib/packaging/rpm/repo_spec.rb +133 -0
  65. data/spec/lib/packaging/sign_spec.rb +133 -0
  66. data/spec/lib/packaging/tar_spec.rb +116 -0
  67. data/spec/lib/packaging/util/execution_spec.rb +56 -0
  68. data/spec/lib/packaging/util/file_spec.rb +139 -0
  69. data/spec/lib/packaging/util/git_spec.rb +160 -0
  70. data/spec/lib/packaging/util/git_tag_spec.rb +36 -0
  71. data/spec/lib/packaging/util/gpg_spec.rb +64 -0
  72. data/spec/lib/packaging/util/jenkins_spec.rb +112 -0
  73. data/spec/lib/packaging/util/misc_spec.rb +31 -0
  74. data/spec/lib/packaging/util/net_spec.rb +259 -0
  75. data/spec/lib/packaging/util/os_spec.rb +31 -0
  76. data/spec/lib/packaging/util/rake_utils_spec.rb +70 -0
  77. data/spec/lib/packaging/util/ship_spec.rb +199 -0
  78. data/spec/lib/packaging/util/version_spec.rb +123 -0
  79. data/spec/lib/packaging_spec.rb +19 -0
  80. data/spec/spec_helper.rb +22 -0
  81. data/static_artifacts/PackageInfo.plist +3 -0
  82. data/tasks/00_utils.rake +214 -0
  83. data/tasks/30_metrics.rake +33 -0
  84. data/tasks/apple.rake +268 -0
  85. data/tasks/archive.rake +69 -0
  86. data/tasks/build.rake +12 -0
  87. data/tasks/clean.rake +5 -0
  88. data/tasks/config.rake +35 -0
  89. data/tasks/deb.rake +129 -0
  90. data/tasks/deb_repos.rake +28 -0
  91. data/tasks/deprecated.rake +130 -0
  92. data/tasks/doc.rake +20 -0
  93. data/tasks/education.rake +57 -0
  94. data/tasks/fetch.rake +60 -0
  95. data/tasks/gem.rake +159 -0
  96. data/tasks/jenkins.rake +538 -0
  97. data/tasks/jenkins_dynamic.rake +202 -0
  98. data/tasks/load_extras.rake +21 -0
  99. data/tasks/mock.rake +348 -0
  100. data/tasks/nightly_repos.rake +286 -0
  101. data/tasks/pe_deb.rake +12 -0
  102. data/tasks/pe_rpm.rake +13 -0
  103. data/tasks/pe_ship.rake +226 -0
  104. data/tasks/pe_sign.rake +13 -0
  105. data/tasks/pe_tar.rake +5 -0
  106. data/tasks/retrieve.rake +52 -0
  107. data/tasks/rpm.rake +66 -0
  108. data/tasks/rpm_repos.rake +29 -0
  109. data/tasks/ship.rake +692 -0
  110. data/tasks/sign.rake +154 -0
  111. data/tasks/tag.rake +8 -0
  112. data/tasks/tar.rake +28 -0
  113. data/tasks/update.rake +16 -0
  114. data/tasks/vanagon.rake +35 -0
  115. data/tasks/vendor_gems.rake +117 -0
  116. data/tasks/version.rake +33 -0
  117. data/tasks/z_data_dump.rake +65 -0
  118. data/templates/README +1 -0
  119. data/templates/downstream.xml.erb +47 -0
  120. data/templates/msi.xml.erb +197 -0
  121. data/templates/packaging.xml.erb +346 -0
  122. data/templates/repo.xml.erb +117 -0
  123. metadata +287 -0
@@ -0,0 +1,70 @@
1
+ require 'json'
2
+ module Pkg::Gem
3
+ class << self
4
+ def ship(file)
5
+ rsync_to_downloads(file)
6
+ ship_to_rubygems(file)
7
+ end
8
+
9
+ # Use rsync to deploy a file and any associated detached signatures,
10
+ # checksums, or other glob-able artifacts to an external download server.
11
+ def rsync_to_downloads(file)
12
+ Pkg::Util.deprecate('Pkg::Gem.rsync_to_downloads', 'Pkg::Util::Ship.ship_pkgs')
13
+ Pkg::Util::Ship.ship_pkgs(["#{file}*"], Pkg::Config.gem_host,
14
+ Pkg::Config.gem_path, platform_independent: true)
15
+ end
16
+
17
+ def shipped_to_rubygems?(gem_name, gem_version, gem_platform)
18
+ rubygems_url = "https://rubygems.org/api/v1/versions/#{gem_name}.json"
19
+ gem_data = JSON.parse(%x(curl --silent #{rubygems_url}))
20
+ gem = gem_data.select do |data|
21
+ data['number'] == gem_version && data['platform'] == gem_platform
22
+ end
23
+ return !gem.empty?
24
+ rescue => e
25
+ puts "Something went wrong searching for gem '#{gem_name}':"
26
+ puts e
27
+ puts "Perhaps you're shipping '#{gem_name}' for the first time?"
28
+ return false
29
+ end
30
+
31
+ # Ship a Ruby gem file to rubygems.org. Requires the existence
32
+ # of a ~/.gem/credentials file or else rubygems.org won't have
33
+ # any idea who you are.
34
+ def ship_to_rubygems(file, options = {})
35
+ # rubygems uses 'ruby' as the platform when it's not a platform-specific
36
+ # gem
37
+ platform = file.match(/\w+-(?:\d+(?:\.)?)+-(.*)\.gem$/)
38
+ unless platform.nil?
39
+ gem_platform = platform[1]
40
+ end
41
+ gem_platform ||= 'ruby'
42
+
43
+ if shipped_to_rubygems?(Pkg::Config.gem_name, Pkg::Config.gemversion, gem_platform)
44
+ puts "#{file} has already been shipped to rubygems, skipping."
45
+ return
46
+ end
47
+ Pkg::Util::File.file_exists?("#{ENV['HOME']}/.gem/credentials", :required => true)
48
+ gem_push_command = "gem push #{file}"
49
+ gem_push_command << " --host #{options[:host]}" if options[:host]
50
+ gem_push_command << " --key #{options[:key]}" if options[:key]
51
+ Pkg::Util::Execution.capture3(gem_push_command)
52
+ rescue => e
53
+ puts "###########################################"
54
+ puts "# Publishing to rubygems failed. Make sure your .gem/credentials"
55
+ puts "# file is set up and you are an owner of #{Pkg::Config.gem_name}"
56
+ puts "###########################################"
57
+ puts
58
+ puts e
59
+ raise e
60
+ end
61
+
62
+ def ship_to_internal_mirror(file)
63
+ internal_mirror_api_key_name = 'artifactory_api_key'
64
+ ship_to_rubygems(file, {
65
+ host: Pkg::Config.internal_gem_host,
66
+ key: internal_mirror_api_key_name
67
+ })
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,15 @@
1
+ module Pkg::Metrics
2
+ module_function
3
+
4
+ def update_release_metrics
5
+ metrics_repo = 'release-metrics'
6
+ command = <<CMD
7
+ git clone git@github.com:puppetlabs/#{metrics_repo}.git
8
+ cd #{metrics_repo}
9
+ bundle exec add-release --date #{Pkg::Util::Date.today} --project #{Pkg::Config.project} --version #{Pkg::Config.ref}
10
+ cd ..
11
+ rm -r #{metrics_repo}
12
+ CMD
13
+ Pkg::Util::Execution.capture3(command, true)
14
+ end
15
+ end
@@ -0,0 +1,39 @@
1
+ module Pkg::Nuget
2
+ class << self
3
+ def ship(packages)
4
+ #
5
+ # Support shipping of Nuget style packages to an Artifactory based nuget feed
6
+ # Using curl to submit the packages rather than windows based choco/mono.
7
+ # This approach gives more flexibility and fits in with the current Puppet
8
+ # release automation practices using linux/mac systems.
9
+
10
+ # Sanity checks
11
+ fail "NUGET_HOST is not defined" if Pkg::Config.nuget_host.empty?
12
+ fail "NUGET_REPO is not defined" if Pkg::Config.nuget_repo_path.to_s.empty?
13
+
14
+ # Retrieve password without revealing it
15
+ puts "Obtaining credentials to ship to nuget feed #{Pkg::Config.nuget_repo_path} on #{Pkg::Config.nuget_host}"
16
+ print "Username please: "
17
+ username = Pkg::Util.get_input(true)
18
+ print "Password please: "
19
+ password = Pkg::Util.get_input(false)
20
+ authentication = Pkg::Util.base64_encode("#{username}:#{password}")
21
+
22
+ uri = "#{Pkg::Config.nuget_host}#{Pkg::Config.nuget_repo_path}"
23
+ form_data = ["-H 'Authorization: Basic #{authentication}'", "-f"]
24
+ packages.each do |pkg|
25
+ puts "Working on package #{pkg}"
26
+ projname, version = File.basename(pkg).match(/^(.*)-([\d+\.]+)\.nupkg$/).captures
27
+ package_form_data = ["--upload-file #{pkg}"]
28
+ package_path = "#{projname}/#{version}/#{File.basename(pkg)}"
29
+ stdout = ''
30
+ retval = ''
31
+ Pkg::Util::Execution.retry_on_fail(:times => 3) do
32
+ stdout, retval = Pkg::Util::Net.curl_form_data("#{uri}/#{package_path}", form_data + package_form_data)
33
+ end
34
+ fail "The Package upload (curl) failed with error #{retval}" unless Pkg::Util::Execution.success?(retval)
35
+ stdout
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,376 @@
1
+ # Utilities surrounding the appropriate paths associated with a platform
2
+ # This includes both reporting the correct path and divining the platform
3
+ # tag associated with a variety of paths
4
+ #
5
+ # rubocop:disable Metrics/ModuleLength
6
+ module Pkg::Paths
7
+ include Pkg::Platforms
8
+
9
+ module_function
10
+
11
+ def arch_from_artifact_path(platform, version, path)
12
+ arches = Pkg::Platforms.arches_for_platform_version(platform, version)
13
+
14
+ # First check if it's a source package
15
+ source_formats = Pkg::Platforms.get_attribute_for_platform_version(platform, version, :source_package_formats)
16
+ if source_formats.find { |fmt| path =~ /#{fmt}$/ }
17
+ return Pkg::Platforms.get_attribute_for_platform_version(platform, version, :source_architecture)
18
+ end
19
+ arches.find { |a| path.include?(package_arch(platform, a)) } || arches[0]
20
+ rescue
21
+ arches.find { |a| path.include?(package_arch(platform, a)) } || arches[0]
22
+ end
23
+
24
+ # Given a path to an artifact, divine the appropriate platform tag associated
25
+ # with the artifact and path
26
+ def tag_from_artifact_path(path)
27
+ platform = Pkg::Platforms.supported_platforms.find { |p| path =~ /(\/|\.)#{p}[^\.]/ }
28
+ platform = 'windowsfips' if path =~ /windowsfips/
29
+
30
+ codename = Pkg::Platforms.codenames.find { |c| path =~ /\/#{c}/ }
31
+
32
+ if codename
33
+ platform, version = Pkg::Platforms.codename_to_platform_version(codename)
34
+ end
35
+
36
+ version = '2012' if platform =~ /^windows.*$/
37
+
38
+ version ||= Pkg::Platforms.versions_for_platform(platform).find { |v| path =~ /#{platform}(\/|-)?#{v}/ }
39
+
40
+ arch = arch_from_artifact_path(platform, version, path)
41
+
42
+ return "#{platform}-#{version}-#{arch}"
43
+ rescue
44
+ fmt = Pkg::Platforms.all_supported_package_formats.find { |ext| path =~ /#{ext}$/ }
45
+
46
+ # We need to make sure this is actually a file, and not simply a path
47
+ file_ext = File.extname(path)
48
+
49
+ # Fail if we do not have a file extension or if that file extension is one
50
+ # that is platform specific
51
+ raise "Cannot determine tag from #{path}" if fmt || file_ext.empty?
52
+
53
+ # Return nil otherwise, assuming that is a file type that is not tied to a
54
+ # specific platform
55
+ return nil
56
+ end
57
+
58
+ # Assign repo name
59
+ # If we are shipping development/beta/non-final packages, they should be
60
+ # shipped to the development/beta/non-final repo, if there is one defined.
61
+ # Otherwise, default to the final repo name. We use this for more than just
62
+ # shipping to the final repos, so we need this to not fail.
63
+ def repo_name(nonfinal = false)
64
+ if nonfinal && Pkg::Config.nonfinal_repo_name
65
+ Pkg::Config.nonfinal_repo_name
66
+ elsif nonfinal
67
+ fail "Nonfinal is set to true but Pkg::Config.nonfinal_repo_name is unset!"
68
+ else
69
+ Pkg::Config.repo_name || ""
70
+ end
71
+ end
72
+
73
+ # Method to determine the yum repo name. Maintains compatibility with legacy
74
+ # projects, where `Pkg::Config.yum_repo_name` is set instead of
75
+ # `Pkg::Config.repo_name`. Defaults to 'products' if nothing is set.
76
+ def yum_repo_name(nonfinal = false)
77
+ if nonfinal && Pkg::Config.nonfinal_repo_name
78
+ return Pkg::Config.nonfinal_repo_name
79
+ elsif nonfinal
80
+ fail "Nonfinal is set to true but Pkg::Config.nonfinal_repo_name is unset!"
81
+ end
82
+
83
+ return Pkg::Config.repo_name || Pkg::Config.yum_repo_name || 'products'
84
+ end
85
+
86
+ # Method to determine the apt repo name. Maintains compatibility with legacy
87
+ # projects, where `Pkg::Config.apt_repo_name` is set instead of
88
+ # `Pkg::Config.repo_name`. Defaults to 'main' if nothing is set.
89
+ def apt_repo_name(nonfinal = false)
90
+ if nonfinal && Pkg::Config.nonfinal_repo_name
91
+ return Pkg::Config.nonfinal_repo_name
92
+ elsif nonfinal
93
+ fail "Nonfinal is set to true but Pkg::Config.nonfinal_repo_name is unset!"
94
+ end
95
+
96
+ return Pkg::Config.repo_name || Pkg::Config.apt_repo_name || 'main'
97
+ end
98
+
99
+ def link_name(nonfinal = false)
100
+ return Pkg::Config.nonfinal_repo_link_target if nonfinal
101
+ return Pkg::Config.repo_link_target
102
+ end
103
+
104
+ # Construct a platform-dependent symlink target path.
105
+ def construct_base_path(path_data)
106
+ package_format = path_data[:package_format]
107
+ prefix = path_data[:prefix]
108
+ is_nonfinal = path_data[:is_nonfinal]
109
+ platform_name = path_data[:platform_name]
110
+ platform_tag = path_data[:platform_tag]
111
+
112
+ repo_name = Pkg::Config.repo_name
113
+
114
+ case package_format
115
+ when 'deb'
116
+ debian_code_name = Pkg::Platforms.get_attribute(platform_tag, :codename)
117
+
118
+ # In puppet7 and beyond, we moved the repo_name to the top to allow each
119
+ # puppet major release to have its own apt repo.
120
+ if %w(FUTURE-puppet7 FUTURE-puppet7-nightly).include? repo_name
121
+ return File.join(prefix, apt_repo_name(is_nonfinal), debian_code_name)
122
+ end
123
+
124
+ # For puppet6 and prior
125
+ return File.join(prefix, debian_code_name, apt_repo_name(is_nonfinal))
126
+ when 'dmg'
127
+ return File.join(prefix, 'mac', repo_name(is_nonfinal))
128
+ when 'msi'
129
+ return File.join(prefix, platform_name, repo_name(is_nonfinal))
130
+ when 'rpm'
131
+ return File.join(prefix, yum_repo_name(is_nonfinal))
132
+ when 'swix'
133
+ return File.join(prefix, platform_name, repo_name(is_nonfinal))
134
+ when 'svr4', 'ips'
135
+ return File.join(prefix, 'solaris', repo_name(is_nonfinal))
136
+ else
137
+ raise "Error: Unknown package format '#{package_format}'"
138
+ end
139
+ end
140
+
141
+ # Construct a platform-dependent link path
142
+ def construct_link_path(path_data)
143
+ package_format = path_data[:package_format]
144
+ prefix = path_data[:prefix]
145
+ platform_name = path_data[:platform_name]
146
+ platform_tag = path_data[:platform_tag]
147
+ link = path_data[:link]
148
+
149
+ return nil if link.nil?
150
+
151
+ case package_format
152
+ when 'rpm'
153
+ return File.join(prefix, link)
154
+ when 'swix'
155
+ return File.join(prefix, platform_name, link)
156
+ when 'deb'
157
+ debian_code_name = Pkg::Platforms.get_attribute(platform_tag, :codename)
158
+ return File.join(prefix, debian_code_name, link)
159
+ when 'svr4', 'ips'
160
+ return File.join(prefix, 'solaris', link)
161
+ when 'dmg'
162
+ return File.join(prefix, 'mac', link)
163
+ when 'msi'
164
+ return File.join(prefix, platform_name, link)
165
+ else
166
+ raise "Error: Unknown package format '#{package_format}'"
167
+ end
168
+ end
169
+
170
+ # Given platform information, create symlink target (base_path) and link path in the
171
+ # form of a 2-element array
172
+ def artifacts_base_path_and_link_path(platform_tag, prefix = 'artifacts', is_nonfinal = false)
173
+ platform_name, _ = Pkg::Platforms.parse_platform_tag(platform_tag)
174
+ package_format = Pkg::Platforms.package_format_for_tag(platform_tag)
175
+
176
+ path_data = {
177
+ is_nonfinal: is_nonfinal,
178
+ link: link_name(is_nonfinal),
179
+ package_format: package_format,
180
+ platform_name: platform_name,
181
+ platform_tag: platform_tag,
182
+ prefix: prefix
183
+ }
184
+
185
+ return [
186
+ construct_base_path(path_data),
187
+ construct_link_path(path_data)
188
+ ]
189
+ end
190
+
191
+ def artifacts_path(platform_tag, path_prefix = 'artifacts', nonfinal = false)
192
+ base_path, _ = artifacts_base_path_and_link_path(platform_tag, path_prefix, nonfinal)
193
+ platform, version, architecture = Pkg::Platforms.parse_platform_tag(platform_tag)
194
+ package_format = Pkg::Platforms.package_format_for_tag(platform_tag)
195
+
196
+ case package_format
197
+ when 'rpm'
198
+ File.join(base_path, platform, version, architecture)
199
+ when 'swix'
200
+ File.join(base_path, version, architecture)
201
+ when 'deb'
202
+ base_path
203
+ when 'svr4', 'ips'
204
+ File.join(base_path, version)
205
+ when 'dmg'
206
+ File.join(base_path, version, architecture)
207
+ when 'msi'
208
+ base_path
209
+ else
210
+ raise "Not sure where to find packages with a package format of '#{package_format}'"
211
+ end
212
+ end
213
+
214
+ def repo_path(platform_tag, options = { :legacy => false, :nonfinal => false })
215
+ repo_target = repo_name(options[:nonfinal])
216
+ # in legacy packaging methods, there was no consistent way to determine the
217
+ # repo name. There were separate variables for apt_repo_name and
218
+ # yum_repo_name. At times, either or both of these were unset, and they had
219
+ # different defaults. So, for legacy automation we need to just use a splat
220
+ # and globbing to find our packages.
221
+ repo_target = '**' if options[:legacy]
222
+ platform, version, arch = Pkg::Platforms.parse_platform_tag(platform_tag)
223
+ package_format = Pkg::Platforms.package_format_for_tag(platform_tag)
224
+
225
+ case package_format
226
+ when 'rpm', 'swix'
227
+ if options[:legacy]
228
+ File.join('repos', platform, version, repo_target, arch)
229
+ else
230
+ File.join('repos', repo_target, platform, version, arch)
231
+ end
232
+ when 'deb'
233
+ File.join('repos', 'apt', Pkg::Platforms.get_attribute(platform_tag, :codename), 'pool', repo_target)
234
+ when 'svr4', 'ips'
235
+ if options[:legacy]
236
+ File.join('repos', 'solaris', version, repo_target)
237
+ else
238
+ File.join('repos', 'solaris', repo_target, version)
239
+ end
240
+ when 'dmg'
241
+ if options[:legacy]
242
+ File.join('repos', 'apple', version, repo_target, arch)
243
+ else
244
+ File.join('repos', 'mac', repo_target, version, arch)
245
+ end
246
+ when 'msi'
247
+ if options[:legacy]
248
+ File.join('repos', 'windows')
249
+ else
250
+ File.join('repos', platform, repo_target)
251
+ end
252
+ else
253
+ raise "Not sure what to do with a package format of '#{package_format}'"
254
+ end
255
+ end
256
+
257
+ def repo_config_path(platform_tag)
258
+ package_format = Pkg::Platforms.package_format_for_tag(platform_tag)
259
+
260
+ case package_format
261
+ when 'rpm'
262
+ # rpm/pl-puppet-agent-1.2.5-el-5-i386.repo for example
263
+ File.join('repo_configs', 'rpm', "*#{platform_tag}*.repo")
264
+ when 'deb'
265
+ # deb/pl-puppet-agent-1.2.5-jessie.list
266
+ File.join('repo_configs', 'deb', "*#{Pkg::Platforms.get_attribute(platform_tag, :codename)}*.list")
267
+ when 'msi', 'swix', 'dmg', 'svr4', 'ips'
268
+ nil
269
+ else
270
+ raise "Not sure what to do with a package format of '#{package_format}'"
271
+ end
272
+ end
273
+
274
+ def remote_repo_base(platform_tag = nil, nonfinal: false, package_format: nil)
275
+ if platform_tag.nil? && package_format.nil?
276
+ raise "Pkg::Paths.remote_repo_base must have `platform_tag` or `package_format` specified."
277
+ end
278
+
279
+ package_format ||= Pkg::Platforms.package_format_for_tag(platform_tag)
280
+
281
+ repo_base = case package_format
282
+ when 'rpm'
283
+ nonfinal ? Pkg::Config.nonfinal_yum_repo_path : Pkg::Config.yum_repo_path
284
+ when 'deb'
285
+ nonfinal ? Pkg::Config.nonfinal_apt_repo_path : Pkg::Config.apt_repo_path
286
+ when 'dmg'
287
+ nonfinal ? Pkg::Config.nonfinal_dmg_path : Pkg::Config.dmg_path
288
+ when 'swix'
289
+ nonfinal ? Pkg::Config.nonfinal_swix_path : Pkg::Config.swix_path
290
+ when 'msi'
291
+ nonfinal ? Pkg::Config.nonfinal_msi_path : Pkg::Config.msi_path
292
+ else
293
+ raise "Can't determine remote repo base path for package format '#{package_format}'."
294
+ end
295
+
296
+ # normalize the path for things shipping to the downloads server
297
+ if repo_base.match(/^\/opt\/downloads\/\w+$/)
298
+ repo_base = '/opt/downloads'
299
+ end
300
+ repo_base
301
+ end
302
+
303
+ # This is where deb packages end up after freight repo updates
304
+ def apt_package_base_path(platform_tag, repo_name, project, nonfinal = false)
305
+ unless Pkg::Platforms.package_format_for_tag(platform_tag) == 'deb'
306
+ fail "Can't determine path for non-debian platform #{platform_tag}."
307
+ end
308
+
309
+ platform, version, _ = Pkg::Platforms.parse_platform_tag(platform_tag)
310
+ code_name = Pkg::Platforms.codename_for_platform_version(platform, version)
311
+ remote_repo_path = remote_repo_base(platform_tag, nonfinal: nonfinal)
312
+
313
+ # In puppet7 and beyond, we moved the puppet major version to near the top to allow each
314
+ # puppet major release to have its own apt repo, for example:
315
+ # /opt/repository/apt/puppet7/pool/bionic/p/puppet-agent
316
+ if %w(FUTURE-puppet7 FUTURE-puppet7-nightly).include? repo_name
317
+ return File.join(remote_repo_path, repo_name, 'pool', code_name, project[0], project)
318
+ end
319
+
320
+ # For repos prior to puppet7, the puppet version was part of the repository
321
+ # For example: /opt/repository/apt/pool/bionic/puppet6/p/puppet-agent
322
+ if %w(puppet7 puppet7-nightly
323
+ puppet6 puppet6-nightly
324
+ puppet5 puppet5-nightly
325
+ puppet puppet-nightly
326
+ puppet-tools).include? repo_name
327
+ return File.join(remote_repo_path, 'pool', code_name, repo_name, project[0], project)
328
+ end
329
+
330
+ raise "Error: Cannot determine apt_package_base_path for repo: \"#{repo_name}\"."
331
+ end
332
+
333
+ def release_package_link_path(platform_tag, nonfinal = false)
334
+ platform, version, _ = Pkg::Platforms.parse_platform_tag(platform_tag)
335
+ package_format = Pkg::Platforms.package_format_for_tag(platform_tag)
336
+ case package_format
337
+ when 'rpm'
338
+ return File.join(remote_repo_base(platform_tag, nonfinal: nonfinal),
339
+ "#{repo_name(nonfinal)}-release-#{platform}-#{version}.noarch.rpm")
340
+ when 'deb'
341
+ codename = Pkg::Platforms.codename_for_platform_version(platform, version)
342
+ return File.join(remote_repo_base(platform_tag, nonfinal: nonfinal),
343
+ "#{repo_name(nonfinal)}-release-#{codename}.deb")
344
+ else
345
+ warn "No release packages for package format '#{package_format}', skipping."
346
+ return nil
347
+ end
348
+ end
349
+
350
+ def debian_component_from_path(path)
351
+ # substitute '.' and '/' since those aren't valid characters for debian components
352
+ matches = path.match(/(\d+\.\d+|master|main)\/(\w+)/)
353
+ regex_for_substitution = /[\.\/]/
354
+ fail "Error: Could not determine Debian Component from path #{path}" if matches.nil?
355
+ base_component = matches[1]
356
+ component_qualifier = matches[2]
357
+ full_component = "#{base_component}/#{component_qualifier}"
358
+ unless regex_for_substitution.nil?
359
+ base_component.gsub!(regex_for_substitution, '_')
360
+ full_component.gsub!(regex_for_substitution, '_')
361
+ end
362
+ return base_component if component_qualifier == 'repos'
363
+ return full_component
364
+ end
365
+
366
+ #for ubuntu-20.04-aarch64, debian package architecture is arm64
367
+ def package_arch(platform, arch)
368
+ if platform == 'ubuntu' && arch == 'aarch64'
369
+ return 'arm64'
370
+ end
371
+ arch
372
+ end
373
+
374
+ private :package_arch
375
+
376
+ end