From 3510bc55f95f13ade87f8ba7c769b40ff84ce7c5 Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Tue, 13 Dec 2022 16:23:00 +0100 Subject: [PATCH 01/22] Move MacOs bulid scripts to more generically name file CURA-6867 --- .../dmg_sign_noterize.py => MacOs/build_macos.py} | 0 packaging/{dmg => MacOs}/cura.entitlements | 0 packaging/{dmg => MacOs}/cura_background_dmg.png | Bin 3 files changed, 0 insertions(+), 0 deletions(-) rename packaging/{dmg/dmg_sign_noterize.py => MacOs/build_macos.py} (100%) rename packaging/{dmg => MacOs}/cura.entitlements (100%) rename packaging/{dmg => MacOs}/cura_background_dmg.png (100%) diff --git a/packaging/dmg/dmg_sign_noterize.py b/packaging/MacOs/build_macos.py similarity index 100% rename from packaging/dmg/dmg_sign_noterize.py rename to packaging/MacOs/build_macos.py diff --git a/packaging/dmg/cura.entitlements b/packaging/MacOs/cura.entitlements similarity index 100% rename from packaging/dmg/cura.entitlements rename to packaging/MacOs/cura.entitlements diff --git a/packaging/dmg/cura_background_dmg.png b/packaging/MacOs/cura_background_dmg.png similarity index 100% rename from packaging/dmg/cura_background_dmg.png rename to packaging/MacOs/cura_background_dmg.png From 4748f4abe6e6830f17b54f9f4b6bf037cc4cd792 Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Tue, 13 Dec 2022 16:23:42 +0100 Subject: [PATCH 02/22] Update workflow to reflect new MacOS build script location CURA-6867 --- .github/workflows/cura-installer.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cura-installer.yml b/.github/workflows/cura-installer.yml index 082c707488..084a82f85e 100644 --- a/.github/workflows/cura-installer.yml +++ b/.github/workflows/cura-installer.yml @@ -235,9 +235,9 @@ jobs: run: python ../cura_inst/packaging/AppImage/create_appimage.py ./UltiMaker-Cura $CURA_VERSION_FULL "UltiMaker-Cura-$CURA_VERSION_FULL-${{ inputs.os_name }}.AppImage" working-directory: dist - - name: Create the MacOS dmg (Bash) + - name: Create the MacOS dmg and/or pkg (Bash) if: ${{ github.event.inputs.installer == 'true' && runner.os == 'Macos' }} - run: python ../cura_inst/packaging/dmg/dmg_sign_noterize.py ../cura_inst . "UltiMaker-Cura-$CURA_VERSION_FULL-${{ inputs.os_name }}.dmg" + run: python ../cura_inst/packaging/MacOs/build_macos.py ../cura_inst . "UltiMaker-Cura-$CURA_VERSION_FULL-${{ inputs.os_name }}" working-directory: dist - name: Upload the artifacts @@ -250,6 +250,7 @@ jobs: dist/*.exe dist/*.msi dist/*.dmg + dist/*.pkg dist/*.AppImage dist/*.asc retention-days: 5 From b6e15084fb118a41fbb944dc32d4c505dcff893d Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Tue, 13 Dec 2022 16:51:28 +0100 Subject: [PATCH 03/22] Update macos build script to build both dmg and pkg. CURA-6867 --- packaging/MacOs/build_macos.py | 108 +++++++++++++++++++++++++++++---- 1 file changed, 95 insertions(+), 13 deletions(-) diff --git a/packaging/MacOs/build_macos.py b/packaging/MacOs/build_macos.py index fcda1e378e..e87ac3dff3 100644 --- a/packaging/MacOs/build_macos.py +++ b/packaging/MacOs/build_macos.py @@ -26,26 +26,66 @@ def build_dmg(source_path: str, dist_path: str, filename: str) -> None: subprocess.run(arguments) +def build_pkg(source_path: str, dist_path: str, app_filename: str, component_filename: str, installer_filename: str) -> None: + pkg_build_executable = os.environ.get("PKG_BUILD_EXECUTABLE", "pkgbuild") + product_build_executable = os.environ.get("PRODUCT_BUILD_EXECUTABLE", "productbuild") -def sign(dist_path: str, filename: str) -> None: + # This builds the component package that contains Ultimaker-Cura.app. This component package will be bundled in a distribution package. + # TODO: sign the packgae with installer certificate + pkg_build_arguments = [ + pkg_build_executable, + "--component", + f"{dist_path}/{app_filename}", + f"{dist_path}/{component_filename}", + "--install-location", "/Applications", + ] + print(f"pkg_build_arguments: {pkg_build_arguments}") + subprocess.run(pkg_build_arguments) + + # This automatically generates a distribution.xml file that is used to build the installer. + # If you want to make any changes to how the installer functions, this file should be changed to do that. + # TODO: Use --product {property_list_file} to pull keys out of file for distribution.xml. This can be used to set min requirements + # TODO: sign the packgae with installer certificate + distribution_creation_arguments = [ + product_build_executable, + "--synthesize", + "--package", f"{dist_path}/{component_filename}", # Package that will be inside installer + f"{dist_path}/distribution.xml", # Output location for sythesized distributions file + ] + print(f"distribution_creation_arguments: {distribution_creation_arguments}") + subprocess.run(distribution_creation_arguments) + + # This creates the distributable package (Installer) + installer_creation_arguments = [ + product_build_executable, + "--distribution", f"{dist_path}/distribution.xml", + "--package-path", dist_path, # Where to find the component packages mentioned in distribution.xml (Ultimaker-Cura.pkg) + f"{dist_path}/{installer_filename}", + ] + print(f"installer_creation_arguments: {installer_creation_arguments}") + subprocess.run(installer_creation_arguments) + +def code_sign(dist_path: str, filename: str) -> None: + """ Sign a file using apple codesign. This uses a different certificate to package signing.""" codesign_executable = os.environ.get("CODESIGN", "codesign") codesign_identity = os.environ.get("CODESIGN_IDENTITY") - arguments = [codesign_executable, + sign_arguments = [codesign_executable, "-s", codesign_identity, "--timestamp", - "-i", f"{ULTIMAKER_CURA_DOMAIN}.dmg", # TODO: check if this really should have the extra dmg. We seem to be doing this also in the old Rundeck scripts + "-i", filename, # This is by default derived from Info.plist or the filename. The documentation does not specify which, so it is explicit here. **This must be unique in the package** f"{dist_path}/{filename}"] - subprocess.run(arguments) + subprocess.run(sign_arguments) -def notarize(dist_path: str, filename: str) -> None: +def notarize_file(dist_path: str, filename: str) -> None: + """ Notarize a file. This takes 5+ minutes, there is indication that this step is successful.""" notarize_user = os.environ.get("MAC_NOTARIZE_USER") notarize_password = os.environ.get("MAC_NOTARIZE_PASS") altool_executable = os.environ.get("ALTOOL_EXECUTABLE", "altool") - arguments = [ + notarize_arguments = [ "xcrun", altool_executable, "--notarize-app", "--primary-bundle-id", ULTIMAKER_CURA_DOMAIN, @@ -54,18 +94,60 @@ def notarize(dist_path: str, filename: str) -> None: "--file", f"{dist_path}/{filename}" ] - subprocess.run(arguments) + subprocess.run(notarize_arguments) + + +def create_pkg_installer(filename: str, dist_path: str, source_path: str) -> None: + """ Creates a pkg installer from {filename}.app called {filename}-Installer.pkg + + The final package structure is Ultimaker-Cura-XXX-Installer.pkg[Ultimaker-Cura.pkg[Ultimaker-Cura.app]] + + @param filename: The name of the app file and the app component package file without the extension + @param dist_path: The location to read the app from and save the pkg to + @param source_path: The location of the project source files + """ + installer_package_name = f"{filename}-Installer.pkg" + cura_component_package_name = f"{filename}.pkg" # This is a component package that is nested inside the installer, it contains the Ultimaker-Cura.app file + app_name = f"{filename}.app" # This is the app file that will end up in your applications folder + + code_sign(dist_path, app_name) # The app is signed using a different certificate than the package files + build_pkg(source_path, dist_path, app_name, cura_component_package_name, installer_package_name) + + notarize = bool(os.environ.get("NOTARIZE_PKG", "TRUE")) + if notarize: + notarize_file(dist_path, installer_package_name) + + +def create_dmg(filename: str, dist_path: str, source_path: str) -> None: + """ Creates a dmg executable from {filename}.app named {filename}.dmg + + @param filename: The name of the app file and the output dmg file without the extension + @param dist_path: The location to read the app from and save the dmg to + @param source_path: The location of the project source files + """ + + dmg_filename = f"{filename}.dmg" + + build_dmg(source_path, dist_path, dmg_filename) + + code_sign(dist_path, dmg_filename) + + notarize_dmg = bool(os.environ.get("NOTARIZE_DMG", "TRUE")) + if notarize_dmg: + notarize_file(dist_path, dmg_filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description = "Create dmg of Cura.") parser.add_argument("source_path", type=str, help="Path to Conan install Cura folder.") parser.add_argument("dist_path", type=str, help="Path to Pyinstaller dist folder") - parser.add_argument("filename", type = str, help = "Filename of the dmg (e.g. 'UltiMaker-Cura-5.1.0-beta-Linux-X64.dmg')") + parser.add_argument("filename", type = str, help = "Filename of the dmg/pkg without the file extension (e.g. 'UltiMaker-Cura-5.1.0-beta-Linux-X64')") args = parser.parse_args() - build_dmg(args.source_path, args.dist_path, args.filename) - sign(args.dist_path, args.filename) - notarize_dmg = bool(os.environ.get("NOTARIZE_DMG", "TRUE")) - if notarize_dmg: - notarize(args.dist_path, args.filename) + build_installer = bool(os.environ.get("BUILD_INSTALLER", "TRUE")) + if build_installer: + create_pkg_installer(args.filename, args.dist_path, args.source_path) + + build_dmg_executable = bool(os.environ.get("BUILD_DMG", "False")) + if build_dmg_executable: + create_dmg(args.filename, args.dist_path, args.source_path) From 36abfbf8bf097fa21b59516aa83ab5fca6ddd3fd Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Tue, 13 Dec 2022 17:17:00 +0100 Subject: [PATCH 04/22] Add missing bundle version metadata, this fixes the application not being searchable in launchpad. CURA-6867 --- UltiMaker-Cura.spec.jinja | 1 + 1 file changed, 1 insertion(+) diff --git a/UltiMaker-Cura.spec.jinja b/UltiMaker-Cura.spec.jinja index 74e4fd098b..6e07b1ece7 100644 --- a/UltiMaker-Cura.spec.jinja +++ b/UltiMaker-Cura.spec.jinja @@ -141,6 +141,7 @@ class UMBUNDLE(BUNDLE): "CFBundleIconFile": os.path.basename(self.icon), "CFBundleInfoDictionaryVersion": "6.0", "CFBundlePackageType": "APPL", + "CFBundleVersionString": self.version, "CFBundleShortVersionString": self.version, } From 2b12343cd21d5e7d8b8ea6d6a5633de75ac6eea7 Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Wed, 14 Dec 2022 10:54:15 +0100 Subject: [PATCH 05/22] Update paths CURA-6867 --- conanfile.py | 4 ++-- packaging/MacOs/build_macos.py | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/conanfile.py b/conanfile.py index 111d4f9b9c..e9d3ba6742 100644 --- a/conanfile.py +++ b/conanfile.py @@ -311,7 +311,7 @@ class CuraConan(ConanFile): self._generate_cura_version(Path(self.source_folder, "cura")) if self.options.devtools: - entitlements_file = "'{}'".format(Path(self.source_folder, "packaging", "dmg", "cura.entitlements")) + entitlements_file = "'{}'".format(Path(self.source_folder, "packaging", "MacOs", "cura.entitlements")) self._generate_pyinstaller_spec(location = self.generators_folder, entrypoint_location = "'{}'".format(Path(self.source_folder, self._um_data()["runinfo"]["entrypoint"])).replace("\\", "\\\\"), icon_path = "'{}'".format(Path(self.source_folder, "packaging", self._um_data()["pyinstaller"]["icon"][str(self.settings.os)])).replace("\\", "\\\\"), @@ -437,7 +437,7 @@ echo "CURA_VERSION_FULL={{ cura_version_full }}" >> ${{ env_prefix }}GITHUB_ENV self._generate_cura_version(Path(self._site_packages, "cura")) - entitlements_file = "'{}'".format(Path(self.cpp_info.res_paths[2], "dmg", "cura.entitlements")) + entitlements_file = "'{}'".format(Path(self.cpp_info.res_paths[2], "MacOs", "cura.entitlements")) self._generate_pyinstaller_spec(location = self._base_dir, entrypoint_location = "'{}'".format(Path(self.cpp_info.bin_paths[0], self._um_data()["runinfo"]["entrypoint"])).replace("\\", "\\\\"), icon_path = "'{}'".format(Path(self.cpp_info.res_paths[2], self._um_data()["pyinstaller"]["icon"][str(self.settings.os)])).replace("\\", "\\\\"), diff --git a/packaging/MacOs/build_macos.py b/packaging/MacOs/build_macos.py index e87ac3dff3..ca1448c8a1 100644 --- a/packaging/MacOs/build_macos.py +++ b/packaging/MacOs/build_macos.py @@ -20,12 +20,13 @@ def build_dmg(source_path: str, dist_path: str, filename: str) -> None: "--icon-size", "90", "--icon", "UltiMaker-Cura.app", "169", "272", "--eula", f"{source_path}/packaging/cura_license.txt", - "--background", f"{source_path}/packaging/dmg/cura_background_dmg.png", + "--background", f"{source_path}/packaging/MacOs/cura_background_dmg.png", f"{dist_path}/{filename}", f"{dist_path}/UltiMaker-Cura.app"] subprocess.run(arguments) + def build_pkg(source_path: str, dist_path: str, app_filename: str, component_filename: str, installer_filename: str) -> None: pkg_build_executable = os.environ.get("PKG_BUILD_EXECUTABLE", "pkgbuild") product_build_executable = os.environ.get("PRODUCT_BUILD_EXECUTABLE", "productbuild") @@ -65,6 +66,7 @@ def build_pkg(source_path: str, dist_path: str, app_filename: str, component_fil print(f"installer_creation_arguments: {installer_creation_arguments}") subprocess.run(installer_creation_arguments) + def code_sign(dist_path: str, filename: str) -> None: """ Sign a file using apple codesign. This uses a different certificate to package signing.""" codesign_executable = os.environ.get("CODESIGN", "codesign") From 095f481310f8f330973d8b0649521ca5da4ca536 Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Wed, 14 Dec 2022 13:11:11 +0100 Subject: [PATCH 06/22] Update MacOS pkg build to use correct .app name. CURA-6867 --- packaging/MacOs/build_macos.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packaging/MacOs/build_macos.py b/packaging/MacOs/build_macos.py index ca1448c8a1..f2773f85b9 100644 --- a/packaging/MacOs/build_macos.py +++ b/packaging/MacOs/build_macos.py @@ -110,7 +110,7 @@ def create_pkg_installer(filename: str, dist_path: str, source_path: str) -> Non """ installer_package_name = f"{filename}-Installer.pkg" cura_component_package_name = f"{filename}.pkg" # This is a component package that is nested inside the installer, it contains the Ultimaker-Cura.app file - app_name = f"{filename}.app" # This is the app file that will end up in your applications folder + app_name = "UltiMaker-Cura.app" # This is the app file that will end up in your applications folder code_sign(dist_path, app_name) # The app is signed using a different certificate than the package files build_pkg(source_path, dist_path, app_name, cura_component_package_name, installer_package_name) @@ -121,7 +121,7 @@ def create_pkg_installer(filename: str, dist_path: str, source_path: str) -> Non def create_dmg(filename: str, dist_path: str, source_path: str) -> None: - """ Creates a dmg executable from {filename}.app named {filename}.dmg + """ Creates a dmg executable from UltiMaker-Cura.app named {filename}.dmg @param filename: The name of the app file and the output dmg file without the extension @param dist_path: The location to read the app from and save the dmg to From 8870ba2964425b1df6d6ab8408e2fee51199e59f Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Mon, 19 Dec 2022 15:23:03 +0100 Subject: [PATCH 07/22] Sign the pkg files Remove the component .pkg file after it is packaged into the installer. This file was being added to the github action output zip file. CURA-6867 --- packaging/MacOs/build_macos.py | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/packaging/MacOs/build_macos.py b/packaging/MacOs/build_macos.py index f2773f85b9..d0233dbbdb 100644 --- a/packaging/MacOs/build_macos.py +++ b/packaging/MacOs/build_macos.py @@ -28,32 +28,38 @@ def build_dmg(source_path: str, dist_path: str, filename: str) -> None: def build_pkg(source_path: str, dist_path: str, app_filename: str, component_filename: str, installer_filename: str) -> None: + """ Builds and signs the pkg installer. + + @param source_path: Path to folder containing source files + @param dist_path: Path to put output pkg in + @param app_filename: name of the .app file to bundle inside the pkg + @param component_filename: Name of the pkg component package to bundle the app in + @param installer_filename: Name of the installer that contains the component package + """ pkg_build_executable = os.environ.get("PKG_BUILD_EXECUTABLE", "pkgbuild") product_build_executable = os.environ.get("PRODUCT_BUILD_EXECUTABLE", "productbuild") + codesign_identity = os.environ.get("CODESIGN_IDENTITY") # This builds the component package that contains Ultimaker-Cura.app. This component package will be bundled in a distribution package. - # TODO: sign the packgae with installer certificate pkg_build_arguments = [ pkg_build_executable, "--component", f"{dist_path}/{app_filename}", f"{dist_path}/{component_filename}", + "--sign", codesign_identity, "--install-location", "/Applications", ] - print(f"pkg_build_arguments: {pkg_build_arguments}") subprocess.run(pkg_build_arguments) # This automatically generates a distribution.xml file that is used to build the installer. # If you want to make any changes to how the installer functions, this file should be changed to do that. # TODO: Use --product {property_list_file} to pull keys out of file for distribution.xml. This can be used to set min requirements - # TODO: sign the packgae with installer certificate distribution_creation_arguments = [ product_build_executable, "--synthesize", "--package", f"{dist_path}/{component_filename}", # Package that will be inside installer f"{dist_path}/distribution.xml", # Output location for sythesized distributions file ] - print(f"distribution_creation_arguments: {distribution_creation_arguments}") subprocess.run(distribution_creation_arguments) # This creates the distributable package (Installer) @@ -61,11 +67,14 @@ def build_pkg(source_path: str, dist_path: str, app_filename: str, component_fil product_build_executable, "--distribution", f"{dist_path}/distribution.xml", "--package-path", dist_path, # Where to find the component packages mentioned in distribution.xml (Ultimaker-Cura.pkg) + "--sign", codesign_identity, f"{dist_path}/{installer_filename}", ] - print(f"installer_creation_arguments: {installer_creation_arguments}") subprocess.run(installer_creation_arguments) + # Remove component package so that it is not added to the output zip file + os.remove(f"{dist_path}/{component_filename}") + def code_sign(dist_path: str, filename: str) -> None: """ Sign a file using apple codesign. This uses a different certificate to package signing.""" @@ -102,7 +111,9 @@ def notarize_file(dist_path: str, filename: str) -> None: def create_pkg_installer(filename: str, dist_path: str, source_path: str) -> None: """ Creates a pkg installer from {filename}.app called {filename}-Installer.pkg - The final package structure is Ultimaker-Cura-XXX-Installer.pkg[Ultimaker-Cura.pkg[Ultimaker-Cura.app]] + The final package structure is Ultimaker-Cura-XXX-Installer.pkg[Ultimaker-Cura.pkg[Ultimaker-Cura.app]]. The outer + pkg file is a distributable pkg (Installer). Inside the distributable pkg there is a component pkg. The component + pkg contains the .app file that will be installed in the users Applications folder. @param filename: The name of the app file and the app component package file without the extension @param dist_path: The location to read the app from and save the pkg to @@ -143,7 +154,7 @@ if __name__ == "__main__": parser = argparse.ArgumentParser(description = "Create dmg of Cura.") parser.add_argument("source_path", type=str, help="Path to Conan install Cura folder.") parser.add_argument("dist_path", type=str, help="Path to Pyinstaller dist folder") - parser.add_argument("filename", type = str, help = "Filename of the dmg/pkg without the file extension (e.g. 'UltiMaker-Cura-5.1.0-beta-Linux-X64')") + parser.add_argument("filename", type = str, help = "Filename of the dmg/pkg without the file extension (e.g. 'UltiMaker-Cura-5.1.0-beta-Macos-X64')") args = parser.parse_args() build_installer = bool(os.environ.get("BUILD_INSTALLER", "TRUE")) From 9366facfe2dfe9bccee6a8f385f9544c8f0b360d Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Tue, 20 Dec 2022 10:23:57 +0100 Subject: [PATCH 08/22] Update workflows to add new MacOs installer certificate CURA-6867 --- .github/workflows/cura-installer.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cura-installer.yml b/.github/workflows/cura-installer.yml index 084a82f85e..dcb65f11f6 100644 --- a/.github/workflows/cura-installer.yml +++ b/.github/workflows/cura-installer.yml @@ -57,6 +57,7 @@ env: MAC_NOTARIZE_USER: ${{ secrets.MAC_NOTARIZE_USER }} MAC_NOTARIZE_PASS: ${{ secrets.MAC_NOTARIZE_PASS }} MACOS_CERT_P12: ${{ secrets.MACOS_CERT_P12 }} + MACOS_CERT_INSTALLER_P12: ${{ secrets.MACOS_CERT_INSTALLER_P12 }} MACOS_CERT_PASS: ${{ secrets.MACOS_CERT_PASS }} MACOS_CERT_USER: ${{ secrets.MACOS_CERT_USER }} GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} @@ -145,7 +146,7 @@ jobs: if: ${{ runner.os == 'Linux' }} run: echo -n "$GPG_PRIVATE_KEY" | base64 --decode | gpg --import - - name: Configure Macos keychain (Bash) + - name: Configure Macos keychain Developer Cert(Bash) id: macos-keychain if: ${{ runner.os == 'Macos' }} uses: apple-actions/import-codesign-certs@v1 @@ -153,6 +154,14 @@ jobs: p12-file-base64: ${{ secrets.MACOS_CERT_P12 }} p12-password: ${{ secrets.MACOS_CERT_PASSPHRASE }} + - name: Configure Macos keychain Installer Cert (Bash) + id: macos-keychain + if: ${{ runner.os == 'Macos' }} + uses: apple-actions/import-codesign-certs@v1 + with: + p12-file-base64: ${{ secrets.MACOS_CERT_INSTALLER_P12 }} + p12-password: ${{ secrets.MACOS_CERT_PASSPHRASE }} + - name: Clean Conan local cache if: ${{ inputs.conan_clean_local_cache }} run: conan remove "*" -f From f56cfd076f825a46c62a49ccab3f70d92fb3c641 Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Tue, 20 Dec 2022 10:24:54 +0100 Subject: [PATCH 09/22] Update comments to match new company name CURA-6867 --- packaging/MacOs/build_macos.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packaging/MacOs/build_macos.py b/packaging/MacOs/build_macos.py index d0233dbbdb..277a922bc6 100644 --- a/packaging/MacOs/build_macos.py +++ b/packaging/MacOs/build_macos.py @@ -40,7 +40,7 @@ def build_pkg(source_path: str, dist_path: str, app_filename: str, component_fil product_build_executable = os.environ.get("PRODUCT_BUILD_EXECUTABLE", "productbuild") codesign_identity = os.environ.get("CODESIGN_IDENTITY") - # This builds the component package that contains Ultimaker-Cura.app. This component package will be bundled in a distribution package. + # This builds the component package that contains UltiMaker-Cura.app. This component package will be bundled in a distribution package. pkg_build_arguments = [ pkg_build_executable, "--component", @@ -66,7 +66,7 @@ def build_pkg(source_path: str, dist_path: str, app_filename: str, component_fil installer_creation_arguments = [ product_build_executable, "--distribution", f"{dist_path}/distribution.xml", - "--package-path", dist_path, # Where to find the component packages mentioned in distribution.xml (Ultimaker-Cura.pkg) + "--package-path", dist_path, # Where to find the component packages mentioned in distribution.xml (UltiMaker-Cura.pkg) "--sign", codesign_identity, f"{dist_path}/{installer_filename}", ] @@ -111,7 +111,7 @@ def notarize_file(dist_path: str, filename: str) -> None: def create_pkg_installer(filename: str, dist_path: str, source_path: str) -> None: """ Creates a pkg installer from {filename}.app called {filename}-Installer.pkg - The final package structure is Ultimaker-Cura-XXX-Installer.pkg[Ultimaker-Cura.pkg[Ultimaker-Cura.app]]. The outer + The final package structure is UltiMaker-Cura-XXX-Installer.pkg[UltiMaker-Cura.pkg[UltiMaker-Cura.app]]. The outer pkg file is a distributable pkg (Installer). Inside the distributable pkg there is a component pkg. The component pkg contains the .app file that will be installed in the users Applications folder. @@ -120,7 +120,7 @@ def create_pkg_installer(filename: str, dist_path: str, source_path: str) -> Non @param source_path: The location of the project source files """ installer_package_name = f"{filename}-Installer.pkg" - cura_component_package_name = f"{filename}.pkg" # This is a component package that is nested inside the installer, it contains the Ultimaker-Cura.app file + cura_component_package_name = f"{filename}.pkg" # This is a component package that is nested inside the installer, it contains the UltiMaker-Cura.app file app_name = "UltiMaker-Cura.app" # This is the app file that will end up in your applications folder code_sign(dist_path, app_name) # The app is signed using a different certificate than the package files From 7057bd6fb78f8a8a8c865984a568aa8e7fc60a62 Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Tue, 20 Dec 2022 10:30:42 +0100 Subject: [PATCH 10/22] Fix workflow CURA-6867 --- .github/workflows/cura-installer.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cura-installer.yml b/.github/workflows/cura-installer.yml index dcb65f11f6..da26288e7c 100644 --- a/.github/workflows/cura-installer.yml +++ b/.github/workflows/cura-installer.yml @@ -147,7 +147,7 @@ jobs: run: echo -n "$GPG_PRIVATE_KEY" | base64 --decode | gpg --import - name: Configure Macos keychain Developer Cert(Bash) - id: macos-keychain + id: macos-keychain-developer-cert if: ${{ runner.os == 'Macos' }} uses: apple-actions/import-codesign-certs@v1 with: @@ -155,7 +155,7 @@ jobs: p12-password: ${{ secrets.MACOS_CERT_PASSPHRASE }} - name: Configure Macos keychain Installer Cert (Bash) - id: macos-keychain + id: macos-keychain-installer-cert if: ${{ runner.os == 'Macos' }} uses: apple-actions/import-codesign-certs@v1 with: @@ -198,7 +198,7 @@ jobs: if: ${{ runner.os == 'Macos' }} run: security unlock -p $TEMP_KEYCHAIN_PASSWORD signing_temp.keychain env: - TEMP_KEYCHAIN_PASSWORD: ${{ steps.macos-keychain.outputs.keychain-password }} + TEMP_KEYCHAIN_PASSWORD: ${{ steps.macos-keychain-developer-cert.outputs.keychain-password }} # FIXME: This is a workaround to ensure that we use and pack a shared library for OpenSSL 1.1.1l. We currently compile # OpenSSL statically for CPython, but our Python Dependenies (such as PyQt6) require a shared library. From 179b29d2c2733c7c3a24a7735e6d7c02e6b959be Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Tue, 20 Dec 2022 11:53:52 +0100 Subject: [PATCH 11/22] Don't create keychain twice. CURA-6867 --- .github/workflows/cura-installer.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/cura-installer.yml b/.github/workflows/cura-installer.yml index da26288e7c..405f7314b6 100644 --- a/.github/workflows/cura-installer.yml +++ b/.github/workflows/cura-installer.yml @@ -159,6 +159,7 @@ jobs: if: ${{ runner.os == 'Macos' }} uses: apple-actions/import-codesign-certs@v1 with: + create-keychain: false # keychain is created in previous use of action. p12-file-base64: ${{ secrets.MACOS_CERT_INSTALLER_P12 }} p12-password: ${{ secrets.MACOS_CERT_PASSPHRASE }} From 0880736de5a6abd45f0f95b11909f389c6c4ec3e Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Tue, 20 Dec 2022 15:00:24 +0100 Subject: [PATCH 12/22] Update cura-installer.yml --- .github/workflows/cura-installer.yml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/.github/workflows/cura-installer.yml b/.github/workflows/cura-installer.yml index 405f7314b6..3600d44a37 100644 --- a/.github/workflows/cura-installer.yml +++ b/.github/workflows/cura-installer.yml @@ -146,20 +146,19 @@ jobs: if: ${{ runner.os == 'Linux' }} run: echo -n "$GPG_PRIVATE_KEY" | base64 --decode | gpg --import - - name: Configure Macos keychain Developer Cert(Bash) - id: macos-keychain-developer-cert - if: ${{ runner.os == 'Macos' }} - uses: apple-actions/import-codesign-certs@v1 - with: - p12-file-base64: ${{ secrets.MACOS_CERT_P12 }} - p12-password: ${{ secrets.MACOS_CERT_PASSPHRASE }} +# - name: Configure Macos keychain Developer Cert(Bash) +# id: macos-keychain-developer-cert +# if: ${{ runner.os == 'Macos' }} +# uses: apple-actions/import-codesign-certs@v1 +# with: +# p12-file-base64: ${{ secrets.MACOS_CERT_P12 }} +# p12-password: ${{ secrets.MACOS_CERT_PASSPHRASE }} - name: Configure Macos keychain Installer Cert (Bash) id: macos-keychain-installer-cert if: ${{ runner.os == 'Macos' }} uses: apple-actions/import-codesign-certs@v1 with: - create-keychain: false # keychain is created in previous use of action. p12-file-base64: ${{ secrets.MACOS_CERT_INSTALLER_P12 }} p12-password: ${{ secrets.MACOS_CERT_PASSPHRASE }} From 8107bf3a6adb52551cc1ac850a159e2ae6b93915 Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Tue, 20 Dec 2022 15:15:06 +0100 Subject: [PATCH 13/22] Update cura-installer.yml --- .github/workflows/cura-installer.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/cura-installer.yml b/.github/workflows/cura-installer.yml index 3600d44a37..995e71060a 100644 --- a/.github/workflows/cura-installer.yml +++ b/.github/workflows/cura-installer.yml @@ -146,19 +146,20 @@ jobs: if: ${{ runner.os == 'Linux' }} run: echo -n "$GPG_PRIVATE_KEY" | base64 --decode | gpg --import -# - name: Configure Macos keychain Developer Cert(Bash) -# id: macos-keychain-developer-cert -# if: ${{ runner.os == 'Macos' }} -# uses: apple-actions/import-codesign-certs@v1 -# with: -# p12-file-base64: ${{ secrets.MACOS_CERT_P12 }} -# p12-password: ${{ secrets.MACOS_CERT_PASSPHRASE }} + - name: Configure Macos keychain Developer Cert(Bash) + id: macos-keychain-developer-cert + if: ${{ runner.os == 'Macos' }} + uses: apple-actions/import-codesign-certs@v1 + with: + p12-file-base64: ${{ secrets.MACOS_CERT_P12 }} + p12-password: ${{ secrets.MACOS_CERT_PASSPHRASE }} - name: Configure Macos keychain Installer Cert (Bash) id: macos-keychain-installer-cert if: ${{ runner.os == 'Macos' }} uses: apple-actions/import-codesign-certs@v1 with: + create-keychain: false # keychain is created in previous use of action. p12-file-base64: ${{ secrets.MACOS_CERT_INSTALLER_P12 }} p12-password: ${{ secrets.MACOS_CERT_PASSPHRASE }} From 0ae24cb66958a572023e119c6455a97dd2d5322f Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Tue, 20 Dec 2022 15:54:50 +0100 Subject: [PATCH 14/22] Update cura-installer.yml Use the same MacOS keychain password for both github actions. --- .github/workflows/cura-installer.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/cura-installer.yml b/.github/workflows/cura-installer.yml index 995e71060a..db80b0cf0d 100644 --- a/.github/workflows/cura-installer.yml +++ b/.github/workflows/cura-installer.yml @@ -151,6 +151,7 @@ jobs: if: ${{ runner.os == 'Macos' }} uses: apple-actions/import-codesign-certs@v1 with: + keychain-password: ${{ secrets.MACOS_KEYCHAIN_PASSWORD }} p12-file-base64: ${{ secrets.MACOS_CERT_P12 }} p12-password: ${{ secrets.MACOS_CERT_PASSPHRASE }} @@ -159,6 +160,7 @@ jobs: if: ${{ runner.os == 'Macos' }} uses: apple-actions/import-codesign-certs@v1 with: + keychain-password: ${{ secrets.MACOS_KEYCHAIN_PASSWORD }} create-keychain: false # keychain is created in previous use of action. p12-file-base64: ${{ secrets.MACOS_CERT_INSTALLER_P12 }} p12-password: ${{ secrets.MACOS_CERT_PASSPHRASE }} From 337b25b954aea0bfd45f17e5ffe8f2ebda0c9dda Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Tue, 20 Dec 2022 16:27:26 +0100 Subject: [PATCH 15/22] Update build_macos.py --- packaging/MacOs/build_macos.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/packaging/MacOs/build_macos.py b/packaging/MacOs/build_macos.py index 277a922bc6..ebb8216870 100644 --- a/packaging/MacOs/build_macos.py +++ b/packaging/MacOs/build_macos.py @@ -72,9 +72,6 @@ def build_pkg(source_path: str, dist_path: str, app_filename: str, component_fil ] subprocess.run(installer_creation_arguments) - # Remove component package so that it is not added to the output zip file - os.remove(f"{dist_path}/{component_filename}") - def code_sign(dist_path: str, filename: str) -> None: """ Sign a file using apple codesign. This uses a different certificate to package signing.""" From da061910ed300739e751314c8055e051dc2e0323 Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Mon, 9 Jan 2023 11:05:49 +0100 Subject: [PATCH 16/22] Try using new codesign identity. This is a more generic code sign identity that should work with multiple certificates. CURA-6867 --- .github/workflows/cura-installer.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cura-installer.yml b/.github/workflows/cura-installer.yml index db80b0cf0d..042bdb7c5b 100644 --- a/.github/workflows/cura-installer.yml +++ b/.github/workflows/cura-installer.yml @@ -53,7 +53,7 @@ env: CONAN_LOG_RUN_TO_OUTPUT: 1 CONAN_LOGGING_LEVEL: ${{ inputs.conan_logging_level }} CONAN_NON_INTERACTIVE: 1 - CODESIGN_IDENTITY: ${{ secrets.CODESIGN_IDENTITY }} + CODESIGN_IDENTITY: ${{ secrets.CODESIGN_IDENTITY_2 }} MAC_NOTARIZE_USER: ${{ secrets.MAC_NOTARIZE_USER }} MAC_NOTARIZE_PASS: ${{ secrets.MAC_NOTARIZE_PASS }} MACOS_CERT_P12: ${{ secrets.MACOS_CERT_P12 }} From 43b672834b23aaf75ebecc30f0de9e1a1e5e0fe2 Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Tue, 10 Jan 2023 09:29:49 +0100 Subject: [PATCH 17/22] Deprecate DMG building. CURA-6867 --- .github/workflows/cura-installer.yml | 6 ++-- packaging/MacOs/build_macos.py | 51 +++------------------------- 2 files changed, 7 insertions(+), 50 deletions(-) diff --git a/.github/workflows/cura-installer.yml b/.github/workflows/cura-installer.yml index 52220783d5..a54fb9f4b2 100644 --- a/.github/workflows/cura-installer.yml +++ b/.github/workflows/cura-installer.yml @@ -120,7 +120,7 @@ jobs: - name: Install MacOS system requirements if: ${{ runner.os == 'Macos' }} - run: brew install autoconf automake ninja create-dmg + run: brew install autoconf automake ninja - name: Install Linux system requirements if: ${{ runner.os == 'Linux' }} @@ -251,7 +251,7 @@ jobs: if "${{ runner.os }}" == "Windows": installer_ext = "msi" if "${{ inputs.msi_installer }}" == "true" else "exe" elif "${{ runner.os }}" == "macOS": - installer_ext = "dmg" + installer_ext = "pkg" else: installer_ext = "AppImage" output_env = os.environ["GITHUB_OUTPUT"] @@ -308,7 +308,7 @@ jobs: run: python ../cura_inst/packaging/AppImage/create_appimage.py ./UltiMaker-Cura $CURA_VERSION_FULL "${{ steps.filename.outputs.FULL_INSTALLER_FILENAME }}" working-directory: dist - - name: Create the MacOS dmg and/or pkg (Bash) + - name: Create the MacOS pkg (Bash) if: ${{ github.event.inputs.installer == 'true' && runner.os == 'Macos' }} run: python ../cura_inst/packaging/MacOs/build_macos.py ../cura_inst . "${{ steps.filename.outputs.FULL_INSTALLER_FILENAME }}" working-directory: dist diff --git a/packaging/MacOs/build_macos.py b/packaging/MacOs/build_macos.py index ebb8216870..e3d64199c9 100644 --- a/packaging/MacOs/build_macos.py +++ b/packaging/MacOs/build_macos.py @@ -1,4 +1,4 @@ -# Copyright (c) 2022 UltiMaker +# Copyright (c) 2023 UltiMaker # Cura is released under the terms of the LGPLv3 or higher. @@ -8,25 +8,6 @@ import subprocess ULTIMAKER_CURA_DOMAIN = os.environ.get("ULTIMAKER_CURA_DOMAIN", "nl.ultimaker.cura") - -def build_dmg(source_path: str, dist_path: str, filename: str) -> None: - create_dmg_executable = os.environ.get("CREATE_DMG_EXECUTABLE", "create-dmg") - - arguments = [create_dmg_executable, - "--window-pos", "640", "360", - "--window-size", "690", "503", - "--app-drop-link", "520", "272", - "--volicon", f"{source_path}/packaging/icons/VolumeIcons_Cura.icns", - "--icon-size", "90", - "--icon", "UltiMaker-Cura.app", "169", "272", - "--eula", f"{source_path}/packaging/cura_license.txt", - "--background", f"{source_path}/packaging/MacOs/cura_background_dmg.png", - f"{dist_path}/{filename}", - f"{dist_path}/UltiMaker-Cura.app"] - - subprocess.run(arguments) - - def build_pkg(source_path: str, dist_path: str, app_filename: str, component_filename: str, installer_filename: str) -> None: """ Builds and signs the pkg installer. @@ -123,41 +104,17 @@ def create_pkg_installer(filename: str, dist_path: str, source_path: str) -> Non code_sign(dist_path, app_name) # The app is signed using a different certificate than the package files build_pkg(source_path, dist_path, app_name, cura_component_package_name, installer_package_name) - notarize = bool(os.environ.get("NOTARIZE_PKG", "TRUE")) + notarize = bool(os.environ.get("NOTARIZE_INSTALLER", "TRUE")) if notarize: notarize_file(dist_path, installer_package_name) - -def create_dmg(filename: str, dist_path: str, source_path: str) -> None: - """ Creates a dmg executable from UltiMaker-Cura.app named {filename}.dmg - - @param filename: The name of the app file and the output dmg file without the extension - @param dist_path: The location to read the app from and save the dmg to - @param source_path: The location of the project source files - """ - - dmg_filename = f"{filename}.dmg" - - build_dmg(source_path, dist_path, dmg_filename) - - code_sign(dist_path, dmg_filename) - - notarize_dmg = bool(os.environ.get("NOTARIZE_DMG", "TRUE")) - if notarize_dmg: - notarize_file(dist_path, dmg_filename) - - if __name__ == "__main__": - parser = argparse.ArgumentParser(description = "Create dmg of Cura.") + parser = argparse.ArgumentParser(description = "Create installer for Cura.") parser.add_argument("source_path", type=str, help="Path to Conan install Cura folder.") parser.add_argument("dist_path", type=str, help="Path to Pyinstaller dist folder") - parser.add_argument("filename", type = str, help = "Filename of the dmg/pkg without the file extension (e.g. 'UltiMaker-Cura-5.1.0-beta-Macos-X64')") + parser.add_argument("filename", type = str, help = "Filename of the pkg without the file extension (e.g. 'UltiMaker-Cura-5.1.0-beta-Macos-X64')") args = parser.parse_args() build_installer = bool(os.environ.get("BUILD_INSTALLER", "TRUE")) if build_installer: create_pkg_installer(args.filename, args.dist_path, args.source_path) - - build_dmg_executable = bool(os.environ.get("BUILD_DMG", "False")) - if build_dmg_executable: - create_dmg(args.filename, args.dist_path, args.source_path) From b96c0dce39fcd0fdab66118a49e7c30a8c146b54 Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Tue, 10 Jan 2023 10:11:27 +0100 Subject: [PATCH 18/22] Remove source path from build_macos.py because it is unused. Refactor filename because it now includes the extension. The component now has -Component.pkg instead of the installer usincg -Installer.pkg. They must have different names but now the input filename is used to upload the artifacts. CURA-6867 --- .github/workflows/cura-installer.yml | 2 +- packaging/MacOs/build_macos.py | 21 ++++++++++----------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/.github/workflows/cura-installer.yml b/.github/workflows/cura-installer.yml index a54fb9f4b2..1c3490df40 100644 --- a/.github/workflows/cura-installer.yml +++ b/.github/workflows/cura-installer.yml @@ -310,7 +310,7 @@ jobs: - name: Create the MacOS pkg (Bash) if: ${{ github.event.inputs.installer == 'true' && runner.os == 'Macos' }} - run: python ../cura_inst/packaging/MacOs/build_macos.py ../cura_inst . "${{ steps.filename.outputs.FULL_INSTALLER_FILENAME }}" + run: python ../cura_inst/packaging/MacOs/build_macos.py . "${{ steps.filename.outputs.FULL_INSTALLER_FILENAME }}" working-directory: dist - name: Upload the artifacts diff --git a/packaging/MacOs/build_macos.py b/packaging/MacOs/build_macos.py index e3d64199c9..e355cc6861 100644 --- a/packaging/MacOs/build_macos.py +++ b/packaging/MacOs/build_macos.py @@ -5,13 +5,13 @@ import os import argparse # Command line arguments parsing and help. import subprocess +from pathlib import Path ULTIMAKER_CURA_DOMAIN = os.environ.get("ULTIMAKER_CURA_DOMAIN", "nl.ultimaker.cura") -def build_pkg(source_path: str, dist_path: str, app_filename: str, component_filename: str, installer_filename: str) -> None: +def build_pkg(dist_path: str, app_filename: str, component_filename: str, installer_filename: str) -> None: """ Builds and signs the pkg installer. - @param source_path: Path to folder containing source files @param dist_path: Path to put output pkg in @param app_filename: name of the .app file to bundle inside the pkg @param component_filename: Name of the pkg component package to bundle the app in @@ -86,7 +86,7 @@ def notarize_file(dist_path: str, filename: str) -> None: subprocess.run(notarize_arguments) -def create_pkg_installer(filename: str, dist_path: str, source_path: str) -> None: +def create_pkg_installer(filename: str, dist_path: str) -> None: """ Creates a pkg installer from {filename}.app called {filename}-Installer.pkg The final package structure is UltiMaker-Cura-XXX-Installer.pkg[UltiMaker-Cura.pkg[UltiMaker-Cura.app]]. The outer @@ -95,26 +95,25 @@ def create_pkg_installer(filename: str, dist_path: str, source_path: str) -> Non @param filename: The name of the app file and the app component package file without the extension @param dist_path: The location to read the app from and save the pkg to - @param source_path: The location of the project source files """ - installer_package_name = f"{filename}-Installer.pkg" - cura_component_package_name = f"{filename}.pkg" # This is a component package that is nested inside the installer, it contains the UltiMaker-Cura.app file + + filename_stem = Path(filename).stem + cura_component_package_name = f"{filename_stem}-Component.pkg" # This is a component package that is nested inside the installer, it contains the UltiMaker-Cura.app file app_name = "UltiMaker-Cura.app" # This is the app file that will end up in your applications folder code_sign(dist_path, app_name) # The app is signed using a different certificate than the package files - build_pkg(source_path, dist_path, app_name, cura_component_package_name, installer_package_name) + build_pkg(dist_path, app_name, cura_component_package_name, filename) notarize = bool(os.environ.get("NOTARIZE_INSTALLER", "TRUE")) if notarize: - notarize_file(dist_path, installer_package_name) + notarize_file(dist_path, filename) if __name__ == "__main__": parser = argparse.ArgumentParser(description = "Create installer for Cura.") - parser.add_argument("source_path", type=str, help="Path to Conan install Cura folder.") parser.add_argument("dist_path", type=str, help="Path to Pyinstaller dist folder") - parser.add_argument("filename", type = str, help = "Filename of the pkg without the file extension (e.g. 'UltiMaker-Cura-5.1.0-beta-Macos-X64')") + parser.add_argument("filename", type = str, help = "Filename of the pkg (e.g. 'UltiMaker-Cura-5.1.0-beta-Macos-X64.pkg')") args = parser.parse_args() build_installer = bool(os.environ.get("BUILD_INSTALLER", "TRUE")) if build_installer: - create_pkg_installer(args.filename, args.dist_path, args.source_path) + create_pkg_installer(args.filename, args.dist_path) From ddb4547598bf658d143ee65d8f2e79705f89595a Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Wed, 11 Jan 2023 11:57:51 +0100 Subject: [PATCH 19/22] Use path to join paths CURA-6867 --- .github/workflows/cura-installer.yml | 2 +- packaging/MacOs/build_macos.py | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.github/workflows/cura-installer.yml b/.github/workflows/cura-installer.yml index 1c3490df40..0dc22f5f1e 100644 --- a/.github/workflows/cura-installer.yml +++ b/.github/workflows/cura-installer.yml @@ -58,7 +58,7 @@ env: CONAN_LOG_RUN_TO_OUTPUT: 1 CONAN_LOGGING_LEVEL: ${{ inputs.conan_logging_level }} CONAN_NON_INTERACTIVE: 1 - CODESIGN_IDENTITY: ${{ secrets.CODESIGN_IDENTITY_2 }} + CODESIGN_IDENTITY: ${{ secrets.CODESIGN_IDENTITY }} MAC_NOTARIZE_USER: ${{ secrets.MAC_NOTARIZE_USER }} MAC_NOTARIZE_PASS: ${{ secrets.MAC_NOTARIZE_PASS }} MACOS_CERT_P12: ${{ secrets.MACOS_CERT_P12 }} diff --git a/packaging/MacOs/build_macos.py b/packaging/MacOs/build_macos.py index e355cc6861..54694afcff 100644 --- a/packaging/MacOs/build_macos.py +++ b/packaging/MacOs/build_macos.py @@ -25,8 +25,8 @@ def build_pkg(dist_path: str, app_filename: str, component_filename: str, instal pkg_build_arguments = [ pkg_build_executable, "--component", - f"{dist_path}/{app_filename}", - f"{dist_path}/{component_filename}", + Path(dist_path, app_filename), + Path(dist_path, component_filename), "--sign", codesign_identity, "--install-location", "/Applications", ] @@ -38,18 +38,18 @@ def build_pkg(dist_path: str, app_filename: str, component_filename: str, instal distribution_creation_arguments = [ product_build_executable, "--synthesize", - "--package", f"{dist_path}/{component_filename}", # Package that will be inside installer - f"{dist_path}/distribution.xml", # Output location for sythesized distributions file + "--package", Path(dist_path, component_filename), # Package that will be inside installer + Path(dist_path, "distribution.xml"), # Output location for sythesized distributions file ] subprocess.run(distribution_creation_arguments) # This creates the distributable package (Installer) installer_creation_arguments = [ product_build_executable, - "--distribution", f"{dist_path}/distribution.xml", + "--distribution", Path(dist_path, "distribution.xml"), "--package-path", dist_path, # Where to find the component packages mentioned in distribution.xml (UltiMaker-Cura.pkg) "--sign", codesign_identity, - f"{dist_path}/{installer_filename}", + Path(dist_path, installer_filename), ] subprocess.run(installer_creation_arguments) @@ -63,7 +63,8 @@ def code_sign(dist_path: str, filename: str) -> None: "-s", codesign_identity, "--timestamp", "-i", filename, # This is by default derived from Info.plist or the filename. The documentation does not specify which, so it is explicit here. **This must be unique in the package** - f"{dist_path}/{filename}"] + Path(dist_path, filename) + ] subprocess.run(sign_arguments) @@ -80,7 +81,7 @@ def notarize_file(dist_path: str, filename: str) -> None: "--primary-bundle-id", ULTIMAKER_CURA_DOMAIN, "--username", notarize_user, "--password", notarize_password, - "--file", f"{dist_path}/{filename}" + "--file", Path(dist_path, filename) ] subprocess.run(notarize_arguments) From a80390efb3f59c92a8594f075ee751469bd3ba1c Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Wed, 11 Jan 2023 12:07:12 +0100 Subject: [PATCH 20/22] Make building easier without signing identity. CURA-6867 --- packaging/MacOs/build_macos.py | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/packaging/MacOs/build_macos.py b/packaging/MacOs/build_macos.py index 54694afcff..018b2fa750 100644 --- a/packaging/MacOs/build_macos.py +++ b/packaging/MacOs/build_macos.py @@ -27,9 +27,14 @@ def build_pkg(dist_path: str, app_filename: str, component_filename: str, instal "--component", Path(dist_path, app_filename), Path(dist_path, component_filename), - "--sign", codesign_identity, "--install-location", "/Applications", ] + + if codesign_identity: + pkg_build_arguments.extend(["--sign", codesign_identity]) + else: + print("CODESIGN_IDENTITY missing. The installer is not being signed") + subprocess.run(pkg_build_arguments) # This automatically generates a distribution.xml file that is used to build the installer. @@ -48,27 +53,15 @@ def build_pkg(dist_path: str, app_filename: str, component_filename: str, instal product_build_executable, "--distribution", Path(dist_path, "distribution.xml"), "--package-path", dist_path, # Where to find the component packages mentioned in distribution.xml (UltiMaker-Cura.pkg) - "--sign", codesign_identity, Path(dist_path, installer_filename), ] + + if codesign_identity: + installer_creation_arguments.extend(["--sign", codesign_identity]) + subprocess.run(installer_creation_arguments) -def code_sign(dist_path: str, filename: str) -> None: - """ Sign a file using apple codesign. This uses a different certificate to package signing.""" - codesign_executable = os.environ.get("CODESIGN", "codesign") - codesign_identity = os.environ.get("CODESIGN_IDENTITY") - - sign_arguments = [codesign_executable, - "-s", codesign_identity, - "--timestamp", - "-i", filename, # This is by default derived from Info.plist or the filename. The documentation does not specify which, so it is explicit here. **This must be unique in the package** - Path(dist_path, filename) - ] - - subprocess.run(sign_arguments) - - def notarize_file(dist_path: str, filename: str) -> None: """ Notarize a file. This takes 5+ minutes, there is indication that this step is successful.""" notarize_user = os.environ.get("MAC_NOTARIZE_USER") @@ -87,7 +80,7 @@ def notarize_file(dist_path: str, filename: str) -> None: subprocess.run(notarize_arguments) -def create_pkg_installer(filename: str, dist_path: str) -> None: +def create_pkg_installer(filename: str, dist_path: str) -> None: """ Creates a pkg installer from {filename}.app called {filename}-Installer.pkg The final package structure is UltiMaker-Cura-XXX-Installer.pkg[UltiMaker-Cura.pkg[UltiMaker-Cura.app]]. The outer @@ -102,10 +95,9 @@ def create_pkg_installer(filename: str, dist_path: str) -> None: cura_component_package_name = f"{filename_stem}-Component.pkg" # This is a component package that is nested inside the installer, it contains the UltiMaker-Cura.app file app_name = "UltiMaker-Cura.app" # This is the app file that will end up in your applications folder - code_sign(dist_path, app_name) # The app is signed using a different certificate than the package files build_pkg(dist_path, app_name, cura_component_package_name, filename) - notarize = bool(os.environ.get("NOTARIZE_INSTALLER", "TRUE")) + notarize = bool(os.environ.get("NOTARIZE_INSTALLER", "FALSE")) if notarize: notarize_file(dist_path, filename) From 11b2c949885b5d0ae77a32c3ea34823d203c8f47 Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Wed, 11 Jan 2023 13:03:16 +0100 Subject: [PATCH 21/22] Remove build installer check. CURA-6867 --- packaging/MacOs/build_macos.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packaging/MacOs/build_macos.py b/packaging/MacOs/build_macos.py index 018b2fa750..b8513cb069 100644 --- a/packaging/MacOs/build_macos.py +++ b/packaging/MacOs/build_macos.py @@ -107,6 +107,4 @@ if __name__ == "__main__": parser.add_argument("filename", type = str, help = "Filename of the pkg (e.g. 'UltiMaker-Cura-5.1.0-beta-Macos-X64.pkg')") args = parser.parse_args() - build_installer = bool(os.environ.get("BUILD_INSTALLER", "TRUE")) - if build_installer: - create_pkg_installer(args.filename, args.dist_path) + create_pkg_installer(args.filename, args.dist_path) From 9ae3bc37dc274a6b856b12fcecabffb8db83a5df Mon Sep 17 00:00:00 2001 From: Joey de l'Arago Date: Wed, 11 Jan 2023 13:27:26 +0100 Subject: [PATCH 22/22] Rename MacOs -> MacOS CURA-6867 --- .github/workflows/cura-all-installers.yml | 2 +- .github/workflows/cura-installer.yml | 2 +- conanfile.py | 4 ++-- packaging/{MacOs => MacOS}/build_macos.py | 2 +- packaging/{MacOs => MacOS}/cura.entitlements | 0 packaging/{MacOs => MacOS}/cura_background_dmg.png | Bin 6 files changed, 5 insertions(+), 5 deletions(-) rename packaging/{MacOs => MacOS}/build_macos.py (98%) rename packaging/{MacOs => MacOS}/cura.entitlements (100%) rename packaging/{MacOs => MacOS}/cura_background_dmg.png (100%) diff --git a/.github/workflows/cura-all-installers.yml b/.github/workflows/cura-all-installers.yml index 34ccffe54b..b024d035a5 100644 --- a/.github/workflows/cura-all-installers.yml +++ b/.github/workflows/cura-all-installers.yml @@ -50,7 +50,7 @@ on: required: true type: boolean build_macos: - description: 'Build for MacOs' + description: 'Build for MacOS' default: true required: true type: boolean diff --git a/.github/workflows/cura-installer.yml b/.github/workflows/cura-installer.yml index 0dc22f5f1e..fef4547891 100644 --- a/.github/workflows/cura-installer.yml +++ b/.github/workflows/cura-installer.yml @@ -310,7 +310,7 @@ jobs: - name: Create the MacOS pkg (Bash) if: ${{ github.event.inputs.installer == 'true' && runner.os == 'Macos' }} - run: python ../cura_inst/packaging/MacOs/build_macos.py . "${{ steps.filename.outputs.FULL_INSTALLER_FILENAME }}" + run: python ../cura_inst/packaging/MacOS/build_macos.py . "${{ steps.filename.outputs.FULL_INSTALLER_FILENAME }}" working-directory: dist - name: Upload the artifacts diff --git a/conanfile.py b/conanfile.py index b1ca074d74..9a2c1773ed 100644 --- a/conanfile.py +++ b/conanfile.py @@ -317,7 +317,7 @@ class CuraConan(ConanFile): self._generate_cura_version(Path(self.source_folder, "cura")) if self.options.devtools: - entitlements_file = "'{}'".format(Path(self.source_folder, "packaging", "MacOs", "cura.entitlements")) + entitlements_file = "'{}'".format(Path(self.source_folder, "packaging", "MacOS", "cura.entitlements")) self._generate_pyinstaller_spec(location = self.generators_folder, entrypoint_location = "'{}'".format(Path(self.source_folder, self._um_data()["runinfo"]["entrypoint"])).replace("\\", "\\\\"), icon_path = "'{}'".format(Path(self.source_folder, "packaging", self._um_data()["pyinstaller"]["icon"][str(self.settings.os)])).replace("\\", "\\\\"), @@ -445,7 +445,7 @@ echo "CURA_APP_NAME={{ cura_app_name }}" >> ${{ env_prefix }}GITHUB_ENV self._generate_cura_version(Path(self._site_packages, "cura")) - entitlements_file = "'{}'".format(Path(self.cpp_info.res_paths[2], "MacOs", "cura.entitlements")) + entitlements_file = "'{}'".format(Path(self.cpp_info.res_paths[2], "MacOS", "cura.entitlements")) self._generate_pyinstaller_spec(location = self._base_dir, entrypoint_location = "'{}'".format(Path(self.cpp_info.bin_paths[0], self._um_data()["runinfo"]["entrypoint"])).replace("\\", "\\\\"), icon_path = "'{}'".format(Path(self.cpp_info.res_paths[2], self._um_data()["pyinstaller"]["icon"][str(self.settings.os)])).replace("\\", "\\\\"), diff --git a/packaging/MacOs/build_macos.py b/packaging/MacOS/build_macos.py similarity index 98% rename from packaging/MacOs/build_macos.py rename to packaging/MacOS/build_macos.py index b8513cb069..06880cf9b7 100644 --- a/packaging/MacOs/build_macos.py +++ b/packaging/MacOS/build_macos.py @@ -103,7 +103,7 @@ def create_pkg_installer(filename: str, dist_path: str) -> None: if __name__ == "__main__": parser = argparse.ArgumentParser(description = "Create installer for Cura.") - parser.add_argument("dist_path", type=str, help="Path to Pyinstaller dist folder") + parser.add_argument("dist_path", type = str, help="Path to Pyinstaller dist folder") parser.add_argument("filename", type = str, help = "Filename of the pkg (e.g. 'UltiMaker-Cura-5.1.0-beta-Macos-X64.pkg')") args = parser.parse_args() diff --git a/packaging/MacOs/cura.entitlements b/packaging/MacOS/cura.entitlements similarity index 100% rename from packaging/MacOs/cura.entitlements rename to packaging/MacOS/cura.entitlements diff --git a/packaging/MacOs/cura_background_dmg.png b/packaging/MacOS/cura_background_dmg.png similarity index 100% rename from packaging/MacOs/cura_background_dmg.png rename to packaging/MacOS/cura_background_dmg.png