@@ -18,7 +18,7 @@ def install_build_dependencies(list_build_dependencies)
1818 #
1919 # @param project [Vanagon::Project] project to build a osx package of
2020 # @return [Array] list of commands required to build a osx package for the given project from a tarball
21- def generate_package ( project ) # rubocop:disable Metrics/AbcSize
21+ def generate_package ( project ) # rubocop:disable Metrics/AbcSize,Metrics/PerceivedComplexity
2222 target_dir = project . repo ? output_dir ( project . repo ) : output_dir
2323
2424 # Here we maintain backward compatibility with older vanagon versions
@@ -35,55 +35,130 @@ def generate_package(project) # rubocop:disable Metrics/AbcSize
3535 bom_install = [ ]
3636 end
3737
38- if project . extra_files_to_sign . any?
39- sign_commands = Vanagon ::Utilities ::ExtraFilesSigner . commands ( project , @mktemp , "/osx/build/root/#{ project . name } -#{ project . version } " )
40- else
41- sign_commands = [ ]
38+ # Previously, the "commands" method would test if it could SSH to the signer node and just skip
39+ # all the signing stuff if it couldn't and VANAGON_FORCE_SIGNING was not set. It never really tested
40+ # that signing actually worked and skipped it if it didn't. Now with the local commands, we really
41+ # can't even do that test. So just don't even try signing unless VANAGON_FORCE_SIGNING is set.
42+ unlock = 'security unlock-keychain -p $$SIGNING_KEYCHAIN_PW $$SIGNING_KEYCHAIN'
43+ extra_sign_commands = [ ]
44+ sign_files_commands = [ ]
45+ # If we're not signing, move the pkg to the right place
46+ sign_package_commands = [ "mv $(tempdir)/osx/build/#{ project . name } -#{ project . version } -#{ project . release } -installer.pkg $(tempdir)/osx/build/pkg/" ]
47+ sign_dmg_commands = [ ]
48+ notarize_dmg_commands = [ ]
49+ if ENV [ 'VANAGON_FORCE_SIGNING' ]
50+ # You should no longer really need to do this, but it's here just in case.
51+ if project . extra_files_to_sign . any?
52+ method = project . use_local_signing ? 'local_commands' : 'commands'
53+ extra_sign_commands = Vanagon ::Utilities ::ExtraFilesSigner . send ( method , project , @mktemp , "/osx/build/root/#{ project . name } -#{ project . version } " )
54+ end
55+
56+ # As of MacOS 15, we have to notarize the dmg. In order to get notarization, we have to
57+ # code sign every single binary, .bundle, and .dylib file in the package. So instead of
58+ # only signing a few files we specify, sign everything we can find that needs to be signed.
59+ # We then need to notarize the resulting dmg.
60+ #
61+ # This requires the VM to have the following env vars set in advance.
62+ # SIGNING_KEYCHAIN - the name of the keychain containing the code/installer signing identities
63+ # SIGNING_KEYCHAIN_PW - the password to unlock the keychain
64+ # APPLICATION_SIGNING_CERT - the identity description used for application signing
65+ # INSTALLER_SIGNING_CERT - the identity description used for installer .pkg signing
66+ # NOTARY_PROFILE - The name of the notary profile stored in the keychain
67+
68+ paths_with_binaries = {
69+ "root/#{ project . name } -#{ project . version } /opt/puppetlabs/bin/" => '*' ,
70+ "root/#{ project . name } -#{ project . version } /opt/puppetlabs/puppet/bin/" => '*' ,
71+ "root/#{ project . name } -#{ project . version } /opt/puppetlabs/puppet/lib/ruby/vendor_gems/bin" => '*' ,
72+ "root/#{ project . name } -#{ project . version } /opt/puppetlabs/puppet/lib/" => '*.dylib' ,
73+ "root/#{ project . name } -#{ project . version } /opt/puppetlabs/puppet/lib" => '*.bundle' ,
74+ 'plugins' => 'puppet-agent-installer-plugin' ,
75+ }
76+
77+ sign_files_commands = [ unlock ]
78+ sign_files_commands += paths_with_binaries . map do |path , name |
79+ "find $(tempdir)/osx/build/#{ path } -name '#{ name } ' -type f -exec codesign --timestamp --options runtime --keychain $$SIGNING_KEYCHAIN -vfs \" $$APPLICATION_SIGNING_CERT\" {} \\ ;"
80+ end
81+ sign_files_commands += paths_with_binaries . map do |path , name |
82+ "find $(tempdir)/osx/build/#{ path } -name '#{ name } ' -type f -exec codesign --verify --strict --verbose=2 {} \\ ;"
83+ end
84+
85+ sign_package_commands = [
86+ unlock ,
87+ "productsign --keychain $$SIGNING_KEYCHAIN --sign \" $$INSTALLER_SIGNING_CERT\" $(tempdir)/osx/build/#{ project . name } -#{ project . version } -#{ project . release } -installer.pkg $(tempdir)/osx/build/pkg/#{ project . name } -#{ project . version } -#{ project . release } -installer.pkg" ,
88+ "rm $(tempdir)/osx/build/#{ project . name } -#{ project . version } -#{ project . release } -installer.pkg" ,
89+ ]
90+
91+ dmg = "$(tempdir)/osx/build/dmg/#{ project . package_name } "
92+ sign_dmg_commands = [
93+ unlock ,
94+ 'cd $(tempdir)/osx/build' ,
95+ "codesign --timestamp --keychain $$SIGNING_KEYCHAIN --sign \" $$APPLICATION_SIGNING_CERT\" #{ dmg } " ,
96+ "codesign --verify --strict --verbose=2 #{ dmg } " ,
97+ ]
98+
99+ notarize_dmg_commands = ENV [ 'NO_NOTARIZE' ] ? [ ] : [
100+ unlock ,
101+ "xcrun notarytool submit #{ dmg } --keychain-profile \" $$NOTARY_PROFILE\" --wait" ,
102+ "xcrun stapler staple #{ dmg } " ,
103+ "spctl --assess --type install --verbose #{ dmg } "
104+ ]
42105 end
43106
44107 # Setup build directories
45- [ "bash -c 'mkdir -p $(tempdir)/osx/build/{dmg,pkg,scripts,resources,root,payload,plugins}'" ,
46- "mkdir -p $(tempdir)/osx/build/root/#{ project . name } -#{ project . version } " ,
47- "mkdir -p $(tempdir)/osx/build/pkg" ,
48- # Grab distribution xml, scripts and other external resources
49- "cp #{ project . name } -installer.xml $(tempdir)/osx/build/" ,
50- #copy the uninstaller to the pkg dir, where eventually the installer will go too
51- "cp #{ project . name } -uninstaller.tool $(tempdir)/osx/build/pkg/" ,
52- "cp scripts/* $(tempdir)/osx/build/scripts/" ,
53- "if [ -d resources/osx/productbuild ] ; then cp -r resources/osx/productbuild/* $(tempdir)/osx/build/; fi" ,
54- # Unpack the project
55- "gunzip -c #{ project . name } -#{ project . version } .tar.gz | '#{ @tar } ' -C '$(tempdir)/osx/build/root/#{ project . name } -#{ project . version } ' --strip-components 1 -xf -" ,
56-
57- bom_install ,
58-
59- # Sign extra files
60- sign_commands ,
61-
62- # Package the project
63- "(cd $(tempdir)/osx/build/; #{ @pkgbuild } --root root/#{ project . name } -#{ project . version } \
64- --scripts $(tempdir)/osx/build/scripts \
65- --identifier #{ project . identifier } .#{ project . name } \
66- --version #{ project . version } \
67- --preserve-xattr \
68- --install-location / \
69- payload/#{ project . name } -#{ project . version } -#{ project . release } .pkg)",
70- # Create a custom installer using the pkg above
71- "(cd $(tempdir)/osx/build/; #{ @productbuild } --distribution #{ project . name } -installer.xml \
72- --identifier #{ project . identifier } .#{ project . name } -installer \
73- --package-path payload/ \
74- --resources $(tempdir)/osx/build/resources \
75- --plugins $(tempdir)/osx/build/plugins \
76- pkg/#{ project . name } -#{ project . version } -#{ project . release } -installer.pkg)",
77- # Create a dmg and ship it to the output directory
78- "(cd $(tempdir)/osx/build; \
79- #{ @hdiutil } create \
80- -volname #{ project . name } -#{ project . version } \
81- -fs JHFS+ \
82- -format UDBZ \
83- -srcfolder pkg \
84- dmg/#{ project . package_name } )",
85- "mkdir -p output/#{ target_dir } " ,
86- "cp $(tempdir)/osx/build/dmg/#{ project . package_name } ./output/#{ target_dir } " ] . flatten . compact
108+ [
109+ "bash -c 'mkdir -p $(tempdir)/osx/build/{dmg,pkg,scripts,resources,root,payload,plugins}'" ,
110+ "mkdir -p $(tempdir)/osx/build/root/#{ project . name } -#{ project . version } " ,
111+ "mkdir -p $(tempdir)/osx/build/pkg" ,
112+ # Grab distribution xml, scripts and other external resources
113+ "cp #{ project . name } -installer.xml $(tempdir)/osx/build/" ,
114+ #copy the uninstaller to the pkg dir, where eventually the installer will go too
115+ "cp #{ project . name } -uninstaller.tool $(tempdir)/osx/build/pkg/" ,
116+ "cp scripts/* $(tempdir)/osx/build/scripts/" ,
117+ "if [ -d resources/osx/productbuild ] ; then cp -r resources/osx/productbuild/* $(tempdir)/osx/build/; fi" ,
118+ # Unpack the project
119+ "gunzip -c #{ project . name } -#{ project . version } .tar.gz | '#{ @tar } ' -C '$(tempdir)/osx/build/root/#{ project . name } -#{ project . version } ' --strip-components 1 -xf -" ,
120+
121+ bom_install ,
122+
123+ # Sign extra files
124+ extra_sign_commands ,
125+
126+ # Sign all binaries
127+ sign_files_commands ,
128+
129+ # Package the project
130+ "(cd $(tempdir)/osx/build/; #{ @pkgbuild } --root root/#{ project . name } -#{ project . version } \
131+ --scripts $(tempdir)/osx/build/scripts \
132+ --identifier #{ project . identifier } .#{ project . name } \
133+ --version #{ project . version } \
134+ --preserve-xattr \
135+ --install-location / \
136+ payload/#{ project . name } -#{ project . version } -#{ project . release } .pkg)",
137+
138+ # Create a custom installer using the pkg above
139+ "(cd $(tempdir)/osx/build/; #{ @productbuild } --distribution #{ project . name } -installer.xml \
140+ --identifier #{ project . identifier } .#{ project . name } -installer \
141+ --package-path payload/ \
142+ --resources $(tempdir)/osx/build/resources \
143+ --plugins $(tempdir)/osx/build/plugins \
144+ #{ project . name } -#{ project . version } -#{ project . release } -installer.pkg)",
145+
146+ sign_package_commands ,
147+
148+ # Create a dmg and ship it to the output directory
149+ "(cd $(tempdir)/osx/build; \
150+ #{ @hdiutil } create \
151+ -volname #{ project . name } -#{ project . version } \
152+ -fs JHFS+ \
153+ -format UDBZ \
154+ -srcfolder pkg \
155+ dmg/#{ project . package_name } )",
156+
157+ sign_dmg_commands ,
158+ notarize_dmg_commands ,
159+ "mkdir -p output/#{ target_dir } " ,
160+ "cp $(tempdir)/osx/build/dmg/#{ project . package_name } ./output/#{ target_dir } "
161+ ] . flatten . compact
87162 end
88163
89164 # Method to generate the files required to build a osx package for the project
0 commit comments