packaging 0.99.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +17 -0
  3. data/README-Solaris.md +117 -0
  4. data/README.md +1031 -0
  5. data/lib/packaging.rb +32 -0
  6. data/lib/packaging/artifactory.rb +278 -0
  7. data/lib/packaging/config.rb +392 -0
  8. data/lib/packaging/config/params.rb +366 -0
  9. data/lib/packaging/deb.rb +28 -0
  10. data/lib/packaging/deb/repo.rb +263 -0
  11. data/lib/packaging/gem.rb +112 -0
  12. data/lib/packaging/ips.rb +57 -0
  13. data/lib/packaging/msi.rb +89 -0
  14. data/lib/packaging/nuget.rb +39 -0
  15. data/lib/packaging/osx.rb +36 -0
  16. data/lib/packaging/paths.rb +238 -0
  17. data/lib/packaging/platforms.rb +480 -0
  18. data/lib/packaging/repo.rb +55 -0
  19. data/lib/packaging/retrieve.rb +46 -0
  20. data/lib/packaging/rpm.rb +5 -0
  21. data/lib/packaging/rpm/repo.rb +257 -0
  22. data/lib/packaging/tar.rb +154 -0
  23. data/lib/packaging/util.rb +146 -0
  24. data/lib/packaging/util/date.rb +15 -0
  25. data/lib/packaging/util/execution.rb +85 -0
  26. data/lib/packaging/util/file.rb +125 -0
  27. data/lib/packaging/util/git.rb +174 -0
  28. data/lib/packaging/util/git_tags.rb +73 -0
  29. data/lib/packaging/util/gpg.rb +62 -0
  30. data/lib/packaging/util/jenkins.rb +95 -0
  31. data/lib/packaging/util/misc.rb +69 -0
  32. data/lib/packaging/util/net.rb +368 -0
  33. data/lib/packaging/util/os.rb +17 -0
  34. data/lib/packaging/util/platform.rb +40 -0
  35. data/lib/packaging/util/rake_utils.rb +111 -0
  36. data/lib/packaging/util/serialization.rb +19 -0
  37. data/lib/packaging/util/ship.rb +171 -0
  38. data/lib/packaging/util/tool.rb +41 -0
  39. data/lib/packaging/util/version.rb +326 -0
  40. data/spec/fixtures/config/ext/build_defaults.yaml +2 -0
  41. data/spec/fixtures/config/ext/project_data.yaml +2 -0
  42. data/spec/fixtures/config/params.yaml +2 -0
  43. data/spec/fixtures/configs/components/test_file.json +1 -0
  44. data/spec/fixtures/configs/components/test_file_2.json +0 -0
  45. data/spec/fixtures/configs/components/test_file_not_tagged.json +1 -0
  46. data/spec/fixtures/configs/components/test_file_wrong_ext.txt +0 -0
  47. data/spec/fixtures/configs/components/test_file_wrong_ext.wrong +0 -0
  48. data/spec/fixtures/util/pre_tasks.yaml +4 -0
  49. data/spec/lib/packaging/artifactory_spec.rb +171 -0
  50. data/spec/lib/packaging/config_spec.rb +556 -0
  51. data/spec/lib/packaging/deb/repo_spec.rb +148 -0
  52. data/spec/lib/packaging/deb_spec.rb +52 -0
  53. data/spec/lib/packaging/paths_spec.rb +153 -0
  54. data/spec/lib/packaging/platforms_spec.rb +153 -0
  55. data/spec/lib/packaging/repo_spec.rb +97 -0
  56. data/spec/lib/packaging/retrieve_spec.rb +61 -0
  57. data/spec/lib/packaging/rpm/repo_spec.rb +133 -0
  58. data/spec/lib/packaging/tar_spec.rb +122 -0
  59. data/spec/lib/packaging/util/execution_spec.rb +56 -0
  60. data/spec/lib/packaging/util/file_spec.rb +139 -0
  61. data/spec/lib/packaging/util/git_spec.rb +160 -0
  62. data/spec/lib/packaging/util/git_tag_spec.rb +36 -0
  63. data/spec/lib/packaging/util/gpg_spec.rb +64 -0
  64. data/spec/lib/packaging/util/jenkins_spec.rb +112 -0
  65. data/spec/lib/packaging/util/misc_spec.rb +31 -0
  66. data/spec/lib/packaging/util/net_spec.rb +239 -0
  67. data/spec/lib/packaging/util/os_spec.rb +31 -0
  68. data/spec/lib/packaging/util/rake_utils_spec.rb +70 -0
  69. data/spec/lib/packaging/util/ship_spec.rb +117 -0
  70. data/spec/lib/packaging/util/version_spec.rb +123 -0
  71. data/spec/lib/packaging_spec.rb +19 -0
  72. data/spec/spec_helper.rb +36 -0
  73. data/static_artifacts/PackageInfo.plist +3 -0
  74. data/tasks/00_utils.rake +216 -0
  75. data/tasks/30_metrics.rake +33 -0
  76. data/tasks/apple.rake +266 -0
  77. data/tasks/build.rake +12 -0
  78. data/tasks/clean.rake +5 -0
  79. data/tasks/config.rake +30 -0
  80. data/tasks/deb.rake +129 -0
  81. data/tasks/deb_repos.rake +28 -0
  82. data/tasks/deprecated.rake +130 -0
  83. data/tasks/doc.rake +20 -0
  84. data/tasks/education.rake +57 -0
  85. data/tasks/fetch.rake +57 -0
  86. data/tasks/gem.rake +146 -0
  87. data/tasks/jenkins.rake +494 -0
  88. data/tasks/jenkins_dynamic.rake +202 -0
  89. data/tasks/load_extras.rake +21 -0
  90. data/tasks/mock.rake +348 -0
  91. data/tasks/nightly_repos.rake +335 -0
  92. data/tasks/pe_deb.rake +12 -0
  93. data/tasks/pe_rpm.rake +13 -0
  94. data/tasks/pe_ship.rake +221 -0
  95. data/tasks/pe_sign.rake +13 -0
  96. data/tasks/pe_tar.rake +5 -0
  97. data/tasks/retrieve.rake +45 -0
  98. data/tasks/rpm.rake +66 -0
  99. data/tasks/rpm_repos.rake +29 -0
  100. data/tasks/ship.rake +752 -0
  101. data/tasks/sign.rake +226 -0
  102. data/tasks/tag.rake +8 -0
  103. data/tasks/tar.rake +34 -0
  104. data/tasks/update.rake +16 -0
  105. data/tasks/vanagon.rake +35 -0
  106. data/tasks/vendor_gems.rake +117 -0
  107. data/tasks/version.rake +33 -0
  108. data/tasks/z_data_dump.rake +65 -0
  109. data/templates/README +1 -0
  110. data/templates/downstream.xml.erb +47 -0
  111. data/templates/msi.xml.erb +197 -0
  112. data/templates/packaging.xml.erb +344 -0
  113. data/templates/repo.xml.erb +114 -0
  114. metadata +234 -0
@@ -0,0 +1,112 @@
1
+ module Pkg::Gem
2
+ @nexus_config = "#{ENV['HOME']}/.gem/nexus"
3
+
4
+ class << self
5
+ # This is preserved because I don't want to update the deprecated code path
6
+ # yet; I'm not entirely sure I've fixed everything that might attempt
7
+ # to call this method so this is now a wrapper for a wrapper.
8
+ def ship(file)
9
+ ship_to_stickler(file)
10
+ ship_to_nexus(file)
11
+ rsync_to_downloads(file)
12
+ ship_to_rubygems(file)
13
+ end
14
+
15
+ def load_nexus_config
16
+ if Pkg::Util::File.file_exists?(@nexus_config)
17
+ config = YAML.load_file(@nexus_config)
18
+ end
19
+ config || {}
20
+ end
21
+
22
+ def write_nexus_config
23
+ hash = load_nexus_config
24
+ if hash["GEM_INTERNAL"].nil? || hash["GEM_INTERNAL"][:authorization].nil?
25
+ puts "Please enter nexus username:"
26
+ username = Pkg::Util.get_input
27
+ puts "Please enter nexus password:"
28
+ password = Pkg::Util.get_input(false)
29
+ hash["GEM_INTERNAL"] = { :authorization => "Basic #{Pkg::Util.base64_encode("#{username}:#{password}")}" }
30
+ end
31
+ if hash["GEM_INTERNAL"][:url].nil? || hash["GEM_INTERNAL"][:url] != Pkg::Config.internal_nexus_host
32
+ hash["GEM_INTERNAL"][:url] = Pkg::Config.internal_nexus_host
33
+ end
34
+ File.open(@nexus_config, "w") do |file|
35
+ file.write(hash.to_yaml)
36
+ end
37
+ end
38
+
39
+ # Ship a Ruby gem file to a Nexus server, because
40
+ # you've lost the ability to feel joy anymore.
41
+ def ship_to_nexus(file)
42
+ write_nexus_config
43
+ cmd = "gem nexus #{file} --repo GEM_INTERNAL"
44
+ if ENV['DRYRUN']
45
+ puts "[DRY-RUN] #{cmd}"
46
+ else
47
+ stdout, _, _ = Pkg::Util::Execution.capture3(cmd, true)
48
+ # The `gem nexus` command always returns `0` regardless of what the
49
+ # command results in. In order to properly handle fail cases, this
50
+ # checks for the success case and fails otherwise. The `ex` command
51
+ # above will print any output, so the user should have enough info
52
+ # to debug the failure, and potentially update this fail case if
53
+ # needed.
54
+ fail unless stdout.include? "Created"
55
+ puts "#{file} pushed to nexus server at #{Pkg::Config.internal_nexus_host}"
56
+ end
57
+ rescue => e
58
+ puts "###########################################"
59
+ puts "# Nexus failed, ensure the nexus gem is installed,"
60
+ puts "# you have access to #{Pkg::Config.internal_nexus_host}"
61
+ puts "# and your settings in #{@nexus_config} are correct"
62
+ puts "###########################################"
63
+ puts
64
+ puts e
65
+ raise e
66
+ end
67
+
68
+ # Ship a Ruby gem file to a Stickler server, because
69
+ # you've lost the ability to feel joy anymore.
70
+ def ship_to_stickler(file)
71
+ Pkg::Util::Tool.check_tool("stickler")
72
+ cmd = "stickler push #{file} --server=#{Pkg::Config.internal_stickler_host} 2>/dev/null"
73
+ if ENV['DRYRUN']
74
+ puts "[DRY-RUN] #{cmd}"
75
+ else
76
+ Pkg::Util::Execution.capture3(cmd)
77
+ puts "#{file} pushed to stickler server at #{Pkg::Config.internal_stickler_host}"
78
+ end
79
+ rescue => e
80
+ puts "###########################################"
81
+ puts "# Stickler failed, ensure it's installed"
82
+ puts "# and you have access to #{Pkg::Config.internal_stickler_host}"
83
+ puts "###########################################"
84
+ puts
85
+ puts e
86
+ raise e
87
+ end
88
+
89
+ # Use rsync to deploy a file and any associated detached signatures,
90
+ # checksums, or other glob-able artifacts to an external download server.
91
+ def rsync_to_downloads(file)
92
+ Pkg::Util.deprecate('Pkg::Gem.rsync_to_downloads', 'Pkg::Util::Ship.ship_pkgs')
93
+ Pkg::Util::Ship.ship_pkgs(["#{file}*"], Pkg::Config.gem_host, Pkg::Config.gem_path, platform_independent: true)
94
+ end
95
+
96
+ # Ship a Ruby gem file to rubygems.org. Requires the existence
97
+ # of a ~/.gem/credentials file or else rubygems.org won't have
98
+ # any idea who you are.
99
+ def ship_to_rubygems(file)
100
+ Pkg::Util::File.file_exists?("#{ENV['HOME']}/.gem/credentials", :required => true)
101
+ Pkg::Util::Execution.capture3("gem push #{file}")
102
+ rescue => e
103
+ puts "###########################################"
104
+ puts "# Publishing to rubygems failed. Make sure your .gem/credentials"
105
+ puts "# file is set up and you are an owner of #{Pkg::Config.gem_name}"
106
+ puts "###########################################"
107
+ puts
108
+ puts e
109
+ raise e
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,57 @@
1
+ module Pkg::IPS
2
+ class << self
3
+ def sign(target_dir = 'pkg')
4
+ use_identity = "-i #{Pkg::Config.ips_signing_ssh_key}" unless Pkg::Config.ips_signing_ssh_key.nil?
5
+
6
+ ssh_host_string = "#{use_identity} #{ENV['USER']}@#{Pkg::Config.ips_signing_server}"
7
+ rsync_host_string = "-e 'ssh #{use_identity}' #{ENV['USER']}@#{Pkg::Config.ips_signing_server}"
8
+
9
+ p5ps = Dir.glob("#{target_dir}/solaris/11/**/*.p5p")
10
+
11
+ p5ps.each do |p5p|
12
+ work_dir = "/tmp/#{Pkg::Util.rand_string}"
13
+ unsigned_dir = "#{work_dir}/unsigned"
14
+ repo_dir = "#{work_dir}/repo"
15
+ signed_dir = "#{work_dir}/pkgs"
16
+
17
+ Pkg::Util::Net.remote_ssh_cmd(ssh_host_string, "mkdir -p #{repo_dir} #{unsigned_dir} #{signed_dir}")
18
+ Pkg::Util::Net.rsync_to(p5p, rsync_host_string, unsigned_dir)
19
+
20
+ # Before we can get started with signing packages we need to create a repo
21
+ Pkg::Util::Net.remote_ssh_cmd(ssh_host_string, "sudo -E /usr/bin/pkgrepo create #{repo_dir}")
22
+ Pkg::Util::Net.remote_ssh_cmd(ssh_host_string, "sudo -E /usr/bin/pkgrepo set -s #{repo_dir} publisher/prefix=puppetlabs.com")
23
+ # And import all the packages into the repo.
24
+ Pkg::Util::Net.remote_ssh_cmd(ssh_host_string, "sudo -E /usr/bin/pkgrecv -s #{unsigned_dir}/#{File.basename(p5p)} -d #{repo_dir} '*'")
25
+ # We are going to hard code the values for signing cert locations for now.
26
+ # This autmation will require an update to actually become reusable, but
27
+ # for now these values will stay this way so solaris signing will stop
28
+ # failing. Please update soon. 06/23/16
29
+ #
30
+ # - Sean P. McDonald
31
+ #
32
+ # We sign the entire repo
33
+ sign_cmd = "sudo -E /usr/bin/pkgsign -c /root/signing/signing_cert_interim_SHA1.pem \
34
+ -i /root/signing/Thawte_Code_Signing_Certificate_interim_SHA1.pem \
35
+ -i /root/signing/Thawte_Primary_Root_CA_interim_SHA1.pem \
36
+ -k /root/signing/signing_key_interim_SHA1.pem \
37
+ -s 'file://#{work_dir}/repo' '*'"
38
+ puts "About to sign #{p5p} with #{sign_cmd} in #{work_dir}"
39
+ Pkg::Util::Net.remote_ssh_cmd(ssh_host_string, sign_cmd.squeeze(' '))
40
+ # pkgrecv with -a will pull packages out of the repo, so we need to do that too to actually get the packages we signed
41
+ Pkg::Util::Net.remote_ssh_cmd(ssh_host_string, "sudo -E /usr/bin/pkgrecv -d #{signed_dir}/#{File.basename(p5p)} -a -s #{repo_dir} '*'")
42
+ begin
43
+ # lets make sure we actually signed something?
44
+ # **NOTE** if we're repeatedly trying to sign the same version this
45
+ # might explode because I don't know how to reset the IPS cache.
46
+ # Everything is amazing.
47
+ Pkg::Util::Net.remote_ssh_cmd(ssh_host_string, "sudo -E /usr/bin/pkg contents -m -g #{signed_dir}/#{File.basename(p5p)} '*' | grep '^signature '")
48
+ rescue RuntimeError
49
+ raise "Looks like #{File.basename(p5p)} was not signed correctly, quitting!"
50
+ end
51
+ # and pull the packages back.
52
+ Pkg::Util::Net.rsync_from("#{signed_dir}/#{File.basename(p5p)}", rsync_host_string, File.dirname(p5p))
53
+ Pkg::Util::Net.remote_ssh_cmd(ssh_host_string, "if [ -e '#{work_dir}' ] ; then sudo rm -r '#{work_dir}' ; fi")
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,89 @@
1
+ module Pkg::MSI
2
+ class << self
3
+ def sign(target_dir = 'pkg')
4
+ use_identity = "-i #{Pkg::Config.msi_signing_ssh_key}" if Pkg::Config.msi_signing_ssh_key
5
+
6
+ ssh_host_string = "#{use_identity} Administrator@#{Pkg::Config.msi_signing_server}"
7
+ rsync_host_string = "-e 'ssh #{use_identity}' Administrator@#{Pkg::Config.msi_signing_server}"
8
+
9
+ work_dir = "Windows/Temp/#{Pkg::Util.rand_string}"
10
+ Pkg::Util::Net.remote_ssh_cmd(ssh_host_string, "mkdir -p C:/#{work_dir}")
11
+ msis = Dir.glob("#{target_dir}/windows/**/*.msi")
12
+ Pkg::Util::Net.rsync_to(msis.join(" "), rsync_host_string, "/cygdrive/c/#{work_dir}")
13
+
14
+ # Please Note:
15
+ # We are currently adding two signatures to the msi.
16
+ #
17
+ # Microsoft compatable Signatures are composed of three different
18
+ # elements.
19
+ # 1) The Certificate used to sign the package. This is the element that
20
+ # is attached to organization. The certificate has an associated
21
+ # algorithm. We recently (February 2016) had to switch from a sha1 to
22
+ # a sha256 certificate. Sha1 was deprecated by many Microsoft
23
+ # elements on 2016-01-01, which forced us to switch to a sha256 cert.
24
+ # This sha256 certificate is recognized by all currently supported
25
+ # windows platforms (Windows 8/Vista forward).
26
+ # 2) The signature used to attach the certificate to the package. This
27
+ # can be a done with a variety of digest algorithms. Older platforms
28
+ # (i.e., Windows 8 and Windows Vista) don't recognize later
29
+ # algorithms like sha256.
30
+ # 3) The timestamp used to validate when the package was signed. This
31
+ # comes from an external source and can be delivered with a variety
32
+ # of digest algorithms. Older platforms do not recognize newer
33
+ # algorithms like sha256.
34
+ #
35
+ # We could have only one signature with the Sha256 Cert, Sha1 Signature,
36
+ # and Sha1 Timestamp, but that would be too easy. The sha256 signature
37
+ # and timestamp add more security to our packages. We can't have only
38
+ # sha256 elements in our package signature, though, because Windows 8
39
+ # and Windows Vista just don't recognize them at all.
40
+ #
41
+ # In order to add two signatures to an MSI, we also need to change the
42
+ # tool we use to sign packages with. Previously, we were using SignTool
43
+ # which is the Microsoft blessed program used to sign packages. However,
44
+ # this tool isn't able to add two signatures to an MSI specifically. It
45
+ # can dual-sign an exe, just not an MSI. In order to get the dual-signed
46
+ # packages, we decided to switch over to using osslsigncode. The original
47
+ # project didn't have support to compile on a windows system, so we
48
+ # decided to use this fork. The binaries on the signer were pulled from
49
+ # https://sourceforge.net/u/keeely/osslsigncode/ci/master/tree/
50
+ #
51
+ # These are our signatures:
52
+ # The first signature:
53
+ # * Sha256 Certificate
54
+ # * Sha1 Signature
55
+ # * Sha1 Timestamp
56
+ #
57
+ # The second signature:
58
+ # * Sha256 Certificate
59
+ # * Sha256 Signature
60
+ # * Sha256 Timestamp
61
+ #
62
+ # Once we no longer support Windows 8/Windows Vista, we can remove the
63
+ # first Sha1 signature.
64
+ Pkg::Util::Net.remote_ssh_cmd(ssh_host_string, %Q(for msi in #{msis.map { |d| File.basename(d) }.join(" ")}; do
65
+ "/cygdrive/c/tools/osslsigncode-fork/osslsigncode.exe" sign \
66
+ -n "Puppet" -i "http://www.puppet.com" \
67
+ -h sha1 \
68
+ -pkcs12 "#{Pkg::Config.msi_signing_cert}" \
69
+ -pass "#{Pkg::Config.msi_signing_cert_pw}" \
70
+ -t "http://timestamp.verisign.com/scripts/timstamp.dll" \
71
+ -in "C:/#{work_dir}/$msi" \
72
+ -out "C:/#{work_dir}/signed-$msi"
73
+ "/cygdrive/c/tools/osslsigncode-fork/osslsigncode.exe" sign \
74
+ -n "Puppet" -i "http://www.puppet.com" \
75
+ -nest -h sha256 \
76
+ -pkcs12 "#{Pkg::Config.msi_signing_cert}" \
77
+ -pass "#{Pkg::Config.msi_signing_cert_pw}" \
78
+ -ts "http://sha256timestamp.ws.symantec.com/sha256/timestamp" \
79
+ -in "C:/#{work_dir}/signed-$msi" \
80
+ -out "C:/#{work_dir}/$msi"
81
+ rm "C:/#{work_dir}/signed-$msi"
82
+ done))
83
+ msis.each do | msi |
84
+ Pkg::Util::Net.rsync_from("/cygdrive/c/#{work_dir}/#{File.basename(msi)}", rsync_host_string, File.dirname(msi))
85
+ end
86
+ Pkg::Util::Net.remote_ssh_cmd(ssh_host_string, "if [ -d '/cygdrive/c/#{work_dir}' ]; then rm -rf '/cygdrive/c/#{work_dir}'; fi")
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,39 @@
1
+ module Pkg::Nuget
2
+ class << self
3
+ def ship(packages)
4
+ #
5
+ # Support shipping of Nuget style packages to a nexus based nuget feed
6
+ # Using curl to submit the packages rather than windows based choco/mono.
7
+ # This approach gives more flexibility and fits in with the current Puppet
8
+ # release automation practices using linux/mac systems.
9
+
10
+ # Sanity checks
11
+ fail "NUGET_HOST is not defined" if Pkg::Config.nuget_host.empty?
12
+ fail "NUGET_REPO is not defined" if Pkg::Config.nuget_repo_path.to_s.empty?
13
+
14
+ # Retrieve password without revealing it
15
+ puts "Obtaining credentials to ship to nuget feed #{Pkg::Config.nuget_repo_path} on #{Pkg::Config.nuget_host}"
16
+ print "Username please: "
17
+ username = Pkg::Util.get_input(true)
18
+ print "Password please: "
19
+ password = Pkg::Util.get_input(false)
20
+ authentication = Pkg::Util.base64_encode("#{username}:#{password}")
21
+
22
+ uri = "#{Pkg::Config.nuget_host}#{Pkg::Config.nuget_repo_path}"
23
+ form_data = ["-H 'Authorization: Basic #{authentication}'", "-f"]
24
+ packages.each do |pkg|
25
+ puts "Working on package #{pkg}"
26
+ projname, version = File.basename(pkg).match(/^(.*)-([\d+\.]+)\.nupkg$/).captures
27
+ package_form_data = ["--upload-file #{pkg}"]
28
+ package_path = "#{projname}/#{version}/#{File.basename(pkg)}"
29
+ stdout = ''
30
+ retval = ''
31
+ Pkg::Util::Execution.retry_on_fail(:times => 3) do
32
+ stdout, retval = Pkg::Util::Net.curl_form_data("#{uri}/#{package_path}", form_data + package_form_data)
33
+ end
34
+ fail "The Package upload (curl) failed with error #{retval}" unless Pkg::Util::Execution.success?(retval)
35
+ stdout
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,36 @@
1
+ module Pkg::OSX
2
+ class << self
3
+ def sign(target_dir = 'pkg')
4
+ use_identity = "-i #{Pkg::Config.osx_signing_ssh_key}" unless Pkg::Config.osx_signing_ssh_key.nil?
5
+
6
+ if Pkg::Config.osx_signing_server =~ /@/
7
+ host_string = "#{Pkg::Config.osx_signing_server}"
8
+ else
9
+ host_string = "#{ENV['USER']}@#{Pkg::Config.osx_signing_server}"
10
+ end
11
+ ssh_host_string = "#{use_identity} #{host_string}"
12
+ rsync_host_string = "-e 'ssh #{use_identity}' #{host_string}"
13
+
14
+ work_dir = "/tmp/#{Pkg::Util.rand_string}"
15
+ mount = File.join(work_dir, "mount")
16
+ signed = File.join(work_dir, "signed")
17
+ Pkg::Util::Net.remote_ssh_cmd(ssh_host_string, "mkdir -p #{mount} #{signed}")
18
+ dmgs = Dir.glob("#{target_dir}/apple/**/*.dmg")
19
+ Pkg::Util::Net.rsync_to(dmgs.join(" "), rsync_host_string, work_dir)
20
+ Pkg::Util::Net.remote_ssh_cmd(ssh_host_string, %Q[for dmg in #{dmgs.map { |d| File.basename(d, ".dmg") }.join(" ")}; do
21
+ /usr/bin/hdiutil attach #{work_dir}/$dmg.dmg -mountpoint #{mount} -nobrowse -quiet ;
22
+ /usr/bin/security -q unlock-keychain -p "#{Pkg::Config.osx_signing_keychain_pw}" "#{Pkg::Config.osx_signing_keychain}" ;
23
+ for pkg in $(ls #{mount}/*.pkg | xargs -n 1 basename); do
24
+ /usr/bin/productsign --keychain "#{Pkg::Config.osx_signing_keychain}" --sign "#{Pkg::Config.osx_signing_cert}" #{mount}/$pkg #{signed}/$pkg ;
25
+ done
26
+ /usr/bin/hdiutil detach #{mount} -quiet ;
27
+ /bin/rm #{work_dir}/$dmg.dmg ;
28
+ /usr/bin/hdiutil create -volname $dmg -srcfolder #{signed}/ #{work_dir}/$dmg.dmg ;
29
+ /bin/rm #{signed}/* ; done])
30
+ dmgs.each do | dmg |
31
+ Pkg::Util::Net.rsync_from("#{work_dir}/#{File.basename(dmg)}", rsync_host_string, File.dirname(dmg))
32
+ end
33
+ Pkg::Util::Net.remote_ssh_cmd(ssh_host_string, "if [ -d '#{work_dir}' ]; then rm -rf '#{work_dir}'; fi")
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,238 @@
1
+ # Utilities surrounding the appropriate paths associated with a platform
2
+ # This includes both reporting the correct path and divining the platform
3
+ # tag associated with a variety of paths
4
+ #
5
+ # rubocop:disable Metrics/ModuleLength
6
+ module Pkg::Paths
7
+ include Pkg::Platforms
8
+
9
+ module_function
10
+
11
+ def arch_from_artifact_path(platform, version, path)
12
+ arches = Pkg::Platforms.arches_for_platform_version(platform, version)
13
+
14
+ # First check if it's a source package
15
+ source_formats = Pkg::Platforms.get_attribute_for_platform_version(platform, version, :source_package_formats)
16
+ if source_formats.find { |fmt| path =~ /#{fmt}$/ }
17
+ return Pkg::Platforms.get_attribute_for_platform_version(platform, version, :source_architecture)
18
+ end
19
+ arches.find { |a| path.include?(a) } || arches[0]
20
+ rescue
21
+ arches.find { |a| path.include?(a) } || arches[0]
22
+ end
23
+
24
+ # Given a path to an artifact, divine the appropriate platform tag associated
25
+ # with the artifact and path
26
+ def tag_from_artifact_path(path)
27
+ platform = Pkg::Platforms.supported_platforms.find { |p| path =~ /(\/|\.)#{p}[^\.]/ }
28
+ codename = Pkg::Platforms.codenames.find { |c| path =~ /\/#{c}/ }
29
+
30
+ if codename
31
+ platform, version = Pkg::Platforms.codename_to_platform_version(codename)
32
+ end
33
+
34
+ version = '2012' if platform == 'windows'
35
+
36
+ version ||= Pkg::Platforms.versions_for_platform(platform).find { |v| path =~ /#{platform}(\/|-)?#{v}/ }
37
+
38
+ arch = arch_from_artifact_path(platform, version, path)
39
+
40
+ return "#{platform}-#{version}-#{arch}"
41
+ rescue
42
+ fmt = Pkg::Platforms.all_supported_package_formats.find { |ext| path =~ /#{ext}$/ }
43
+
44
+ # We need to make sure this is actually a file, and not simply a path
45
+ file_ext = File.extname(path)
46
+
47
+ # Fail if we do not have a file extension or if that file extension is one
48
+ # that is platform specific
49
+ raise "Cannot determine tag from #{path}" if fmt || file_ext.empty?
50
+
51
+ # Return nil otherwise, assuming that is a file type that is not tied to a
52
+ # specific platform
53
+ return nil
54
+ end
55
+
56
+ # Assign repo name
57
+ # If we are shipping development/beta/non-final packages, they should be
58
+ # shipped to the development/beta/non-final repo, if there is one defined.
59
+ # Otherwise, default to the final repo name. We use this for more than just
60
+ # shipping to the final repos, so we need this to not fail.
61
+ def repo_name
62
+ if Pkg::Util::Version.final?
63
+ Pkg::Config.repo_name || ""
64
+ else
65
+ if Pkg::Config.nonfinal_repo_name
66
+ Pkg::Config.nonfinal_repo_name
67
+ else
68
+ Pkg::Config.repo_name || ""
69
+ end
70
+ end
71
+ end
72
+
73
+ def link_name
74
+ if Pkg::Util::Version.final?
75
+ Pkg::Config.repo_link_target || nil
76
+ else
77
+ Pkg::Config.nonfinal_repo_link_target || nil
78
+ end
79
+ end
80
+
81
+ # TODO: please please please clean this up
82
+ # This is so terrible. I really dislike it. But in order to maintain backward
83
+ # compatibility, we need to maintain these path differences between PC1 and
84
+ # everything else. Once we stop shipping things to PC1, we can remove all the
85
+ # PC1 specific cases. That's likely to not happen until the current LTS
86
+ # (2016.4) is EOL'd. Hopefully also we do not choose to further change these
87
+ # path structures, as it is no bueno.
88
+ # --MAS 2017-08-16
89
+ def artifacts_base_path_and_link_path(platform_tag, path_prefix = 'artifacts')
90
+ platform, version, architecture = Pkg::Platforms.parse_platform_tag(platform_tag)
91
+ package_format = Pkg::Platforms.package_format_for_tag(platform_tag)
92
+
93
+ case package_format
94
+ when 'rpm'
95
+ if repo_name == 'PC1'
96
+ [File.join(path_prefix, platform, version, repo_name), nil]
97
+ else
98
+ [File.join(path_prefix, repo_name), link_name.nil? ? nil : File.join(path_prefix, link_name)]
99
+ end
100
+ when 'swix'
101
+ if repo_name == 'PC1'
102
+ [File.join(path_prefix, platform, version, repo_name), nil]
103
+ else
104
+ [File.join(path_prefix, platform, repo_name), link_name.nil? ? nil : File.join(path_prefix, platform, link_name)]
105
+ end
106
+ when 'deb'
107
+ [File.join(path_prefix, Pkg::Platforms.get_attribute(platform_tag, :codename), repo_name),
108
+ link_name.nil? ? nil : File.join(path_prefix, Pkg::Platforms.get_attribute(platform_tag, :codename), link_name)]
109
+ when 'svr4', 'ips'
110
+ if repo_name == 'PC1'
111
+ [File.join(path_prefix, 'solaris', repo_name, version), nil]
112
+ else
113
+ [File.join(path_prefix, 'solaris', repo_name), link_name.nil? ? nil : File.join(path_prefix, 'solaris', link_name)]
114
+ end
115
+ when 'dmg'
116
+ if repo_name == 'PC1'
117
+ [File.join(path_prefix, 'mac', version, repo_name), nil]
118
+ else
119
+ [File.join(path_prefix, 'mac', repo_name), link_name.nil? ? nil : File.join(path_prefix, 'mac', link_name)]
120
+ end
121
+ when 'msi'
122
+ if repo_name == 'PC1'
123
+ [File.join(path_prefix, 'windows'), nil]
124
+ else
125
+ [File.join(path_prefix, 'windows', repo_name), link_name.nil? ? nil : File.join(path_prefix, 'windows', link_name)]
126
+ end
127
+ else
128
+ raise "Not sure where to find packages with a package format of '#{package_format}'"
129
+ end
130
+ end
131
+
132
+ # TODO: please please please clean this up
133
+ # This is so terrible. I really dislike it. But in order to maintain backward
134
+ # compatibility, we need to maintain these path differences between PC1 and
135
+ # everything else. Once we stop shipping things to PC1, we can remove all the
136
+ # PC1 specific cases. That's likely to not happen until the current LTS
137
+ # (2016.4) is EOL'd. Hopefully also we do not choose to further change these
138
+ # path structures, as it is no bueno.
139
+ # --MAS 2017-08-16
140
+ def artifacts_path(platform_tag, path_prefix = 'artifacts')
141
+ base_path, _ = artifacts_base_path_and_link_path(platform_tag, path_prefix)
142
+ platform, version, architecture = Pkg::Platforms.parse_platform_tag(platform_tag)
143
+ package_format = Pkg::Platforms.package_format_for_tag(platform_tag)
144
+
145
+ case package_format
146
+ when 'rpm'
147
+ if repo_name == 'PC1'
148
+ File.join(base_path, architecture)
149
+ else
150
+ File.join(base_path, platform, version, architecture)
151
+ end
152
+ when 'swix'
153
+ if repo_name == 'PC1'
154
+ File.join(base_path, architecture)
155
+ else
156
+ File.join(base_path, version, architecture)
157
+ end
158
+ when 'deb'
159
+ base_path
160
+ when 'svr4', 'ips'
161
+ if repo_name == 'PC1'
162
+ base_path
163
+ else
164
+ File.join(base_path, version)
165
+ end
166
+ when 'dmg'
167
+ if repo_name == 'PC1'
168
+ File.join(base_path, architecture)
169
+ else
170
+ File.join(base_path, version, architecture)
171
+ end
172
+ when 'msi'
173
+ base_path
174
+ else
175
+ raise "Not sure where to find packages with a package format of '#{package_format}'"
176
+ end
177
+ end
178
+
179
+ def repo_path(platform_tag, options = { :legacy => false })
180
+ repo_target = repo_name
181
+ # in legacy packaging methods, there was no consistent way to determine the
182
+ # repo name. There were separate variables for apt_repo_name and
183
+ # yum_repo_name. At times, either or both of these were unset, and they had
184
+ # different defaults. So, for legacy automation we need to just use a splat
185
+ # and globbing to find our packages.
186
+ repo_target = '**' if options[:legacy]
187
+ platform, version, arch = Pkg::Platforms.parse_platform_tag(platform_tag)
188
+ package_format = Pkg::Platforms.package_format_for_tag(platform_tag)
189
+
190
+ case package_format
191
+ when 'rpm', 'swix'
192
+ if options[:legacy]
193
+ File.join('repos', platform, version, repo_target, arch)
194
+ else
195
+ File.join('repos', repo_target, platform, version, arch)
196
+ end
197
+ when 'deb'
198
+ File.join('repos', 'apt', Pkg::Platforms.get_attribute(platform_tag, :codename), 'pool', repo_target)
199
+ when 'svr4', 'ips'
200
+ if options[:legacy]
201
+ File.join('repos', 'solaris', version, repo_target)
202
+ else
203
+ File.join('repos', 'solaris', repo_target, version)
204
+ end
205
+ when 'dmg'
206
+ if options[:legacy]
207
+ File.join('repos', 'apple', version, repo_target, arch)
208
+ else
209
+ File.join('repos', 'mac', repo_target, version, arch)
210
+ end
211
+ when 'msi'
212
+ if options[:legacy]
213
+ File.join('repos', 'windows')
214
+ else
215
+ File.join('repos', 'windows', repo_target)
216
+ end
217
+ else
218
+ raise "Not sure what to do with a package format of '#{package_format}'"
219
+ end
220
+ end
221
+
222
+ def repo_config_path(platform_tag)
223
+ package_format = Pkg::Platforms.package_format_for_tag(platform_tag)
224
+
225
+ case package_format
226
+ when 'rpm'
227
+ # rpm/pl-puppet-agent-1.2.5-el-5-i386.repo for example
228
+ File.join('repo_configs', 'rpm', "*#{platform_tag}*.repo")
229
+ when 'deb'
230
+ # deb/pl-puppet-agent-1.2.5-jessie.list
231
+ File.join('repo_configs', 'deb', "*#{Pkg::Platforms.get_attribute(platform_tag, :codename)}*.list")
232
+ when 'msi', 'swix', 'dmg', 'svr4', 'ips'
233
+ nil
234
+ else
235
+ raise "Not sure what to do with a package format of '#{package_format}'"
236
+ end
237
+ end
238
+ end