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
@@ -0,0 +1,202 @@
|
|
1
|
+
# Rake Task to dynamically create a Jenkins job to model the
|
2
|
+
# pl:jenkins:uber_build set of tasks in a Matrix job where each cell is an
|
3
|
+
# individual build to be run. This would be nice if we only had to create one job,
|
4
|
+
# but alas, we're actually creating three jobs.
|
5
|
+
# 1) a packaging job that builds the packages
|
6
|
+
# |
|
7
|
+
# V
|
8
|
+
# 2) a repo creation job that creates repos from those packages
|
9
|
+
# |
|
10
|
+
# V
|
11
|
+
# 3) (optional) a job to proxy the downstream job passed in via DOWNSTREAM_JOB
|
12
|
+
#
|
13
|
+
|
14
|
+
namespace :pl do
|
15
|
+
namespace :jenkins do
|
16
|
+
desc "Dynamic Jenkins UBER build: Build all the things with ONE job"
|
17
|
+
task :uber_build, [:poll_interval] => "pl:fetch" do |t, args|
|
18
|
+
args.with_defaults(:poll_interval => 0)
|
19
|
+
poll_interval = args.poll_interval.to_i
|
20
|
+
|
21
|
+
# If we have a dirty source, bail, because changes won't get reflected in
|
22
|
+
# the package builds
|
23
|
+
Pkg::Util::Git.fail_on_dirty_source
|
24
|
+
|
25
|
+
# Use JSON to parse the json part of the submission, so we want to fail
|
26
|
+
# here also if JSON isn't available
|
27
|
+
Pkg::Util.require_library_or_fail 'json'
|
28
|
+
|
29
|
+
# The uber_build.xml.erb file is an XML erb template that will define a
|
30
|
+
# job in Jenkins with all of the appropriate tasks
|
31
|
+
work_dir = Pkg::Util::File.mktemp
|
32
|
+
template_dir = File.join(File.dirname(__FILE__), '..', 'templates')
|
33
|
+
templates = ['repo.xml.erb', 'packaging.xml.erb']
|
34
|
+
templates << ('msi.xml.erb') if Pkg::Config.build_msi
|
35
|
+
templates << ('downstream.xml.erb') if ENV['DOWNSTREAM_JOB']
|
36
|
+
|
37
|
+
# Generate an XML file for every job configuration erb and attempt to
|
38
|
+
# create a jenkins job from that XML config
|
39
|
+
templates.each do |t|
|
40
|
+
erb_template = File.join(template_dir, t)
|
41
|
+
xml_file = File.join(work_dir, t.gsub('.erb', ''))
|
42
|
+
Pkg::Util::File.erb_file(erb_template, xml_file, nil, :binding => Pkg::Config.get_binding)
|
43
|
+
# If we're creating a job meant to run on a windows box, we need to limit the path length
|
44
|
+
# Max path length allowed is 260 chars, which we manage to exceed with this job name. Luckily,
|
45
|
+
# simply using the short sha rather than the long sha gets us just under the length limit. Gross fix,
|
46
|
+
# I know, but hey, it works for now.
|
47
|
+
if t == "msi.xml.erb"
|
48
|
+
ref = Pkg::Config.short_ref
|
49
|
+
else
|
50
|
+
ref = Pkg::Config.ref
|
51
|
+
end
|
52
|
+
job_name = "#{Pkg::Config.project}-#{t.gsub('.xml.erb', '')}-#{Pkg::Config.build_date}-#{ref}"
|
53
|
+
puts "Checking for existence of #{job_name}..."
|
54
|
+
if Pkg::Util::Jenkins.jenkins_job_exists?(job_name)
|
55
|
+
raise "Job #{job_name} already exists on #{Pkg::Config.jenkins_build_host}"
|
56
|
+
else
|
57
|
+
Pkg::Util::Execution.retry_on_fail(:times => 3) do
|
58
|
+
url = Pkg::Util::Jenkins.create_jenkins_job(job_name, xml_file)
|
59
|
+
if t == "packaging.xml.erb"
|
60
|
+
ENV["PACKAGE_BUILD_URL"] = url
|
61
|
+
end
|
62
|
+
puts "Verifying job created successfully..."
|
63
|
+
unless Pkg::Util::Jenkins.jenkins_job_exists?(job_name)
|
64
|
+
raise "Unable to verify Jenkins job, trying again..."
|
65
|
+
end
|
66
|
+
puts "Jenkins job created at #{url}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
rm_r work_dir
|
71
|
+
packaging_name = "#{Pkg::Config.project}-packaging-#{Pkg::Config.build_date}-#{Pkg::Config.ref}"
|
72
|
+
Pkg::Util::RakeUtils.invoke_task("pl:jenkins:trigger_dynamic_job", packaging_name)
|
73
|
+
|
74
|
+
if poll_interval > 0
|
75
|
+
##
|
76
|
+
# Wait for the '*packaging*' job to finish.
|
77
|
+
#
|
78
|
+
name = "#{Pkg::Config.project}-packaging-#{Pkg::Config.build_date}-#{Pkg::Config.ref}"
|
79
|
+
packaging_job_url = "http://#{Pkg::Config.jenkins_build_host}/job/#{name}"
|
80
|
+
|
81
|
+
packaging_build_hash = nil
|
82
|
+
Pkg::Util::Execution.retry_on_fail(:times => 10, :delay => 1) do
|
83
|
+
packaging_build_hash = Pkg::Util::Jenkins.poll_jenkins_job(packaging_job_url)
|
84
|
+
end
|
85
|
+
|
86
|
+
##
|
87
|
+
# Output status of packaging build for cli consumption
|
88
|
+
#
|
89
|
+
puts "Packaging #{packaging_build_hash['result']}"
|
90
|
+
|
91
|
+
if packaging_build_hash['result'] == 'FAILURE'
|
92
|
+
fail "Please see #{packaging_job_url} for failure details."
|
93
|
+
end
|
94
|
+
|
95
|
+
if Pkg::Config.build_msi
|
96
|
+
##
|
97
|
+
# Wait for the '*msi*' job to finish.
|
98
|
+
#
|
99
|
+
name = "#{Pkg::Config.project}-msi-#{Pkg::Config.build_date}-#{Pkg::Config.short_ref}"
|
100
|
+
msi_job_url = "http://#{Pkg::Config.jenkins_build_host}/job/#{name}"
|
101
|
+
|
102
|
+
msi_build_hash = nil
|
103
|
+
Pkg::Util::Execution.retry_on_fail(:times => 10, :delay => 1) do
|
104
|
+
msi_build_hash = Pkg::Util::Jenkins.poll_jenkins_job(msi_job_url)
|
105
|
+
end
|
106
|
+
|
107
|
+
##
|
108
|
+
# Output status of msi build for cli consumption
|
109
|
+
#
|
110
|
+
puts "MSI #{msi_build_hash['result']}"
|
111
|
+
|
112
|
+
if msi_build_hash['result'] == 'FAILURE'
|
113
|
+
fail "Please see #{msi_job_url} for failure details."
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
##
|
118
|
+
# Wait for the '*repo*' job to finish.
|
119
|
+
#
|
120
|
+
name = "#{Pkg::Config.project}-repo-#{Pkg::Config.build_date}-#{Pkg::Config.ref}"
|
121
|
+
repo_job_url = "http://#{Pkg::Config.jenkins_build_host}/job/#{name}"
|
122
|
+
|
123
|
+
repo_build_hash = nil
|
124
|
+
Pkg::Util::Execution.retry_on_fail(:times => 10, :delay => 1) do
|
125
|
+
repo_build_hash = Pkg::Util::Jenkins.poll_jenkins_job(repo_job_url)
|
126
|
+
end
|
127
|
+
|
128
|
+
##
|
129
|
+
# Output status of repo build for cli consumption
|
130
|
+
#
|
131
|
+
puts "Repo Creation #{repo_build_hash['result']}"
|
132
|
+
|
133
|
+
if repo_build_hash['result'] == 'FAILURE'
|
134
|
+
fail "Please see #{repo_job_url} for failure details."
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# Task to trigger the jenkins job we just created. This uses a lot of the
|
140
|
+
# same logic in jenkins.rake, with different parameters.
|
141
|
+
# TODO make all this replicated code a better, more abstract method
|
142
|
+
task :trigger_dynamic_job, :name do |t, args|
|
143
|
+
name = args.name
|
144
|
+
|
145
|
+
properties = Pkg::Config.config_to_yaml
|
146
|
+
bundle = Pkg::Util::Git.bundle('HEAD')
|
147
|
+
|
148
|
+
# Create a string of metrics to send to Jenkins for data analysis
|
149
|
+
if Pkg::Config.pe_version
|
150
|
+
metrics = "#{ENV['USER']}~#{Pkg::Config.version}~#{Pkg::Config.pe_version}~#{Pkg::Config.team}"
|
151
|
+
else
|
152
|
+
metrics = "#{ENV['USER']}~#{Pkg::Config.version}~N/A~#{Pkg::Config.team}"
|
153
|
+
end
|
154
|
+
|
155
|
+
# Construct the parameters, which is an array of hashes we turn into JSON
|
156
|
+
parameters = [{ "name" => "BUILD_PROPERTIES", "file" => "file0" },
|
157
|
+
{ "name" => "PROJECT_BUNDLE", "file" => "file1" },
|
158
|
+
{ "name" => "PROJECT", "value" => "#{Pkg::Config.project}" },
|
159
|
+
{ "name" => "METRICS", "value" => "#{metrics}" }]
|
160
|
+
|
161
|
+
# Contruct the json string
|
162
|
+
json = JSON.generate("parameter" => parameters)
|
163
|
+
|
164
|
+
# The args array that holds all of the arguments we pass
|
165
|
+
# to the curl utility method.
|
166
|
+
curl_args = [
|
167
|
+
"-Fname=BUILD_PROPERTIES", "-Ffile0=@#{properties}",
|
168
|
+
"-Fname=PROJECT_BUNDLE", "-Ffile1=@#{bundle}",
|
169
|
+
"-Fname=PROJECT", "-Fvalue=#{Pkg::Config.project}",
|
170
|
+
"-Fname=METRICS", "-Fvalue=#{metrics}",
|
171
|
+
"-FSubmit=Build",
|
172
|
+
"-Fjson=#{json.to_json}",
|
173
|
+
]
|
174
|
+
|
175
|
+
# Contstruct the job url
|
176
|
+
trigger_url = "#{Pkg::Config.jenkins_build_host}/job/#{name}/build"
|
177
|
+
|
178
|
+
_, retval = Pkg::Util::Net.curl_form_data(trigger_url, curl_args)
|
179
|
+
if Pkg::Util::Execution.success?(retval)
|
180
|
+
Pkg::Util::Net.print_url_info("http://#{Pkg::Config.jenkins_build_host}/job/#{name}")
|
181
|
+
puts "Your packages will be available at http://#{Pkg::Config.builds_server}/#{Pkg::Config.project}/#{Pkg::Config.ref}"
|
182
|
+
else
|
183
|
+
fail "An error occurred submitting the job to jenkins. Take a look at the preceding http response for more info."
|
184
|
+
end
|
185
|
+
|
186
|
+
# Clean up after ourselves
|
187
|
+
rm bundle
|
188
|
+
rm properties
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
namespace :pe do
|
194
|
+
namespace :jenkins do
|
195
|
+
desc "Dynamic Jenkins UBER build: Build all the things with ONE job"
|
196
|
+
task :uber_build, [:poll_interval] do |t, args|
|
197
|
+
Pkg::Util.check_var("PE_VER", Pkg::Config.pe_version)
|
198
|
+
args.with_defaults(:poll_interval => 0)
|
199
|
+
Rake::Task["pl:jenkins:uber_build"].invoke(args.poll_interval)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# The pl:load_extras tasks is intended to load variables
|
2
|
+
# from the extra yaml file downloaded by the pl:fetch task.
|
3
|
+
# The goal is to be able to augment/override settings in the
|
4
|
+
# source project's build_data.yaml and project_data.yaml with
|
5
|
+
# Puppet Labs-specific data, rather than having to clutter the
|
6
|
+
# generic tasks with data not generally useful outside the
|
7
|
+
# PL Release team
|
8
|
+
namespace :pl do
|
9
|
+
task :load_extras, :tempdir do |t, args|
|
10
|
+
unless ENV['PARAMS_FILE'] && ENV['PARAMS_FILE'] != ''
|
11
|
+
tempdir = args.tempdir
|
12
|
+
raise "pl:load_extras requires a directory containing extras data" if tempdir.nil?
|
13
|
+
Pkg::Config.config_from_yaml("#{tempdir}/#{Pkg::Config.builder_data_file}")
|
14
|
+
|
15
|
+
# Environment variables take precedence over those loaded from configs,
|
16
|
+
# so we make sure that any we clobbered are reset.
|
17
|
+
Pkg::Config.load_envvars
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
data/tasks/mock.rake
ADDED
@@ -0,0 +1,348 @@
|
|
1
|
+
# The mock methods/tasks are fairly specific to puppetlabs infrastructure, e.g., the mock configs
|
2
|
+
# have to be named in a format like the PL mocks, e.g. dist-version-architecture, such as:
|
3
|
+
# el-5-i386
|
4
|
+
# fedora-17-i386
|
5
|
+
# as well as the oddly formatted exception, 'pl-5-i386' which is the default puppetlabs FOSS mock
|
6
|
+
# format for 'el-5-i386' (note swap 'pl' for 'el')
|
7
|
+
#
|
8
|
+
# The mock-built rpms are placed in a directory structure under 'pkg' based on how the Puppet Labs
|
9
|
+
# repo structure is laid out in order to facilitate easy shipping from the local repository to the
|
10
|
+
# Puppet Labs repos. For open source, the directory structure mirrors that of yum.puppetlabs.com:
|
11
|
+
# pkg/<dist>/<version>/{products,devel,dependencies}/<arch>/*.rpm
|
12
|
+
# e.g.,
|
13
|
+
# pkg/el/5/products/i386/*.rpm
|
14
|
+
# pkg/fedora/f16/products/i386/*.rpm
|
15
|
+
#
|
16
|
+
# For PE, the directory structure is flatter:
|
17
|
+
# pkg/<dist>-<version>-<arch>/*.rpm
|
18
|
+
# e.g.,
|
19
|
+
# pkg/el-5-i386/*.rpm
|
20
|
+
def mock_artifact(mock_config, cmd_args, mockfile)
|
21
|
+
unless mock = Pkg::Util::Tool.find_tool('mock')
|
22
|
+
raise "mock is required for building srpms with mock. Please install mock and try again."
|
23
|
+
end
|
24
|
+
randomize = Pkg::Config.random_mockroot
|
25
|
+
configdir = nil
|
26
|
+
basedir = File.join('var', 'lib', 'mock')
|
27
|
+
|
28
|
+
if randomize
|
29
|
+
basedir, configdir = randomize_mock_config_dir(mock_config, mockfile)
|
30
|
+
configdir_arg = " --configdir #{configdir}"
|
31
|
+
end
|
32
|
+
result_dir = Pkg::Util::File.mktemp
|
33
|
+
resultdir_arg = " --resultdir #{result_dir}"
|
34
|
+
|
35
|
+
begin
|
36
|
+
sh "#{mock} -r #{mock_config} #{resultdir_arg} #{configdir_arg} #{cmd_args}"
|
37
|
+
|
38
|
+
# Return a FileList of the build artifacts
|
39
|
+
return FileList[File.join(result_dir, '*.rpm')]
|
40
|
+
|
41
|
+
rescue RuntimeError => error
|
42
|
+
build_log = File.join(result_dir, 'build.log')
|
43
|
+
root_log = File.join(result_dir, 'root.log')
|
44
|
+
content = File.read(build_log) if File.readable?(build_log)
|
45
|
+
|
46
|
+
if File.readable?(root_log)
|
47
|
+
$stderr.puts File.read(root_log)
|
48
|
+
end
|
49
|
+
if content and content.lines.count > 2
|
50
|
+
$stderr.puts content
|
51
|
+
end
|
52
|
+
|
53
|
+
# Any useful info has now been gleaned from the logs in the case of a
|
54
|
+
# failure, so we can safely remove basedir if this is a randomized mockroot
|
55
|
+
# build. Scarily enough, because of mock permissions, we can't actually
|
56
|
+
# just remove it, we have to sudo remove it.
|
57
|
+
|
58
|
+
if randomize and basedir and File.directory?(basedir)
|
59
|
+
sh "sudo -n rm -r #{basedir}"
|
60
|
+
sh "sudo -n rm -r #{result_dir}"
|
61
|
+
end
|
62
|
+
|
63
|
+
raise error
|
64
|
+
ensure
|
65
|
+
# Unlike basedir, which we keep in the success case, we don't need
|
66
|
+
# configdir anymore either way, so we always clean it up if we're using
|
67
|
+
# randomized mockroots.
|
68
|
+
#
|
69
|
+
rm_r configdir if randomize
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Use mock to build an SRPM
|
74
|
+
# Return the path to the srpm
|
75
|
+
def mock_srpm(mock_config, spec, sources, mockfile, defines = nil)
|
76
|
+
cmd_args = "--buildsrpm #{defines} --sources #{sources} --spec #{spec}"
|
77
|
+
srpms = mock_artifact(mock_config, cmd_args, mockfile)
|
78
|
+
|
79
|
+
unless srpms.size == 1
|
80
|
+
fail "#{srpms} contains an unexpected number of artifacts."
|
81
|
+
end
|
82
|
+
srpms[0]
|
83
|
+
end
|
84
|
+
|
85
|
+
# Use mock to build rpms from an srpm
|
86
|
+
# Return a FileList containing the built RPMs
|
87
|
+
def mock_rpm(mock_config, srpm, mockfile)
|
88
|
+
cmd_args = " #{srpm}"
|
89
|
+
mock_artifact(mock_config, cmd_args, mockfile)
|
90
|
+
end
|
91
|
+
|
92
|
+
# Determine the "family" of the target distribution based on the mock config name,
|
93
|
+
# e.g. pupent-3.0-el5-i386 = "el"
|
94
|
+
# and pl-fedora-17-i386 = "fedora"
|
95
|
+
#
|
96
|
+
def mock_el_family(mock_config)
|
97
|
+
if Pkg::Config.build_pe
|
98
|
+
# This uses a regex capture instead of splitting to allow the now defunct PE version component to be optional
|
99
|
+
family = mock_config.match(/^pupent-(\d\.\d-)?([a-z]+)([0-9]+)-(.*)$/)[2]
|
100
|
+
else
|
101
|
+
first, second = mock_config.split('-')
|
102
|
+
if first == 'el' || first == 'fedora'
|
103
|
+
family = first
|
104
|
+
elsif first == 'pl'
|
105
|
+
if second.match(/^\d+$/)
|
106
|
+
family = 'el'
|
107
|
+
else
|
108
|
+
family = second
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
family
|
113
|
+
end
|
114
|
+
|
115
|
+
# Determine the major version of the target distribution based on the mock config name,
|
116
|
+
# e.g. pupent-3.0-el5-i386 = "5"
|
117
|
+
# and "pl-fedora-17-i386" = "17"
|
118
|
+
#
|
119
|
+
def mock_el_ver(mock_config)
|
120
|
+
if Pkg::Config.build_pe
|
121
|
+
# This uses a regex capture instead of splitting to allow the now defunct PE version component to be optional
|
122
|
+
version = mock_config.match(/^pupent-(\d\.\d-)?([a-z]+)([0-9]+)-(.*)$/)[3]
|
123
|
+
else
|
124
|
+
first, second, third = mock_config.split('-')
|
125
|
+
if (first == 'el' || first == 'fedora') || (first == 'pl' && second.match(/^\d+$/))
|
126
|
+
version = second
|
127
|
+
else
|
128
|
+
version = third
|
129
|
+
end
|
130
|
+
end
|
131
|
+
if [first, second].include?('fedora')
|
132
|
+
version = "f#{version}"
|
133
|
+
end
|
134
|
+
version
|
135
|
+
end
|
136
|
+
|
137
|
+
# Return the RPM family and version for a Vanagon or Packaging repo built project.
|
138
|
+
def rpm_family_and_version
|
139
|
+
if Pkg::Config.vanagon_project
|
140
|
+
Pkg::Config.rpm_targets.split(' ').map do |target|
|
141
|
+
rpm_el_family, rpm_el_version, arch = target.split('-')
|
142
|
+
"#{rpm_el_family}-#{rpm_el_version}"
|
143
|
+
end
|
144
|
+
else
|
145
|
+
Pkg::Config.final_mocks.split.map { |mock| "#{mock_el_family(mock)}-#{mock_el_ver(mock) }" }
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
|
150
|
+
# Checks to see if the pe agnostic config template is in place.
|
151
|
+
# If it is then the mock config is set to point to the generated config file.
|
152
|
+
# The generated config file is formed by substituting the pe_version into the erb
|
153
|
+
#
|
154
|
+
def mock_template(mock_config)
|
155
|
+
Pkg::Util.check_var("PE version, ENV[PE_VER]", Pkg::Config.pe_version)
|
156
|
+
# pe_version is used in the erb template
|
157
|
+
pe_version = Pkg::Config.pe_version
|
158
|
+
# This bit is fun, here we remove any x.y version in the PE version location in the string from the mock_config
|
159
|
+
# for example, pupent-3.4-el5-i386.cfg would become pupent-el5-i386 while pupent-el7-x86_64 would remain unmodified.
|
160
|
+
template = mock_config.sub(/([^-]*)-\d\.\d-([^-]*)-([^-]*)/, '\1-\2-\3')
|
161
|
+
template_location = File.join(File::SEPARATOR, "etc", "mock", "#{template}.cfg.erb")
|
162
|
+
if File.exists?(template_location)
|
163
|
+
return template, Pkg::Util::File.erb_file(template_location, nil, false, { :binding => binding })
|
164
|
+
else
|
165
|
+
return mock_config
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
# Determine the appropriate rpm macro definitions based on the mock config name
|
170
|
+
# Return a string of space separated macros prefixed with --define
|
171
|
+
#
|
172
|
+
def mock_defines(mock_config)
|
173
|
+
family = mock_el_family(mock_config)
|
174
|
+
version = mock_el_ver(mock_config)
|
175
|
+
defines = ""
|
176
|
+
if version =~ /^(4|5)$/ or family == "sles"
|
177
|
+
defines = %Q(--define "dist .#{family}#{version}" \
|
178
|
+
--define "_source_filedigest_algorithm 1" \
|
179
|
+
--define "_binary_filedigest_algorithm 1" \
|
180
|
+
--define "_binary_payload w9.gzdio" \
|
181
|
+
--define "_source_payload w9.gzdio" \
|
182
|
+
--define "_default_patch_fuzz 2")
|
183
|
+
end
|
184
|
+
defines
|
185
|
+
end
|
186
|
+
|
187
|
+
def build_rpm_with_mock(mocks)
|
188
|
+
mocks.split(' ').each do |mock_config|
|
189
|
+
family = mock_el_family(mock_config)
|
190
|
+
version = mock_el_ver(mock_config)
|
191
|
+
subdir = if Pkg::Config.yum_repo_name
|
192
|
+
Pkg::Config.yum_repo_name
|
193
|
+
else
|
194
|
+
Pkg::Util::Version.is_final? ? 'products' : 'devel'
|
195
|
+
end
|
196
|
+
bench = Benchmark.realtime do
|
197
|
+
# Set up the rpmbuild dir in a temp space, with our tarball and spec
|
198
|
+
workdir = prep_rpm_build_dir
|
199
|
+
spec = Dir.glob(File.join(workdir, "SPECS", "*.spec"))[0]
|
200
|
+
sources = File.join(workdir, "SOURCES")
|
201
|
+
defines = mock_defines(mock_config)
|
202
|
+
if Pkg::Config.build_pe
|
203
|
+
mock_config, mockfile = mock_template(mock_config)
|
204
|
+
end
|
205
|
+
# Build the srpm inside a mock chroot
|
206
|
+
srpm = mock_srpm(mock_config, spec, sources, mockfile, defines)
|
207
|
+
|
208
|
+
# Now that we have the srpm, build the rpm in a mock chroot
|
209
|
+
rpms = mock_rpm(mock_config, srpm, mockfile)
|
210
|
+
|
211
|
+
rpms.each do |rpm|
|
212
|
+
rpm.strip!
|
213
|
+
|
214
|
+
if Pkg::Config.build_pe
|
215
|
+
%x(mkdir -p pkg/pe/rpm/#{family}-#{version}-{srpms,i386,x86_64})
|
216
|
+
case File.basename(rpm)
|
217
|
+
when /debuginfo/
|
218
|
+
rm_rf(rpm)
|
219
|
+
when /src\.rpm/
|
220
|
+
FileUtils.cp_r(rpm, "pkg/pe/rpm/#{family}-#{version}-srpms", { :preserve => true })
|
221
|
+
when /i.?86/
|
222
|
+
FileUtils.cp_r(rpm, "pkg/pe/rpm/#{family}-#{version}-i386", { :preserve => true })
|
223
|
+
when /x86_64/
|
224
|
+
FileUtils.cp_r(rpm, "pkg/pe/rpm/#{family}-#{version}-x86_64", { :preserve => true })
|
225
|
+
when /noarch/
|
226
|
+
FileUtils.cp_r(rpm, "pkg/pe/rpm/#{family}-#{version}-i386", { :preserve => true })
|
227
|
+
FileUtils.ln("pkg/pe/rpm/#{family}-#{version}-i386/#{File.basename(rpm)}", "pkg/pe/rpm/#{family}-#{version}-x86_64/", :force => true, :verbose => true)
|
228
|
+
end
|
229
|
+
elsif subdir == 'PC1' || !Pkg::Config.yum_repo_name
|
230
|
+
%x(mkdir -p pkg/#{family}/#{version}/#{subdir}/{SRPMS,i386,x86_64})
|
231
|
+
case File.basename(rpm)
|
232
|
+
when /debuginfo/
|
233
|
+
rm_rf(rpm)
|
234
|
+
when /src\.rpm/
|
235
|
+
FileUtils.cp_r(rpm, "pkg/#{family}/#{version}/#{subdir}/SRPMS", { :preserve => true })
|
236
|
+
when /i.?86/
|
237
|
+
FileUtils.cp_r(rpm, "pkg/#{family}/#{version}/#{subdir}/i386", { :preserve => true })
|
238
|
+
when /x86_64/
|
239
|
+
FileUtils.cp_r(rpm, "pkg/#{family}/#{version}/#{subdir}/x86_64", { :preserve => true })
|
240
|
+
when /noarch/
|
241
|
+
FileUtils.cp_r(rpm, "pkg/#{family}/#{version}/#{subdir}/i386", { :preserve => true })
|
242
|
+
FileUtils.ln("pkg/#{family}/#{version}/#{subdir}/i386/#{File.basename(rpm)}", "pkg/#{family}/#{version}/#{subdir}/x86_64/", :force => true, :verbose => true)
|
243
|
+
end
|
244
|
+
else
|
245
|
+
%x(mkdir -p pkg/#{subdir}/#{family}/#{version}/{SRPMS,i386,x86_64})
|
246
|
+
case File.basename(rpm)
|
247
|
+
when /debuginfo/
|
248
|
+
rm_rf(rpm)
|
249
|
+
when /src\.rpm/
|
250
|
+
FileUtils.cp_r(rpm, "pkg/#{subdir}/#{family}/#{version}/SRPMS", { :preserve => true })
|
251
|
+
when /i.?86/
|
252
|
+
FileUtils.cp_r(rpm, "pkg/#{subdir}/#{family}/#{version}/i386", { :preserve => true })
|
253
|
+
when /x86_64/
|
254
|
+
FileUtils.cp_r(rpm, "pkg/#{subdir}/#{family}/#{version}/x86_64", { :preserve => true })
|
255
|
+
when /noarch/
|
256
|
+
FileUtils.cp_r(rpm, "pkg/#{subdir}/#{family}/#{version}/i386", { :preserve => true })
|
257
|
+
FileUtils.ln("pkg/#{subdir}/#{family}/#{version}/i386/#{File.basename(rpm)}", "pkg/#{subdir}/#{family}/#{version}/x86_64/", :force => true, :verbose => true)
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
# To avoid filling up the system with our random mockroots, we should
|
262
|
+
# clean up. However, this requires sudo. If we don't have sudo, we'll
|
263
|
+
# just fail and not clean up, but warn the user about it.
|
264
|
+
if Pkg::Config.random_mockroot
|
265
|
+
%x(sudo -n echo 'Cleaning build root.')
|
266
|
+
if $?.success?
|
267
|
+
sh "sudo -n rm -r #{File.dirname(srpm)}" unless File.dirname(srpm).nil?
|
268
|
+
sh "sudo -n rm -r #{File.dirname(rpms[0])}" unless File.dirname(rpms[0]).nil?
|
269
|
+
sh "sudo -n rm -r #{workdir}" unless workdir.nil?
|
270
|
+
else
|
271
|
+
warn "Couldn't clean rpm build areas without sudo. Leaving."
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
puts "Finished building in: #{bench}"
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
# With the advent of using Jenkins to parallelize builds, it becomes critical
|
280
|
+
# that we be able to use the same mock at the same time for > 1 builds without
|
281
|
+
# clobbering the mock root every time. Here we add a method that takes the full
|
282
|
+
# path to a mock configuration and a path, and adds a base directory
|
283
|
+
# configuration directive to the mock to use the path as the directory for the
|
284
|
+
# mock build root. The new mock config is written to a temporary space, and its
|
285
|
+
# location is returned. This allows us to create mock configs with randomized
|
286
|
+
# temporary mock roots.
|
287
|
+
#
|
288
|
+
def mock_with_basedir(mock, basedir)
|
289
|
+
config = IO.readlines(mock)
|
290
|
+
basedir = "config_opts['basedir'] = '#{basedir}'"
|
291
|
+
config.unshift(basedir)
|
292
|
+
tempdir = Pkg::Util::File.mktemp
|
293
|
+
newmock = File.join(tempdir, File.basename(mock))
|
294
|
+
File.open(newmock, 'w') { |f| f.puts config }
|
295
|
+
newmock
|
296
|
+
end
|
297
|
+
|
298
|
+
# Mock accepts an alternate configuration directory to /etc/mock for mock
|
299
|
+
# configs, but the directory has to include both site-defaults.cfg and
|
300
|
+
# logging.ini. This is a simple utility method to set a mock configuration dir
|
301
|
+
# by copying a mock and the required defaults to a temporary directory and
|
302
|
+
# returning that directory. This method takes the full path to a mock
|
303
|
+
# configuration file and returns the path to the new configuration dir.
|
304
|
+
#
|
305
|
+
def setup_mock_config_dir(mock)
|
306
|
+
tempdir = Pkg::Util::File.mktemp
|
307
|
+
cp File.join('/', 'etc', 'mock', 'site-defaults.cfg'), tempdir
|
308
|
+
cp File.join('/', 'etc', 'mock', 'logging.ini'), tempdir
|
309
|
+
cp mock, tempdir
|
310
|
+
tempdir
|
311
|
+
end
|
312
|
+
|
313
|
+
# Create a mock config file from an existing one, except insert the 'basedir'
|
314
|
+
# option. 'basedir' will be set to a random directory we create. Move the new
|
315
|
+
# mock config and the required default mock settings files into a new config
|
316
|
+
# dir to pass to mock. Return the path to the config dir.
|
317
|
+
#
|
318
|
+
def randomize_mock_config_dir(mock_config, mockfile)
|
319
|
+
# basedir will be the location of our temporary mock root
|
320
|
+
basedir = Pkg::Util::File.mktemp
|
321
|
+
chown("#{ENV['USER']}", "mock", basedir)
|
322
|
+
# Mock requires the sticky bit be set on the basedir
|
323
|
+
chmod(02775, basedir)
|
324
|
+
mockfile ||= File.join('/', 'etc', 'mock', "#{mock_config}.cfg")
|
325
|
+
puts "Setting mock basedir to #{basedir}"
|
326
|
+
# Create a new mock config file with 'basedir' set to our basedir
|
327
|
+
config = mock_with_basedir(mockfile, basedir)
|
328
|
+
# Setup a mock config dir, copying in our mock config and logging.ini etc
|
329
|
+
configdir = setup_mock_config_dir(config)
|
330
|
+
# Clean up the directory with the temporary mock config
|
331
|
+
rm_r File.dirname(config)
|
332
|
+
return basedir, configdir
|
333
|
+
end
|
334
|
+
|
335
|
+
|
336
|
+
namespace :pl do
|
337
|
+
desc "Use default mock to make a final rpm, keyed to PL infrastructure, pass MOCK to specify config"
|
338
|
+
task :mock => "package:tar" do
|
339
|
+
# If default mock isn't specified, just take the first one in the Pkg::Config.final_mocks list
|
340
|
+
Pkg::Config.default_mock ||= Pkg::Config.final_mocks.split(' ')[0]
|
341
|
+
build_rpm_with_mock(Pkg::Config.default_mock)
|
342
|
+
end
|
343
|
+
|
344
|
+
desc "Use specified mocks to make rpms, keyed to PL infrastructure, pass MOCK to specifiy config"
|
345
|
+
task :mock_all => "package:tar" do
|
346
|
+
build_rpm_with_mock(Pkg::Config.final_mocks)
|
347
|
+
end
|
348
|
+
end
|