From 6f242f284f1aeb1cb55549f08cf0fac39ae106d2 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 19 Apr 2019 18:08:21 +0400 Subject: [PATCH] Notarize update builds. --- Telegram/build/updates.py | 156 +++++++++++++++++++++++++++----------- 1 file changed, 111 insertions(+), 45 deletions(-) diff --git a/Telegram/build/updates.py b/Telegram/build/updates.py index 6ec2414a45..d497d8b147 100644 --- a/Telegram/build/updates.py +++ b/Telegram/build/updates.py @@ -1,4 +1,4 @@ -import os, sys, re, subprocess, datetime +import os, sys, re, subprocess, datetime, time executePath = os.getcwd() scriptPath = os.path.dirname(os.path.realpath(__file__)) @@ -26,13 +26,19 @@ for arg in sys.argv: elif arg == 'date': nextDate = True -def finish(code): +def finish(code, error = ''): + if error != '': + print('[ERROR] ' + error) global executePath os.chdir(executePath) sys.exit(code) os.chdir(scriptPath + '/..') +if 'AC_USERNAME' not in os.environ: + finish(1, 'AC_USERNAME not found!') +username = os.environ['AC_USERNAME'] + if today == '': today = datetime.datetime.now().strftime("%d_%m_%y") outputFolder = 'updates/' + today @@ -43,68 +49,135 @@ if building: print('Building debug version for OS X 10.8+..') if os.path.exists('../out/Debug/' + outputFolder): - print('[ERROR] Todays updates version exists.') - finish(1) + finish(1, 'Todays updates version exists.') result = subprocess.call('gyp/refresh.sh', shell=True) if result != 0: - print('[ERROR] While calling GYP.') - finish(1) + finish(1, 'While calling GYP.') result = subprocess.call('xcodebuild -project Telegram.xcodeproj -alltargets -configuration Debug build', shell=True) if result != 0: - print('[ERROR] While building Telegram.') - finish(1) + finish(1, 'While building Telegram.') os.chdir('../out/Debug') if not os.path.exists('Telegram.app'): - print('[ERROR] Telegram.app not found.') - finish(1) + finish(1, 'Telegram.app not found.') result = subprocess.call('strip Telegram.app/Contents/MacOS/Telegram', shell=True) if result != 0: - print('[ERROR] While stripping Telegram.') - finish(1) + finish(1, 'While stripping Telegram.') - result = subprocess.call('codesign --force --deep --sign "Developer ID Application: John Preston" Telegram.app', shell=True) + result = subprocess.call('codesign --force --deep --timestamp --options runtime --sign "Developer ID Application: John Preston" Telegram.app --entitlements "../../Telegram/Telegram/Telegram.entitlements"', shell=True) if result != 0: - print('[ERROR] While signing Telegram.') - finish(1) + finish(1, 'While signing Telegram.') if not os.path.exists('Telegram.app/Contents/Frameworks/Updater'): - print('[ERROR] Updater not found.') - finish(1) + finish(1, 'Updater not found.') elif not os.path.exists('Telegram.app/Contents/Helpers/crashpad_handler'): - print('[ERROR] crashpad_handler not found.') - finish(1) + finish(1, 'crashpad_handler not found.') elif not os.path.exists('Telegram.app/Contents/Resources/Icon.icns'): - print('[ERROR] Icon not found.') - finish(1) + finish(1, 'Icon not found.') elif not os.path.exists('Telegram.app/Contents/_CodeSignature'): - print('[ERROR] Signature not found.') - finish(1) + finish(1, 'Signature not found.') if os.path.exists(today): subprocess.call('rm -rf ' + today, shell=True) result = subprocess.call('mkdir -p ' + today + '/TelegramForcePortable', shell=True) if result != 0: - print('[ERROR] Creating folder ' + today + '/TelegramForcePortable') - finish(1) + finish(1, 'Creating folder ' + today + '/TelegramForcePortable') result = subprocess.call('cp -r Telegram.app ' + today + '/', shell=True) if result != 0: - print('[ERROR] Cloning Telegram.app to ' + today + '.') - finish(1) + finish(1, 'Cloning Telegram.app to ' + today + '.') result = subprocess.call('zip -r ' + archive + ' ' + today, shell=True) if result != 0: - print('[ERROR] Adding tdesktop to archive.') - finish(1) + finish(1, 'Adding tdesktop to archive.') + + print('Beginning notarization process.') + lines = subprocess.check_output('xcrun altool --notarize-app --primary-bundle-id "com.tdesktop.TelegramDebug" --username "' + username + '" --password "@keychain:AC_PASSWORD" --file "' + archive + '"', stderr=subprocess.STDOUT, shell=True) + print('Response received.') + uuid = '' + for line in lines.split('\n'): + parts = line.strip().split(' ') + if len(parts) > 2 and parts[0] == 'RequestUUID': + uuid = parts[2] + if uuid == '': + finish(1, 'Could not extract Request UUID. Response: ' + lines) + print('Request UUID: ' + uuid) + + requestStatus = '' + logUrl = '' + while requestStatus == '': + time.sleep(5) + print('Checking...') + lines = subprocess.check_output('xcrun altool --notarization-info "' + uuid + '" --username "' + username + '" --password "@keychain:AC_PASSWORD"', stderr=subprocess.STDOUT, shell=True) + statusFound = False + for line in lines.split('\n'): + parts = line.strip().split(' ') + if len(parts) > 1: + if parts[0] == 'LogFileURL:': + logUrl = parts[1] + elif parts[0] == 'Status:': + if parts[1] == 'in': + print('In progress.') + statusFound = True + else: + requestStatus = parts[1] + print('Status: ' + requestStatus) + statusFound = True + if not statusFound: + print('Nothing: ' + lines) + if requestStatus != 'success': + print('Notarization problems, response: ' + lines) + if logUrl != '': + print('Requesting log...') + result = subprocess.call('curl ' + logUrl, shell=True) + if result != 0: + finish(1, 'Error calling curl ' + logUrl) + finish(1, 'Notarization failed.') + logLines = '' + if logUrl != '': + print('Requesting log...') + logLines = subprocess.check_output('curl ' + logUrl, shell=True) + result = subprocess.call('xcrun stapler staple Telegram.app', shell=True) + if result != 0: + finish(1, 'Error calling stapler') + + subprocess.call('rm -rf ' + today + '/Telegram.app', shell=True) + subprocess.call('rm ' + archive, shell=True) + result = subprocess.call('cp -r Telegram.app ' + today + '/', shell=True) + if result != 0: + finish(1, 'Re-Cloning Telegram.app to ' + today + '.') + + result = subprocess.call('zip -r ' + archive + ' ' + today, shell=True) + if result != 0: + finish(1, 'Re-Adding tdesktop to archive.') + print('Re-Archived.') subprocess.call('mkdir -p ' + outputFolder, shell=True) subprocess.call('mv ' + archive + ' ' + outputFolder + '/', shell=True) subprocess.call('rm -rf ' + today, shell=True) print('Finished.') + + if logLines != '': + displayingLog = 0 + for line in logLines.split('\n'): + if displayingLog == 1: + print(line) + else: + parts = line.strip().split(' ') + if len(parts) > 1 and parts[0] == '"issues":': + if parts[1] != 'null': + print('NB! Notarization log issues:') + print(line) + displayingLog = 1 + else: + displayingLog = -1 + if displayingLog == 0: + print('NB! Notarization issues not found: ' + logLines) + else: + print('NB! Notarization log not found.') finish(0) commandPath = scriptPath + '/../../out/Debug/' + outputFolder + '/command.txt' @@ -112,12 +185,10 @@ commandPath = scriptPath + '/../../out/Debug/' + outputFolder + '/command.txt' if composing: templatePath = scriptPath + '/../../../TelegramPrivate/updates_template.txt' if not os.path.exists(templatePath): - print('[ERROR] Template file "' + templatePath + '" not found.') - finish(1) + finish(1, 'Template file "' + templatePath + '" not found.') if not re.match(r'^[a-f0-9]{40}$', lastCommit): - print('[ERROR] Wrong last commit: ' + lastCommit) - finish(1) + finish(1, 'Wrong last commit: ' + lastCommit) log = subprocess.check_output(['git', 'log', lastCommit+'..HEAD']) logLines = log.split('\n') @@ -134,17 +205,15 @@ if composing: if not len(stripped): continue elif not len(commits): - print('[ERROR] Bad git log output:') print(log) - finish(1) + finish(1, 'Bad git log output.') if len(commits[len(commits) - 1]): commits[len(commits) - 1] += '\n' + stripped else: commits[len(commits) - 1] = '- ' + stripped commits.reverse() if not len(commits): - print('[ERROR] No commits since last build :(') - finish(1) + finish(1, 'No commits since last build :(') changelog = '\n'.join(commits) print('\n\nReady! File: ' + archive + '\nChangelog:\n' + changelog) @@ -161,8 +230,7 @@ if composing: finish(0) if not os.path.exists(commandPath): - print('[ERROR] Command file not found.') - finish(1) + finish(1, 'Command file not found.') readingCaption = False caption = '' @@ -174,17 +242,15 @@ with open(commandPath, 'r') as f: readingCaption = True caption = line[len('caption: '):] if not caption.startswith('TDesktop at ' + today.replace('_', '.') + ':'): - print('[ERROR] Wrong caption start.') - finish(1) + finish(1, 'Wrong caption start.') print('\n\nSending! File: ' + archive + '\nChangelog:\n' + caption) if len(caption) > 1024: - print('[ERROR] Length: ' + str(len(caption))) + print('Length: ' + str(len(caption))) print('vi ' + commandPath) - finish(1) + finish(1, 'Too large.') if not os.path.exists('../out/Debug/' + outputFolder + '/' + archive): - print('[ERROR] Not built yet.') - finish(1) + finish(1, 'Not built yet.') subprocess.call(scriptPath + '/../../out/Debug/Telegram.app/Contents/MacOS/Telegram -sendpath interpret://' + scriptPath + '/../../out/Debug/' + outputFolder + '/command.txt', shell=True)