import os import argparse from shell_runner import ShellRunner import time import string parser=argparse.ArgumentParser() parser.add_argument('-w','--work_dir', help='Working directory', required=True) parser.add_argument('-d','--dmg', help='Working directory', required=True) parser.add_argument('-p','--python', help='Python version. For example 3.8', required=False) args=parser.parse_args() work_dir = args.work_dir in_dmg = args.dmg print("Working directory: " + work_dir) print("Dmg: " + in_dmg) dmg = in_dmg.split("/")[-1] print("Filename: " + dmg) username = os.environ['ALTOOL_USER'] password = os.environ['ALTOOL_PASSWORD'] sig = os.environ['SIGN_SIG'] mydir = os.path.dirname(os.path.realpath(__file__)) ent = mydir + "/ent.plist" print("ent.plist: " + ent) python_version = "3.6" if args.python is not None: python_version = args.python shell = ShellRunner() # This is a loosey-goosey check. Do not attempt to re-use as is. # References: # https://stackoverflow.com/questions/1446549/how-to-identify-binary-and-text-files-using-python # http://code.activestate.com/recipes/173220/ def istext(filename): try: s=open(filename).read(512) text_characters = "".join(map(chr, range(32, 127))) + "\n\r\t\b" if not s: # Empty files are considered text return True if "\0" in s: # Files with null bytes are likely binary return False # Get the non-text characters (maps a character to itself then # use the 'remove' option to get rid of the text characters.) t = s.translate(str.maketrans("", "",text_characters)) # If more than 30% non-text characters, then # this is considered a binary file if float(len(t))/float(len(s)) > 0.30: return False return True # Ignore broken symlinks except FileNotFoundError: print("FileNotFoundError" + filename) raise FileNotFoundError # Treat as binary if UnicodeDecode fails except UnicodeDecodeError: print("UnicodeDecodeError: " + filename ) return False def copy_app(): print("Attaching " + in_dmg) cmd = ("hdiutil attach " + in_dmg).split() shell.runshell(cmd, work_dir) print("Copying /Volumes/" + dmg + " to " + work_dir) cmd = ("cp -pR /Volumes/" + dmg + "/CASA.app" + " " + work_dir + "/").split() shell.runshell(cmd, work_dir) print("Detaching volume /Volumes/" + dmg ) cmd = ("hdiutil detach /Volumes/" + dmg).split() shell.runshell(cmd, work_dir) def sign_app(): print("Sign binaries") binaries = [] for root, dirs, files in os.walk(work_dir + "/CASA.app"): for file in files: print("root " + root) print("dirs " + str(dirs)) print("file " + file) file_with_path=os.path.join(root, file) print("file " + file_with_path) if not ("casa-data" in file_with_path \ or "casadata" in file_with_path or "CASA.app/Contents/Resources/" in file_with_path\ or file.endswith(".pyc") \ or file.endswith(".txt")) \ and (file.startswith("protoc") \ or file.startswith("grpc")\ or file.endswith(".dylib") \ or file.endswith(".so") \ or file.endswith(".app")\ or not istext(file_with_path)): print(file_with_path) binaries.append(file_with_path) for f in binaries: cmd = ("codesign --timestamp --options=runtime -f --signature-size 10240 --entitlements " + ent + " -s " + sig + " " + f) print("cmd") shell.runshell(cmd.split(), work_dir + "/CASA.app") print("Sign casaviewer executable") cmd = ("codesign --timestamp --options=runtime -f --signature-size 10240 --entitlements " + ent + " -s " + sig + " Contents/Frameworks/Python.framework/Versions/" + python_version + "/lib/python" + python_version + "/site-packages/casaviewer/__bin__/casaviewer.app/Contents/MacOS/casaviewer") print("Signing casaviewer ") print("cmd") shell.runshell(cmd.split(), work_dir + "/CASA.app") print("Sign casaplotms") cmd = ("codesign --timestamp --options=runtime -f --signature-size 10240 --entitlements " + ent + " -s " + sig + " Contents/Frameworks/Python.framework/Versions/" + python_version + "/lib/python" + python_version + "/site-packages/casaplotms/__bin__/casaplotms.app/Contents/MacOS/casaplotms") print("Signing casaplotms ") print("cmd") shell.runshell(cmd.split(), work_dir + "/CASA.app") print("Sign casaplotserver") cmd = ("codesign --timestamp --options=runtime -f --signature-size 10240 --entitlements " + ent + " -s " + sig + " Contents/Frameworks/Python.framework/Versions/" + python_version + "/lib/python" + python_version + "/site-packages/casaplotserver/__bin__/casaplotserver.app/Contents/MacOS/casaplotserver") print("Signing casaplotserver ") print("cmd") shell.runshell(cmd.split(), work_dir + "/CASA.app") print("Sign applet") cmd = ("codesign --timestamp --options=runtime -f --signature-size 10240 --entitlements " + ent + " -s " + sig + " Contents/MacOS/applet") print("Signing applet ") print("cmd") shell.runshell(cmd.split(), work_dir + "/CASA.app") print("Sign breakpad") cmd = ("codesign --timestamp --options=runtime -f --signature-size 10240 --entitlements " + ent + " -s " + sig + " Contents/Frameworks/Breakpad.framework/Versions/A/Breakpad") print("Signing breakpad") print("cmd") shell.runshell(cmd.split(), work_dir + "/CASA.app") print("Sign python") cmd = ("codesign --timestamp --options=runtime -f --signature-size 10240 --entitlements " + ent + " -s " + sig + " Contents/Frameworks/Python.framework/Versions/" + python_version + "/Python") print("Signing python") print("cmd") shell.runshell(cmd.split(), work_dir + "/CASA.app") print("Sign CASA.app (again)") cmd = ("codesign --timestamp --options=runtime -f --signature-size 10240 --entitlements " + ent + " -s " + sig + " CASA.app") print("cmd") shell.runshell(cmd.split(), work_dir) def zip_app(): print("Create zip") cmd = ("ditto -ck --sequesterRsrc --keepParent CASA.app CASA.zip") shell.runshell(cmd.split(), work_dir) def init_shell_state(): class State: uuid = "" request_status="" shell.state = State() def process_submit_output(x): message = x.decode('utf-8').rstrip("\n\r") print("%s" % message) data = [] if "RequestUUID" in message: uuid = message.split() print("Found request uuid: " + message.split(" = ")[1].strip()) shell.state.uuid = message.split(" = ")[1].strip() return data def process_status(x): message = x.decode('utf-8').rstrip("\n\r") print(">>>>%s" % message) data = [] if "Status:" in message: status = message.split(": ")[1].strip() print("Found status: " + status) shell.state.request_status = status return data def submit_app(): print("Submit app") print(work_dir) cmd = ('xcrun altool --notarize-app --primary-bundle-id edu.nrao.casa -u ' + username+' -p ' + password + ' --file CASA.zip') shell.runshell(cmd.split(), work_dir, False,process_stdout=process_submit_output) def sim_submit_app(): print("Submit app") print(work_dir) cmd = (os.path.dirname(os.path.realpath(__file__))+"/notarization_simulator.sh") shell.runshell(cmd.split(), work_dir, True,process_stderr=process_submit_stderr) def read_results(): print("Waiting for results") print(work_dir) cmd = ("xcrun altool --notarization-info " + shell.state.uuid + " -u " + username + " -p " + password) shell.runshell(cmd.split(), work_dir, False, process_stdout=process_status) def staple(): print("Stapling") print(work_dir) cmd = ("xcrun stapler staple CASA.app") shell.runshell(cmd.split(), work_dir, False) def create_dmg(): print("Creating .dmg") print(work_dir) cmd = (mydir+"/make-dmg " + work_dir +"/CASA.app " + dmg) shell.runshell(cmd.split(), work_dir, False) copy_app() sign_app() zip_app() init_shell_state() submit_app() #sim_submit_app() print("uuid: " + str(shell.state.uuid)) time.sleep(300) read_results() print(">>" + shell.state.request_status) while (shell.state.request_status =="in progress"): time.sleep(300) read_results() print(shell.state.request_status) status = shell.state.request_status print("Final status: " + shell.state.request_status) if status == "success": staple() create_dmg() exit(0) else: exit(1)