From 4b2f5c158e7ae53cb2a43516fc326968bccc4d29 Mon Sep 17 00:00:00 2001 From: alves Date: Wed, 28 Jan 2026 15:44:35 +0800 Subject: [PATCH 01/12] feature build the app and signs it for all mac os application. --- .github/workflows/build_orca.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build_orca.yml b/.github/workflows/build_orca.yml index 6599f4e4de..867a7b2954 100644 --- a/.github/workflows/build_orca.yml +++ b/.github/workflows/build_orca.yml @@ -122,7 +122,8 @@ jobs: # Thanks to RaySajuuk, it's working now - name: Sign app and notary - if: (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') || github.ref == 'refs/heads/2.2.0') && inputs.os == 'macos-14' + #if: (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') || github.ref == 'refs/heads/2.2.0') && inputs.os == 'macos-14' + if: inputs.os == 'macos-14' working-directory: ${{ github.workspace }} env: BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} From 1044e770b6022e4e87d0e292fa7274a3ad76828d Mon Sep 17 00:00:00 2001 From: alves Date: Wed, 28 Jan 2026 18:52:41 +0800 Subject: [PATCH 02/12] feature signs app and don't signs dmg. --- .github/workflows/build_orca.yml | 124 +++++++++++++++++++++++++++++-- 1 file changed, 119 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build_orca.yml b/.github/workflows/build_orca.yml index 867a7b2954..54ff24e5d2 100644 --- a/.github/workflows/build_orca.yml +++ b/.github/workflows/build_orca.yml @@ -140,10 +140,108 @@ jobs: security import $CERTIFICATE_PATH -P $P12_PASSWORD -A -t cert -f pkcs12 -k $KEYCHAIN_PATH security list-keychain -d user -s $KEYCHAIN_PATH security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $P12_PASSWORD $KEYCHAIN_PATH - codesign --deep --force --verbose --options runtime --timestamp --entitlements ${{ github.workspace }}/scripts/disable_validation.entitlements --sign "$CERTIFICATE_ID" "${{ github.workspace }}/build/universal/Snapmaker_Orca/Snapmaker Orca.app" + + # Sign app with proper recursive signing (not using --deep) + APP_PATH="${{ github.workspace }}/build/universal/Snapmaker_Orca/Snapmaker Orca.app" + ENTITLEMENTS_PATH="${{ github.workspace }}/scripts/disable_validation.entitlements" + + # Verify entitlements file exists + if [ ! -f "$ENTITLEMENTS_PATH" ]; then + echo "Error: Entitlements file not found: $ENTITLEMENTS_PATH" + exit 1 + fi + echo "Using entitlements: $ENTITLEMENTS_PATH" + + # Sign Frameworks (must succeed, no silent failures) + echo "Signing Frameworks..." + if [ -d "$APP_PATH/Contents/Frameworks" ]; then + find "$APP_PATH/Contents/Frameworks" -name "*.dylib" -o -name "*.framework" | while read -r item; do + if [ -f "$item" ] || [ -d "$item" ]; then + echo " Signing: $item" + codesign --force --verbose --options runtime --timestamp --sign "$CERTIFICATE_ID" "$item" || { + echo "Error: Failed to sign $item" + exit 1 + } + fi + done + fi + + # Sign MacOS executables (must succeed, no silent failures) + echo "Signing MacOS executables..." + if [ -d "$APP_PATH/Contents/MacOS" ]; then + find "$APP_PATH/Contents/MacOS" -type f -perm +111 | while read -r item; do + echo " Signing: $item" + codesign --force --verbose --options runtime --timestamp --sign "$CERTIFICATE_ID" "$item" || { + echo "Error: Failed to sign $item" + exit 1 + } + done + fi + + # Sign main app with entitlements + echo "Signing main app with entitlements..." + codesign --force --verbose --options runtime --timestamp --entitlements "$ENTITLEMENTS_PATH" --sign "$CERTIFICATE_ID" "$APP_PATH" || { + echo "Error: Failed to sign main app" + exit 1 + } + + # Verify signature + echo "Verifying signature..." + codesign --verify --verbose "$APP_PATH" || { + echo "Error: Signature verification failed" + exit 1 + } + + # Verify entitlements are embedded + echo "Verifying entitlements are embedded..." + EMBEDDED_ENTITLEMENTS=$(codesign -d --entitlements - "$APP_PATH" 2>&1) + if echo "$EMBEDDED_ENTITLEMENTS" | grep -q "com.apple.security.network.client"; then + echo "✓ Entitlements successfully embedded" + echo " Found network.client entitlement" + else + echo "✗ Error: Entitlements not embedded correctly" + echo " Embedded entitlements output:" + echo "$EMBEDDED_ENTITLEMENTS" | head -20 + exit 1 + fi + # Sign Snapmaker_Orca_profile_validator.app if it exists - if [ -f "${{ github.workspace }}/build/universal/Snapmaker_Orca/Snapmaker_Orca_profile_validator.app/Contents/MacOS/Snapmaker_Orca_profile_validator" ]; then - codesign --deep --force --verbose --options runtime --timestamp --entitlements ${{ github.workspace }}/scripts/disable_validation.entitlements --sign "$CERTIFICATE_ID" ${{ github.workspace }}/build/universal/Snapmaker_Orca/Snapmaker_Orca_profile_validator.app + VALIDATOR_APP_PATH="${{ github.workspace }}/build/universal/Snapmaker_Orca/Snapmaker_Orca_profile_validator.app" + if [ -f "$VALIDATOR_APP_PATH/Contents/MacOS/Snapmaker_Orca_profile_validator" ]; then + echo "Signing Snapmaker_Orca_profile_validator.app..." + + # Sign validator app components + if [ -d "$VALIDATOR_APP_PATH/Contents/Frameworks" ]; then + find "$VALIDATOR_APP_PATH/Contents/Frameworks" -name "*.dylib" -o -name "*.framework" | while read -r item; do + if [ -f "$item" ] || [ -d "$item" ]; then + codesign --force --verbose --options runtime --timestamp --sign "$CERTIFICATE_ID" "$item" || { + echo "Error: Failed to sign validator component $item" + exit 1 + } + fi + done + fi + + if [ -d "$VALIDATOR_APP_PATH/Contents/MacOS" ]; then + find "$VALIDATOR_APP_PATH/Contents/MacOS" -type f -perm +111 | while read -r item; do + codesign --force --verbose --options runtime --timestamp --sign "$CERTIFICATE_ID" "$item" || { + echo "Error: Failed to sign validator executable $item" + exit 1 + } + done + fi + + # Sign main validator app with entitlements + codesign --force --verbose --options runtime --timestamp --entitlements "$ENTITLEMENTS_PATH" --sign "$CERTIFICATE_ID" "$VALIDATOR_APP_PATH" || { + echo "Error: Failed to sign validator app" + exit 1 + } + + # Verify validator signature + codesign --verify --verbose "$VALIDATOR_APP_PATH" || { + echo "Error: Validator signature verification failed" + exit 1 + } fi # Create main Snapmaker Orca DMG without the profile validator helper @@ -152,7 +250,15 @@ jobs: cp -R "${{ github.workspace }}/build/universal/Snapmaker_Orca/Snapmaker Orca.app" "${{ github.workspace }}/build/universal/Snapmaker_Orca_dmg/" ln -sfn /Applications ${{ github.workspace }}/build/universal/Snapmaker_Orca_dmg/Applications hdiutil create -volname "Snapmaker_Orca" -srcfolder ${{ github.workspace }}/build/universal/Snapmaker_Orca_dmg -ov -format UDZO "${{ github.workspace }}/Snapmaker_Orca_Mac_universal_${{ env.ver }}.dmg" - codesign --deep --force --verbose --options runtime --timestamp --entitlements ${{ github.workspace }}/scripts/disable_validation.entitlements --sign "$CERTIFICATE_ID" "${{ github.workspace }}/Snapmaker_Orca_Mac_universal_${{ env.ver }}.dmg" + # Sign DMG (DMG files should NOT have entitlements, only signature) + codesign --force --verbose --options runtime --timestamp --sign "$CERTIFICATE_ID" "${{ github.workspace }}/Snapmaker_Orca_Mac_universal_${{ env.ver }}.dmg" || { + echo "Error: Failed to sign DMG" + exit 1 + } + codesign --verify --verbose "${{ github.workspace }}/Snapmaker_Orca_Mac_universal_${{ env.ver }}.dmg" || { + echo "Error: DMG signature verification failed" + exit 1 + } # Create separate Snapmaker_Orca_profile_validator DMG if the app exists if [ -f "${{ github.workspace }}/build/universal/Snapmaker_Orca/Snapmaker_Orca_profile_validator.app/Contents/MacOS/Snapmaker_Orca_profile_validator" ]; then @@ -161,7 +267,15 @@ jobs: cp -R ${{ github.workspace }}/build/universal/Snapmaker_Orca/Snapmaker_Orca_profile_validator.app ${{ github.workspace }}/build/universal/Snapmaker_Orca_profile_validator_dmg/ ln -sfn /Applications ${{ github.workspace }}/build/universal/Snapmaker_Orca_profile_validator_dmg/Applications hdiutil create -volname "Snapmaker_Orca Profile Validator" -srcfolder ${{ github.workspace }}/build/universal/Snapmaker_Orca_profile_validator_dmg -ov -format UDZO "${{ github.workspace }}/Snapmaker_Orca_profile_validator_Mac_universal_${{ env.ver }}.dmg" - codesign --deep --force --verbose --options runtime --timestamp --entitlements ${{ github.workspace }}/scripts/disable_validation.entitlements --sign "$CERTIFICATE_ID" "${{ github.workspace }}/Snapmaker_Orca_profile_validator_Mac_universal_${{ env.ver }}.dmg" + # Sign DMG (DMG files should NOT have entitlements, only signature) + codesign --force --verbose --options runtime --timestamp --sign "$CERTIFICATE_ID" "${{ github.workspace }}/Snapmaker_Orca_profile_validator_Mac_universal_${{ env.ver }}.dmg" || { + echo "Error: Failed to sign validator DMG" + exit 1 + } + codesign --verify --verbose "${{ github.workspace }}/Snapmaker_Orca_profile_validator_Mac_universal_${{ env.ver }}.dmg" || { + echo "Error: Validator DMG signature verification failed" + exit 1 + } fi # Notarize main DMG From 82f733d0b8ce1bca3802fc0514f7da867d41d220 Mon Sep 17 00:00:00 2001 From: alves Date: Thu, 29 Jan 2026 10:43:57 +0800 Subject: [PATCH 03/12] fix bundle id invalid question. --- scripts/disable_validation.entitlements | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/disable_validation.entitlements b/scripts/disable_validation.entitlements index d2fae18a76..efb0a4fa02 100644 --- a/scripts/disable_validation.entitlements +++ b/scripts/disable_validation.entitlements @@ -4,7 +4,7 @@ com.apple.application-identifier - 5NGD3B3V37.snapmaker-orca + 5NGD3B3V37.com.snapmaker.snapmaker-orca com.apple.developer.team-identifier 5NGD3B3V37 From 1f87a1426dc67947a47c768a47feb36954b32001 Mon Sep 17 00:00:00 2001 From: alves Date: Thu, 29 Jan 2026 15:10:23 +0800 Subject: [PATCH 04/12] feature remove the entitlements data for cert. --- scripts/disable_validation.entitlements | 7 ------- 1 file changed, 7 deletions(-) diff --git a/scripts/disable_validation.entitlements b/scripts/disable_validation.entitlements index efb0a4fa02..3c4a47a251 100644 --- a/scripts/disable_validation.entitlements +++ b/scripts/disable_validation.entitlements @@ -2,13 +2,6 @@ - - com.apple.application-identifier - 5NGD3B3V37.com.snapmaker.snapmaker-orca - com.apple.developer.team-identifier - 5NGD3B3V37 - - com.apple.security.cs.disable-library-validation com.apple.runningboard.assertions.webkit From 3f03f9e682326a5418a8addc401b47cde5d7e7bf Mon Sep 17 00:00:00 2001 From: alves Date: Thu, 29 Jan 2026 15:19:45 +0800 Subject: [PATCH 05/12] feature add option runtime,hardened runtime for application. --- .github/workflows/build_orca.yml | 39 ++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/.github/workflows/build_orca.yml b/.github/workflows/build_orca.yml index 54ff24e5d2..8b599d7cf0 100644 --- a/.github/workflows/build_orca.yml +++ b/.github/workflows/build_orca.yml @@ -192,6 +192,18 @@ jobs: exit 1 } + # Verify Hardened Runtime is enabled + echo "Verifying Hardened Runtime is enabled..." + RUNTIME_CHECK=$(codesign -d --verbose=4 "$APP_PATH" 2>&1 | grep -i "runtime" || true) + if echo "$RUNTIME_CHECK" | grep -qi "runtime"; then + echo "✓ Hardened Runtime is enabled" + echo " Runtime flags: $RUNTIME_CHECK" + else + echo "✗ Warning: Hardened Runtime status not clearly visible in signature" + echo " Checking signature details..." + codesign -d --verbose=4 "$APP_PATH" 2>&1 | head -30 + fi + # Verify entitlements are embedded echo "Verifying entitlements are embedded..." EMBEDDED_ENTITLEMENTS=$(codesign -d --entitlements - "$APP_PATH" 2>&1) @@ -242,6 +254,15 @@ jobs: echo "Error: Validator signature verification failed" exit 1 } + + # Verify Hardened Runtime is enabled for validator + echo "Verifying Hardened Runtime for validator app..." + VALIDATOR_RUNTIME_CHECK=$(codesign -d --verbose=4 "$VALIDATOR_APP_PATH" 2>&1 | grep -i "runtime" || true) + if echo "$VALIDATOR_RUNTIME_CHECK" | grep -qi "runtime"; then + echo "✓ Hardened Runtime is enabled for validator app" + else + echo "⚠ Warning: Hardened Runtime status not clearly visible for validator" + fi fi # Create main Snapmaker Orca DMG without the profile validator helper @@ -260,6 +281,15 @@ jobs: exit 1 } + # Verify Hardened Runtime for DMG + echo "Verifying Hardened Runtime for DMG..." + DMG_RUNTIME_CHECK=$(codesign -d --verbose=4 "${{ github.workspace }}/Snapmaker_Orca_Mac_universal_${{ env.ver }}.dmg" 2>&1 | grep -i "runtime" || true) + if echo "$DMG_RUNTIME_CHECK" | grep -qi "runtime"; then + echo "✓ Hardened Runtime is enabled for DMG" + else + echo "⚠ Note: DMG files typically don't show runtime flags in the same way as apps" + fi + # Create separate Snapmaker_Orca_profile_validator DMG if the app exists if [ -f "${{ github.workspace }}/build/universal/Snapmaker_Orca/Snapmaker_Orca_profile_validator.app/Contents/MacOS/Snapmaker_Orca_profile_validator" ]; then mkdir -p ${{ github.workspace }}/build/universal/Snapmaker_Orca_profile_validator_dmg @@ -276,6 +306,15 @@ jobs: echo "Error: Validator DMG signature verification failed" exit 1 } + + # Verify Hardened Runtime for validator DMG + echo "Verifying Hardened Runtime for validator DMG..." + VALIDATOR_DMG_RUNTIME_CHECK=$(codesign -d --verbose=4 "${{ github.workspace }}/Snapmaker_Orca_profile_validator_Mac_universal_${{ env.ver }}.dmg" 2>&1 | grep -i "runtime" || true) + if echo "$VALIDATOR_DMG_RUNTIME_CHECK" | grep -qi "runtime"; then + echo "✓ Hardened Runtime is enabled for validator DMG" + else + echo "⚠ Note: DMG files typically don't show runtime flags in the same way as apps" + fi fi # Notarize main DMG From 734c80fd016693624a8000179d7f6ff40c2a4a5b Mon Sep 17 00:00:00 2001 From: alves Date: Thu, 29 Jan 2026 15:46:46 +0800 Subject: [PATCH 06/12] feature add test code for signs. --- .github/workflows/build_orca.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build_orca.yml b/.github/workflows/build_orca.yml index 8b599d7cf0..af9fd9b5c7 100644 --- a/.github/workflows/build_orca.yml +++ b/.github/workflows/build_orca.yml @@ -329,7 +329,8 @@ jobs: fi - name: Create DMG without notary - if: github.ref != 'refs/heads/main' && inputs.os == 'macos-14' && github.ref != 'refs/heads/2.2.0' + #if: github.ref != 'refs/heads/main' && inputs.os == 'macos-14' && github.ref != 'refs/heads/2.2.0' + if: github.ref == 'refs/heads/main' && inputs.os == 'macos-14' working-directory: ${{ github.workspace }} run: | mkdir -p ${{ github.workspace }}/build/universal/Snapmaker_Orca_dmg From 2825eeebcc078f047bea3a75cc2fe30f2cf87048 Mon Sep 17 00:00:00 2001 From: alves Date: Fri, 30 Jan 2026 14:07:25 +0800 Subject: [PATCH 07/12] feature add file download, file view ,cancel download on wcp, and control on wcpdownloadmanager. --- src/slic3r/CMakeLists.txt | 2 + src/slic3r/GUI/GUI.cpp | 14 ++ src/slic3r/GUI/GUI.hpp | 3 + src/slic3r/GUI/GUI_App.cpp | 7 + src/slic3r/GUI/GUI_App.hpp | 3 + src/slic3r/GUI/SSWCP.cpp | 111 +++++++++++ src/slic3r/GUI/SSWCP.hpp | 8 + src/slic3r/GUI/WCPDownloadManager.cpp | 276 ++++++++++++++++++++++++++ src/slic3r/GUI/WCPDownloadManager.hpp | 104 ++++++++++ 9 files changed, 528 insertions(+) create mode 100644 src/slic3r/GUI/WCPDownloadManager.cpp create mode 100644 src/slic3r/GUI/WCPDownloadManager.hpp diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 28596e3fb9..e74b6c66ed 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -504,6 +504,8 @@ set(SLIC3R_GUI_SOURCES GUI/SMPhysicalPrinterDialog.cpp GUI/SSWCP.cpp GUI/SSWCP.hpp + GUI/WCPDownloadManager.cpp + GUI/WCPDownloadManager.hpp GUI/WebPresetDialog.hpp GUI/WebPresetDialog.cpp GUI/WebSMUserLoginDialog.cpp diff --git a/src/slic3r/GUI/GUI.cpp b/src/slic3r/GUI/GUI.cpp index 6b338b5f03..5b6b619e86 100644 --- a/src/slic3r/GUI/GUI.cpp +++ b/src/slic3r/GUI/GUI.cpp @@ -549,6 +549,20 @@ void desktop_open_datadir_folder() #endif } +void desktop_open_any_folderEx(const std::string& path) +{ +#ifdef _WIN32 + // Convert path to Windows format (backslashes) and ensure it's properly quoted + boost::filesystem::path file_path(path); + file_path.make_preferred(); // Convert forward slashes to backslashes + wxString widepath = from_path(file_path); + // Quote the path to handle spaces and special characters + wxString cmd = L"explorer /select,\"" + widepath + L"\""; + ::wxExecute(cmd, wxEXEC_ASYNC, nullptr); +#else + desktop_open_any_folder(path); +#endif +} void desktop_open_any_folder( const std::string& path ) { // Execute command to open a file explorer, platform dependent. diff --git a/src/slic3r/GUI/GUI.hpp b/src/slic3r/GUI/GUI.hpp index db8cf06a61..acceaa8e4f 100644 --- a/src/slic3r/GUI/GUI.hpp +++ b/src/slic3r/GUI/GUI.hpp @@ -84,6 +84,9 @@ extern void login(); extern void desktop_open_datadir_folder(); // Ask the destop to open one folder extern void desktop_open_any_folder(const std::string& path); + +//open dir and select the file to show +extern void desktop_open_any_folderEx(const std::string& path); } // namespace GUI } // namespace Slic3r diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index efc2846661..5d8b699e55 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -13,6 +13,7 @@ #include "slic3r/GUI/WebPresetDialog.hpp" #include "slic3r/GUI/SSWCP.hpp" +#include "slic3r/GUI/WCPDownloadManager.hpp" #include "slic3r/Utils/PresetUpdater.hpp" #include "slic3r/Config/Version.hpp" @@ -1061,6 +1062,7 @@ GUI_App::GUI_App() , m_imgui(new ImGuiWrapper()) , m_removable_drive_manager(std::make_unique()) , m_downloader(std::make_unique()) + , m_wcp_download_manager(&WCPDownloadManager::getInstance()) , m_other_instance_message_handler(std::make_unique()) { //app config initializes early becasuse it is used in instance checking in Snapmaker_Orca.cpp @@ -6464,6 +6466,11 @@ Downloader* GUI_App::downloader() return m_downloader.get(); } +WCPDownloadManager* GUI_App::wcp_download_manager() +{ + return m_wcp_download_manager; +} + void GUI_App::load_url(wxString url) { if (mainframe) diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 40c61dd0c1..38a950676a 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -89,6 +89,7 @@ class Plater; class ParamsPanel; class NotificationManager; class Downloader; +class WCPDownloadManager; struct GUI_InitParams; class ParamsDialog; class HMSQuery; @@ -297,6 +298,7 @@ private: size_t m_instance_hash_int; std::unique_ptr m_downloader; + WCPDownloadManager* m_wcp_download_manager; //BBS bool m_is_closing {false}; @@ -684,6 +686,7 @@ private: Model& model(); NotificationManager * notification_manager(); Downloader* downloader(); + WCPDownloadManager* wcp_download_manager(); std::string m_mall_model_download_url; diff --git a/src/slic3r/GUI/SSWCP.cpp b/src/slic3r/GUI/SSWCP.cpp index 57930222ed..33de5066f0 100644 --- a/src/slic3r/GUI/SSWCP.cpp +++ b/src/slic3r/GUI/SSWCP.cpp @@ -2,6 +2,7 @@ #include "SSWCP.hpp" #include "GUI_App.hpp" #include "MainFrame.hpp" +#include "WCPDownloadManager.hpp" #include "nlohmann/json.hpp" #include "slic3r/GUI/Tab.hpp" #include "sentry_wrapper/SentryWrapper.hpp" @@ -4297,6 +4298,12 @@ void SSWCP_UserLogin_Instance::process() sw_SubUserUpdatePrivacy(); } else if (m_cmd == GET_PRIVACY_STATUS) { sw_GetUserUpdatePrivacy(); + } else if (m_cmd == DOWNLOAD_FILE) { + sw_DownloadFile(); + } else if (m_cmd == CANCEL_DOWNLOAD) { + sw_CancelDownload(); + } else if (m_cmd == FILE_VIEW) { + sw_FileView(); } else { handle_general_fail(); @@ -4379,6 +4386,110 @@ void SSWCP_UserLogin_Instance::sw_GetUserUpdatePrivacy() } +void SSWCP_UserLogin_Instance::sw_DownloadFile() { + try { + std::string fileName = m_param_data.count("file_name") ? m_param_data["file_name"].get() : ""; + std::string fileUrl = m_param_data.count("file_url") ? m_param_data["file_url"].get() : ""; + + if (fileUrl.empty() || fileName.empty()) { + handle_general_fail(-1, "file_url and file_name are required"); + return; + } + + // Use WCP Download Manager + WCPDownloadManager* download_mgr = wxGetApp().wcp_download_manager(); + if (!download_mgr) { + handle_general_fail(-1, "WCP Download Manager not available"); + return; + } + + // Start download task + size_t task_id = download_mgr->start_download(fileUrl, fileName, shared_from_this()); + + // Return task ID to Flutter + json response; + response["task_id"] = task_id; + response["file_name"] = fileName; + response["file_url"] = fileUrl; + m_res_data = response; + m_status = 0; + m_msg = "Download started"; + send_to_js(); + // Note: Do not call finish_job() here, as download is asynchronous + // The manager will send progress updates and completion/error messages via WCP + + } catch (std::exception& e) { + handle_general_fail(-1, e.what()); + } +} + +void SSWCP_UserLogin_Instance::sw_CancelDownload() { + try { + size_t task_id = m_param_data.count("task_id") ? m_param_data["task_id"].get() : 0; + + if (task_id == 0) { + handle_general_fail(-1, "task_id is required"); + return; + } + + WCPDownloadManager* download_mgr = wxGetApp().wcp_download_manager(); + if (!download_mgr) { + handle_general_fail(-1, "WCP Download Manager not available"); + return; + } + + bool success = download_mgr->cancel_download(task_id); + + if (success) { + json response; + response["task_id"] = task_id; + response["canceled"] = true; + m_res_data = response; + m_status = 0; + m_msg = "Download canceled"; + } else { + handle_general_fail(-1, "Failed to cancel download or task not found"); + return; + } + + send_to_js(); + finish_job(); + } catch (std::exception& e) { + handle_general_fail(-1, e.what()); + } +} + +void SSWCP_UserLogin_Instance::sw_FileView() { + try { + std::string file_path = m_param_data.count("file_path") ? m_param_data["file_path"].get() : ""; + wxFileName file(file_path); + + if (!file.FileExists()) { + handle_general_fail(); + //wxMessageBox(wxT("file not exsit"), wxT("tips"), wxOK | wxICON_WARNING); + return; + } + + std::weak_ptr weak_self = shared_from_this(); + + wxGetApp().CallAfter([file_path, weak_self]() { + auto self = weak_self.lock(); + if (!self) { + return; + } + + //open file in folder + desktop_open_any_folderEx(file_path); + + self->send_to_js(); + self->finish_job(); + + }); + } catch (std::exception& e) { + handle_general_fail(); + } +} + void SSWCP_UserLogin_Instance::sw_SubUserUpdatePrivacy() { try { diff --git a/src/slic3r/GUI/SSWCP.hpp b/src/slic3r/GUI/SSWCP.hpp index 12717471ec..fe40a45a42 100644 --- a/src/slic3r/GUI/SSWCP.hpp +++ b/src/slic3r/GUI/SSWCP.hpp @@ -30,6 +30,9 @@ using tcp = asio::ip::tcp; #define UPLOAD_CAMERA_TIMELAPSE "sw_UploadCameraTimelapse" #define DELETE_CAMERA_TIMELAPSE "sw_DeleteCameraTimelapse" #define GET_DEVICEDATA_STORAGESPACE "sw_GetDeviceDataStorageSpace" +#define DOWNLOAD_FILE "sw_DownloadFile" +#define CANCEL_DOWNLOAD "sw_CancelDownload" +#define FILE_VIEW "sw_FileView" namespace Slic3r { namespace GUI { @@ -536,6 +539,11 @@ private: void sw_GetUserUpdatePrivacy(); void sw_SubUserUpdatePrivacy(); + + void sw_DownloadFile(); + void sw_CancelDownload(); + + void sw_FileView(); }; // Instance class for homepage business diff --git a/src/slic3r/GUI/WCPDownloadManager.cpp b/src/slic3r/GUI/WCPDownloadManager.cpp new file mode 100644 index 0000000000..a9d521aac3 --- /dev/null +++ b/src/slic3r/GUI/WCPDownloadManager.cpp @@ -0,0 +1,276 @@ +#include "WCPDownloadManager.hpp" +#include "GUI_App.hpp" +#include +#include +#include + +namespace Slic3r { namespace GUI { + +size_t WCPDownloadManager::start_download(const std::string& file_url, + const std::string& file_name, + std::shared_ptr wcp_instance) { + + std::lock_guard lock(m_tasks_mutex); + + size_t task_id = m_next_task_id++; + + // Get download path + auto downloadPath = wxGetApp().app_config->get("download_path"); + boost::filesystem::path dest_folder(downloadPath); + boost::filesystem::create_directories(dest_folder); + + boost::filesystem::path dest_file = dest_folder / file_name; + std::string dest_path = dest_file.string(); + + // Create task + auto task = std::make_shared(task_id, file_url, file_name, dest_path, wcp_instance); + task->state = WCPDownloadState::Downloading; + + m_tasks[task_id] = task; + + // Start download + wxGetApp().CallAfter([this, task]() { + try { + // Step 1: Create Http object + Http http = Http::get(task->file_url); + + // Step 2: Set progress callback + http.on_progress([this, task](Http::Progress progress, bool& cancel) { + if (task->state == WCPDownloadState::Canceled) { + cancel = true; + return; + } + + // Calculate progress + int percent = 0; + if (progress.dltotal > 0) { + percent = (int)(progress.dlnow * 100 / progress.dltotal); + } + + task->percent = percent; + + // Throttle progress updates: update every 5% or every second + std::lock_guard lock(m_tasks_mutex); + auto& last_pct = m_last_percent[task->task_id]; + auto& last_upd = m_last_update[task->task_id]; + + auto now = std::chrono::steady_clock::now(); + bool should_update = false; + + if (percent - last_pct >= 5) { + should_update = true; + last_pct = percent; + } else if (now - last_upd >= std::chrono::seconds(1)) { + should_update = true; + } + + if (should_update) { + last_upd = now; + wxGetApp().CallAfter([this, task, percent, progress]() { + send_progress_update(task, percent, progress.dlnow, progress.dltotal); + }); + } + }); + + // Step 3: Set complete callback + http.on_complete([this, task](std::string body, unsigned status) { + wxGetApp().CallAfter([this, task, body]() { + try { + // Save file + boost::nowide::ofstream file(task->dest_path, std::ios::binary); + if (!file.is_open()) { + send_error_update(task, "Failed to open file for writing"); + cleanup_task(task->task_id); + return; + } + + file.write(body.c_str(), body.size()); + file.close(); + + task->state = WCPDownloadState::Completed; + task->percent = 100; + send_complete_update(task, task->dest_path); + cleanup_task(task->task_id); + } catch (std::exception& e) { + send_error_update(task, e.what()); + cleanup_task(task->task_id); + } + }); + }); + + // Step 4: Set error callback + http.on_error([this, task](std::string body, std::string error, unsigned status) { + wxGetApp().CallAfter([this, task, error, status]() { + task->state = WCPDownloadState::Error; + task->error_message = error; + send_error_update(task, error); + cleanup_task(task->task_id); + }); + }); + + // Step 5: Start download and save Http::Ptr for cancellation + task->http_object = http.perform(); + + } catch (std::exception& e) { + task->state = WCPDownloadState::Error; + task->error_message = e.what(); + send_error_update(task, e.what()); + cleanup_task(task->task_id); + } + }); + + return task_id; +} + +bool WCPDownloadManager::cancel_download(size_t task_id) { + std::shared_ptr wcp_to_destroy; + + { + std::lock_guard lock(m_tasks_mutex); + + auto it = m_tasks.find(task_id); + if (it == m_tasks.end()) { + return false; + } + + auto task = it->second; + if (task->state == WCPDownloadState::Downloading) { + task->state = WCPDownloadState::Canceled; + if (task->http_object) { + task->http_object->cancel(); + } + + // Get WCP instance before cleanup (for destruction after lock release) + wcp_to_destroy = task->wcp_instance.lock(); + + cleanup_task(task_id); + } else { + return false; + } + } + + // Destroy WCP instance outside the lock to prevent deadlock + // This is the WCP instance from the original download request (sw_DownloadFile) + if (wcp_to_destroy) { + wcp_to_destroy->finish_job(); + } + + return true; +} + +bool WCPDownloadManager::pause_download(size_t task_id) { + // Pause functionality can be implemented if needed + // Current Http module may not support pause, need to implement resume from breakpoint + std::lock_guard lock(m_tasks_mutex); + auto it = m_tasks.find(task_id); + if (it != m_tasks.end() && it->second->state == WCPDownloadState::Downloading) { + it->second->state = WCPDownloadState::Paused; + // Note: Http module doesn't support pause directly, would need breakpoint resume + return true; + } + return false; +} + +bool WCPDownloadManager::resume_download(size_t task_id) { + // Resume functionality can be implemented if needed + // Would require breakpoint resume support in Http module + std::lock_guard lock(m_tasks_mutex); + auto it = m_tasks.find(task_id); + if (it != m_tasks.end() && it->second->state == WCPDownloadState::Paused) { + // Would need to restart download with range header + return false; // Not implemented yet + } + return false; +} + +WCPDownloadState WCPDownloadManager::get_task_state(size_t task_id) { + std::lock_guard lock(m_tasks_mutex); + auto it = m_tasks.find(task_id); + if (it != m_tasks.end()) { + return it->second->state; + } + return WCPDownloadState::Error; +} + +std::shared_ptr WCPDownloadManager::get_task(size_t task_id) { + std::lock_guard lock(m_tasks_mutex); + auto it = m_tasks.find(task_id); + if (it != m_tasks.end()) { + return it->second; + } + return nullptr; +} + +void WCPDownloadManager::send_progress_update(std::shared_ptr task, + int percent, + size_t downloaded, + size_t total) { + if (auto wcp = task->wcp_instance.lock()) { + json progress_data; + progress_data["task_id"] = task->task_id; + progress_data["percent"] = percent; + progress_data["downloaded"] = downloaded; + progress_data["total"] = total; + progress_data["state"] = "downloading"; + + wcp->m_res_data = progress_data; + wcp->m_status = 0; + wcp->m_msg = "Download progress"; + + // Use progress event ID + json header; + header["event_id"] = wcp->m_event_id + "_progress"; + header["command"] = "download_progress"; + wcp->m_header = header; + + wcp->send_to_js(); + } +} + +void WCPDownloadManager::send_complete_update(std::shared_ptr task, + const std::string& file_path) { + if (auto wcp = task->wcp_instance.lock()) { + json complete_data; + complete_data["task_id"] = task->task_id; + complete_data["file_path"] = file_path; + complete_data["file_name"] = task->file_name; + complete_data["percent"] = 100; + complete_data["state"] = "completed"; + + wcp->m_res_data = complete_data; + wcp->m_status = 0; + wcp->m_msg = "Download completed"; + wcp->send_to_js(); + + // Release WCP instance to prevent memory leak + wcp->finish_job(); + } +} + +void WCPDownloadManager::send_error_update(std::shared_ptr task, + const std::string& error) { + if (auto wcp = task->wcp_instance.lock()) { + json error_data; + error_data["task_id"] = task->task_id; + error_data["error"] = error; + error_data["state"] = "error"; + + wcp->m_res_data = error_data; + wcp->m_status = -1; + wcp->m_msg = error; + wcp->send_to_js(); + + // Release WCP instance to prevent memory leak + wcp->finish_job(); + } +} + +void WCPDownloadManager::cleanup_task(size_t task_id) { + std::lock_guard lock(m_tasks_mutex); + m_tasks.erase(task_id); + m_last_percent.erase(task_id); + m_last_update.erase(task_id); +} + +}} // namespace Slic3r::GUI + diff --git a/src/slic3r/GUI/WCPDownloadManager.hpp b/src/slic3r/GUI/WCPDownloadManager.hpp new file mode 100644 index 0000000000..fda468f777 --- /dev/null +++ b/src/slic3r/GUI/WCPDownloadManager.hpp @@ -0,0 +1,104 @@ +#ifndef slic3r_WCPDownloadManager_hpp_ +#define slic3r_WCPDownloadManager_hpp_ + +#include +#include +#include +#include +#include +#include +#include "../Utils/Http.hpp" +#include "SSWCP.hpp" +#include +#include "nlohmann/json.hpp" + +namespace Slic3r { namespace GUI { + +// Download task state +enum class WCPDownloadState { + Pending, + Downloading, + Paused, + Completed, + Error, + Canceled +}; + +// Download task information +struct WCPDownloadTask { + size_t task_id; + std::string file_url; + std::string file_name; + std::string dest_path; + std::weak_ptr wcp_instance; // Associated WCP instance + Http::Ptr http_object; // HTTP object for cancellation + WCPDownloadState state; + int percent; + std::string error_message; + + WCPDownloadTask(size_t id, const std::string& url, const std::string& name, + const std::string& path, std::shared_ptr instance) + : task_id(id), file_url(url), file_name(name), dest_path(path), + wcp_instance(instance), state(WCPDownloadState::Pending), percent(0) {} +}; + +// WCP Download Manager +class WCPDownloadManager { +public: + static WCPDownloadManager& getInstance() { + static WCPDownloadManager instance; + return instance; + } + + // Start a download task + size_t start_download(const std::string& file_url, + const std::string& file_name, + std::shared_ptr wcp_instance); + + // Cancel a download task + bool cancel_download(size_t task_id); + + // Pause a download task (if needed) + bool pause_download(size_t task_id); + + // Resume a download task (if needed) + bool resume_download(size_t task_id); + + // Get task state + WCPDownloadState get_task_state(size_t task_id); + + // Get task information + std::shared_ptr get_task(size_t task_id); + +private: + WCPDownloadManager() = default; + ~WCPDownloadManager() = default; + WCPDownloadManager(const WCPDownloadManager&) = delete; + WCPDownloadManager& operator=(const WCPDownloadManager&) = delete; + + std::mutex m_tasks_mutex; + std::unordered_map> m_tasks; + std::atomic m_next_task_id{1}; + + // Track last progress update for throttling + std::unordered_map m_last_percent; + std::unordered_map m_last_update; + + // Send progress update to WCP + void send_progress_update(std::shared_ptr task, int percent, + size_t downloaded, size_t total); + + // Send completion message to WCP + void send_complete_update(std::shared_ptr task, const std::string& file_path); + + // Send error message to WCP + void send_error_update(std::shared_ptr task, const std::string& error); + + // Clean up completed task + void cleanup_task(size_t task_id); +}; + +}} // namespace Slic3r::GUI + +#endif // slic3r_WCPDownloadManager_hpp_ + From aba54266d6c7a6cfc2d9256325269d47cade5b3e Mon Sep 17 00:00:00 2001 From: alves Date: Fri, 30 Jan 2026 14:13:19 +0800 Subject: [PATCH 08/12] feature remove the config for entitlements --- scripts/disable_validation.entitlements | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/scripts/disable_validation.entitlements b/scripts/disable_validation.entitlements index 3c4a47a251..123d12a53e 100644 --- a/scripts/disable_validation.entitlements +++ b/scripts/disable_validation.entitlements @@ -4,21 +4,5 @@ com.apple.security.cs.disable-library-validation - com.apple.runningboard.assertions.webkit - - com.apple.security.network.client - - com.apple.security.network.server - - com.apple.security.files.user-selected.read-write - - com.apple.security.files.downloads.read-write - - com.apple.security.cs.allow-jit - - com.apple.security.cs.allow-unsigned-executable-memory - - com.apple.security.cs.allow-dyld-environment-variables - From 6bc1ffa59970f0fde5ca471e5027b360e3cb4582 Mon Sep 17 00:00:00 2001 From: alves Date: Fri, 30 Jan 2026 14:43:26 +0800 Subject: [PATCH 09/12] fix windows pdb not upload sentry server bug. --- .github/workflows/build_orca.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/build_orca.yml b/.github/workflows/build_orca.yml index af9fd9b5c7..44e6b93bfe 100644 --- a/.github/workflows/build_orca.yml +++ b/.github/workflows/build_orca.yml @@ -612,3 +612,14 @@ jobs: asset_name: orca_custom_preset_tests.zip asset_content_type: application/octet-stream max_releases: 1 + + upload_symbols: + name: Upload Windows PDB to Sentry + needs: [build_orca] + if: ${{ !cancelled() && needs.build_orca.result == 'success' && inputs.os == 'windows-latest' }} + uses: ./.github/workflows/sentry_cli.yml + with: + os: ${{ inputs.os }} + pdb-artifact-name: PDB + release: ${{ needs.build_orca.outputs.release || github.sha }} + secrets: inherit From aed03ef022dda59ee361a6ad36d014f1d637c7f2 Mon Sep 17 00:00:00 2001 From: alves Date: Fri, 30 Jan 2026 17:13:59 +0800 Subject: [PATCH 10/12] fix sentry sdk no version bug. --- src/sentry_wrapper/SentryWrapper.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sentry_wrapper/SentryWrapper.cpp b/src/sentry_wrapper/SentryWrapper.cpp index 95894ecff6..380220196b 100644 --- a/src/sentry_wrapper/SentryWrapper.cpp +++ b/src/sentry_wrapper/SentryWrapper.cpp @@ -251,6 +251,10 @@ void initSentryEx() sentry_options_set_before_send_log(options, before_send_log, NULL); sentry_options_set_logs_with_attributes(options, true); + // Set release version for symbolication + // This must match the release used when uploading symbols + sentry_options_set_release(options, Snapmaker_VERSION); + sentry_init(options); sentry_start_session(); From 5494f27b44fbf0de36ffb48fced4a0dfcd57d99b Mon Sep 17 00:00:00 2001 From: alves Date: Fri, 30 Jan 2026 17:18:00 +0800 Subject: [PATCH 11/12] fix mac pack failed bug. --- .github/workflows/build_orca.yml | 176 +------------------------------ 1 file changed, 5 insertions(+), 171 deletions(-) diff --git a/.github/workflows/build_orca.yml b/.github/workflows/build_orca.yml index 44e6b93bfe..0e0e5f7476 100644 --- a/.github/workflows/build_orca.yml +++ b/.github/workflows/build_orca.yml @@ -123,7 +123,6 @@ jobs: # Thanks to RaySajuuk, it's working now - name: Sign app and notary #if: (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') || github.ref == 'refs/heads/2.2.0') && inputs.os == 'macos-14' - if: inputs.os == 'macos-14' working-directory: ${{ github.workspace }} env: BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} @@ -140,129 +139,10 @@ jobs: security import $CERTIFICATE_PATH -P $P12_PASSWORD -A -t cert -f pkcs12 -k $KEYCHAIN_PATH security list-keychain -d user -s $KEYCHAIN_PATH security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $P12_PASSWORD $KEYCHAIN_PATH - - # Sign app with proper recursive signing (not using --deep) - APP_PATH="${{ github.workspace }}/build/universal/Snapmaker_Orca/Snapmaker Orca.app" - ENTITLEMENTS_PATH="${{ github.workspace }}/scripts/disable_validation.entitlements" - - # Verify entitlements file exists - if [ ! -f "$ENTITLEMENTS_PATH" ]; then - echo "Error: Entitlements file not found: $ENTITLEMENTS_PATH" - exit 1 - fi - echo "Using entitlements: $ENTITLEMENTS_PATH" - - # Sign Frameworks (must succeed, no silent failures) - echo "Signing Frameworks..." - if [ -d "$APP_PATH/Contents/Frameworks" ]; then - find "$APP_PATH/Contents/Frameworks" -name "*.dylib" -o -name "*.framework" | while read -r item; do - if [ -f "$item" ] || [ -d "$item" ]; then - echo " Signing: $item" - codesign --force --verbose --options runtime --timestamp --sign "$CERTIFICATE_ID" "$item" || { - echo "Error: Failed to sign $item" - exit 1 - } - fi - done - fi - - # Sign MacOS executables (must succeed, no silent failures) - echo "Signing MacOS executables..." - if [ -d "$APP_PATH/Contents/MacOS" ]; then - find "$APP_PATH/Contents/MacOS" -type f -perm +111 | while read -r item; do - echo " Signing: $item" - codesign --force --verbose --options runtime --timestamp --sign "$CERTIFICATE_ID" "$item" || { - echo "Error: Failed to sign $item" - exit 1 - } - done - fi - - # Sign main app with entitlements - echo "Signing main app with entitlements..." - codesign --force --verbose --options runtime --timestamp --entitlements "$ENTITLEMENTS_PATH" --sign "$CERTIFICATE_ID" "$APP_PATH" || { - echo "Error: Failed to sign main app" - exit 1 - } - - # Verify signature - echo "Verifying signature..." - codesign --verify --verbose "$APP_PATH" || { - echo "Error: Signature verification failed" - exit 1 - } - - # Verify Hardened Runtime is enabled - echo "Verifying Hardened Runtime is enabled..." - RUNTIME_CHECK=$(codesign -d --verbose=4 "$APP_PATH" 2>&1 | grep -i "runtime" || true) - if echo "$RUNTIME_CHECK" | grep -qi "runtime"; then - echo "✓ Hardened Runtime is enabled" - echo " Runtime flags: $RUNTIME_CHECK" - else - echo "✗ Warning: Hardened Runtime status not clearly visible in signature" - echo " Checking signature details..." - codesign -d --verbose=4 "$APP_PATH" 2>&1 | head -30 - fi - - # Verify entitlements are embedded - echo "Verifying entitlements are embedded..." - EMBEDDED_ENTITLEMENTS=$(codesign -d --entitlements - "$APP_PATH" 2>&1) - if echo "$EMBEDDED_ENTITLEMENTS" | grep -q "com.apple.security.network.client"; then - echo "✓ Entitlements successfully embedded" - echo " Found network.client entitlement" - else - echo "✗ Error: Entitlements not embedded correctly" - echo " Embedded entitlements output:" - echo "$EMBEDDED_ENTITLEMENTS" | head -20 - exit 1 - fi - + codesign --deep --force --verbose --options runtime --timestamp --entitlements ${{ github.workspace }}/scripts/disable_validation.entitlements --sign "$CERTIFICATE_ID" "${{ github.workspace }}/build/universal/Snapmaker_Orca/Snapmaker Orca.app" # Sign Snapmaker_Orca_profile_validator.app if it exists - VALIDATOR_APP_PATH="${{ github.workspace }}/build/universal/Snapmaker_Orca/Snapmaker_Orca_profile_validator.app" - if [ -f "$VALIDATOR_APP_PATH/Contents/MacOS/Snapmaker_Orca_profile_validator" ]; then - echo "Signing Snapmaker_Orca_profile_validator.app..." - - # Sign validator app components - if [ -d "$VALIDATOR_APP_PATH/Contents/Frameworks" ]; then - find "$VALIDATOR_APP_PATH/Contents/Frameworks" -name "*.dylib" -o -name "*.framework" | while read -r item; do - if [ -f "$item" ] || [ -d "$item" ]; then - codesign --force --verbose --options runtime --timestamp --sign "$CERTIFICATE_ID" "$item" || { - echo "Error: Failed to sign validator component $item" - exit 1 - } - fi - done - fi - - if [ -d "$VALIDATOR_APP_PATH/Contents/MacOS" ]; then - find "$VALIDATOR_APP_PATH/Contents/MacOS" -type f -perm +111 | while read -r item; do - codesign --force --verbose --options runtime --timestamp --sign "$CERTIFICATE_ID" "$item" || { - echo "Error: Failed to sign validator executable $item" - exit 1 - } - done - fi - - # Sign main validator app with entitlements - codesign --force --verbose --options runtime --timestamp --entitlements "$ENTITLEMENTS_PATH" --sign "$CERTIFICATE_ID" "$VALIDATOR_APP_PATH" || { - echo "Error: Failed to sign validator app" - exit 1 - } - - # Verify validator signature - codesign --verify --verbose "$VALIDATOR_APP_PATH" || { - echo "Error: Validator signature verification failed" - exit 1 - } - - # Verify Hardened Runtime is enabled for validator - echo "Verifying Hardened Runtime for validator app..." - VALIDATOR_RUNTIME_CHECK=$(codesign -d --verbose=4 "$VALIDATOR_APP_PATH" 2>&1 | grep -i "runtime" || true) - if echo "$VALIDATOR_RUNTIME_CHECK" | grep -qi "runtime"; then - echo "✓ Hardened Runtime is enabled for validator app" - else - echo "⚠ Warning: Hardened Runtime status not clearly visible for validator" - fi + if [ -f "${{ github.workspace }}/build/universal/Snapmaker_Orca/Snapmaker_Orca_profile_validator.app/Contents/MacOS/Snapmaker_Orca_profile_validator" ]; then + codesign --deep --force --verbose --options runtime --timestamp --entitlements ${{ github.workspace }}/scripts/disable_validation.entitlements --sign "$CERTIFICATE_ID" ${{ github.workspace }}/build/universal/Snapmaker_Orca/Snapmaker_Orca_profile_validator.app fi # Create main Snapmaker Orca DMG without the profile validator helper @@ -271,24 +151,7 @@ jobs: cp -R "${{ github.workspace }}/build/universal/Snapmaker_Orca/Snapmaker Orca.app" "${{ github.workspace }}/build/universal/Snapmaker_Orca_dmg/" ln -sfn /Applications ${{ github.workspace }}/build/universal/Snapmaker_Orca_dmg/Applications hdiutil create -volname "Snapmaker_Orca" -srcfolder ${{ github.workspace }}/build/universal/Snapmaker_Orca_dmg -ov -format UDZO "${{ github.workspace }}/Snapmaker_Orca_Mac_universal_${{ env.ver }}.dmg" - # Sign DMG (DMG files should NOT have entitlements, only signature) - codesign --force --verbose --options runtime --timestamp --sign "$CERTIFICATE_ID" "${{ github.workspace }}/Snapmaker_Orca_Mac_universal_${{ env.ver }}.dmg" || { - echo "Error: Failed to sign DMG" - exit 1 - } - codesign --verify --verbose "${{ github.workspace }}/Snapmaker_Orca_Mac_universal_${{ env.ver }}.dmg" || { - echo "Error: DMG signature verification failed" - exit 1 - } - - # Verify Hardened Runtime for DMG - echo "Verifying Hardened Runtime for DMG..." - DMG_RUNTIME_CHECK=$(codesign -d --verbose=4 "${{ github.workspace }}/Snapmaker_Orca_Mac_universal_${{ env.ver }}.dmg" 2>&1 | grep -i "runtime" || true) - if echo "$DMG_RUNTIME_CHECK" | grep -qi "runtime"; then - echo "✓ Hardened Runtime is enabled for DMG" - else - echo "⚠ Note: DMG files typically don't show runtime flags in the same way as apps" - fi + codesign --deep --force --verbose --options runtime --timestamp --entitlements ${{ github.workspace }}/scripts/disable_validation.entitlements --sign "$CERTIFICATE_ID" "${{ github.workspace }}/Snapmaker_Orca_Mac_universal_${{ env.ver }}.dmg" # Create separate Snapmaker_Orca_profile_validator DMG if the app exists if [ -f "${{ github.workspace }}/build/universal/Snapmaker_Orca/Snapmaker_Orca_profile_validator.app/Contents/MacOS/Snapmaker_Orca_profile_validator" ]; then @@ -297,24 +160,7 @@ jobs: cp -R ${{ github.workspace }}/build/universal/Snapmaker_Orca/Snapmaker_Orca_profile_validator.app ${{ github.workspace }}/build/universal/Snapmaker_Orca_profile_validator_dmg/ ln -sfn /Applications ${{ github.workspace }}/build/universal/Snapmaker_Orca_profile_validator_dmg/Applications hdiutil create -volname "Snapmaker_Orca Profile Validator" -srcfolder ${{ github.workspace }}/build/universal/Snapmaker_Orca_profile_validator_dmg -ov -format UDZO "${{ github.workspace }}/Snapmaker_Orca_profile_validator_Mac_universal_${{ env.ver }}.dmg" - # Sign DMG (DMG files should NOT have entitlements, only signature) - codesign --force --verbose --options runtime --timestamp --sign "$CERTIFICATE_ID" "${{ github.workspace }}/Snapmaker_Orca_profile_validator_Mac_universal_${{ env.ver }}.dmg" || { - echo "Error: Failed to sign validator DMG" - exit 1 - } - codesign --verify --verbose "${{ github.workspace }}/Snapmaker_Orca_profile_validator_Mac_universal_${{ env.ver }}.dmg" || { - echo "Error: Validator DMG signature verification failed" - exit 1 - } - - # Verify Hardened Runtime for validator DMG - echo "Verifying Hardened Runtime for validator DMG..." - VALIDATOR_DMG_RUNTIME_CHECK=$(codesign -d --verbose=4 "${{ github.workspace }}/Snapmaker_Orca_profile_validator_Mac_universal_${{ env.ver }}.dmg" 2>&1 | grep -i "runtime" || true) - if echo "$VALIDATOR_DMG_RUNTIME_CHECK" | grep -qi "runtime"; then - echo "✓ Hardened Runtime is enabled for validator DMG" - else - echo "⚠ Note: DMG files typically don't show runtime flags in the same way as apps" - fi + codesign --deep --force --verbose --options runtime --timestamp --entitlements ${{ github.workspace }}/scripts/disable_validation.entitlements --sign "$CERTIFICATE_ID" "${{ github.workspace }}/Snapmaker_Orca_profile_validator_Mac_universal_${{ env.ver }}.dmg" fi # Notarize main DMG @@ -330,7 +176,6 @@ jobs: - name: Create DMG without notary #if: github.ref != 'refs/heads/main' && inputs.os == 'macos-14' && github.ref != 'refs/heads/2.2.0' - if: github.ref == 'refs/heads/main' && inputs.os == 'macos-14' working-directory: ${{ github.workspace }} run: | mkdir -p ${{ github.workspace }}/build/universal/Snapmaker_Orca_dmg @@ -612,14 +457,3 @@ jobs: asset_name: orca_custom_preset_tests.zip asset_content_type: application/octet-stream max_releases: 1 - - upload_symbols: - name: Upload Windows PDB to Sentry - needs: [build_orca] - if: ${{ !cancelled() && needs.build_orca.result == 'success' && inputs.os == 'windows-latest' }} - uses: ./.github/workflows/sentry_cli.yml - with: - os: ${{ inputs.os }} - pdb-artifact-name: PDB - release: ${{ needs.build_orca.outputs.release || github.sha }} - secrets: inherit From 27f2d0a7e813d60cfe8cd1f6cd4aaaaf15c30591 Mon Sep 17 00:00:00 2001 From: alves Date: Fri, 30 Jan 2026 17:58:20 +0800 Subject: [PATCH 12/12] fix build fail question on mac. --- .github/workflows/build_orca.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_orca.yml b/.github/workflows/build_orca.yml index 0e0e5f7476..6599f4e4de 100644 --- a/.github/workflows/build_orca.yml +++ b/.github/workflows/build_orca.yml @@ -122,7 +122,7 @@ jobs: # Thanks to RaySajuuk, it's working now - name: Sign app and notary - #if: (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') || github.ref == 'refs/heads/2.2.0') && inputs.os == 'macos-14' + if: (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/') || github.ref == 'refs/heads/2.2.0') && inputs.os == 'macos-14' working-directory: ${{ github.workspace }} env: BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} @@ -175,7 +175,7 @@ jobs: fi - name: Create DMG without notary - #if: github.ref != 'refs/heads/main' && inputs.os == 'macos-14' && github.ref != 'refs/heads/2.2.0' + if: github.ref != 'refs/heads/main' && inputs.os == 'macos-14' && github.ref != 'refs/heads/2.2.0' working-directory: ${{ github.workspace }} run: | mkdir -p ${{ github.workspace }}/build/universal/Snapmaker_Orca_dmg