diff --git a/RELEASE.md b/RELEASE.md index 91fa2e91..b85e82f3 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -130,28 +130,47 @@ poetry run python .\scripts\build-windows.py package [onionshare_win32_path] [on This will create: - `desktop/dist/OnionShare-win32-$VERSION.msi` -= `desktop/dist/OnionShare-win64-$VERSION.msi` +- `desktop/dist/OnionShare-win64-$VERSION.msi` ## macOS Set up the development environment described in `README.md`. -Then build an executable, make it a macOS app bundle, and package it in a dmg: +Then build an executable, make it a macOS app bundle, and package it in a dmg. + +CircleCI will build the binary and delete extra files, basically running these: ```sh poetry run python ./setup-freeze.py bdist_mac poetry run python ./scripts/build-macos.py cleanup-build +``` + +Find the CircleCI job `build-macos`, switch to the artifacts tab, and download: + +- `onionshare-macos.zip` + +Extract this file, then run: + +```sh poetry run python ./scripts/build-macos.py codesign [app_path] poetry run python ./scripts/build-macos.py package [app_path] ``` The will create `dist/OnionShare-$VERSION.dmg`. -Now, notarize the release. You must have an app-specific Apple ID password saved in the login keychain called `onionshare-notarize`. +Now, notarize the release. -- Notarize it: `xcrun altool --notarize-app --primary-bundle-id "com.micahflee.onionshare" -u "micah@micahflee.com" -p "@keychain:onionshare-notarize" --file dist/OnionShare-$VERSION.dmg` -- Wait for it to get approved, check status with: `xcrun altool --notarization-history 0 -u "micah@micahflee.com" -p "@keychain:onionshare-notarize"` -- After it's approved, staple the ticket: `xcrun stapler staple dist/OnionShare-$VERSION.dmg` +```sh +export APPLE_PASSWORD="changeme" # app-specific Apple ID password +export VERSION=$(cat ../cli/onionshare_cli/resources/version.txt) + +# Notarize it +xcrun altool --notarize-app --primary-bundle-id "com.micahflee.onionshare" -u "micah@micahflee.com" -p "$APPLE_PASSWORD" --file dist/OnionShare-$VERSION.dmg +# Wait for it to get approved, ceck status with +xcrun altool --notarization-history 0 -u "micah@micahflee.com" -p "$APPLE_PASSWORD" +# After it's approved, staple the ticket +xcrun stapler staple dist/OnionShare-$VERSION.dmg +``` This will create `desktop/dist/OnionShare-$VERSION.dmg`, signed and notarized. diff --git a/desktop/scripts/build-macos.py b/desktop/scripts/build-macos.py index f9586de0..10af26ce 100644 --- a/desktop/scripts/build-macos.py +++ b/desktop/scripts/build-macos.py @@ -69,75 +69,78 @@ def cleanup_build(): print("> Delete unused Qt Frameworks") for framework in [ - "Qt3DAnimation", - "Qt3DCore", - "Qt3DExtras", - "Qt3DInput", - "Qt3DLogic", - "Qt3DQuick", - "Qt3DQuickAnimation", - "Qt3DQuickExtras", - "Qt3DQuickInput", - "Qt3DQuickRender", - "Qt3DQuickScene2D", - "Qt3DRender", - "QtBluetooth", - "QtBodymovin", - "QtCharts", - "QtConcurrent", - "QtDataVisualization", - "QtDesigner", - "QtDesignerComponents", - "QtGamepad", - "QtHelp", - "QtLocation", - "QtMultimedia", "QtMultimediaQuick", - "QtMultimediaWidgets", - "QtNetwork", - "QtNetworkAuth", - "QtNfc", - "QtOpenGL", - "QtPdf", - "QtPdfWidgets", - "QtPositioning", - "QtPositioningQuick", - "QtPrintSupport", - "QtPurchasing", - "QtQml", - "QtQmlModels", - "QtQmlWorkerScript", - "QtQuick", - "QtQuick3D", - "QtQuick3DAssetImport", - "QtQuick3DRender", - "QtQuick3DRuntimeRender", - "QtQuick3DUtils", "QtQuickControls2", "QtQuickParticles", - "QtQuickShapes", - "QtQuickTemplates2", - "QtQuickTest", - "QtQuickWidgets", "QtRemoteObjects", - "QtScript", + "Qt3DInput", + "QtPdfWidgets", "QtScriptTools", - "QtScxml", - "QtSensors", - "QtSerialBus", - "QtSerialPort", - "QtSql", - "QtSvg", - "QtTest", - "QtTextToSpeech", - "QtVirtualKeyboard", - "QtWebChannel", - "QtWebEngine", + "QtNetworkAuth", + "QtDataVisualization", + "QtWebEngineCore", + "Qt3DQuickRender", + "Qt3DQuickExtras", + "QtQuick3DRender", + "QtDesigner", + "QtNfc", + "QtQuick3DAssetImport", + "QtBodymovin", "QtWebEngineWidgets", + "QtQuickWidgets", + "Qt3DQuickInput", + "Qt3DQuickScene2D", + "QtUiPlugin", + "QtPdf", + "Qt3DRender", + "QtQuick3DRuntimeRender", + "QtHelp", + "QtPrintSupport", + "QtCharts", "QtWebSockets", - "QtWebView", + "QtQuick3DUtils", + "QtQuickTemplates2", + "QtScript", + "QtPositioningQuick", + "Qt3DCore", + "QtLocation", "QtXml", + "QtSerialPort", + "QtWebView", + "QtQuick", + "QtScxml", + "QtQml", + "Qt3DExtras", + "QtWebChannel", + "QtMultimedia", + "QtQmlWorkerScript", + "QtVirtualKeyboard", + "QtPurchasing", + "QtOpenGL", + "QtWebEngine", + "Qt3DQuick", + "QtTest", + "QtPositioning", + "QtBluetooth", + "QtQuick3D", + "Qt3DLogic", + "QtQuickShapes", + "QtQuickTest", + "QtNetwork", "QtXmlPatterns", + "QtSvg", + "QtDesignerComponents", + "QtMultimediaWidgets", + "QtQmlModels", + "Qt3DQuickAnimation", + "QtSensors", + "Qt3DAnimation", + "QtRepParser", + "QtTextToSpeech", + "QtGamepad", + "QtSerialBus", + "QtSql", + "QtConcurrent" ]: shutil.rmtree( f"{app_path}/Contents/MacOS/lib/PySide2/Qt/lib/{framework}.framework" @@ -147,8 +150,11 @@ def cleanup_build(): ) try: os.remove(f"{app_path}/Contents/MacOS/lib/PySide2/{framework}.abi3.so") - os.remove(f"{app_path}/Contents/MacOS/lib/PySide2/{framework}.pyi") print(f"Deleted: {app_path}/Contents/MacOS/lib/PySide2/{framework}.abi3.so") + except FileNotFoundError: + pass + try: + os.remove(f"{app_path}/Contents/MacOS/lib/PySide2/{framework}.pyi") print(f"Deleted: {app_path}/Contents/MacOS/lib/PySide2/{framework}.pyi") except FileNotFoundError: pass @@ -214,15 +220,12 @@ def cleanup_build(): f"{app_path}/Contents/Resources/lib/PySide2/glue", f"{app_path}/Contents/Resources/lib/PySide2/include", f"{app_path}/Contents/Resources/lib/PySide2/pyside2-lupdate", - f"{app_path}/Contents/Resources/lib/PySide2/Qt/qml", - f"{app_path}/Contents/Resources/lib/PySide2/libpyside2.abi3.5.15.dylib", - f"{app_path}/Contents/Resources/lib/PySide2/Qt/lib/QtRepParser.framework", - f"{app_path}/Contents/Resources/lib/PySide2/Qt/lib/QtUiPlugin.framework", - f"{app_path}/Contents/Resources/lib/PySide2/Qt/lib/QtWebEngineCore.framework/Helpers", - f"{app_path}/Contents/Resources/lib/shiboken2/libshiboken2.abi3.5.15.dylib", - f"{app_path}/Contents/Resources/lib/shiboken2/docs", f"{app_path}/Contents/Resources/lib/PySide2/rcc", f"{app_path}/Contents/Resources/lib/PySide2/uic", + f"{app_path}/Contents/Resources/lib/PySide2/libpyside2.abi3.5.15.dylib", + f"{app_path}/Contents/Resources/lib/PySide2/Qt/qml", + f"{app_path}/Contents/Resources/lib/shiboken2/libshiboken2.abi3.5.15.dylib", + f"{app_path}/Contents/Resources/lib/shiboken2/docs", ]: if os.path.isfile(filename) or os.path.islink(filename): os.remove(filename) @@ -263,7 +266,7 @@ def codesign(app_path): f"{app_path}", ], ): - codesign(path, entitlements_plist_path, identity_name_application) + sign(path, entitlements_plist_path, identity_name_application) print(f"> Signed app bundle: {app_path}")