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
@@ -0,0 +1,155 @@
1
+ module Pkg::Repo
2
+
3
+ class << self
4
+
5
+ ##
6
+ ## Construct a local_target based upon the versioning style
7
+ ##
8
+ def construct_local_target_path(project, versioning)
9
+ case versioning
10
+ when 'ref'
11
+ return File.join(project, Pkg::Config.ref)
12
+ when 'version'
13
+ return File.join(project, Pkg::Util::Version.dot_version)
14
+ else
15
+ fail "Error: Unknown versioning argument: #{versioning}"
16
+ end
17
+ end
18
+
19
+ ##
20
+ ## Put a single signed repo into a tarball stored in
21
+ ## 'pkg/<local_target>/<archive_name>.tar.gz'
22
+ ##
23
+ def create_signed_repo_archive(repo_location, archive_name, versioning)
24
+ tar = Pkg::Util::Tool.check_tool('tar')
25
+
26
+ local_target = construct_local_target_path(Pkg::Config.project, versioning)
27
+
28
+ if Pkg::Util::File.empty_dir?(File.join('pkg', local_target, repo_location))
29
+ if ENV['FAIL_ON_MISSING_TARGET'] == "true"
30
+ raise "Error: missing packages under #{repo_location}"
31
+ end
32
+ warn "Warn: Skipping #{archive_name} because #{repo_location} has no files"
33
+ return
34
+ end
35
+
36
+ Dir.chdir(File.join('pkg', local_target)) do
37
+ puts "Info: Archiving #{repo_location} as #{archive_name}"
38
+ target_tarball = File.join('repos', "#{archive_name}.tar.gz")
39
+ tar_command = "#{tar} --owner=0 --group=0 --create --gzip --file #{target_tarball} #{repo_location}"
40
+ stdout, _, _ = Pkg::Util::Execution.capture3(tar_command)
41
+ return stdout
42
+ end
43
+ end
44
+
45
+ ##
46
+ ## Add a single repo tarball into the 'all' tarball located in
47
+ ## 'pkg/<local_target>/<project>-all.tar'
48
+ ## Create the 'all' tarball if needed.
49
+ ##
50
+ def update_tarball_of_all_repos(project, platform, versioning)
51
+ tar = Pkg::Util::Tool.check_tool('tar')
52
+
53
+ all_repos_tarball_name = "#{project}-all.tar"
54
+ archive_name = "#{project}-#{platform['name']}"
55
+ local_target = construct_local_target_path(project, versioning)
56
+ repo_tarball_name = "#{archive_name}.tar.gz"
57
+ repo_tarball_path = File.join('repos', repo_tarball_name)
58
+
59
+ Dir.chdir(File.join('pkg', local_target)) do
60
+ unless Pkg::Util::File.exist?(repo_tarball_path)
61
+ warn "Skipping #{archive_name} because it (#{repo_tarball_path}) contains no files"
62
+ next
63
+ end
64
+
65
+ tar_action = "--create"
66
+ if File.exist?(all_repos_tarball_name)
67
+ tar_action = "--update"
68
+ end
69
+
70
+ tar_command = "#{tar} --owner=0 --group=0 #{tar_action} --file #{all_repos_tarball_name} #{repo_tarball_path}"
71
+ stdout, _, _ = Pkg::Util::Execution.capture3(tar_command)
72
+ puts stdout
73
+ end
74
+ end
75
+
76
+ ##
77
+ ## Invoke gzip to compress the 'all' tarball located in
78
+ ## 'pkg/<local_target>/<project>-all.tar'
79
+ ##
80
+ def compress_tarball_of_all_repos(all_repos_tarball_name)
81
+ gzip = Pkg::Util::Tool.check_tool('gzip')
82
+
83
+ gzip_command = "#{gzip} --fast #{all_repos_tarball_name}"
84
+ stdout, _, _ = Pkg::Util::Execution.capture3(gzip_command)
85
+ puts stdout
86
+ end
87
+
88
+ ##
89
+ ## Generate each of the repos listed in <Config.platform_repos>.
90
+ ## Update the 'all repos' tarball as we do each one.
91
+ ## Compress the 'all repos' tarball when all the repos have been generated
92
+ ##
93
+ def create_all_repo_archives(project, versioning)
94
+ platforms = Pkg::Config.platform_repos
95
+ local_target = construct_local_target_path(project, versioning)
96
+ all_repos_tarball_name = "#{project}-all.tar"
97
+
98
+ platforms.each do |platform|
99
+ archive_name = "#{project}-#{platform['name']}"
100
+ create_signed_repo_archive(platform['repo_location'], archive_name, versioning)
101
+ update_tarball_of_all_repos(project, platform, versioning)
102
+ end
103
+
104
+ Dir.chdir(File.join('pkg', local_target)) do
105
+ compress_tarball_of_all_repos(all_repos_tarball_name)
106
+ end
107
+ end
108
+
109
+ def directories_that_contain_packages(artifact_directory, pkg_ext)
110
+ cmd = "[ -d #{artifact_directory} ] || exit 1 ; "
111
+ cmd << "pushd #{artifact_directory} > /dev/null && "
112
+ cmd << "find . -name '*.#{pkg_ext}' -print0 | xargs --no-run-if-empty -0 -I {} dirname {} "
113
+ stdout, _ = Pkg::Util::Net.remote_execute(
114
+ Pkg::Config.distribution_server,
115
+ cmd,
116
+ { capture_output: true }
117
+ )
118
+ return stdout.split
119
+ rescue => e
120
+ fail "Error: Could not retrieve directories that contain #{pkg_ext} packages in #{Pkg::Config.distribution_server}:#{artifact_directory}"
121
+ end
122
+
123
+ def populate_repo_directory(artifact_parent_directory)
124
+ cmd = "[ -d #{artifact_parent_directory}/artifacts ] || exit 1 ; "
125
+ cmd << "pushd #{artifact_parent_directory} > /dev/null && "
126
+ cmd << 'rsync --archive --verbose --one-file-system --ignore-existing artifacts/ repos/ '
127
+ Pkg::Util::Net.remote_execute(Pkg::Config.distribution_server, cmd)
128
+ rescue => e
129
+ fail "Error: Could not populate repos directory in #{Pkg::Config.distribution_server}:#{artifact_parent_directory}"
130
+ end
131
+
132
+ def argument_required?(argument_name, repo_command)
133
+ repo_command.include?("__#{argument_name.upcase}__")
134
+ end
135
+
136
+ def update_repo(remote_host, command, options = {})
137
+ fail_message = "Error: Missing required argument '%s', update your build_defaults?"
138
+ [:repo_name, :repo_path, :repo_host, :repo_url].each do |option|
139
+ fail fail_message % option.to_s if argument_required?(option.to_s, command) && !options[option]
140
+ end
141
+
142
+ whitelist = {
143
+ __REPO_NAME__: options[:repo_name],
144
+ __REPO_PATH__: options[:repo_path],
145
+ __REPO_HOST__: options[:repo_host],
146
+ __REPO_URL__: options[:repo_url],
147
+ __APT_PLATFORMS__: Pkg::Config.apt_releases.join(' '),
148
+ __GPG_KEY__: Pkg::Util::Gpg.key
149
+ }
150
+ Pkg::Util::Net.remote_execute(
151
+ remote_host,
152
+ Pkg::Util::Misc.search_and_replace(command, whitelist))
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,75 @@
1
+ module Pkg::Retrieve
2
+ module_function
3
+
4
+ # --no-parent = Only descend when recursing, never ascend
5
+ # --no-host-directories = Discard http://#{Pkg::Config.builds_server} when saving to disk
6
+ # --level=0 = infinitely recurse, no limit
7
+ # --cut-dirs 3 = will cut off #{Pkg::Config.project}, #{Pkg::Config.ref}, and the first directory in #{remote_target} from the url when saving to disk
8
+ # --directory-prefix = where to save to disk (defaults to ./)
9
+ # --reject = Reject all hits that match the supplied regex
10
+
11
+ def default_wget_command(local_target, url, additional_options = {})
12
+ default_options = {
13
+ 'quiet' => true,
14
+ 'recursive' => true,
15
+ 'no-parent' => true,
16
+ 'no-host-directories' => true,
17
+ 'level' => 0,
18
+ 'cut-dirs' => 3,
19
+ 'directory-prefix' => local_target,
20
+ 'reject' => "'index*'",
21
+ }
22
+ options = default_options.merge(additional_options)
23
+ wget = Pkg::Util::Tool.check_tool('wget')
24
+ wget_command = wget
25
+ options.each do |option, value|
26
+ next unless value
27
+ if value.is_a?(TrueClass)
28
+ wget_command << " --#{option}"
29
+ else
30
+ wget_command << " --#{option}=#{value}"
31
+ end
32
+ end
33
+ wget_command << " #{url}"
34
+ return wget_command
35
+ end
36
+
37
+ # NOTE: When supplying additional options, if you want your value to be
38
+ # quoted (e.g. --reject='index*'), you must include the quotes as part of
39
+ # your string (e.g. {'reject' => "'index*'"}).
40
+ def default_wget(local_target, url, additional_options = {})
41
+ wget_command = default_wget_command(local_target, url, additional_options)
42
+ puts "Executing #{wget_command} . . ."
43
+ %x(#{wget_command})
44
+ end
45
+
46
+ # This will always retrieve from under the 'artifacts' directory
47
+ def foss_only_retrieve(build_url, local_target)
48
+ unless Pkg::Config.foss_platforms
49
+ fail "FOSS_ONLY specified, but I don't know anything about FOSS_PLATFORMS. Retrieve cancelled."
50
+ end
51
+ default_wget(local_target, "#{build_url}/", { 'level' => 1 })
52
+ yaml_path = File.join(local_target, "#{Pkg::Config.ref}.yaml")
53
+ unless File.readable?(yaml_path)
54
+ fail "Couldn't read #{Pkg::Config.ref}.yaml, which is necessary for FOSS_ONLY. Retrieve cancelled."
55
+ end
56
+ platform_data = Pkg::Util::Serialization.load_yaml(yaml_path)[:platform_data]
57
+ platform_data.each do |platform, paths|
58
+ path_to_retrieve = File.dirname(paths[:artifact])
59
+ default_wget(local_target, "#{build_url}/#{path_to_retrieve}/") if Pkg::Config.foss_platforms.include?(platform)
60
+ end
61
+ end
62
+
63
+ def retrieve_all(build_url, rsync_path, local_target)
64
+ if Pkg::Util::Tool.find_tool("wget")
65
+ default_wget(local_target, "#{build_url}/")
66
+ else
67
+ warn "Could not find `wget` tool. Falling back to rsyncing from #{Pkg::Config.distribution_server}."
68
+ begin
69
+ Pkg::Util::Net.rsync_from("#{rsync_path}/", Pkg::Config.distribution_server, "#{local_target}/")
70
+ rescue => e
71
+ fail "Couldn't rsync packages from distribution server.\n#{e}"
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,5 @@
1
+ # RPM methods used by various libraries and rake tasks
2
+
3
+ module Pkg::Rpm
4
+ require 'packaging/rpm/repo'
5
+ end
@@ -0,0 +1,254 @@
1
+ # Utilities for working with rpm repos
2
+ require 'fileutils'
3
+ require 'find'
4
+
5
+ module Pkg::Rpm::Repo
6
+ class << self
7
+ def base_url
8
+ "http://#{Pkg::Config.builds_server}/#{Pkg::Config.project}/#{Pkg::Config.ref}"
9
+ end
10
+
11
+ def ship_repo_configs(target = "repo_configs")
12
+ if Pkg::Util::File.empty_dir?("pkg/#{target}/rpm")
13
+ warn "No repo configs have been generated! Try pl:rpm_repo_configs."
14
+ return
15
+ end
16
+
17
+ Pkg::Util::RakeUtils.invoke_task("pl:fetch")
18
+ repo_dir = "#{Pkg::Config.jenkins_repo_path}/#{Pkg::Config.project}/#{Pkg::Config.ref}/#{target}/rpm"
19
+ Pkg::Util::Net.remote_execute(Pkg::Config.distribution_server, "mkdir -p #{repo_dir}")
20
+ Pkg::Util::Execution.retry_on_fail(:times => 3) do
21
+ Pkg::Util::Net.rsync_to("pkg/#{target}/rpm/", Pkg::Config.distribution_server, repo_dir)
22
+ end
23
+ end
24
+
25
+ def repo_creation_command(repo_directory, artifact_paths = nil)
26
+ cmd = "[ -d #{repo_directory} ] || exit 1 ; "
27
+ cmd << "pushd #{repo_directory} > /dev/null && "
28
+ cmd << 'echo "Checking for running repo creation. Will wait if detected." && '
29
+ cmd << 'while [ -f .lock ] ; do sleep 1 ; echo -n "." ; done && '
30
+ cmd << 'echo "Setting lock" && '
31
+ cmd << 'touch .lock && '
32
+ cmd << 'createrepo=$(which createrepo) ; '
33
+
34
+ # Added for compatibility.
35
+ # The nightly repo ships operate differently and do not want to be calculating
36
+ # the correct paths based on which packages are available on the distribution
37
+ # host, we just want to be `createrepo`ing for what we've staged locally
38
+ #
39
+ # We should only assume repo_directory exists locally if we didn't pass
40
+ # artifact paths
41
+ if artifact_paths.nil?
42
+ # Since the command already has a `pushd #{repo_directory}` let's make sure
43
+ # we're calculating artifact paths relative to that.
44
+ Dir.chdir repo_directory do
45
+ artifact_paths = Dir.glob('**/*.rpm').map { |package| File.dirname(package) }
46
+ end
47
+ end
48
+
49
+ artifact_paths.each do |path|
50
+ next if path.include? 'aix'
51
+ cmd << "if [ -d #{path} ]; then "
52
+ cmd << "pushd #{path} && "
53
+ cmd << '$createrepo --checksum=sha --checkts --update --delta-workers=0 --database . && '
54
+ cmd << 'popd ; '
55
+ cmd << 'fi ;'
56
+ end
57
+ cmd
58
+ end
59
+
60
+ # @deprecated this command will die a painful death when we are
61
+ # able to sit down with Operations and refactor our distribution infra.
62
+ # At a minimum, it should be refactored alongside its Debian counterpart
63
+ # into something modestly more generic.
64
+ # - Ryan McKern 11/2015
65
+ #
66
+ # @param origin_path [String] path for RPM repos on local filesystem
67
+ # @param destination_path [String] path for RPM repos on remote filesystem
68
+ # @param destination [String] remote host to send rsynced content to. If
69
+ # nil will copy locally
70
+ # @param dryrun [Boolean] whether or not to use '--dry-run'
71
+ #
72
+ # @return [String] an rsync command that can be executed on a remote host
73
+ # to copy local content from that host to a remote node.
74
+ def repo_deployment_command(origin_path, destination_path, destination, dryrun = false)
75
+ path = Pathname.new(origin_path)
76
+ dest_path = Pathname.new(destination_path)
77
+
78
+ options = %w(
79
+ rsync
80
+ --recursive
81
+ --links
82
+ --hard-links
83
+ --update
84
+ --human-readable
85
+ --itemize-changes
86
+ --progress
87
+ --verbose
88
+ --super
89
+ --delay-updates
90
+ --omit-dir-times
91
+ --no-perms
92
+ --no-owner
93
+ --no-group
94
+ )
95
+
96
+ options << '--dry-run' if dryrun
97
+ options << path
98
+
99
+ if destination
100
+ options << "#{destination}:#{dest_path.parent}"
101
+ else
102
+ options << "#{dest_path.parent}"
103
+ end
104
+
105
+ options.join("\s")
106
+ end
107
+
108
+ def sign_repos(directory)
109
+ files_to_sign = Find.find(directory).select { |file| file.match(/repomd.xml$/) }
110
+ files_to_sign.each do |file|
111
+ Pkg::Util::Gpg.sign_file(file)
112
+ end
113
+ end
114
+
115
+ def retrieve_repo_configs(target = "repo_configs")
116
+ wget = Pkg::Util::Tool.check_tool("wget")
117
+ FileUtils.mkdir_p("pkg/#{target}")
118
+ config_url = "#{base_url}/#{target}/rpm/"
119
+ begin
120
+ stdout, _, _ = Pkg::Util::Execution.capture3("#{wget} -r -np -nH --cut-dirs 3 -P pkg/#{target} --reject 'index*' #{config_url}")
121
+ stdout
122
+ rescue => e
123
+ fail "Couldn't retrieve rpm yum repo configs.\n#{e}"
124
+ end
125
+ end
126
+
127
+ # Generate yum configuration files that point to the repositories created
128
+ # on the distribution server with packages created from the current source
129
+ # repo commit. There is one for each dist/version that is packaged (e.g.
130
+ # el5, el6, etc). Files are created in pkg/repo_configs/rpm and are named
131
+ # pl-$project-$sha.conf, and can be placed in /etc/yum.repos.d to enable
132
+ # clients to install these packages.
133
+ #
134
+ def generate_repo_configs(source = "repos", target = "repo_configs", signed = false)
135
+ # We have a hard requirement on wget because of all the download magicks
136
+ # we have to do
137
+ #
138
+ wget = Pkg::Util::Tool.check_tool("wget")
139
+
140
+ # This is the standard path to all build artifacts on the distribution
141
+ # server for this commit
142
+ #
143
+ repo_base = "#{base_url}/#{source}/"
144
+
145
+ # First check if the artifacts directory exists
146
+ #
147
+
148
+ # We have to do two checks here - first that there are directories with
149
+ # repodata folders in them, and second that those same directories also
150
+ # contain rpms
151
+ #
152
+ stdout, _, _ = Pkg::Util::Execution.capture3("#{wget} --spider -r -l 5 --no-parent #{repo_base} 2>&1")
153
+ stdout = stdout.split.uniq.reject { |x| x =~ /\?|index/ }.select { |x| x =~ /http:.*repodata\/$/ }
154
+
155
+ # RPMs will always exist at the same directory level as the repodata
156
+ # folder, which means if we go up a level we should find rpms
157
+ #
158
+ yum_repos = []
159
+ stdout.map { |x| x.chomp('repodata/') }.each do |url|
160
+ output, _, _ = Pkg::Util::Execution.capture3("#{wget} --spider -r -l 1 --no-parent #{url} 2>&1")
161
+ unless output.split.uniq.reject { |x| x =~ /\?|index/ }.select { |x| x =~ /http:.*\.rpm$/ }.empty?
162
+ yum_repos << url
163
+ end
164
+ end
165
+
166
+ if yum_repos.empty?
167
+ warn "No rpm repos were found to generate configs from!"
168
+ return
169
+ end
170
+
171
+ FileUtils.mkdir_p(File.join("pkg", target, "rpm"))
172
+
173
+ # Parse the rpm configs file to generate repository configs. Each line in
174
+ # the rpm_configs file corresponds with a repo directory on the
175
+ # distribution server.
176
+ #
177
+ yum_repos.each do |url|
178
+ # We ship a base 'srpm' that gets turned into a repo, but we want to
179
+ # ignore this one because its an extra
180
+ next if url == "#{repo_base}srpm/"
181
+
182
+ platform_tag = Pkg::Paths.tag_from_artifact_path(url)
183
+ platform, version, arch = Pkg::Platforms.parse_platform_tag(platform_tag)
184
+
185
+ # Create an array of lines that will become our yum config
186
+ #
187
+ config = ["[pl-#{Pkg::Config.project}-#{Pkg::Config.ref}]"]
188
+ config << ["name=PL Repo for #{Pkg::Config.project} at commit #{Pkg::Config.ref}"]
189
+ config << ["baseurl=#{url}"]
190
+ config << ["enabled=1"]
191
+ if signed
192
+ config << ["gpgcheck=1"]
193
+ config << ["gpgkey=http://#{Pkg::Config.builds_server}/#{Pkg::Util::Gpg.key}"]
194
+ else
195
+ config << ["gpgcheck=0"]
196
+ end
197
+
198
+ # Write the new config to a file under our repo configs dir
199
+ #
200
+ config_file = File.join("pkg", target, "rpm", "pl-#{Pkg::Config.project}-#{Pkg::Config.ref}-#{platform}-#{version}-#{arch}.repo")
201
+ File.open(config_file, 'w') { |f| f.puts config }
202
+ end
203
+ puts "Wrote yum configuration files for #{Pkg::Config.project} at #{Pkg::Config.ref} to pkg/#{target}/rpm"
204
+ end
205
+
206
+ def create_local_repos(directory = "repos")
207
+ stdout, _, _ = Pkg::Util::Execution.capture3("bash -c '#{repo_creation_command(directory)}'")
208
+ stdout
209
+ end
210
+
211
+ def create_remote_repos(directory = 'repos')
212
+ artifact_directory = File.join(Pkg::Config.jenkins_repo_path, Pkg::Config.project, Pkg::Config.ref)
213
+ artifact_paths = Pkg::Repo.directories_that_contain_packages(File.join(artifact_directory, 'artifacts'), 'rpm')
214
+ Pkg::Repo.populate_repo_directory(artifact_directory)
215
+ command = Pkg::Rpm::Repo.repo_creation_command(File.join(artifact_directory, directory), artifact_paths)
216
+
217
+ begin
218
+ Pkg::Util::Net.remote_execute(Pkg::Config.distribution_server, command)
219
+ # Now that we've created our package repositories, we can generate repo
220
+ # configurations for use with downstream jobs, acceptance clients, etc.
221
+ Pkg::Rpm::Repo.generate_repo_configs
222
+
223
+ # Now that we've created the repo configs, we can ship them
224
+ Pkg::Rpm::Repo.ship_repo_configs
225
+ ensure
226
+ # Always remove the lock file, even if we've failed
227
+ Pkg::Util::Net.remote_execute(Pkg::Config.distribution_server, "rm -f #{artifact_directory}/repos/.lock")
228
+ end
229
+ end
230
+
231
+ def create_repos_from_artifacts(directory = "repos")
232
+ Pkg::Util.deprecate('Pkg::Rpm::Repo.create_repos_from_artifacts', 'Pkg::Rpm::Repo.create_remote_repos')
233
+ create_remote_repos(directory)
234
+ end
235
+
236
+ def create_repos(directory = "repos")
237
+ Pkg::Util.deprecate('Pkg::Rpm::Repo.create_repos', 'Pkg::Rpm::Repo.create_local_repos')
238
+ create_local_repos(directory)
239
+ end
240
+
241
+ # @deprecated this command is exactly as awful as you think it is.
242
+ # -- Ryan McKern 12/2015
243
+ #
244
+ # @param yum_path [String] path for rpm repos on local and remote filesystem
245
+ # @param origin_server [String] remote host to start the rsync from
246
+ # @param destination_server [String] remote host to send rsynced content to
247
+ # @param dryrun [Boolean] whether or not to use '--dry-run'
248
+ def deploy_repos(yum_path, origin_server, destination_server, dryrun = false)
249
+ rsync_command = repo_deployment_command(yum_path, yum_path, destination_server, dryrun)
250
+
251
+ Pkg::Util::Net.remote_execute(origin_server, rsync_command)
252
+ end
253
+ end
254
+ end