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,146 @@
1
+ if Pkg::Config.build_gem
2
+ require 'rubygems/package_task'
3
+
4
+ def glob_gem_files
5
+ gem_files = []
6
+ gem_excludes_file_list = []
7
+ gem_excludes_raw = Pkg::Config.gem_excludes.nil? ? [] : Pkg::Config.gem_excludes.split(' ')
8
+ gem_excludes_raw << 'ext/packaging'
9
+ gem_excludes_raw << 'pkg'
10
+ gem_excludes_raw.each do |exclude|
11
+ if File.directory?(exclude)
12
+ gem_excludes_file_list += FileList["#{exclude}/**/*"]
13
+ else
14
+ gem_excludes_file_list << exclude
15
+ end
16
+ end
17
+ files = FileList[Pkg::Config.gem_files.split(' ')]
18
+ files.each do |file|
19
+ if File.directory?(file)
20
+ gem_files += FileList["#{file}/**/*"]
21
+ else
22
+ gem_files << file
23
+ end
24
+ end
25
+ gem_files -= gem_excludes_file_list
26
+ end
27
+
28
+ def add_gem_dependency(opts = {})
29
+ spec = opts[:spec]
30
+ version = opts[:version]
31
+ type = opts[:type].to_s
32
+ gem = opts[:gem].to_s
33
+ if opts[:version].nil? or opts[:version].empty?
34
+ spec.send("add_#{type}_dependency".to_sym, gem)
35
+ else
36
+ spec.send("add_#{type}_dependency".to_sym, gem, version)
37
+ end
38
+ spec
39
+ end
40
+
41
+ def create_default_gem_spec
42
+ spec = Gem::Specification.new do |s|
43
+ s.name = Pkg::Config.project unless Pkg::Config.project.nil?
44
+ s.name = Pkg::Config.gem_name unless Pkg::Config.gem_name.nil?
45
+ s.version = Pkg::Config.gemversion unless Pkg::Config.gemversion.nil?
46
+ s.author = Pkg::Config.author unless Pkg::Config.author.nil?
47
+ s.email = Pkg::Config.email unless Pkg::Config.email.nil?
48
+ s.homepage = Pkg::Config.homepage unless Pkg::Config.homepage.nil?
49
+ s.summary = Pkg::Config.summary unless Pkg::Config.summary.nil?
50
+ s.summary = Pkg::Config.gem_summary unless Pkg::Config.gem_summary.nil?
51
+ s.description = Pkg::Config.description unless Pkg::Config.description.nil?
52
+ s.description = Pkg::Config.gem_description unless Pkg::Config.gem_description.nil?
53
+ s.files = glob_gem_files unless glob_gem_files.nil?
54
+ s.executables = Pkg::Config.gem_executables unless Pkg::Config.gem_executables.nil?
55
+ s.require_path = Pkg::Config.gem_require_path unless Pkg::Config.gem_require_path.nil?
56
+ s.required_ruby_version = Pkg::Config.gem_required_ruby_version unless Pkg::Config.gem_required_ruby_version.nil?
57
+ s.required_rubygems_version = Pkg::Config.gem_required_rubygems_version unless Pkg::Config.gem_required_rubygems_version.nil?
58
+ s.test_files = FileList[Pkg::Config.gem_test_files.split(' ')] unless Pkg::Config.gem_test_files.nil?
59
+ s.rubyforge_project = Pkg::Config.gem_forge_project unless Pkg::Config.gem_forge_project.nil?
60
+ Pkg::Config.gem_rdoc_options.each do |option|
61
+ s.rdoc_options << option
62
+ end unless Pkg::Config.gem_rdoc_options.nil?
63
+ end
64
+
65
+ Pkg::Config.gem_runtime_dependencies.each do |gem, version|
66
+ spec = add_gem_dependency(:spec => spec, :gem => gem, :version => version, :type => :runtime)
67
+ end unless Pkg::Config.gem_runtime_dependencies.nil?
68
+
69
+ Pkg::Config.gem_development_dependencies.each do |gem, version|
70
+ spec = add_gem_dependency(:spec => spec, :gem => gem, :version => version, :type => :development)
71
+ end unless Pkg::Config.gem_development_dependencies.nil?
72
+ spec
73
+ end
74
+
75
+ def create_gem(spec, gembuilddir)
76
+ gem_files = glob_gem_files + FileList[(Pkg::Config.gem_test_files || '').split(' ')]
77
+ workdir = File.join(Pkg::Util::File.mktemp)
78
+
79
+ bench = Benchmark.realtime do
80
+ Pkg::Util::File.install_files_into_dir(gem_files, workdir)
81
+
82
+ cd workdir do
83
+ gem_task = Gem::PackageTask.new(spec)
84
+ gem_task.define
85
+ Rake::Task[:gem].reenable
86
+ Rake::Task[:gem].invoke
87
+ rm_rf File.join("pkg", gembuilddir)
88
+ mv Dir.glob("pkg/#{Pkg::Config.gem_name}-#{Pkg::Config.gemversion}*.gem"), File.join(Pkg::Config.project_root, "pkg")
89
+ end
90
+ end
91
+
92
+ rm_rf workdir
93
+ puts "Finished building in: #{bench}"
94
+ end
95
+
96
+ def create_default_gem
97
+ spec = create_default_gem_spec
98
+ create_gem(spec, "#{Pkg::Config.gem_name}-#{Pkg::Config.gemversion}")
99
+ end
100
+
101
+ def unknown_gems_platform?(platform)
102
+ return true if platform.os == "unknown"
103
+ false
104
+ end
105
+
106
+ def create_platform_specific_gems
107
+ Pkg::Config.gem_platform_dependencies.each do |platform, dependency_hash|
108
+ spec = create_default_gem_spec
109
+ pf = Gem::Platform.new(platform)
110
+ fail "
111
+ Platform: '#{platform}' is not recognized by rubygems.
112
+ This is probably an erroneous 'gem_platform_dependencies' entry!" if unknown_gems_platform?(pf)
113
+ spec.platform = pf
114
+ dependency_hash.each do |type, gems|
115
+ t = case type
116
+ when "gem_runtime_dependencies"
117
+ "runtime"
118
+ when "gem_development_dependencies"
119
+ "development"
120
+ else
121
+ fail "Platform specific gem dependency type must be 'gem_runtime_dependencies' or 'gem_development_dependencies', not '#{type}'"
122
+ end
123
+ gems.each do |gem, version|
124
+ spec = add_gem_dependency(:spec => spec, :gem => gem, :version => version, :type => t)
125
+ end
126
+ end
127
+ create_gem(spec, "#{Pkg::Config.gem_name}-#{Pkg::Config.gemversion}-#{platform}")
128
+ end
129
+ end
130
+
131
+ namespace :package do
132
+ desc "Build a gem - All gems if platform specific"
133
+ task :gem => ["clean"] do
134
+ mkdir_p File.join(Pkg::Config.project_root, "pkg")
135
+ create_default_gem
136
+ if Pkg::Config.gem_platform_dependencies
137
+ create_platform_specific_gems
138
+ end
139
+ end
140
+ end
141
+
142
+ # An alias task to simplify our remote logic in jenkins.rake
143
+ namespace :pl do
144
+ task :gem => "package:gem"
145
+ end
146
+ end
@@ -0,0 +1,494 @@
1
+ ##
2
+ # The jenkins tasks enable the packaging repo to kick off packaging builds on a
3
+ # remote jenkins slave. They work in a similar way to the :remote tasks, but
4
+ # with a few key differences. The jenkins tasks transmit information to a
5
+ # jenkins coordinator, which handles the rest. The data passed are the
6
+ # following:
7
+ #
8
+ # 1) $PROJECT_BUNDLE - a tar.gz of a git-bundle from HEAD of the current
9
+ # project, which is cloned on the builder to set up a duplicate of this
10
+ # environment
11
+ #
12
+ # 2) $BUILD_PROPERTIES - a build parameters file, containing all information about the build
13
+ #
14
+ # 3) $BUILD_TYPE - the "type" of build, e.g. rpm, deb, gem, etc The jenkins url and job name
15
+ # are obtained via the team build-data file at
16
+ # git@github.com/puppetlabs/build-data
17
+ #
18
+ # 4) $PROJECT - the project we're building, e.g. facter, puppet. This is used later in
19
+ # determining the target for the build artifacts on the distribution server
20
+ #
21
+ # On the Jenkins end, the job is a parameterized job that accepts four
22
+ # parameters. Jenkins has the Parameterized Trigger Plugin, Workspace Cleanup
23
+ # Plugin, and Node and Label Parameter Plugin in use for this job. The
24
+ # workspace cleanup plugin cleans the workspace before each build. Two are file
25
+ # parameters, a string parameter, and a Label parameter provided by the Node
26
+ # and Label Parameter Plugin, as described above. When th pl:jenkins:post task
27
+ # triggers a build, it passes values for all of these parameters. The Label
28
+ # parameter is associated with the build type. This way we can queue the job on
29
+ # a builder with the appropriate capabilities just by assigning a builder the
30
+ # label "deb" or "rpm," etc. The actual build itself is accomplished via a
31
+ # shell build task. The contents of the task are:
32
+ #
33
+ #################
34
+ #
35
+ # #!/bin/bash
36
+ #
37
+ # SHA=$(echo $BUILD_PROPERTIES | cut -d '.' -f1)
38
+ #
39
+ # echo "Build type: $BUILD_TYPE"
40
+ #
41
+ # ### Create a local clone of the git-bundle that was passed
42
+ # # The bundle is a tarball, and since this is a project-agnostic
43
+ # # job, we don't actually know what's in it, just that it's a
44
+ # # git bundle.
45
+ # #
46
+ #
47
+ # [ -f "PROJECT_BUNDLE" ] || exit 1
48
+ # mkdir project && tar -xzf PROJECT_BUNDLE -C project/
49
+ #
50
+ # pushd project
51
+ # git clone --recursive $(ls) git_repo
52
+ #
53
+ # pushd git_repo
54
+ #
55
+ # ### Clone the packaging repo
56
+ # rake package:bootstrap
57
+ #
58
+ # ### Perform the build
59
+ # rake pl:build_from_params PARAMS_FILE=$WORKSPACE/BUILD_PROPERTIES
60
+ #
61
+ # ### Send the results
62
+ # rake pl:jenkins:ship["artifacts"] PARAMS_FILE=$WORKSPACE/BUILD_PROPERTIES
63
+ #
64
+ # popd
65
+ # popd
66
+ #
67
+ # ### Create the repositories from our project by trigger a downstream job
68
+ # ### Because we can't trigger downstream with a File Parameter, we use curl
69
+ # if [ "$BUILD_TYPE" = "rpm" ] || [ "$BUILD_TYPE" = "deb" ] ; then
70
+ # curl -i -Fname=PROJECT_BUNDLE -Ffile0=@PROJECT_BUNDLE -FSubmit=Build -Fjson="{\"parameter\":[{\"name\":\"PROJECT_BUNDLE\",\"file\":\"file0\"}]}" \
71
+ # http://jenkins-release.delivery.puppetlabs.net/job/puppetlabs-packaging-repo-creation/build
72
+ # fi
73
+ #
74
+ # ### If a downstream job was passed, trigger it now
75
+ # if [ -n "$DOWNSTREAM_JOB" ] ; then
76
+ # pushd project
77
+ # pushd git_repo
78
+ # rake pl:jenkins:post["$DOWNSTREAM_JOB"] PARAMS_FILE=$WORKSPACE/BUILD_PROPERTIES
79
+ # popd
80
+ # popd
81
+ # fi
82
+ #
83
+ #################
84
+
85
+ namespace :pl do
86
+ namespace :jenkins do
87
+ ##
88
+ # Do the heavy lifting. This task generates the URL for the jenkins job and posts it.
89
+ # It expects a the following arguments
90
+ # 1. :build_task => The lower-level pl: or pe: task we're executing, e.g. pl:deb_all
91
+ #
92
+ task :post_build, :build_task do |t, args|
93
+ # Check for a dirty tree before allowing a remote build that is doomed to unexpected results
94
+ Pkg::Util::Git.fail_on_dirty_source
95
+
96
+ # We use JSON for parsing the json part of the submission to JSON
97
+ Pkg::Util.require_library_or_fail 'json'
98
+
99
+ build_task = args.build_task
100
+ ##
101
+ # We set @:task of Pkg::Config manually with our task data so the remote
102
+ # build knows what to do. Puppetdb needs early knowledge of if this is
103
+ # a PE build, so we always this along as an environment variable task
104
+ # argument if its the case.
105
+ #
106
+ Pkg::Config.task = { :task => "#{build_task}", :args => nil }
107
+ Pkg::Config.task[:args] = ["PE_BUILD=true"] if @build_pe
108
+ #
109
+ # Determine the type of build we're doing to inform jenkins
110
+ build_type = case build_task
111
+ when /deb/
112
+ if Pkg::Config.default_cow.split('-')[1] =~ /cumulus/
113
+ "cumulus"
114
+ else
115
+ "deb"
116
+ end
117
+ when /mock/ then "rpm"
118
+ when /dmg|apple/ then "dmg"
119
+ when /gem/ then "gem"
120
+ when /tar/ then "tar"
121
+ else raise "Could not determine build type for #{build_task}"
122
+ end
123
+
124
+ # Create a string of metrics to send to Jenkins for data analysis
125
+ dist = case build_type
126
+ when /deb/ then Pkg::Config.default_cow.split('-')[1]
127
+ when /rpm/
128
+ if Pkg::Config.pe_version
129
+ Pkg::Config.final_mocks.split(' ')[0].split('-')[2]
130
+ else
131
+ Pkg::Config.final_mocks.split(' ')[0].split('-')[1..2].join("")
132
+ end
133
+ when /dmg/ then "apple"
134
+ when /gem/ then "gem"
135
+ when /sles/ then "sles"
136
+ when /tar/ then "tar"
137
+ else raise "Could not determine build type for #{build_task}"
138
+ end
139
+
140
+ if Pkg::Config.pe_version
141
+ metrics = "#{ENV['USER']}~#{Pkg::Config.version}~#{Pkg::Config.pe_version}~#{dist}~#{Pkg::Config.team}"
142
+ else
143
+ metrics = "#{ENV['USER']}~#{Pkg::Config.version}~N/A~#{dist}~#{Pkg::Config.team}"
144
+ end
145
+ #
146
+ # Create the data files to send to jenkins
147
+ properties = Pkg::Config.config_to_yaml
148
+ bundle = Pkg::Util::Git.bundle('HEAD')
149
+
150
+ # Construct the parameters, which is an array of hashes we turn into JSON
151
+ parameters = [{ "name" => "BUILD_PROPERTIES", "file" => "file0" },
152
+ { "name" => "PROJECT_BUNDLE", "file" => "file1" },
153
+ { "name" => "PROJECT", "value" => "#{Pkg::Config.project}" },
154
+ { "name" => "BUILD_TYPE", "label" => "#{build_type}" },
155
+ { "name" => "METRICS", "value" => "#{metrics}" }]
156
+
157
+ # Initialize the args array that will hold all of the arguments we pass
158
+ # to the curl utility method.
159
+ args = []
160
+
161
+ # If the environment variable "DOWNSTREAM_JOB" was passed, we want to
162
+ # send this value to the build job as well, so it knows to trigger a
163
+ # downstream job, and with what URI.
164
+ if ENV['DOWNSTREAM_JOB']
165
+ parameters << { "name" => "DOWNSTREAM_JOB", "value" => ENV['DOWNSTREAM_JOB'] }
166
+ args << ["-Fname=DOWNSTREAM_JOB", "-Fvalue=#{ENV['DOWNSTREAM_JOB']}"]
167
+ end
168
+
169
+ # Contruct the json string
170
+ json = JSON.generate("parameter" => parameters)
171
+
172
+ # Construct the remaining form arguments. For visual clarity, params that are tied
173
+ # together are on the same line.
174
+ #
175
+ args << [
176
+ "-Fname=BUILD_PROPERTIES", "-Ffile0=@#{properties}",
177
+ "-Fname=PROJECT_BUNDLE", "-Ffile1=@#{bundle}",
178
+ "-Fname=PROJECT", "-Fvalue=#{Pkg::Config.project}",
179
+ "-Fname=BUILD_TYPE", "-Fvalue=#{build_type}",
180
+ "-Fname=METRICS", "-Fvalue=#{metrics}",
181
+ "-FSubmit=Build",
182
+ "-Fjson=#{json.to_json}",
183
+ ]
184
+
185
+ # We have several arrays inside args by now, flatten it up.
186
+ args.flatten!
187
+
188
+ # Construct the job url
189
+ #
190
+ job_url = "#{Pkg::Config.jenkins_build_host}/job/#{Pkg::Config.jenkins_packaging_job}"
191
+ trigger_url = "#{job_url}/build"
192
+
193
+ # Call out to the curl_form_data utility method in 00_utils.rake
194
+ #
195
+ begin
196
+ _, retval = Pkg::Util::Net.curl_form_data(trigger_url, args)
197
+ if Pkg::Util::Execution.success?(retval)
198
+ puts "Build submitted. To view your build results, go to #{job_url}"
199
+ puts "Your packages will be available at http://#{Pkg::Config.builds_server}/#{Pkg::Config.project}/#{Pkg::Config.ref}"
200
+ else
201
+ fail "An error occurred submitting the job to jenkins. Take a look at the preceding http response for more info."
202
+ end
203
+ ensure
204
+ # Clean up after ourselves
205
+ rm bundle
206
+ rm properties
207
+ end
208
+ end
209
+ end
210
+ end
211
+
212
+ ##
213
+ # A task listing for creating jenkins tasks for our various pl: and pe: build
214
+ # tasks. We can assume deb, mock, but not gem/dmg.
215
+ #
216
+ tasks = ["deb", "mock", "tar"]
217
+ tasks << "gem" if Pkg::Config.build_gem and !Pkg::Config.build_pe
218
+ tasks << "dmg" if Pkg::Config.build_dmg and !Pkg::Config.build_pe
219
+
220
+ namespace :pl do
221
+ namespace :jenkins do
222
+ tasks.each do |build_task|
223
+ desc "Queue pl:#{build_task} build on jenkins builder"
224
+ task build_task => "pl:fetch" do
225
+ Pkg::Util::RakeUtils.invoke_task("pl:jenkins:post_build", "pl:#{build_task}")
226
+ end
227
+ end
228
+
229
+ # While pl:remote:deb_all does all cows in serially, with jenkins we
230
+ # parallelize them. This breaks the cows up and posts a build for all of
231
+ # them. We have to sleep 5 because jenkins drops the builds when we're
232
+ # DOSing it with our packaging.
233
+ desc "Queue pl:deb_all on jenkins builder"
234
+ task :deb_all => "pl:fetch" do
235
+ Pkg::Config.cows.split(' ').each do |cow|
236
+ Pkg::Config.default_cow = cow
237
+ Pkg::Util::RakeUtils.invoke_task("pl:jenkins:post_build", "pl:deb")
238
+ sleep 5
239
+ end
240
+ end
241
+
242
+ # This does the mocks in parallel
243
+ desc "Queue pl:mock_all on jenkins builder"
244
+ task :mock_all => "pl:fetch" do
245
+ Pkg::Config.final_mocks.split(' ').each do |mock|
246
+ Pkg::Config.default_mock = mock
247
+ Pkg::Util::RakeUtils.invoke_task("pl:jenkins:post_build", "pl:mock")
248
+ sleep 5
249
+ end
250
+ end
251
+
252
+ task :uber_ship_lite => "pl:fetch" do
253
+ tasks = %w(
254
+ jenkins:retrieve
255
+ jenkins:sign_all
256
+ ship_rpms
257
+ ship_debs
258
+ ship_dmg
259
+ ship_swix
260
+ ship_msi
261
+ )
262
+ tasks.map { |t| "pl:#{t}" }.each do |t|
263
+ puts "Running #{t} . . ."
264
+ Rake::Task[t].invoke
265
+ end
266
+ end
267
+
268
+ task :ship_nightlies => "pl:fetch" do
269
+ Rake::Task['pl:jenkins:uber_ship_lite'].invoke
270
+ Rake::Task['pl:remote:update_foss_repos'].invoke
271
+ Rake::Task['pl:remote:deploy_nightlies_to_s3'].invoke
272
+ end
273
+
274
+ task :ship_final => "pl:fetch" do
275
+ Rake::Task['pl:jenkins:uber_ship_lite'].invoke
276
+ Rake::Task['pl:remote:update_foss_repos'].invoke
277
+ Rake::Task['pl:remote:deploy_final_builds_to_s3'].invoke
278
+ Rake::Task['pl:remote:deploy_to_rsync_server'].invoke
279
+ end
280
+
281
+ desc "Retrieve packages built by jenkins, sign, and ship all!"
282
+ task :uber_ship => "pl:fetch" do
283
+ uber_tasks = %w(
284
+ jenkins:retrieve
285
+ jenkins:sign_all
286
+ uber_ship
287
+ ship_gem
288
+ remote:update_apt_repo
289
+ remote:update_yum_repo
290
+ remote:update_ips_repo
291
+ remote:deploy_apt_repo
292
+ remote:deploy_yum_repo
293
+ remote:deploy_dmg_repo
294
+ remote:deploy_swix_repo
295
+ remote:deploy_msi_repo
296
+ remote:deploy_tar_repo
297
+ remote:deploy_apt_repo_to_s3
298
+ remote:deploy_yum_repo_to_s3
299
+ remote:deploy_downloads_to_s3
300
+ remote:deploy_to_rsync_server
301
+ )
302
+
303
+ if Pkg::Util.boolean_value(Pkg::Config.answer_override) && !Pkg::Config.foss_only
304
+ fail "Using ANSWER_OVERRIDE without FOSS_ONLY=true is dangerous!"
305
+ end
306
+
307
+ # Some projects such as pl-build-tools do not stage to a separate server - so we do to deploy
308
+ uber_tasks.delete("remote:deploy_apt_repo") if Pkg::Config.apt_host == Pkg::Config.apt_signing_server
309
+ uber_tasks.delete("remote:deploy_yum_repo") if Pkg::Config.yum_host == Pkg::Config.yum_staging_server
310
+ uber_tasks.delete("remote:deploy_dmg_repo") if Pkg::Config.dmg_host == Pkg::Config.dmg_staging_server
311
+ uber_tasks.delete("remote:deploy_swix_repo") if Pkg::Config.swix_host == Pkg::Config.swix_staging_server
312
+ uber_tasks.delete("remote:deploy_tar_repo") if Pkg::Config.tar_host == Pkg::Config.tar_staging_server
313
+
314
+ if Pkg::Config.s3_ship
315
+ uber_tasks.delete("remote:deploy_apt_repo")
316
+ uber_tasks.delete("remote:deploy_yum_repo")
317
+ uber_tasks.delete("remote:deploy_dmg_repo")
318
+ uber_tasks.delete("remote:deploy_swix_repo")
319
+ uber_tasks.delete("remote:deploy_msi_repo")
320
+ uber_tasks.delete("remote:deploy_tar_repo")
321
+ else
322
+ uber_tasks.delete("remote:deploy_apt_repo_to_s3")
323
+ uber_tasks.delete("remote:deploy_yum_repo_to_s3")
324
+ uber_tasks.delete("remote:deploy_downloads_to_s3")
325
+ uber_tasks.delete("remote:deploy_to_rsync_server")
326
+ end
327
+
328
+ # Delete the ship_gem task if we aren't building gems
329
+ uber_tasks.delete("ship_gem") unless Pkg::Config.build_gem
330
+
331
+ # I'm adding this check here because if we rework the task ordering we're
332
+ # probably going to need to muck about in here. -morgan
333
+ if uber_tasks.first == 'jenkins:retrieve'
334
+ # We need to run retrieve before we can delete tasks based on what
335
+ # packages were built. Before this we were deleting tasks based on files
336
+ # in a directory that hadn't been populated yet, so this would either
337
+ # fail since all tasks would be removed, or would be running based on
338
+ # files left over in packaging from the last ship.
339
+ puts 'Do you want to run pl:jenkins:retrieve?'
340
+ Rake::Task['pl:jenkins:retrieve'].invoke if Pkg::Util.ask_yes_or_no
341
+ uber_tasks.delete('jenkins:retrieve')
342
+ end
343
+
344
+ # Don't update and deploy repos if packages don't exist
345
+ # If we can't find a certain file type, delete the task
346
+ if Dir.glob("pkg/**/*.deb").empty?
347
+ uber_tasks.delete("remote:update_apt_repo")
348
+ uber_tasks.delete("remote:deploy_apt_repo")
349
+ end
350
+
351
+ if Dir.glob("pkg/**/*.rpm").empty?
352
+ uber_tasks.delete("remote:update_yum_repo")
353
+ uber_tasks.delete("remote:deploy_yum_repo")
354
+ end
355
+
356
+ if Dir.glob("pkg/**/*.p5p").empty?
357
+ uber_tasks.delete("remote:update_ips_repo")
358
+ end
359
+
360
+ if Dir.glob("pkg/**/*.dmg").empty?
361
+ uber_tasks.delete("remote:deploy_dmg_repo")
362
+ end
363
+
364
+ if Dir.glob("pkg/**/*.swix").empty?
365
+ uber_tasks.delete("remote:deploy_swix_repo")
366
+ end
367
+
368
+ if Dir.glob("pkg/**/*.msi").empty?
369
+ uber_tasks.delete("remote:deploy_msi_repo")
370
+ end
371
+
372
+ if Dir.glob("pkg/*.tar.gz").empty?
373
+ uber_tasks.delete("remote:deploy_tar_repo")
374
+ end
375
+
376
+ uber_tasks.map { |t| "pl:#{t}" }.each do |t|
377
+ puts "Do you want to run #{t}?"
378
+ Rake::Task[t].invoke if Pkg::Util.ask_yes_or_no
379
+ end
380
+
381
+ puts "Do you want to mark this release as successfully shipped?"
382
+ Rake::Task["pl:jenkins:ship"].invoke("shipped") if Pkg::Util.ask_yes_or_no
383
+ end
384
+
385
+ desc "Test shipping by replacing hosts with a VM"
386
+ task :test_ship, [:vm, :ship_task] do |t, args|
387
+ vm = args.vm or fail "`vm` is a required argument for #{t}"
388
+ ship_task = args.ship_task or fail "`ship_task` is a required argument for #{t}"
389
+ Pkg::Util::Ship.test_ship(vm, ship_task)
390
+ end
391
+ end
392
+ end
393
+
394
+ ##
395
+ # If this is a PE project, we want PE tasks as well.
396
+ #
397
+ if Pkg::Config.build_pe
398
+ namespace :pe do
399
+ namespace :jenkins do
400
+ tasks.each do |build_task|
401
+ desc "Queue pe:#{build_task} build on jenkins builder"
402
+ task build_task => "pl:fetch" do
403
+ Pkg::Util.check_var("PE_VER", Pkg::Config.pe_version)
404
+ Pkg::Util::RakeUtils.invoke_task("pl:jenkins:post_build", "pe:#{build_task}")
405
+ end
406
+ end
407
+
408
+ # While pl:remote:deb_all does all cows in serially, with jenkins we
409
+ # parallelize them. This breaks the cows up and posts a build for all of
410
+ # them. We have to sleep 5 because jenkins drops the builds when we're
411
+ # DOSing it with our packaging.
412
+ desc "Queue pe:deb_all on jenkins builder"
413
+ task :deb_all => "pl:fetch" do
414
+ Pkg::Util.check_var("PE_VER", Pkg::Config.pe_version)
415
+ Pkg::Config.cows.split(' ').each do |cow|
416
+ Pkg::Config.default_cow = cow
417
+ Pkg::Util::RakeUtils.invoke_task("pl:jenkins:post_build", "pe:deb")
418
+ sleep 5
419
+ end
420
+ end
421
+
422
+ # This does the mocks in parallel
423
+ desc "Queue pe:mock_all on jenkins builder"
424
+ task :mock_all => "pl:fetch" do
425
+ Pkg::Config.final_mocks.split(' ').each do |mock|
426
+ Pkg::Config.default_mock = mock
427
+ Pkg::Util::RakeUtils.invoke_task("pl:jenkins:post_build", "pe:mock")
428
+ sleep 5
429
+ end
430
+ end
431
+
432
+ desc "Retrieve PE packages built by jenkins, sign, and ship all!"
433
+ task :uber_ship => "pl:fetch" do
434
+ Pkg::Util.check_var("PE_VER", Pkg::Config.pe_version)
435
+ ["pl:jenkins:retrieve", "pl:jenkins:sign_all", "pe:ship_rpms", "pe:ship_debs"].each do |task|
436
+ Rake::Task[task].invoke
437
+ end
438
+ Rake::Task["pl:jenkins:ship"].invoke("shipped")
439
+ end
440
+ end
441
+ end
442
+ end
443
+
444
+ ##
445
+ # This task allows the packaging repo to post to an arbitrary jenkins job but
446
+ # it is very limited in that it does not model well the key => value format
447
+ # used when submitting form data on websites. This is primarily because rake
448
+ # does not allow us to elegantly pass arbitrary key => value pairs on the
449
+ # command line and have any idea how to reference them inside rake. We can pass
450
+ # KEY=VALUE along with our invokation, but unless KEY is statically coded into
451
+ # our task, we won't know how to reference it. Thus, this task will only take
452
+ # one argument, the uri of the jenkins job to post to. This can be passed
453
+ # either as an argument directly or as an environment variable "JOB" with the
454
+ # uri as the value. The argument is required. The second requirement is that
455
+ # the job to be called accept a string parameter with the name SHA. This will
456
+ # be the SHA of the commit of the project source code HEAD, and should be used
457
+ # by the job to check out this specific ref. To maintain the abstraction of the
458
+ # jenkins jobs, this specific task passes on no information about the build
459
+ # itself. The assumption is that the upstream jobs know about their project,
460
+ # and so do the downstream jobs, but packaging itself has no business knowing
461
+ # about it.
462
+ #
463
+ namespace :pl do
464
+ namespace :jenkins do
465
+ desc "Trigger a jenkins uri with SHA of HEAD as a string param, requires \"URI\""
466
+ task :post, :uri do |t, args|
467
+ uri = (args.uri or ENV['URI']) or fail "pl:jenkins:post requires a URI, either via URI= or pl:jenkin:post[URI]"
468
+
469
+ # We use JSON for parsing the json part of the submission.
470
+ begin
471
+ require 'json'
472
+ rescue LoadError
473
+ fail "Couldn't require 'json'. JSON is required for sanely generating the string we curl to Jenkins."
474
+ end
475
+
476
+ # Assemble the JSON string for the JSON parameter
477
+ json = JSON.generate("parameter" => [{ "name" => "SHA", "value" => "#{Pkg::Config.ref}" }])
478
+
479
+ # Assemble our arguments to the post
480
+ args = [
481
+ "-Fname=SHA", "-Fvalue=#{Pkg::Config.ref}",
482
+ "-Fjson=#{json.to_json}",
483
+ "-FSubmit=Build"
484
+ ]
485
+
486
+ _, retval = Pkg::Util::Net.curl_form_data(uri, args)
487
+ if Pkg::Util::Execution.success?(retval)
488
+ puts "Job triggered at #{uri}."
489
+ else
490
+ fail "An error occurred attempting to trigger the job at #{uri}. Please see the preceding http response for more info."
491
+ end
492
+ end
493
+ end
494
+ end