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.
- checksums.yaml +7 -0
- data/LICENSE +17 -0
- data/README-Solaris.md +117 -0
- data/README.md +1031 -0
- data/lib/packaging.rb +32 -0
- data/lib/packaging/artifactory.rb +278 -0
- data/lib/packaging/config.rb +392 -0
- data/lib/packaging/config/params.rb +366 -0
- data/lib/packaging/deb.rb +28 -0
- data/lib/packaging/deb/repo.rb +263 -0
- data/lib/packaging/gem.rb +112 -0
- data/lib/packaging/ips.rb +57 -0
- data/lib/packaging/msi.rb +89 -0
- data/lib/packaging/nuget.rb +39 -0
- data/lib/packaging/osx.rb +36 -0
- data/lib/packaging/paths.rb +238 -0
- data/lib/packaging/platforms.rb +480 -0
- data/lib/packaging/repo.rb +55 -0
- data/lib/packaging/retrieve.rb +46 -0
- data/lib/packaging/rpm.rb +5 -0
- data/lib/packaging/rpm/repo.rb +257 -0
- data/lib/packaging/tar.rb +154 -0
- data/lib/packaging/util.rb +146 -0
- data/lib/packaging/util/date.rb +15 -0
- data/lib/packaging/util/execution.rb +85 -0
- data/lib/packaging/util/file.rb +125 -0
- data/lib/packaging/util/git.rb +174 -0
- data/lib/packaging/util/git_tags.rb +73 -0
- data/lib/packaging/util/gpg.rb +62 -0
- data/lib/packaging/util/jenkins.rb +95 -0
- data/lib/packaging/util/misc.rb +69 -0
- data/lib/packaging/util/net.rb +368 -0
- data/lib/packaging/util/os.rb +17 -0
- data/lib/packaging/util/platform.rb +40 -0
- data/lib/packaging/util/rake_utils.rb +111 -0
- data/lib/packaging/util/serialization.rb +19 -0
- data/lib/packaging/util/ship.rb +171 -0
- data/lib/packaging/util/tool.rb +41 -0
- data/lib/packaging/util/version.rb +326 -0
- data/spec/fixtures/config/ext/build_defaults.yaml +2 -0
- data/spec/fixtures/config/ext/project_data.yaml +2 -0
- data/spec/fixtures/config/params.yaml +2 -0
- data/spec/fixtures/configs/components/test_file.json +1 -0
- data/spec/fixtures/configs/components/test_file_2.json +0 -0
- data/spec/fixtures/configs/components/test_file_not_tagged.json +1 -0
- data/spec/fixtures/configs/components/test_file_wrong_ext.txt +0 -0
- data/spec/fixtures/configs/components/test_file_wrong_ext.wrong +0 -0
- data/spec/fixtures/util/pre_tasks.yaml +4 -0
- data/spec/lib/packaging/artifactory_spec.rb +171 -0
- data/spec/lib/packaging/config_spec.rb +556 -0
- data/spec/lib/packaging/deb/repo_spec.rb +148 -0
- data/spec/lib/packaging/deb_spec.rb +52 -0
- data/spec/lib/packaging/paths_spec.rb +153 -0
- data/spec/lib/packaging/platforms_spec.rb +153 -0
- data/spec/lib/packaging/repo_spec.rb +97 -0
- data/spec/lib/packaging/retrieve_spec.rb +61 -0
- data/spec/lib/packaging/rpm/repo_spec.rb +133 -0
- data/spec/lib/packaging/tar_spec.rb +122 -0
- data/spec/lib/packaging/util/execution_spec.rb +56 -0
- data/spec/lib/packaging/util/file_spec.rb +139 -0
- data/spec/lib/packaging/util/git_spec.rb +160 -0
- data/spec/lib/packaging/util/git_tag_spec.rb +36 -0
- data/spec/lib/packaging/util/gpg_spec.rb +64 -0
- data/spec/lib/packaging/util/jenkins_spec.rb +112 -0
- data/spec/lib/packaging/util/misc_spec.rb +31 -0
- data/spec/lib/packaging/util/net_spec.rb +239 -0
- data/spec/lib/packaging/util/os_spec.rb +31 -0
- data/spec/lib/packaging/util/rake_utils_spec.rb +70 -0
- data/spec/lib/packaging/util/ship_spec.rb +117 -0
- data/spec/lib/packaging/util/version_spec.rb +123 -0
- data/spec/lib/packaging_spec.rb +19 -0
- data/spec/spec_helper.rb +36 -0
- data/static_artifacts/PackageInfo.plist +3 -0
- data/tasks/00_utils.rake +216 -0
- data/tasks/30_metrics.rake +33 -0
- data/tasks/apple.rake +266 -0
- data/tasks/build.rake +12 -0
- data/tasks/clean.rake +5 -0
- data/tasks/config.rake +30 -0
- data/tasks/deb.rake +129 -0
- data/tasks/deb_repos.rake +28 -0
- data/tasks/deprecated.rake +130 -0
- data/tasks/doc.rake +20 -0
- data/tasks/education.rake +57 -0
- data/tasks/fetch.rake +57 -0
- data/tasks/gem.rake +146 -0
- data/tasks/jenkins.rake +494 -0
- data/tasks/jenkins_dynamic.rake +202 -0
- data/tasks/load_extras.rake +21 -0
- data/tasks/mock.rake +348 -0
- data/tasks/nightly_repos.rake +335 -0
- data/tasks/pe_deb.rake +12 -0
- data/tasks/pe_rpm.rake +13 -0
- data/tasks/pe_ship.rake +221 -0
- data/tasks/pe_sign.rake +13 -0
- data/tasks/pe_tar.rake +5 -0
- data/tasks/retrieve.rake +45 -0
- data/tasks/rpm.rake +66 -0
- data/tasks/rpm_repos.rake +29 -0
- data/tasks/ship.rake +752 -0
- data/tasks/sign.rake +226 -0
- data/tasks/tag.rake +8 -0
- data/tasks/tar.rake +34 -0
- data/tasks/update.rake +16 -0
- data/tasks/vanagon.rake +35 -0
- data/tasks/vendor_gems.rake +117 -0
- data/tasks/version.rake +33 -0
- data/tasks/z_data_dump.rake +65 -0
- data/templates/README +1 -0
- data/templates/downstream.xml.erb +47 -0
- data/templates/msi.xml.erb +197 -0
- data/templates/packaging.xml.erb +344 -0
- data/templates/repo.xml.erb +114 -0
- metadata +234 -0
data/lib/packaging.rb
ADDED
@@ -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
|