packaging 0.88.77

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 (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