Module: Pkg::Sign::Dmg

Defined in:
lib/packaging/sign/dmg.rb

Class Method Summary collapse

Class Method Details

.sign(pkg_directory = 'pkg') ⇒ Object



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/packaging/sign/dmg.rb', line 4

def sign(pkg_directory = 'pkg')
  use_identity = ''
  unless Pkg::Config.osx_signing_ssh_key.nil?
    use_identity = "-i #{Pkg::Config.osx_signing_ssh_key}"
  end

  host_string = "#{ENV['USER']}@#{Pkg::Config.osx_signing_server}"
  host_string = Pkg::Config.osx_signing_server.to_s if Pkg::Config.osx_signing_server =~ /@/

  ssh_host_string = "#{use_identity} #{host_string}"
  rsync_host_string = "-e 'ssh #{use_identity}' #{host_string}"
  archs = Dir.glob("#{pkg_directory}/{apple,mac,osx}/**/{x86_64,arm64}").map { |el| el.split('/').last }

  if archs.empty?
    warn "Error: no architectures found in #{pkg_directory}/{apple,mac,osx}"
    exit 1
  end

  archs.each do |arch|
    remote_working_directory = "/tmp/#{Pkg::Util.rand_string}/#{arch}"
    dmg_mount_point = File.join(remote_working_directory, "mount")
    signed_items_directory = File.join(remote_working_directory, "signed")

    dmgs = Dir.glob("#{pkg_directory}/{apple,mac,osx}/**/#{arch}/*.dmg")
    if dmgs.empty?
      warn "Error: no dmgs found in #{pkg_directory}/{apple,mac,osx} for #{arch} architecture."
      exit 1
    end

    dmg_basenames = dmgs.map { |d| File.basename(d, '.dmg') }.join(' ')

    # (See: RE-15379) Refactor opportunity; we really shouldn't do this this way.
    # When it works, it's fine, but diagnosing problems when we or Apple change
    # the details is a pain. We should either have a script on the signing machine
    # that does this work OR we should ship a script to the signing directory that
    # can be modified/repeated when problems arise.
    #
    # Note especially, the '-size 500m' hack in the 'hdiutil create' command. This
    # is useful but arbitrary at the moment and could cause problems in the future.
    sign_package_command = %W[
      for dmg in #{dmg_basenames}; do
        /usr/bin/hdiutil attach #{remote_working_directory}/$dmg.dmg
          -mountpoint #{dmg_mount_point} -nobrowse -quiet ;

        /usr/bin/security -q unlock-keychain
          -p "#{Pkg::Config.osx_signing_keychain_pw}" "#{Pkg::Config.osx_signing_keychain}" ;

        for pkg in #{dmg_mount_point}/*.pkg; do
          pkg_basename=$(basename $pkg) ;
          if /usr/sbin/pkgutil --check-signature $pkg ; then
            echo Warning: $pkg is already signed skipping ;
            cp $pkg #{signed_items_directory}/$pkg_basename ;
            continue ;
          fi ;

          /usr/bin/productsign --keychain "#{Pkg::Config.osx_signing_keychain}"
            --sign "#{Pkg::Config.osx_signing_cert}"
            $pkg #{signed_items_directory}/$pkg_basename ;
        done ;

        /usr/bin/hdiutil detach #{dmg_mount_point} -quiet ;
        /bin/rm #{remote_working_directory}/$dmg.dmg ;
        /usr/bin/hdiutil create -volname $dmg -size 500m
          -srcfolder #{signed_items_directory}/ #{remote_working_directory}/$dmg.dmg ;
        /bin/rm #{signed_items_directory}/* ;
      done
    ].join(' ')

    Pkg::Util::Net.remote_execute(ssh_host_string,
                                  "mkdir -p #{dmg_mount_point} #{signed_items_directory}")

    Pkg::Util::Net.rsync_to(dmgs.join(' '), rsync_host_string, remote_working_directory)

    Pkg::Util::Net.remote_execute(ssh_host_string, sign_package_command)

    dmgs.each do |dmg|
      Pkg::Util::Net.rsync_from(
        "#{remote_working_directory}/#{File.basename(dmg)}", rsync_host_string, File.dirname(dmg)
      )
    end

    Pkg::Util::Net.remote_execute(ssh_host_string, "rm -rf '#{remote_working_directory}'")
  end
end