I’ve been pre-flighting and code signing my apps using SD Notary via a script, and I have a question. First, here’s the pre-flighting script. Question to follow
The question comes with this handler. Basically, I want to automate the Application Bundle & Export settings.
This handler opens the applet in Script Debugger, and sets the Bundle and exports settings to the desired values, then saves the app.
The problem is after doing this, none of the script libraries are included in the bundle. (Don’t know about frameworks, because none of the ones I use would need to be bundled).
Note, I have stopped trying to submit the dmg via the script until some issues are resolved, so that command is noted out.
But this is pretty smooth. I just drop the folder containing the apps I want to sign and put in a DMG. After the preflight is done, SD Notary is left open and I just click the submit button and the navigation window is already in the directory containing the DMG.
Mostly in the user script libraries folder, but a couple are in an app (your app!) in that folder.
I think I figured out what the issue is.
When I preflight, I’m not saving the document as run only, those only get bundled if it’s run-only. I’m not sure where in the code signing submission process they become run-only, but I think I need to do that myself before code signing, right?
If so, I may need to rethink my workflow. I’d hate to accidentally make an app run-only.
Saving as run-only doesn’t seem to work. But sometimes it displays a dialog that says it did work.
direct export command does work (bundles libraries, results in a read only app) but it does not return a result, and puts the exported file in a new folder in the same directory as the file with a different name.
Here’s a suggestion: If direct export returned the new path it would be easy to put the run-only file where I want, and remove the new folder. Instead I need to write a routine to get the name of the folder, to get the path of the run-only file inside the folder.
Here’s a new version of the applet that Preflights, code signs and makes DMGs (ready to submit to Apple) from folders dropped on it. (Once the scripting of submissions using SD Notary is resolved it can be modified to do that too).
The makes a copy of the folder, then works only on the copy so no worry of overwriting your work.
Since the Script Debugger export command does not return a result, a script could keep going before the export is complete. So I added a repeat loop that waits until the file is found then continues.
I would suggest that command be modified to return a result (shouldn’t break pre-existing scripts, even this one).
Same thing with SD Notary. When it does it’s thing it leaves folders that we need to clean up after which makes it tricky to automate the process.
But, all that said, this is far easier to automate than earlier versions of SD Notary would have been. In fact I wanted to but didn’t even try.
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
use script "filemanagerlib"
property exportSlug : ""
on open folderList
set dmgList to {}
set submittedDMGs to {}
set notarizeFolder to NotarizeFolderPath()
repeat with thisFolder in folderList
set folderName to full_name of (parse object thisFolder)
set notarizeLocation to create folder at notarizeFolder ¬
use name folderName & "(Run only - notarized)"
set dupeFolder to copy object thisFolder ¬
to folder notarizeLocation ¬
replacing true ¬
with return path
set thisDMG to PreFlightFolderMakeDMG(dupeFolder)
set the end of dmgList to thisDMG
-- set submittedDMG to SubmitDMG(thisDMG)
end repeat
end open
on NotarizeFolderPath()
set myPath to path to me
set notaryLocation to ¬
parent_folder_path of (parse object myPath ¬
with HFS results)
set rightNow to current date
set yearString to year of rightNow
set monthString to TwoDigit(month of rightNow as integer)
set dayString to TwoDigit(day of rightNow as integer)
set exportSlug to " Export " & yearString & "-" & monthString & "-" & dayString
return notaryLocation
end NotarizeFolderPath
on TwoDigit(aNumberString)
if aNumberString < 10 then
return "0" & (aNumberString as text)
else
return (aNumberString as text)
end if
end TwoDigit
on PreFlightFolderMakeDMG(sourceFolder)
--set sourceFolder to POSIX path of sourceFolder
set searchString to ".app"
set appList to AppsInFolder(sourceFolder)
set appletFilesFixed to FixAppletFiles(appList)
set signingErrors to SignApps(appList)
if signingErrors is {} then
set folderInfo to (parse object sourceFolder)
set folderName to name_stub of folderInfo
set folderLocation to parent_folder_path of folderInfo
set dmgPath to folderLocation & "/" & folderName & ".dmg"
set newDMG to MakeDMGFromFolder(sourceFolder, dmgPath, folderName)
return newDMG
else
set AppleScript's text item delimiters to {return}
set signingErrors to signingErrors as text
--display dialog
set buttonList to {¬
("Cancel"), ¬
("Send to BBEdit"), ¬
("Okay") ¬
}
tell me to activate
set DialogReply to display dialog ("An error occured. No DMG will be created") & return & ("Full error text is below") ¬
with title ("Pre-flight Error") ¬
default answer (signingErrors) ¬
buttons buttonList ¬
default button 2 ¬
cancel button 1 ¬
hidden answer false ¬
giving up after 10 ¬
with icon 2
if button returned of DialogReply is item 2 of buttonList then
tell application "BBEdit"
activate
make new window at beginning
set text of window 1 to signingErrors
end tell
end if
end if
end PreFlightFolderMakeDMG
on SubmitDMG(aDMG)
tell application "SD Notary 2"
set submittingDocument to make new document with properties {allow library loading:true, create disk image:true}
tell submittingDocument
try
set notarizedDocument to submit app at aDMG
on error errMsg number errNum
--DisplayDialog Full
set dialogText to "Notary Submission Error"
set defaultAnswer to "Notary Submission Error number: " & errNum & return & return & errMsg
set dialogButtons to {"Cancel", "Skip", "OK"}
set defaultButton to 3
set cancelButton to 1
set dialogTitle to "Notary Submission Error"
set dialogIcon to caution --caution --note --stop
set givingUpAfter to 60
set DialogReply to ¬
display dialog dialogText ¬
default answer defaultAnswer ¬
buttons dialogButtons ¬
default button defaultButton ¬
cancel button cancelButton ¬
with title dialogTitle ¬
with icon dialogIcon ¬
giving up after givingUpAfter
return errorMsg
end try
end tell
end tell
return notarizedDocument
end SubmitDMG
on FixAppletFiles(appList)
local appPath
set fixedAppletNames to {}
repeat with thisApp in appList
set appPath to thisApp as text
set appPath to appPath & "/Contents/MacOS/"
--Contents of
set FilesInMacOS to objects of appPath ¬
include folders false ¬
include files true ¬
result type files list
if the (count of FilesInMacOS) > 1 then
set appName to full_name of (parse object thisApp)
repeat with thisFile in FilesInMacOS
set fileName to full_name of (parse object thisFile)
if fileName is not in {"applet", "fancyDroplet"} then
set the end of fixedAppletNames to appName
set fileRemoved to remove object thisFile
end if
end repeat
end if
end repeat
return fixedAppletNames
end FixAppletFiles
on AppBundleExportsSettings(thisApp)
local exportFolderPath, exportedAppPath
--nameStub
set appInfo to (parse object thisApp)
set appName to name_stub of appInfo
set appFullName to full_name of appInfo
set appLocation to parent_folder_path of appInfo
tell application "Script Debugger"
set thisDoc to open thisApp
set exportFolderName to appName & exportSlug
set exportFolderPath to appLocation & "/" & exportFolderName & "/"
set exportedAppPath to exportFolderPath & appFullName
set codesignBundlesToo to true
set autoincrementBuildNumber to true
set codesignOnExportOnly to false
set embedUsedFrameworks to true
set embedUsedLibraries to true
--set theCopyRight to ""
--set codesignIdentity to ""
set bundleExportProperties to {}
set bundleExportProperties to bundleExportProperties & {codesign bundles too:codesignBundlesToo}
set bundleExportProperties to bundleExportProperties & {codesign bundles too:codesignBundlesToo}
set bundleExportProperties to bundleExportProperties & {autoincrement build number:autoincrementBuildNumber}
set bundleExportProperties to bundleExportProperties & {codesign on export only:codesignOnExportOnly}
set bundleExportProperties to bundleExportProperties & {embed used frameworks:embedUsedFrameworks}
set bundleExportProperties to bundleExportProperties & {embed used libraries:embedUsedLibraries}
--set bundleExportProperties to bundleExportProperties & {copyright:theCopyRight}
--set bundleExportProperties to bundleExportProperties & {codesign identity:codesignIdentity}
tell thisDoc
set its properties to bundleExportProperties
direct export
close saving no
repeat 10 times
set folderIsThere to exists object exportFolderPath
set runOnlyAppIsThere to exists object exportedAppPath
if runOnlyAppIsThere then exit repeat
delay 1
end repeat
if runOnlyAppIsThere then
set finalApp to move object exportedAppPath ¬
to folder appLocation ¬
replacing true ¬
with return path
set folderDeleted to remove object exportFolderPath ¬
with folders included
end if
end tell
end tell
return appLocation
end AppBundleExportsSettings
on SignApps(appList)
set errorLog to {}
local appPath
repeat with thisApp in appList
set notaryError to false
set appLocation to AppBundleExportsSettings(thisApp)
--do shell script "codesign -dv " & quoted form of thisApp
tell application "SD Notary 2"
set codeSignDocument to make new document
tell codeSignDocument
try
set appPath to codesign only at thisApp without showing dialogs
on error errMsg number errNum
tell me to activate
set alertMessage to ("Error message: ") & return & return & ("The file:") & return & ¬
thisApp & return & return & ("Could not be signed.") & ¬
return & return & ("Error message:") & errMsg & return & return & "Error number: " & errNum
set the end of errorLog to alertMessage
display alert alertMessage giving up after 5
set notaryError to true
tell application "Finder" to activate
end try
end tell
delay 1
close codeSignDocument
end tell
if not notaryError then
set signedAppInfo to (parse object appPath without HFS results)
set appName to full_name of signedAppInfo
set signedAppLocation to parent_folder_path of signedAppInfo
set signedApp to move object appPath ¬
to folder appLocation ¬
with replacing and return path
set folderRemoved to remove object signedAppLocation ¬
with folders included
end if
end repeat
return errorLog
end SignApps
on MakeDMGFromFolder(folderPath, dmgPath, folderName)
local folderPath, dmgPath, folderName, dmgShellScript
if (exists object dmgPath) then
remove object dmgPath
end if
set folderPath to quoted form of POSIX path of folderPath
set dmgPath to quoted form of POSIX path of dmgPath
set folderName to quoted form of folderName
set dmgShellScript to "hdiutil create -srcfolder " & folderPath & " -format UDZO -volname " & folderName & " " & dmgPath
do shell script dmgShellScript
return dmgPath
end MakeDMGFromFolder
on AppsInFolder(sourceFolder)
set allFiles to objects of sourceFolder ¬
searching subfolders true ¬
include invisible items false ¬
include folders false ¬
include files true ¬
result type paths list
set foundApps to {}
repeat with thisFile in allFiles
set thisFile to thisFile as item
set nameExtension to name_extension of (parse object thisFile)
if nameExtension is "app" then set the end of foundApps to thisFile
end repeat
return foundApps
end AppsInFolder
Also, when scripting an export, Script Debugger displays a dialog, which is fine in the UI but a pain when scripting.
Would it be possible to export without UI?
Typically what happens I’m preflighting a folder with a bunch of apps and each one opens and makes a few changes, then exports (bundling libraries). When it’s done that dialog appears. When the process is done there’s one app window left open with one dialog.
Also, I just had an annoying experience.
After preflighting, signing and submitting several apps (some repeatedly), I closed all SD windows and quit. When I launched SD later, all the windows from my previous session reopened, including all of the run-only export windows. And the run-only export windows opened in one window in tabs (probably over 100 of them).
When I tried to close each one I got that same dialog again (Buttons: Reveal and OKAY). If I tried to close the window the mac would make this buzzing screaching sound (I think trying to beep for each tab), and only one tab would show the close dialog.
So I had to individually close each tab (which required two clicks because command-w tried to close the window, and the OK button wasn’t activated.
After closing them all I quit script debugger and opened it again and did not get the windows.
I just prefilighted and submitted a couple more and quit and relaunched SD and it didn’t happen.
Anyone else get failures with notarytool (SD Notary 2) which have meaningless errors… but if I submit using the old SD Notary with altool it gives me a meaningful error which I can address (in this case I needed to sign with --timestamp the plugins in the DMG I was submitting).