packaging 0.99.0

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.
Files changed (114) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +17 -0
  3. data/README-Solaris.md +117 -0
  4. data/README.md +1031 -0
  5. data/lib/packaging.rb +32 -0
  6. data/lib/packaging/artifactory.rb +278 -0
  7. data/lib/packaging/config.rb +392 -0
  8. data/lib/packaging/config/params.rb +366 -0
  9. data/lib/packaging/deb.rb +28 -0
  10. data/lib/packaging/deb/repo.rb +263 -0
  11. data/lib/packaging/gem.rb +112 -0
  12. data/lib/packaging/ips.rb +57 -0
  13. data/lib/packaging/msi.rb +89 -0
  14. data/lib/packaging/nuget.rb +39 -0
  15. data/lib/packaging/osx.rb +36 -0
  16. data/lib/packaging/paths.rb +238 -0
  17. data/lib/packaging/platforms.rb +480 -0
  18. data/lib/packaging/repo.rb +55 -0
  19. data/lib/packaging/retrieve.rb +46 -0
  20. data/lib/packaging/rpm.rb +5 -0
  21. data/lib/packaging/rpm/repo.rb +257 -0
  22. data/lib/packaging/tar.rb +154 -0
  23. data/lib/packaging/util.rb +146 -0
  24. data/lib/packaging/util/date.rb +15 -0
  25. data/lib/packaging/util/execution.rb +85 -0
  26. data/lib/packaging/util/file.rb +125 -0
  27. data/lib/packaging/util/git.rb +174 -0
  28. data/lib/packaging/util/git_tags.rb +73 -0
  29. data/lib/packaging/util/gpg.rb +62 -0
  30. data/lib/packaging/util/jenkins.rb +95 -0
  31. data/lib/packaging/util/misc.rb +69 -0
  32. data/lib/packaging/util/net.rb +368 -0
  33. data/lib/packaging/util/os.rb +17 -0
  34. data/lib/packaging/util/platform.rb +40 -0
  35. data/lib/packaging/util/rake_utils.rb +111 -0
  36. data/lib/packaging/util/serialization.rb +19 -0
  37. data/lib/packaging/util/ship.rb +171 -0
  38. data/lib/packaging/util/tool.rb +41 -0
  39. data/lib/packaging/util/version.rb +326 -0
  40. data/spec/fixtures/config/ext/build_defaults.yaml +2 -0
  41. data/spec/fixtures/config/ext/project_data.yaml +2 -0
  42. data/spec/fixtures/config/params.yaml +2 -0
  43. data/spec/fixtures/configs/components/test_file.json +1 -0
  44. data/spec/fixtures/configs/components/test_file_2.json +0 -0
  45. data/spec/fixtures/configs/components/test_file_not_tagged.json +1 -0
  46. data/spec/fixtures/configs/components/test_file_wrong_ext.txt +0 -0
  47. data/spec/fixtures/configs/components/test_file_wrong_ext.wrong +0 -0
  48. data/spec/fixtures/util/pre_tasks.yaml +4 -0
  49. data/spec/lib/packaging/artifactory_spec.rb +171 -0
  50. data/spec/lib/packaging/config_spec.rb +556 -0
  51. data/spec/lib/packaging/deb/repo_spec.rb +148 -0
  52. data/spec/lib/packaging/deb_spec.rb +52 -0
  53. data/spec/lib/packaging/paths_spec.rb +153 -0
  54. data/spec/lib/packaging/platforms_spec.rb +153 -0
  55. data/spec/lib/packaging/repo_spec.rb +97 -0
  56. data/spec/lib/packaging/retrieve_spec.rb +61 -0
  57. data/spec/lib/packaging/rpm/repo_spec.rb +133 -0
  58. data/spec/lib/packaging/tar_spec.rb +122 -0
  59. data/spec/lib/packaging/util/execution_spec.rb +56 -0
  60. data/spec/lib/packaging/util/file_spec.rb +139 -0
  61. data/spec/lib/packaging/util/git_spec.rb +160 -0
  62. data/spec/lib/packaging/util/git_tag_spec.rb +36 -0
  63. data/spec/lib/packaging/util/gpg_spec.rb +64 -0
  64. data/spec/lib/packaging/util/jenkins_spec.rb +112 -0
  65. data/spec/lib/packaging/util/misc_spec.rb +31 -0
  66. data/spec/lib/packaging/util/net_spec.rb +239 -0
  67. data/spec/lib/packaging/util/os_spec.rb +31 -0
  68. data/spec/lib/packaging/util/rake_utils_spec.rb +70 -0
  69. data/spec/lib/packaging/util/ship_spec.rb +117 -0
  70. data/spec/lib/packaging/util/version_spec.rb +123 -0
  71. data/spec/lib/packaging_spec.rb +19 -0
  72. data/spec/spec_helper.rb +36 -0
  73. data/static_artifacts/PackageInfo.plist +3 -0
  74. data/tasks/00_utils.rake +216 -0
  75. data/tasks/30_metrics.rake +33 -0
  76. data/tasks/apple.rake +266 -0
  77. data/tasks/build.rake +12 -0
  78. data/tasks/clean.rake +5 -0
  79. data/tasks/config.rake +30 -0
  80. data/tasks/deb.rake +129 -0
  81. data/tasks/deb_repos.rake +28 -0
  82. data/tasks/deprecated.rake +130 -0
  83. data/tasks/doc.rake +20 -0
  84. data/tasks/education.rake +57 -0
  85. data/tasks/fetch.rake +57 -0
  86. data/tasks/gem.rake +146 -0
  87. data/tasks/jenkins.rake +494 -0
  88. data/tasks/jenkins_dynamic.rake +202 -0
  89. data/tasks/load_extras.rake +21 -0
  90. data/tasks/mock.rake +348 -0
  91. data/tasks/nightly_repos.rake +335 -0
  92. data/tasks/pe_deb.rake +12 -0
  93. data/tasks/pe_rpm.rake +13 -0
  94. data/tasks/pe_ship.rake +221 -0
  95. data/tasks/pe_sign.rake +13 -0
  96. data/tasks/pe_tar.rake +5 -0
  97. data/tasks/retrieve.rake +45 -0
  98. data/tasks/rpm.rake +66 -0
  99. data/tasks/rpm_repos.rake +29 -0
  100. data/tasks/ship.rake +752 -0
  101. data/tasks/sign.rake +226 -0
  102. data/tasks/tag.rake +8 -0
  103. data/tasks/tar.rake +34 -0
  104. data/tasks/update.rake +16 -0
  105. data/tasks/vanagon.rake +35 -0
  106. data/tasks/vendor_gems.rake +117 -0
  107. data/tasks/version.rake +33 -0
  108. data/tasks/z_data_dump.rake +65 -0
  109. data/templates/README +1 -0
  110. data/templates/downstream.xml.erb +47 -0
  111. data/templates/msi.xml.erb +197 -0
  112. data/templates/packaging.xml.erb +344 -0
  113. data/templates/repo.xml.erb +114 -0
  114. metadata +234 -0
@@ -0,0 +1,32 @@
1
+ module Pkg
2
+
3
+ LIBDIR = File.expand_path(File.dirname(__FILE__))
4
+
5
+ $:.unshift(LIBDIR) unless
6
+ $:.include?(File.dirname(__FILE__)) || $:.include?(LIBDIR)
7
+
8
+ require 'packaging/platforms'
9
+ require 'packaging/util'
10
+ require 'packaging/config'
11
+ require 'packaging/paths'
12
+ require 'packaging/tar'
13
+ require 'packaging/deb'
14
+ require 'packaging/rpm'
15
+ require 'packaging/osx'
16
+ require 'packaging/ips'
17
+ require 'packaging/nuget'
18
+ require 'packaging/gem'
19
+ require 'packaging/msi'
20
+ require 'packaging/repo'
21
+ require 'packaging/artifactory'
22
+ require 'packaging/retrieve'
23
+
24
+ # Load configuration defaults
25
+ Pkg::Config.load_defaults
26
+ Pkg::Config.load_default_configs
27
+ Pkg::Config.load_versioning
28
+ Pkg::Config.load_overrides
29
+ Pkg::Config.load_envvars
30
+ Pkg::Config.issue_reassignments
31
+ Pkg::Config.issue_deprecations
32
+ end
@@ -0,0 +1,278 @@
1
+ module Pkg
2
+
3
+ # The Artifactory class
4
+ # This class provides automation to access the artifactory repos maintained
5
+ # by the Release Engineering team at Puppet. It has the ability to both push
6
+ # artifacts to the repos, and to retrieve them back from the repos.
7
+ class ManageArtifactory
8
+
9
+ DEFAULT_REPO_TYPE = 'generic'
10
+ DEFAULT_REPO_BASE = 'development'
11
+
12
+ # @param project [String] The name of the project this package is for
13
+ # @param project_version [String] The version of the project we want the
14
+ # package for. This can be one of three things:
15
+ # 1) the final tag of the project the packages were built from
16
+ # 2) the long git sha the project the packages were built from
17
+ # 3) the EZBake generated development sha where the packages live
18
+ # @option :artifactory_uri [String] the uri for the artifactory server.
19
+ # This currently defaults to 'https://artifactory.delivery.puppetlabs.net/artifactory'
20
+ # @option :repo_base [String] The base of all repos, set for consistency.
21
+ # This currently defaults to 'development'
22
+ def initialize(project, project_version, opts = {})
23
+ require 'artifactory'
24
+
25
+ @artifactory_uri = opts[:artifactory_uri] || 'https://artifactory.delivery.puppetlabs.net/artifactory'
26
+ @repo_base = opts[:repo_base] || DEFAULT_REPO_BASE
27
+
28
+ @project = project
29
+ @project_version = project_version
30
+
31
+ Artifactory.endpoint = @artifactory_uri
32
+ end
33
+
34
+ # @param platform_tag [String] The platform tag string for the repo we need
35
+ # information on. If generic information is needed, pass in `generic`
36
+ # @return [Array] An array containing three items, first being the main repo
37
+ # name for the platform_tag, the second being the subdirectories of the
38
+ # repo leading to the artifact we want to install, and the third being the
39
+ # alternate subdirectories for a given repo. This last option is only
40
+ # currently used for debian platforms, where the path to the repo
41
+ # specified in the list file is different than the full path to the repo.
42
+ def location_for(platform_tag)
43
+ toplevel_repo = DEFAULT_REPO_TYPE
44
+ repo_subdirectories = File.join(@repo_base, @project, @project_version)
45
+ alternate_subdirectories = repo_subdirectories
46
+
47
+ unless platform_tag == DEFAULT_REPO_TYPE
48
+ format = Pkg::Platforms.package_format_for_tag(platform_tag)
49
+ platform, version, architecture = Pkg::Platforms.parse_platform_tag(platform_tag)
50
+ end
51
+
52
+ case format
53
+ when 'rpm'
54
+ toplevel_repo = 'rpm'
55
+ repo_subdirectories = File.join(repo_subdirectories, "#{platform}-#{version}-#{architecture}")
56
+ alternate_subdirectories = repo_subdirectories
57
+ when 'deb'
58
+ toplevel_repo = 'debian__local'
59
+ repo_subdirectories = File.join(repo_subdirectories, "#{platform}-#{version}")
60
+ alternate_subdirectories = File.join('pool', repo_subdirectories)
61
+ when 'swix', 'dmg', 'svr4', 'ips'
62
+ repo_subdirectories = File.join(repo_subdirectories, "#{platform}-#{version}-#{architecture}")
63
+ alternate_subdirectories = repo_subdirectories
64
+ when 'msi'
65
+ repo_subdirectories = File.join(repo_subdirectories, "#{platform}-#{architecture}")
66
+ alternate_subdirectories = repo_subdirectories
67
+ end
68
+
69
+ [toplevel_repo, repo_subdirectories, alternate_subdirectories]
70
+ end
71
+
72
+ # @param platform_tag [String] The platform tag specific to the information
73
+ # we need. If only the generic information is needed, pass in `generic`
74
+ # @return [Hash] Returns a hash of data specific to this platform tag
75
+ def platform_specific_data(platform_tag)
76
+ unless platform_tag == DEFAULT_REPO_TYPE
77
+ platform, version, architecture = Pkg::Platforms.parse_platform_tag(platform_tag)
78
+ package_format = Pkg::Platforms.package_format_for_tag(platform_tag)
79
+ if package_format == 'deb'
80
+ codename = Pkg::Platforms.codename_for_platform_version(platform, version)
81
+ end
82
+ end
83
+
84
+ repo_name, repo_subdirectories, alternate_subdirectories = location_for(platform_tag)
85
+ full_artifactory_path = File.join(repo_name, alternate_subdirectories)
86
+
87
+ {
88
+ platform: platform,
89
+ platform_version: version,
90
+ architecture: architecture,
91
+ codename: codename,
92
+ package_format: package_format,
93
+ repo_name: repo_name,
94
+ repo_subdirectories: repo_subdirectories,
95
+ alternate_subdirectories: alternate_subdirectories,
96
+ full_artifactory_path: full_artifactory_path
97
+ }
98
+ end
99
+
100
+ # @param platform_tag [String] The platform to generate the list contents
101
+ # for
102
+ # @return [String] The contents of the debian list file to enable the
103
+ # debian artifactory repos for the specified project and version
104
+ def deb_list_contents(platform_tag)
105
+ data = platform_specific_data(platform_tag)
106
+ if data[:package_format] == 'deb'
107
+ return "deb #{@artifactory_uri}/#{data[:repo_name]} #{data[:codename]} #{data[:repo_subdirectories]}"
108
+ end
109
+ raise "The platform '#{platform_tag}' is not an apt-based system."
110
+ end
111
+
112
+ # @param platform_tag [String] The platform to generate the repo file
113
+ # contents for
114
+ # @return [String] The contents of the rpm repo file to enable the rpm
115
+ # artifactory repo for the specified project and version
116
+ def rpm_repo_contents(platform_tag)
117
+ data = platform_specific_data(platform_tag)
118
+ if data[:package_format] == 'rpm'
119
+ return <<-DOC
120
+ [Artifactory #{@project} #{@project_version} for #{platform_tag}]
121
+ name=Artifactory Repository for #{@project} #{@project_version} for #{platform_tag}
122
+ baseurl=#{@artifactory_uri}/#{data[:repo_name]}/#{data[:repo_subdirectories]}
123
+ enabled=1
124
+ gpgcheck=0
125
+ #Optional - if you have GPG signing keys installed, use the below flags to verify the repository metadata signature:
126
+ #gpgkey=#{@artifactory_uri}/#{data[:repo_name]}/#{data[:repo_subdirectories]}/repomd.xml.key
127
+ #repo_gpgcheck=1
128
+ DOC
129
+ end
130
+ raise "The platform '#{platform_tag}' is not a yum-based system"
131
+ end
132
+
133
+ # Verify the correct environment variables are set in order to process
134
+ # authorization to access the artifactory repos
135
+ def check_authorization
136
+ unless (ENV['ARTIFACTORY_USERNAME'] && ENV['ARTIFACTORY_PASSWORD']) || ENV['ARTIFACTORY_API_KEY']
137
+ raise <<-DOC
138
+ Unable to determine credentials for Artifactory. Please set one of the
139
+ following environment variables:
140
+
141
+ For basic authentication, please set:
142
+ ARTIFACTORY_USERNAME
143
+ ARTIFACTORY_PASSWORD
144
+
145
+ If you would like to use the API key, ensure ARTIFACTORY_USERNAME and
146
+ ARTIFACTORY_PASSWORD are not set, as these take precedence. Instead, please
147
+ set:
148
+ ARTIFACTORY_API_KEY
149
+
150
+ You can also set the path to a pem file with your custom certificates with:
151
+ ARTIFACTORY_SSL_PEM_FILE
152
+ DOC
153
+ end
154
+ end
155
+
156
+ # @param platform_tag [String] The platform tag to generate deploy
157
+ # properties for
158
+ # @return [String] Any required extra bits that we need for the curl
159
+ # command used to deploy packages to artifactory
160
+ #
161
+ # These are a few examples from chef/artifactory-client. These could
162
+ # potentially be very powerful, but we should decide how to use them.
163
+ # status: 'DEV',
164
+ # rating: 5,
165
+ # branch: 'master'
166
+ #
167
+ # Currently we are including everything that would be included in the yaml
168
+ # file that is generated at package build time.
169
+ def deploy_properties(platform_tag)
170
+ data = platform_specific_data(platform_tag)
171
+
172
+ # TODO This method should be returning the entire contents of the yaml
173
+ # file in hash form to include as metadata for these artifacts. In this
174
+ # current iteration, the hash isn't formatted properly and the attempt to
175
+ # deploy to Artifactory bails out. I'm leaving this in so that we at least
176
+ # have multiple places to remind us that it needs to happen.
177
+ #properties_hash = Pkg::Config.config_to_hash
178
+ properties_hash = {}
179
+ if data[:package_format] == 'deb'
180
+ properties_hash.merge!({
181
+ 'deb.distribution' => data[:codename],
182
+ 'deb.component' => data[:repo_subdirectories],
183
+ 'deb.architecture' => data[:architecture],
184
+ })
185
+ end
186
+ properties_hash
187
+ end
188
+
189
+ # @param package [String] The full relative path to the package to be
190
+ # shipped, relative from the current working directory
191
+ def deploy_package(package)
192
+ platform_tag = Pkg::Paths.tag_from_artifact_path(package) || DEFAULT_REPO_TYPE
193
+ data = platform_specific_data(platform_tag)
194
+
195
+ check_authorization
196
+ artifact = Artifactory::Resource::Artifact.new(local_path: package)
197
+ artifact.upload(
198
+ data[:repo_name],
199
+ File.join(data[:alternate_subdirectories], File.basename(package)),
200
+ deploy_properties(platform_tag)
201
+ )
202
+ rescue
203
+ raise "Attempt to upload '#{package}' to #{File.join(@artifactory_uri, data[:full_artifactory_path])} failed"
204
+ end
205
+
206
+ # @param directory [String] optional, The directory where the yaml file will
207
+ # be downloaded
208
+ # @return [String] The path to the downloaded file
209
+ def retrieve_yaml_data_file(directory = nil)
210
+ directory ||= Dir.mktmpdir
211
+ retrieve_package(DEFAULT_REPO_TYPE, "#{@project_version}.yaml", directory)
212
+ File.join(directory, "#{@project_version}.yaml")
213
+ end
214
+
215
+ # @param platform_data [Hash] The has of the platform data that needs to be
216
+ # parsed
217
+ # @param platform_tag [String] The tag that the data we want belongs to
218
+ # @return [String] The name of the package for the given project,
219
+ # project_version, and platform_tag
220
+ def package_name(platform_data, platform_tag)
221
+ return File.basename(platform_data[platform_tag][:artifact])
222
+ rescue
223
+ fail_message = <<-DOC
224
+ Package name could not be found from loaded yaml data. Either this package
225
+ does not exist, or '#{@platform_tag}' is not present in this dataset.
226
+
227
+ The following are available platform tags for '#{@project}' '#{@project_version}':
228
+ #{platform_data.keys.sort}
229
+ DOC
230
+ raise fail_message
231
+ end
232
+
233
+ # @param platform_tags [Array[String], String] optional, either a string, or
234
+ # an array of strings. These are the platform or platforms that we will
235
+ # download packages for.
236
+ # @param package [String] optional, the name of the package to be
237
+ # retrieved. If the user does not know this information, we can derive it
238
+ # from the yaml data. This ignores everything but the package name. Any
239
+ # customization for where the user wants to fetch the package is via the
240
+ # download_path parameter.
241
+ # @param download_path [String] Optional, an optional path set to where
242
+ # the user wants the retrieved package to end up. If no path is specified
243
+ # this defaults to the pkg directory.
244
+ def retrieve_package(platform_tags = nil, package = nil, download_path = nil)
245
+
246
+ if platform_tags.nil? && !package.nil?
247
+ platform_tags = Pkg::Paths.tag_from_artifact_path(package) || DEFAULT_REPO_TYPE
248
+ elsif platform_tags.nil? && package.nil?
249
+ yaml_file = retrieve_yaml_data_file(download_path)
250
+ yaml_data = Pkg::Config.config_from_yaml(yaml_file)
251
+ platform_data = yaml_data[:platform_data]
252
+ platform_tags = platform_data.keys
253
+ end
254
+
255
+ Array(platform_tags).each do |platform_tag|
256
+ puts "fetching package for #{platform_tag}"
257
+ data = platform_specific_data(platform_tag)
258
+ if package.nil?
259
+ package_for_tag = package_name(platform_data, platform_tag)
260
+ puts "package name is #{package_for_tag}"
261
+ else
262
+ package_for_tag = package
263
+ end
264
+ download_path_for_tag = download_path || data[:repo_subdirectories].sub(@repo_base, 'pkg')
265
+
266
+ check_authorization
267
+ artifact = Artifactory::Resource::Artifact.new(
268
+ download_uri: File.join(@artifactory_uri, data[:full_artifactory_path], File.basename(package_for_tag))
269
+ )
270
+ artifact.download(download_path_for_tag)
271
+ end
272
+ rescue
273
+ raise "Attempt to download '#{File.basename(package)}' from #{File.join(@artifactory_uri, data[:full_artifactory_path])} failed."
274
+ end
275
+
276
+ private :check_authorization
277
+ end
278
+ end
@@ -0,0 +1,392 @@
1
+ module Pkg
2
+ ##
3
+ # This class is meant to encapsulate all of the data we know about a build invoked with
4
+ # `rake package:<build>` or `rake pl:<build>`. It can read in this data via a yaml file,
5
+ # have it set via accessors, and serialize it back to yaml for easy transport.
6
+ #
7
+ class Config
8
+ require 'packaging/config/params.rb'
9
+ require 'yaml'
10
+
11
+ class << self
12
+ ##
13
+ # Returns a hash with string keys that maps instance variable
14
+ # names without "@"" to their corresponding values.
15
+ #
16
+ def instance_values
17
+ Hash[instance_variables.map { |name| [name[1..-1], instance_variable_get(name)] }]
18
+ end
19
+
20
+ # Every element in Pkg::Params::BUILD_PARAMS is a configurable setting
21
+ # for the build. We use Pkg::Params::BUILD_PARAMS as the source of
22
+ # truth for defining the the class instance variables and their
23
+ # accessors of the Pkg::Config class
24
+ Pkg::Params::BUILD_PARAMS.each do |v|
25
+ attr_accessor v
26
+ end
27
+
28
+ # Return the binding of class context. Used for erb templates.
29
+ #
30
+ def get_binding
31
+ return binding
32
+ end
33
+
34
+ ##
35
+ # Take a hash of Config parameters, and iterate over them, setting the
36
+ # value for each Config param to the corresponding hash key,value.
37
+ #
38
+ def config_from_hash(data = {})
39
+ data.each do |param, value|
40
+ if Pkg::Params::BUILD_PARAMS.include?(param.to_sym)
41
+ self.instance_variable_set("@#{param}", value)
42
+ else
43
+ warn "Warning - No build data parameter found for '#{param}'. Perhaps you have an erroneous entry in your yaml file?"
44
+ end
45
+ end
46
+ end
47
+
48
+ ##
49
+ # Load a yaml file and use its contents to set the values for Pkg::Config
50
+ # class instance variables
51
+ #
52
+ def config_from_yaml(file)
53
+ build_data = Pkg::Util::Serialization.load_yaml(file)
54
+ config_from_hash(build_data)
55
+ end
56
+
57
+ ##
58
+ # By default return a hash of the names, values of current Pkg::Config
59
+ # instance variables. With :format => :yaml, write a yaml file containing
60
+ # the current names,values of Pkg::Config class instance variables
61
+ #
62
+ def config(args = { :target => nil, :format => :hash })
63
+ case args[:format]
64
+ when :hash
65
+ self.config_to_hash
66
+ when :yaml
67
+ self.config_to_yaml(args[:target])
68
+ end
69
+ end
70
+
71
+ ##
72
+ # For each platform we ship for, find paths to its artifact and repo_config (if applicable).
73
+ # This is to be consumed by beaker and later replaced with our metadata service.
74
+ #
75
+ def platform_data
76
+ if self.project && self.ref && Pkg::Util::Net.check_host_ssh([self.builds_server]).empty?
77
+ dir = "/opt/jenkins-builds/#{self.project}/#{self.ref}"
78
+ cmd = "if [ -s \"#{dir}/artifacts\" ]; then cd #{dir}; find ./artifacts/ -mindepth 2 -type f; fi"
79
+ artifacts, _ = Pkg::Util::Net.remote_ssh_cmd(self.builds_server, cmd, true)
80
+ artifacts = artifacts.split("\n")
81
+ data = {}
82
+ artifacts.each do |artifact|
83
+ tag = Pkg::Paths.tag_from_artifact_path(artifact)
84
+ platform, version, arch = Pkg::Platforms.parse_platform_tag(tag)
85
+ arch = 'ppc' if platform == 'aix'
86
+ package_format = Pkg::Platforms.get_attribute(tag, :package_format)
87
+
88
+ # Skip this if it's an unversioned MSI. We create these to help
89
+ # beaker install the msi without having to know any version
90
+ # information, but we should report the versioned artifact in
91
+ # platform_data
92
+ next if platform == 'windows' && File.basename(artifact) == "#{self.project}-#{arch}.#{package_format}"
93
+ # Sometimes we have source or debug packages. We don't want to save
94
+ # these paths in favor of the artifact paths.
95
+ if platform == 'solaris'
96
+ next if version == '10' && File.extname(artifact) != '.gz'
97
+ next if version == '11' && File.extname(artifact) != '.p5p'
98
+ else
99
+ next if File.extname(artifact) != ".#{package_format}"
100
+ end
101
+ next if /#{self.project}-[a-z]+/.match(File.basename(artifact))
102
+
103
+ case package_format
104
+ when 'deb'
105
+ repo_config = "../repo_configs/deb/pl-#{self.project}-#{self.ref}-#{Pkg::Platforms.get_attribute(tag, :codename)}.list"
106
+ when 'rpm'
107
+ repo_config = "../repo_configs/rpm/pl-#{self.project}-#{self.ref}-#{tag}.repo" unless tag.include? 'aix'
108
+ when 'swix', 'svr4', 'ips', 'dmg', 'msi'
109
+ # No repo_configs for these platforms, so do nothing.
110
+ else
111
+ fail "Not sure what to do with packages with a package format of '#{package_format}' - maybe update PLATFORM_INFO?"
112
+ end
113
+ # Remove the f-prefix from the fedora platform tag keys so that
114
+ # beaker can rely on consistent keys once we rip out the f for good
115
+ tag = tag.sub(/fedora-f/, 'fedora-')
116
+ data[tag] = { :artifact => artifact.sub('artifacts/', ''),
117
+ :repo_config => repo_config,
118
+ }
119
+ end
120
+ return data
121
+ else
122
+ warn "Skipping platform_data collection, but don't worry about it."
123
+ return nil
124
+ end
125
+ end
126
+
127
+ ##
128
+ # Return a hash of all build parameters and their values, nil if unassigned.
129
+ #
130
+ def config_to_hash
131
+ data = {}
132
+ Pkg::Params::BUILD_PARAMS.each do |param|
133
+ data.store(param, self.instance_variable_get("@#{param}"))
134
+ end
135
+ data.store(:platform_data, platform_data)
136
+ data
137
+ end
138
+
139
+ ##
140
+ # Write all build parameters to a yaml file, either one specified or in a
141
+ # temporary location. Print the path to the file and return it as a
142
+ # string. Accept an argument for the write target file. If not specified,
143
+ # the name of the params file is the current git commit sha or tag.
144
+ #
145
+ def config_to_yaml(target = nil)
146
+ file = "#{self.ref}.yaml"
147
+ target = target.nil? ? File.join(Pkg::Util::File.mktemp, "#{self.ref}.yaml") : File.join(target, file)
148
+ Pkg::Util::File.file_writable?(File.dirname(target), :required => true)
149
+ File.open(target, 'w') do |f|
150
+ f.puts self.config_to_hash.to_yaml
151
+ end
152
+ puts target
153
+ target
154
+ end
155
+
156
+ ##
157
+ # Print the names and values of all the params known to the build object
158
+ #
159
+ def print_config
160
+ self.config_to_hash.each { |k, v| puts "#{k}: #{v}" }
161
+ end
162
+
163
+ ##
164
+ # Return the names of all of the cows for the project, taking off the
165
+ # base prefix, the architecture, and the .cow suffix. This is helpful in
166
+ # the debian changelog.
167
+ #
168
+ def cow_list
169
+ self.cows.split(' ').map do
170
+ |cow| cow.split('-')[1]
171
+ end.uniq.join(' ')
172
+ end
173
+
174
+ def default_project_root
175
+ # Assume that either PROJECT_ROOT has been set, or we're running from the
176
+ # project root
177
+ #
178
+ ENV['PROJECT_ROOT'] || Dir.pwd
179
+ end
180
+
181
+ def default_packaging_root
182
+ # Assume that PACKAGING_ROOT has been set, or set the PACKAGING_ROOT to
183
+ # one directory above the LIBDIR
184
+ #
185
+ defined?(PACKAGING_ROOT) ? File.expand_path(PACKAGING_ROOT) : File.expand_path(File.join(LIBDIR, ".."))
186
+ end
187
+
188
+ def load_default_configs
189
+ got_config = false
190
+ default_project_data = { :path => File.join(@project_root, "ext", "project_data.yaml"), :required => false }
191
+ default_build_defaults = { :path => File.join(@project_root, "ext", "build_defaults.yaml"), :required => true }
192
+
193
+ [default_project_data, default_build_defaults].each do |config|
194
+ if File.readable? config[:path]
195
+ self.config_from_yaml(config[:path])
196
+ got_config = true if config[:required]
197
+ else
198
+ puts "Skipping load of expected default config #{config[:path]}, cannot read file."
199
+ end
200
+ end
201
+
202
+ if got_config
203
+ self.config
204
+ else
205
+ # Since the default configuration files are not readable, most
206
+ # likely not present, at this point we assume the project_root
207
+ # isn't what we hoped it would be, and unset it.
208
+ @project_root = nil
209
+ end
210
+ end
211
+
212
+ # Set all aspects of how the package will be versioned. Versioning
213
+ # relies exclusively on the git describe of the project, which will
214
+ # fail if either Pkg::Config.project_root is nil, isn't in a git repo,
215
+ # or is in a git repo, but there are no tags in the repo, in which case
216
+ # git-describe will fail.
217
+ #
218
+ # It probably seems odd to load packaging-specific version
219
+ # determinations, such as rpmversion here, at the top-level, and it is.
220
+ # The reason for this that the creation of the most basic package
221
+ # composition, the tarball, includes the generation of many different
222
+ # packaging-specific files from templates in the source, and if faced
223
+ # with loading rpmversion in the Tar object vs rpmversion in the
224
+ # Config, I opt for the latter. It's basically a lose-lose, since it
225
+ # really belongs in the Rpm object.
226
+
227
+ def load_versioning
228
+ if @project_root and Pkg::Util::Git.describe
229
+ @ref = Pkg::Util::Git.sha_or_tag
230
+ @short_ref = Pkg::Util::Git.sha_or_tag(7)
231
+ @version = Pkg::Util::Version.dash_version
232
+ @gemversion = Pkg::Util::Version.dot_version
233
+ @debversion = Pkg::Util::Version.debversion
234
+ @origversion = Pkg::Util::Version.origversion
235
+ @rpmversion = Pkg::Util::Version.rpmversion
236
+ @rpmrelease = Pkg::Util::Version.rpmrelease
237
+ else
238
+ puts "Skipping determination of version via git describe, Pkg::Config.project_root is not set to the path of a tagged git repo."
239
+ end
240
+ end
241
+
242
+ ##
243
+ # Since we're dealing with rake, much of the parameter override support
244
+ # is via environment variables passed on the command line to a rake task.
245
+ # These override any existing values of Pkg::Config class instance
246
+ # variables
247
+ #
248
+ def load_envvars
249
+ Pkg::Params::ENV_VARS.each do |v|
250
+ if var = ENV[v[:envvar].to_s]
251
+ case v[:type]
252
+ when :bool
253
+ self.instance_variable_set("@#{v[:var]}", Pkg::Util.boolean_value(var))
254
+ when :array
255
+ self.instance_variable_set("@#{v[:var]}", string_to_array(var))
256
+ else
257
+ self.instance_variable_set("@#{v[:var]}", var)
258
+ end
259
+ end
260
+ end
261
+ end
262
+
263
+ ##
264
+ # We supply several values by default, if they haven't been specified
265
+ # already by config or environment variable. This includes the project
266
+ # root as the default project root, which is relative to the
267
+ # packaging path
268
+ #
269
+ def load_defaults
270
+ @project_root ||= default_project_root
271
+ @packaging_root ||= default_packaging_root
272
+
273
+ Pkg::Params::DEFAULTS.each do |v|
274
+ unless self.instance_variable_get("@#{v[:var]}")
275
+ self.instance_variable_set("@#{v[:var]}", v[:val])
276
+ end
277
+ end
278
+ end
279
+
280
+ ##
281
+ #
282
+ # Several workflows rely on being able to supply an optional yaml
283
+ # parameters file that overrides all set values with its data. This has
284
+ # always been supplied as an environment variable, "PARAMS_FILE." To
285
+ # honor this, we have a method in config to override values as
286
+ # expected. There is, however, a twist - it is absolutely essential
287
+ # that the overrides do not override the project_root or packaging_root
288
+ # settings, because this is environment-specific, and any value in a
289
+ # params file is going to be wrong. Thus, if we have a project root or
290
+ # packaging root before we begin overriding, we save it and restore it
291
+ # after overrides.
292
+ #
293
+ def load_overrides
294
+ if ENV['PARAMS_FILE'] && ENV['PARAMS_FILE'] != ''
295
+ if File.readable?(ENV['PARAMS_FILE'])
296
+ project_root = self.instance_variable_get("@project_root")
297
+ packaging_root = self.instance_variable_get("@packaging_root")
298
+ self.config_from_yaml(ENV['PARAMS_FILE'])
299
+ self.instance_variable_set("@project_root", project_root) if project_root
300
+ self.instance_variable_set("@packaging_root", packaging_root) if packaging_root
301
+ else
302
+ fail "PARAMS_FILE was set, but not to the path to a readable file."
303
+ end
304
+ end
305
+ end
306
+
307
+ ##
308
+ # We also have renamed various variables as part of deprecations, and
309
+ # if any of these are still in use, we want to assign the values to the
310
+ # new variables. However, we skip this if they target variable is already
311
+ # populated, to avoid overwriting in the case that the user has started
312
+ # by populating the new variable name but left the old crufty one behind.
313
+ #
314
+ def issue_reassignments
315
+ Pkg::Params::REASSIGNMENTS.each do |v|
316
+ oldval = self.instance_variable_get("@#{v[:oldvar]}")
317
+ newval = self.instance_variable_get("@#{v[:newvar]}")
318
+ if newval.nil? && oldval
319
+ self.instance_variable_set("@#{v[:newvar]}", oldval)
320
+ end
321
+ end
322
+ end
323
+
324
+ ##
325
+ # Quite a few variables we also want to issue custom warnings about.
326
+ # These are they.
327
+ #
328
+ def issue_deprecations
329
+ Pkg::Params::DEPRECATIONS.each do |v|
330
+ if self.instance_variable_get("@#{v[:var]}")
331
+ warn v[:message]
332
+ end
333
+ end
334
+ end
335
+
336
+ def string_to_array(str)
337
+ delimiters = /[,\s;]/
338
+ return str if str.respond_to?('each')
339
+ str.split(delimiters).reject { |s| s.empty? }.map { |s| s.strip }
340
+ end
341
+
342
+ # This method is duplicated from enterprise-dist so we can access it here.
343
+ def cow_to_codename_arch(cow)
344
+ /^base-(.*)-(.*)\.cow$/.match(cow).captures
345
+ end
346
+
347
+ # This method is duplicated from enterprise-dist so we can access it here.
348
+ def mock_to_dist_version_arch(mock)
349
+ # We care about matching against two patterns here:
350
+ # pupent-3.4-el5-i386 <= old style with PE_VER baked into the mock name
351
+ # pupent-el5-i386 <= new style derived from a template
352
+ mock.match(/pupent(-\d\.\d)?-([a-z]*)(\d*)-([^-]*)/)[2..4]
353
+ end
354
+
355
+ def deb_build_targets
356
+ if self.vanagon_project
357
+ self.deb_targets.split(' ')
358
+ else
359
+ self.cows.split(' ').map do |cow|
360
+ codename, arch = self.cow_to_codename_arch(cow)
361
+ "#{codename}-#{arch}"
362
+ end
363
+ end
364
+ end
365
+
366
+ def rpm_build_targets
367
+ if self.vanagon_project
368
+ self.rpm_targets.split(' ')
369
+ else
370
+ self.final_mocks.split(' ').map do |mock|
371
+ platform, version, arch = self.mock_to_dist_version_arch(mock)
372
+ "#{platform}-#{version}-#{arch}"
373
+ end
374
+ end
375
+ end
376
+
377
+ def yum_target_path(feature_branch = false)
378
+ if feature_branch || Pkg::Config.pe_feature_branch
379
+ return "#{Pkg::Config.yum_repo_path}/#{Pkg::Config.pe_version}/feature/repos/"
380
+ end
381
+ "#{Pkg::Config.yum_repo_path}/#{Pkg::Config.pe_version}/repos/"
382
+ end
383
+
384
+ def apt_target_path(feature_branch = false)
385
+ if feature_branch || Pkg::Config.pe_feature_branch
386
+ return "#{Pkg::Config.apt_repo_path}/#{Pkg::Config.pe_version}/feature/repos/"
387
+ end
388
+ "#{Pkg::Config.apt_repo_path}/#{Pkg::Config.pe_version}/repos/"
389
+ end
390
+ end
391
+ end
392
+ end