packaging 0.88.77

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +17 -0
  3. data/README-Solaris.md +117 -0
  4. data/README.md +977 -0
  5. data/lib/packaging.rb +32 -0
  6. data/lib/packaging/archive.rb +126 -0
  7. data/lib/packaging/artifactory.rb +651 -0
  8. data/lib/packaging/artifactory/extensions.rb +94 -0
  9. data/lib/packaging/config.rb +492 -0
  10. data/lib/packaging/config/params.rb +387 -0
  11. data/lib/packaging/config/validations.rb +13 -0
  12. data/lib/packaging/deb.rb +28 -0
  13. data/lib/packaging/deb/repo.rb +264 -0
  14. data/lib/packaging/gem.rb +70 -0
  15. data/lib/packaging/metrics.rb +15 -0
  16. data/lib/packaging/nuget.rb +39 -0
  17. data/lib/packaging/paths.rb +376 -0
  18. data/lib/packaging/platforms.rb +507 -0
  19. data/lib/packaging/repo.rb +155 -0
  20. data/lib/packaging/retrieve.rb +75 -0
  21. data/lib/packaging/rpm.rb +5 -0
  22. data/lib/packaging/rpm/repo.rb +254 -0
  23. data/lib/packaging/sign.rb +8 -0
  24. data/lib/packaging/sign/deb.rb +9 -0
  25. data/lib/packaging/sign/dmg.rb +41 -0
  26. data/lib/packaging/sign/ips.rb +57 -0
  27. data/lib/packaging/sign/msi.rb +124 -0
  28. data/lib/packaging/sign/rpm.rb +115 -0
  29. data/lib/packaging/tar.rb +163 -0
  30. data/lib/packaging/util.rb +146 -0
  31. data/lib/packaging/util/date.rb +20 -0
  32. data/lib/packaging/util/execution.rb +85 -0
  33. data/lib/packaging/util/file.rb +125 -0
  34. data/lib/packaging/util/git.rb +174 -0
  35. data/lib/packaging/util/git_tags.rb +73 -0
  36. data/lib/packaging/util/gpg.rb +66 -0
  37. data/lib/packaging/util/jenkins.rb +95 -0
  38. data/lib/packaging/util/misc.rb +69 -0
  39. data/lib/packaging/util/net.rb +410 -0
  40. data/lib/packaging/util/os.rb +17 -0
  41. data/lib/packaging/util/platform.rb +40 -0
  42. data/lib/packaging/util/rake_utils.rb +112 -0
  43. data/lib/packaging/util/serialization.rb +19 -0
  44. data/lib/packaging/util/ship.rb +300 -0
  45. data/lib/packaging/util/tool.rb +41 -0
  46. data/lib/packaging/util/version.rb +334 -0
  47. data/spec/fixtures/config/ext/build_defaults.yaml +2 -0
  48. data/spec/fixtures/config/ext/project_data.yaml +2 -0
  49. data/spec/fixtures/configs/components/test_file.json +1 -0
  50. data/spec/fixtures/configs/components/test_file_2.json +0 -0
  51. data/spec/fixtures/configs/components/test_file_not_tagged.json +1 -0
  52. data/spec/fixtures/configs/components/test_file_wrong_ext.txt +0 -0
  53. data/spec/fixtures/configs/components/test_file_wrong_ext.wrong +0 -0
  54. data/spec/fixtures/util/pre_tasks.yaml +4 -0
  55. data/spec/lib/packaging/artifactory_spec.rb +221 -0
  56. data/spec/lib/packaging/config_spec.rb +576 -0
  57. data/spec/lib/packaging/deb/repo_spec.rb +157 -0
  58. data/spec/lib/packaging/deb_spec.rb +52 -0
  59. data/spec/lib/packaging/gem_spec.rb +86 -0
  60. data/spec/lib/packaging/paths_spec.rb +418 -0
  61. data/spec/lib/packaging/platforms_spec.rb +178 -0
  62. data/spec/lib/packaging/repo_spec.rb +135 -0
  63. data/spec/lib/packaging/retrieve_spec.rb +100 -0
  64. data/spec/lib/packaging/rpm/repo_spec.rb +133 -0
  65. data/spec/lib/packaging/sign_spec.rb +133 -0
  66. data/spec/lib/packaging/tar_spec.rb +116 -0
  67. data/spec/lib/packaging/util/execution_spec.rb +56 -0
  68. data/spec/lib/packaging/util/file_spec.rb +139 -0
  69. data/spec/lib/packaging/util/git_spec.rb +160 -0
  70. data/spec/lib/packaging/util/git_tag_spec.rb +36 -0
  71. data/spec/lib/packaging/util/gpg_spec.rb +64 -0
  72. data/spec/lib/packaging/util/jenkins_spec.rb +112 -0
  73. data/spec/lib/packaging/util/misc_spec.rb +31 -0
  74. data/spec/lib/packaging/util/net_spec.rb +259 -0
  75. data/spec/lib/packaging/util/os_spec.rb +31 -0
  76. data/spec/lib/packaging/util/rake_utils_spec.rb +70 -0
  77. data/spec/lib/packaging/util/ship_spec.rb +199 -0
  78. data/spec/lib/packaging/util/version_spec.rb +123 -0
  79. data/spec/lib/packaging_spec.rb +19 -0
  80. data/spec/spec_helper.rb +22 -0
  81. data/static_artifacts/PackageInfo.plist +3 -0
  82. data/tasks/00_utils.rake +214 -0
  83. data/tasks/30_metrics.rake +33 -0
  84. data/tasks/apple.rake +268 -0
  85. data/tasks/archive.rake +69 -0
  86. data/tasks/build.rake +12 -0
  87. data/tasks/clean.rake +5 -0
  88. data/tasks/config.rake +35 -0
  89. data/tasks/deb.rake +129 -0
  90. data/tasks/deb_repos.rake +28 -0
  91. data/tasks/deprecated.rake +130 -0
  92. data/tasks/doc.rake +20 -0
  93. data/tasks/education.rake +57 -0
  94. data/tasks/fetch.rake +60 -0
  95. data/tasks/gem.rake +159 -0
  96. data/tasks/jenkins.rake +538 -0
  97. data/tasks/jenkins_dynamic.rake +202 -0
  98. data/tasks/load_extras.rake +21 -0
  99. data/tasks/mock.rake +348 -0
  100. data/tasks/nightly_repos.rake +286 -0
  101. data/tasks/pe_deb.rake +12 -0
  102. data/tasks/pe_rpm.rake +13 -0
  103. data/tasks/pe_ship.rake +226 -0
  104. data/tasks/pe_sign.rake +13 -0
  105. data/tasks/pe_tar.rake +5 -0
  106. data/tasks/retrieve.rake +52 -0
  107. data/tasks/rpm.rake +66 -0
  108. data/tasks/rpm_repos.rake +29 -0
  109. data/tasks/ship.rake +692 -0
  110. data/tasks/sign.rake +154 -0
  111. data/tasks/tag.rake +8 -0
  112. data/tasks/tar.rake +28 -0
  113. data/tasks/update.rake +16 -0
  114. data/tasks/vanagon.rake +35 -0
  115. data/tasks/vendor_gems.rake +117 -0
  116. data/tasks/version.rake +33 -0
  117. data/tasks/z_data_dump.rake +65 -0
  118. data/templates/README +1 -0
  119. data/templates/downstream.xml.erb +47 -0
  120. data/templates/msi.xml.erb +197 -0
  121. data/templates/packaging.xml.erb +346 -0
  122. data/templates/repo.xml.erb +117 -0
  123. metadata +287 -0
data/tasks/fetch.rake ADDED
@@ -0,0 +1,60 @@
1
+ # Each team has a build-defaults file that specifies local infrastructure targets
2
+ # for things like builders, target locations for build artifacts, etc Since much
3
+ # of these don't change, one file can be maintained for the team. Each project
4
+ # also has a data file for information specific to it. If the project builds
5
+ # both PE and not PE, it has two files, one for PE, and the other for FOSS
6
+ #
7
+ data_repo = Pkg::Config.build_data_repo
8
+
9
+ if Pkg::Config.dev_build
10
+ puts "NOTICE: This is a dev build!"
11
+ project_data_branch = "#{Pkg::Config.project}-dev"
12
+ else
13
+ project_data_branch = Pkg::Config.project
14
+ end
15
+ team_data_branch = Pkg::Config.team
16
+
17
+ if Pkg::Config.build_pe
18
+ project_data_branch = 'pe-' + project_data_branch unless project_data_branch =~ /^pe-/
19
+ team_data_branch = 'pe-' + team_data_branch unless team_data_branch =~ /^pe-/
20
+ end
21
+
22
+ # The pl:fetch task pulls down two files from the build-data repo that contain additional
23
+ # data specific to Puppet Labs release infrastructure intended to augment/override any
24
+ # defaults specified in the source project repo, e.g. in ext/build_defaults.yaml
25
+ #
26
+ # It uses curl to download the files, and places them in a temporary
27
+ # directory, e.g. /tmp/somedirectory/{project,team}/Pkg::Config.builder_data_file
28
+ namespace :pl do
29
+ desc "retrieve build-data configurations to override/extend local build_defaults"
30
+ task :fetch do
31
+ # Remove .packaging directory from old-style extras loading
32
+ rm_rf "#{ENV['HOME']}/.packaging" if File.directory?("#{ENV['HOME']}/.packaging")
33
+
34
+ # Touch the .packaging file which is allows packaging to present remote tasks
35
+ touch "#{ENV['HOME']}/.packaging"
36
+
37
+ begin
38
+ build_data_directory = Pkg::Util::File.mktemp
39
+ %x(git clone #{data_repo} #{build_data_directory})
40
+ unless $?.success?
41
+ fail 'Error: could not fetch the build-data repo. Maybe you do not have the correct permissions?'
42
+ end
43
+
44
+ Dir.chdir(build_data_directory) do
45
+ [team_data_branch, project_data_branch].each do |branch|
46
+ %x(git checkout #{branch})
47
+ unless $?.success?
48
+ warn "Warning: no build_defaults found in branch '#{branch}' of '#{data_repo}'. Skipping."
49
+ next
50
+ end
51
+ Pkg::Util::RakeUtils.invoke_task('pl:load_extras', build_data_directory)
52
+ end
53
+ end
54
+ ensure
55
+ rm_rf build_data_directory
56
+ end
57
+
58
+ Pkg::Util::RakeUtils.invoke_task('config:validate')
59
+ end
60
+ end
data/tasks/gem.rake ADDED
@@ -0,0 +1,159 @@
1
+ require 'rubygems/package_task'
2
+
3
+ def glob_gem_files
4
+ gem_files = []
5
+ gem_excludes_file_list = []
6
+ gem_excludes_raw = Pkg::Config.gem_excludes.nil? ? [] : Pkg::Config.gem_excludes.split(' ')
7
+ gem_excludes_raw << 'ext/packaging'
8
+ gem_excludes_raw << 'pkg'
9
+ gem_excludes_raw.each do |exclude|
10
+ if File.directory?(exclude)
11
+ gem_excludes_file_list += FileList["#{exclude}/**/*"]
12
+ else
13
+ gem_excludes_file_list << exclude
14
+ end
15
+ end
16
+ files = FileList[Pkg::Config.gem_files.split(' ')]
17
+ files.each do |file|
18
+ if File.directory?(file)
19
+ gem_files += FileList["#{file}/**/*"]
20
+ else
21
+ gem_files << file
22
+ end
23
+ end
24
+ gem_files -= gem_excludes_file_list
25
+ end
26
+
27
+ def add_gem_dependency(opts = {})
28
+ spec = opts[:spec]
29
+ version = opts[:version]
30
+ type = opts[:type].to_s
31
+ gem = opts[:gem].to_s
32
+ if opts[:version].nil? or opts[:version].empty?
33
+ spec.send("add_#{type}_dependency".to_sym, gem)
34
+ else
35
+ spec.send("add_#{type}_dependency".to_sym, gem, version)
36
+ end
37
+ spec
38
+ end
39
+
40
+ def create_default_gem_spec
41
+ spec = Gem::Specification.new do |s|
42
+ s.name = Pkg::Config.project unless Pkg::Config.project.nil?
43
+ s.name = Pkg::Config.gem_name unless Pkg::Config.gem_name.nil?
44
+ s.version = Pkg::Config.gemversion unless Pkg::Config.gemversion.nil?
45
+ s.author = Pkg::Config.author unless Pkg::Config.author.nil?
46
+ s.email = Pkg::Config.email unless Pkg::Config.email.nil?
47
+ s.homepage = Pkg::Config.homepage unless Pkg::Config.homepage.nil?
48
+ s.summary = Pkg::Config.summary unless Pkg::Config.summary.nil?
49
+ s.summary = Pkg::Config.gem_summary unless Pkg::Config.gem_summary.nil?
50
+ s.description = Pkg::Config.description unless Pkg::Config.description.nil?
51
+ s.description = Pkg::Config.gem_description unless Pkg::Config.gem_description.nil?
52
+ s.files = glob_gem_files unless glob_gem_files.nil?
53
+ s.executables = Pkg::Config.gem_executables unless Pkg::Config.gem_executables.nil?
54
+ s.require_path = Pkg::Config.gem_require_path unless Pkg::Config.gem_require_path.nil?
55
+ s.required_ruby_version = Pkg::Config.gem_required_ruby_version unless Pkg::Config.gem_required_ruby_version.nil?
56
+ s.required_rubygems_version = Pkg::Config.gem_required_rubygems_version unless Pkg::Config.gem_required_rubygems_version.nil?
57
+ s.test_files = FileList[Pkg::Config.gem_test_files.split(' ')] unless Pkg::Config.gem_test_files.nil?
58
+ s.rubyforge_project = Pkg::Config.gem_forge_project unless Pkg::Config.gem_forge_project.nil?
59
+ Pkg::Config.gem_rdoc_options.each do |option|
60
+ s.rdoc_options << option
61
+ end unless Pkg::Config.gem_rdoc_options.nil?
62
+ end
63
+
64
+ Pkg::Config.gem_runtime_dependencies.each do |gem, version|
65
+ spec = add_gem_dependency(:spec => spec, :gem => gem, :version => version, :type => :runtime)
66
+ end unless Pkg::Config.gem_runtime_dependencies.nil?
67
+
68
+ Pkg::Config.gem_development_dependencies.each do |gem, version|
69
+ spec = add_gem_dependency(:spec => spec, :gem => gem, :version => version, :type => :development)
70
+ end unless Pkg::Config.gem_development_dependencies.nil?
71
+ spec
72
+ end
73
+
74
+ def create_gem(spec, gembuilddir)
75
+ gem_files = glob_gem_files + FileList[(Pkg::Config.gem_test_files || '').split(' ')]
76
+ workdir = File.join(Pkg::Util::File.mktemp)
77
+
78
+ bench = Benchmark.realtime do
79
+ Pkg::Util::File.install_files_into_dir(gem_files, workdir)
80
+
81
+ cd workdir do
82
+ gem_task = Gem::PackageTask.new(spec)
83
+ gem_task.define
84
+ Rake::Task[:gem].reenable
85
+ Rake::Task[:gem].invoke
86
+ rm_rf File.join("pkg", gembuilddir)
87
+ mv Dir.glob("pkg/#{Pkg::Config.gem_name}-#{Pkg::Config.gemversion}*.gem"), File.join(Pkg::Config.project_root, "pkg")
88
+ end
89
+ end
90
+
91
+ rm_rf workdir
92
+ puts "Finished building in: #{bench}"
93
+ end
94
+
95
+ def create_default_gem
96
+ spec = create_default_gem_spec
97
+ create_gem(spec, "#{Pkg::Config.gem_name}-#{Pkg::Config.gemversion}")
98
+ end
99
+
100
+ def unknown_gems_platform?(platform)
101
+ return true if platform.os == "unknown"
102
+ false
103
+ end
104
+
105
+ def create_platform_specific_gems
106
+ Pkg::Config.gem_platform_dependencies.each do |platform, dependency_hash|
107
+ spec = create_default_gem_spec
108
+ pf = Gem::Platform.new(platform)
109
+ fail "
110
+ Platform: '#{platform}' is not recognized by rubygems.
111
+ This is probably an erroneous 'gem_platform_dependencies' entry!" if unknown_gems_platform?(pf)
112
+ spec.platform = pf
113
+ dependency_hash.each do |type, gems|
114
+ t = case type
115
+ when "gem_runtime_dependencies"
116
+ "runtime"
117
+ when "gem_development_dependencies"
118
+ "development"
119
+ else
120
+ fail "Platform specific gem dependency type must be 'gem_runtime_dependencies' or 'gem_development_dependencies', not '#{type}'"
121
+ end
122
+ gems.each do |gem, version|
123
+ spec = add_gem_dependency(:spec => spec, :gem => gem, :version => version, :type => t)
124
+ end
125
+ end
126
+ create_gem(spec, "#{Pkg::Config.gem_name}-#{Pkg::Config.gemversion}-#{platform}")
127
+ end
128
+ end
129
+
130
+ def package_gem
131
+ unless Pkg::Config.build_gem
132
+ puts "The #{Pkg::Config.project} project does not build any gems! Passing through ..."
133
+ return
134
+ end
135
+
136
+ mkdir_p File.join(Pkg::Config.project_root, "pkg")
137
+ create_default_gem
138
+ if Pkg::Config.gem_platform_dependencies
139
+ create_platform_specific_gems
140
+ end
141
+ end
142
+
143
+ namespace :package do
144
+ desc "Build a gem - All gems if platform specific"
145
+ task :gem => ["clean"] do
146
+ package_gem
147
+ end
148
+
149
+ task :nightly_gem => ["clean"] do
150
+ Pkg::Config.gemversion = Pkg::Util::Version.extended_dot_version
151
+ package_gem
152
+ end
153
+ end
154
+
155
+ # An alias task to simplify our remote logic in jenkins.rake
156
+ namespace :pl do
157
+ task :gem => "package:gem"
158
+ task :nightly_gem => "package:nightly_gem"
159
+ end
@@ -0,0 +1,538 @@
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
+ # ### Install the packaging gem via Bundler
56
+ # bundle install
57
+ #
58
+ # ### Perform the build
59
+ # bundle exec rake pl:build_from_params PARAMS_FILE=$WORKSPACE/BUILD_PROPERTIES
60
+ #
61
+ # ### Send the results
62
+ # bundle exec 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
+ # bundle exec 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_tar
261
+ ship_msi
262
+ ship_gem
263
+ )
264
+ tasks.map { |t| "pl:#{t}" }.each do |t|
265
+ puts "Running #{t} . . ."
266
+ Rake::Task[t].invoke
267
+ end
268
+ # mark the build as successfully shipped
269
+ Rake::Task["pl:jenkins:ship"].invoke("shipped")
270
+ # add the release to release-metrics
271
+ begin
272
+ Rake::Task["pl:update_release_metrics"].invoke
273
+ rescue => e
274
+ fail "Error updating release-metrics:\n#{e}\nYou will need to add this release manually."
275
+ end
276
+ end
277
+
278
+ task :stage_nightlies => "pl:fetch" do
279
+ tasks = %w(
280
+ jenkins:retrieve
281
+ jenkins:sign_all
282
+ ship_nightly_rpms
283
+ ship_nightly_debs
284
+ ship_nightly_dmg
285
+ ship_nightly_swix
286
+ ship_nightly_msi
287
+ )
288
+ tasks.map { |t| "pl:#{t}" }.each do |t|
289
+ puts "Running #{t} . . ."
290
+ Rake::Task[t].invoke
291
+ end
292
+ end
293
+
294
+ task :ship_nightlies => "pl:fetch" do
295
+ Rake::Task['pl:jenkins:stage_nightlies'].invoke
296
+ Rake::Task['pl:remote:update_nightly_repos'].invoke
297
+ Rake::Task['pl:remote:deploy_nightlies_to_s3'].invoke
298
+ end
299
+
300
+ task :ship_final => "pl:fetch" do
301
+ Rake::Task['pl:jenkins:uber_ship_lite'].invoke
302
+ Rake::Task['pl:remote:update_foss_repos'].invoke
303
+ Rake::Task['pl:remote:deploy_final_builds_to_s3'].invoke
304
+ Rake::Task['pl:remote:deploy_to_rsync_server'].invoke
305
+ end
306
+
307
+ task :stage_release_packages => "pl:fetch" do
308
+ Rake::Task['pl:jenkins:uber_ship_lite'].invoke
309
+ # Deb packages only appear in the freight directory until repo updates.
310
+ # We must run that before creating symlinks so we can link from packages
311
+ # in the apt repository.
312
+ Rake::Task['pl:remote:update_apt_repo'].invoke
313
+ Pkg::Util::Ship.update_release_package_symlinks('pkg')
314
+ end
315
+
316
+ task :stage_nightly_release_packages => "pl:fetch" do
317
+ Rake::Task['pl:jenkins:stage_nightlies'].invoke
318
+ # Deb packages only appear in the freight directory until repo updates.
319
+ # We must run that before creating symlinks so we can link from packages
320
+ # in the apt repository.
321
+ Rake::Task['pl:remote:update_nightlies_apt_repo'].invoke
322
+ Pkg::Util::Ship.update_release_package_symlinks('pkg', true)
323
+ end
324
+
325
+ desc "Retrieve packages built by jenkins, sign, and ship all!"
326
+ task :uber_ship => "pl:fetch" do
327
+ uber_tasks = %w(
328
+ jenkins:retrieve
329
+ jenkins:sign_all
330
+ uber_ship
331
+ ship_gem
332
+ remote:update_apt_repo
333
+ remote:update_yum_repo
334
+ remote:update_ips_repo
335
+ remote:deploy_apt_repo
336
+ remote:deploy_yum_repo
337
+ remote:deploy_dmg_repo
338
+ remote:deploy_swix_repo
339
+ remote:deploy_msi_repo
340
+ remote:deploy_tar_repo
341
+ remote:deploy_apt_repo_to_s3
342
+ remote:deploy_yum_repo_to_s3
343
+ remote:deploy_downloads_to_s3
344
+ remote:deploy_to_rsync_server
345
+ )
346
+
347
+ if Pkg::Util.boolean_value(Pkg::Config.answer_override) && !Pkg::Config.foss_only
348
+ fail "Using ANSWER_OVERRIDE without FOSS_ONLY=true is dangerous!"
349
+ end
350
+
351
+ # Some projects such as pl-build-tools do not stage to a separate server - so we do to deploy
352
+ uber_tasks.delete("remote:deploy_apt_repo") if Pkg::Config.apt_host == Pkg::Config.apt_signing_server
353
+ uber_tasks.delete("remote:deploy_yum_repo") if Pkg::Config.yum_host == Pkg::Config.yum_staging_server
354
+ uber_tasks.delete("remote:deploy_dmg_repo") if Pkg::Config.dmg_host == Pkg::Config.dmg_staging_server
355
+ uber_tasks.delete("remote:deploy_swix_repo") if Pkg::Config.swix_host == Pkg::Config.swix_staging_server
356
+ uber_tasks.delete("remote:deploy_tar_repo") if Pkg::Config.tar_host == Pkg::Config.tar_staging_server
357
+
358
+ if Pkg::Config.s3_ship
359
+ uber_tasks.delete("remote:deploy_apt_repo")
360
+ uber_tasks.delete("remote:deploy_yum_repo")
361
+ uber_tasks.delete("remote:deploy_dmg_repo")
362
+ uber_tasks.delete("remote:deploy_swix_repo")
363
+ uber_tasks.delete("remote:deploy_msi_repo")
364
+ uber_tasks.delete("remote:deploy_tar_repo")
365
+ else
366
+ uber_tasks.delete("remote:deploy_apt_repo_to_s3")
367
+ uber_tasks.delete("remote:deploy_yum_repo_to_s3")
368
+ uber_tasks.delete("remote:deploy_downloads_to_s3")
369
+ uber_tasks.delete("remote:deploy_to_rsync_server")
370
+ end
371
+
372
+ # Delete the ship_gem task if we aren't building gems
373
+ uber_tasks.delete("ship_gem") unless Pkg::Config.build_gem
374
+
375
+ # I'm adding this check here because if we rework the task ordering we're
376
+ # probably going to need to muck about in here. -morgan
377
+ if uber_tasks.first == 'jenkins:retrieve'
378
+ # We need to run retrieve before we can delete tasks based on what
379
+ # packages were built. Before this we were deleting tasks based on files
380
+ # in a directory that hadn't been populated yet, so this would either
381
+ # fail since all tasks would be removed, or would be running based on
382
+ # files left over in packaging from the last ship.
383
+ puts 'Do you want to run pl:jenkins:retrieve?'
384
+ Rake::Task['pl:jenkins:retrieve'].invoke if Pkg::Util.ask_yes_or_no
385
+ uber_tasks.delete('jenkins:retrieve')
386
+ end
387
+
388
+ # Don't update and deploy repos if packages don't exist
389
+ # If we can't find a certain file type, delete the task
390
+ if Dir.glob("pkg/**/*.deb").empty?
391
+ uber_tasks.delete("remote:update_apt_repo")
392
+ uber_tasks.delete("remote:deploy_apt_repo")
393
+ end
394
+
395
+ if Dir.glob("pkg/**/*.rpm").empty?
396
+ uber_tasks.delete("remote:update_yum_repo")
397
+ uber_tasks.delete("remote:deploy_yum_repo")
398
+ end
399
+
400
+ if Dir.glob("pkg/**/*.p5p").empty?
401
+ uber_tasks.delete("remote:update_ips_repo")
402
+ end
403
+
404
+ if Dir.glob("pkg/**/*.dmg").empty?
405
+ uber_tasks.delete("remote:deploy_dmg_repo")
406
+ end
407
+
408
+ if Dir.glob("pkg/**/*.swix").empty?
409
+ uber_tasks.delete("remote:deploy_swix_repo")
410
+ end
411
+
412
+ if Dir.glob("pkg/**/*.msi").empty?
413
+ uber_tasks.delete("remote:deploy_msi_repo")
414
+ end
415
+
416
+ if Dir.glob("pkg/*.tar.gz").empty?
417
+ uber_tasks.delete("remote:deploy_tar_repo")
418
+ end
419
+
420
+ uber_tasks.map { |t| "pl:#{t}" }.each do |t|
421
+ puts "Do you want to run #{t}?"
422
+ Rake::Task[t].invoke if Pkg::Util.ask_yes_or_no
423
+ end
424
+
425
+ puts "Do you want to mark this release as successfully shipped?"
426
+ Rake::Task["pl:jenkins:ship"].invoke("shipped") if Pkg::Util.ask_yes_or_no
427
+ end
428
+
429
+ desc "Test shipping by replacing hosts with a VM"
430
+ task :test_ship, [:vm, :ship_task] do |t, args|
431
+ vm = args.vm or fail "`vm` is a required argument for #{t}"
432
+ ship_task = args.ship_task or fail "`ship_task` is a required argument for #{t}"
433
+ Pkg::Util::Ship.test_ship(vm, ship_task)
434
+ end
435
+ end
436
+ end
437
+
438
+ ##
439
+ # If this is a PE project, we want PE tasks as well.
440
+ #
441
+ if Pkg::Config.build_pe
442
+ namespace :pe do
443
+ namespace :jenkins do
444
+ tasks.each do |build_task|
445
+ desc "Queue pe:#{build_task} build on jenkins builder"
446
+ task build_task => "pl:fetch" do
447
+ Pkg::Util.check_var("PE_VER", Pkg::Config.pe_version)
448
+ Pkg::Util::RakeUtils.invoke_task("pl:jenkins:post_build", "pe:#{build_task}")
449
+ end
450
+ end
451
+
452
+ # While pl:remote:deb_all does all cows in serially, with jenkins we
453
+ # parallelize them. This breaks the cows up and posts a build for all of
454
+ # them. We have to sleep 5 because jenkins drops the builds when we're
455
+ # DOSing it with our packaging.
456
+ desc "Queue pe:deb_all on jenkins builder"
457
+ task :deb_all => "pl:fetch" do
458
+ Pkg::Util.check_var("PE_VER", Pkg::Config.pe_version)
459
+ Pkg::Config.cows.split(' ').each do |cow|
460
+ Pkg::Config.default_cow = cow
461
+ Pkg::Util::RakeUtils.invoke_task("pl:jenkins:post_build", "pe:deb")
462
+ sleep 5
463
+ end
464
+ end
465
+
466
+ # This does the mocks in parallel
467
+ desc "Queue pe:mock_all on jenkins builder"
468
+ task :mock_all => "pl:fetch" do
469
+ Pkg::Config.final_mocks.split(' ').each do |mock|
470
+ Pkg::Config.default_mock = mock
471
+ Pkg::Util::RakeUtils.invoke_task("pl:jenkins:post_build", "pe:mock")
472
+ sleep 5
473
+ end
474
+ end
475
+
476
+ desc "Retrieve PE packages built by jenkins, sign, and ship all!"
477
+ task :uber_ship => "pl:fetch" do
478
+ Pkg::Util.check_var("PE_VER", Pkg::Config.pe_version)
479
+ ["pl:jenkins:retrieve", "pl:jenkins:sign_all", "pe:ship_rpms", "pe:ship_debs"].each do |task|
480
+ Rake::Task[task].invoke
481
+ end
482
+ Rake::Task["pl:jenkins:ship"].invoke("shipped")
483
+ end
484
+ end
485
+ end
486
+ end
487
+
488
+ ##
489
+ # This task allows the packaging repo to post to an arbitrary jenkins job but
490
+ # it is very limited in that it does not model well the key => value format
491
+ # used when submitting form data on websites. This is primarily because rake
492
+ # does not allow us to elegantly pass arbitrary key => value pairs on the
493
+ # command line and have any idea how to reference them inside rake. We can pass
494
+ # KEY=VALUE along with our invokation, but unless KEY is statically coded into
495
+ # our task, we won't know how to reference it. Thus, this task will only take
496
+ # one argument, the uri of the jenkins job to post to. This can be passed
497
+ # either as an argument directly or as an environment variable "JOB" with the
498
+ # uri as the value. The argument is required. The second requirement is that
499
+ # the job to be called accept a string parameter with the name SHA. This will
500
+ # be the SHA of the commit of the project source code HEAD, and should be used
501
+ # by the job to check out this specific ref. To maintain the abstraction of the
502
+ # jenkins jobs, this specific task passes on no information about the build
503
+ # itself. The assumption is that the upstream jobs know about their project,
504
+ # and so do the downstream jobs, but packaging itself has no business knowing
505
+ # about it.
506
+ #
507
+ namespace :pl do
508
+ namespace :jenkins do
509
+ desc "Trigger a jenkins uri with SHA of HEAD as a string param, requires \"URI\""
510
+ task :post, :uri do |t, args|
511
+ uri = (args.uri or ENV['URI']) or fail "pl:jenkins:post requires a URI, either via URI= or pl:jenkin:post[URI]"
512
+
513
+ # We use JSON for parsing the json part of the submission.
514
+ begin
515
+ require 'json'
516
+ rescue LoadError
517
+ fail "Couldn't require 'json'. JSON is required for sanely generating the string we curl to Jenkins."
518
+ end
519
+
520
+ # Assemble the JSON string for the JSON parameter
521
+ json = JSON.generate("parameter" => [{ "name" => "SHA", "value" => "#{Pkg::Config.ref}" }])
522
+
523
+ # Assemble our arguments to the post
524
+ args = [
525
+ "-Fname=SHA", "-Fvalue=#{Pkg::Config.ref}",
526
+ "-Fjson=#{json.to_json}",
527
+ "-FSubmit=Build"
528
+ ]
529
+
530
+ _, retval = Pkg::Util::Net.curl_form_data(uri, args)
531
+ if Pkg::Util::Execution.success?(retval)
532
+ puts "Job triggered at #{uri}."
533
+ else
534
+ fail "An error occurred attempting to trigger the job at #{uri}. Please see the preceding http response for more info."
535
+ end
536
+ end
537
+ end
538
+ end