From 08ba6e30f7fd555fe94b7a74f914b93efc68a0a1 Mon Sep 17 00:00:00 2001 From: Haitao Pan Date: Tue, 30 Jun 2026 10:48:35 +0800 Subject: [PATCH] fix(macos): workaround App Store Connect dSYM validation bug (#62) * fix(macos): workaround App Store Connect dSYM validation bug for App.framework * test: mock device and package plugins and increase timeout - Increase sync loop timeout in thread workspace binding test to avoid flakiness - Mock device_info and package_info plugins for gateway runtime tests - Update pubspec.yaml version * test: fix missing plugin in runtime_controllers_settings_account_test * build: make sync-version.sh auto-increment build number --------- Co-authored-by: Haitao Pan --- pubspec.yaml | 6 +-- scripts/ensure-framework-dsyms.sh | 8 ++++ scripts/sync-version.sh | 29 +++++++++++++ test/mock_plugins.dart | 41 +++++++++++++++++++ ...troller_thread_workspace_binding_test.dart | 2 +- .../gateway_runtime_bridge_skills_test.dart | 2 + ...ime_controllers_settings_account_test.dart | 3 ++ 7 files changed, 87 insertions(+), 4 deletions(-) create mode 100755 scripts/sync-version.sh create mode 100644 test/mock_plugins.dart diff --git a/pubspec.yaml b/pubspec.yaml index 7f4c5d7a..7adc1c6b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,9 +2,9 @@ name: xworkmate description: "XWorkmate desktop-first AI workspace shell." publish_to: 'none' -version: 1.1.5+1 -build-date: 2026-06-28 -build-id: 4e02107 +version: 1.1.5+2 +build-date: 2026-06-30 +build-id: a876e3b environment: sdk: ^3.11.0 diff --git a/scripts/ensure-framework-dsyms.sh b/scripts/ensure-framework-dsyms.sh index df8a0192..269952cc 100755 --- a/scripts/ensure-framework-dsyms.sh +++ b/scripts/ensure-framework-dsyms.sh @@ -46,3 +46,11 @@ for framework_path in "${frameworks_dir}"/*.framework; do rm -rf "${dsym_path}" || true fi done + +# Workaround for App Store Connect bug where it expects the DWARF file for App.framework to be named "A" +# because the binary is located at App.framework/Versions/A/App. +app_dwarf_dir="${DWARF_DSYM_FOLDER_PATH}/App.framework.dSYM/Contents/Resources/DWARF" +if [[ -d "${app_dwarf_dir}" && -f "${app_dwarf_dir}/App" && ! -f "${app_dwarf_dir}/A" ]]; then + echo "Applying workaround: Copying App DWARF file to A for App Store Connect validation" + cp "${app_dwarf_dir}/App" "${app_dwarf_dir}/A" +fi diff --git a/scripts/sync-version.sh b/scripts/sync-version.sh new file mode 100755 index 00000000..ebac392a --- /dev/null +++ b/scripts/sync-version.sh @@ -0,0 +1,29 @@ +#!/bin/bash +set -e + +if [ -n "$1" ]; then + TARGET_VERSION="$1" +else + # Extract current version from pubspec.yaml + CURRENT_VERSION=$(grep "^version: " pubspec.yaml | awk '{print $2}') + + if [[ "$CURRENT_VERSION" == *"+"* ]]; then + BASE_VERSION=$(echo "$CURRENT_VERSION" | cut -d'+' -f1) + BUILD_NUM=$(echo "$CURRENT_VERSION" | cut -d'+' -f2) + NEXT_BUILD_NUM=$((BUILD_NUM + 1)) + TARGET_VERSION="${BASE_VERSION}+${NEXT_BUILD_NUM}" + else + TARGET_VERSION="${CURRENT_VERSION}+1" + fi +fi +DATE=$(date +%Y-%m-%d) +COMMIT=$(git rev-parse --short HEAD) + +# Update version in pubspec.yaml +sed -i.bak -e "s/^version: .*/version: ${TARGET_VERSION}/" \ + -e "s/^build-date: .*/build-date: ${DATE}/" \ + -e "s/^build-id: .*/build-id: ${COMMIT}/" pubspec.yaml + +rm -f pubspec.yaml.bak + +echo "Updated pubspec.yaml to version=${TARGET_VERSION}, build-date=${DATE}, build-id=${COMMIT}" diff --git a/test/mock_plugins.dart b/test/mock_plugins.dart new file mode 100644 index 00000000..24c9c03b --- /dev/null +++ b/test/mock_plugins.dart @@ -0,0 +1,41 @@ +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void mockPlugins() { + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMethodCallHandler( + const MethodChannel('dev.fluttercommunity.plus/package_info'), + (MethodCall methodCall) async { + return { + 'appName': 'XWorkmate', + 'packageName': 'com.xevor.xworkmate', + 'version': '1.1.5', + 'buildNumber': '1', + }; + }, + ); + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMethodCallHandler( + const MethodChannel('dev.fluttercommunity.plus/device_info'), + (MethodCall methodCall) async { + return { + 'computerName': 'Test-Mac', + 'hostName': 'Test-Mac', + 'arch': 'arm64', + 'model': 'MacBookPro18,1', + 'kernelVersion': 'Darwin 21.4.0', + 'osRelease': '21.4.0', + 'activeCPUs': 10, + 'memorySize': 34359738368, + 'cpuFrequency': 3200000000, + }; + }, + ); + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMethodCallHandler( + const MethodChannel('plugins.flutter.io/path_provider'), + (MethodCall methodCall) async { + return '/tmp'; + }, + ); +} diff --git a/test/runtime/app_controller_thread_workspace_binding_test.dart b/test/runtime/app_controller_thread_workspace_binding_test.dart index 57ef91f4..4ce8c1d8 100644 --- a/test/runtime/app_controller_thread_workspace_binding_test.dart +++ b/test/runtime/app_controller_thread_workspace_binding_test.dart @@ -1230,7 +1230,7 @@ void main() { ); for ( var attempt = 0; - attempt < 300 && + attempt < 1000 && controller .requireTaskThreadForSessionInternal('unit-fixture-task-a') .lastArtifactSyncStatus != diff --git a/test/runtime/gateway_runtime_bridge_skills_test.dart b/test/runtime/gateway_runtime_bridge_skills_test.dart index 9d5f2285..a72e11ec 100644 --- a/test/runtime/gateway_runtime_bridge_skills_test.dart +++ b/test/runtime/gateway_runtime_bridge_skills_test.dart @@ -1,3 +1,4 @@ +import "../mock_plugins.dart"; import 'dart:convert'; import 'dart:io'; @@ -11,6 +12,7 @@ import 'package:xworkmate/runtime/secure_config_store.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); + mockPlugins(); HttpOverrides.global = null; test( diff --git a/test/runtime/runtime_controllers_settings_account_test.dart b/test/runtime/runtime_controllers_settings_account_test.dart index 3c1bef3c..bc4b0f67 100644 --- a/test/runtime/runtime_controllers_settings_account_test.dart +++ b/test/runtime/runtime_controllers_settings_account_test.dart @@ -1,3 +1,4 @@ +import "../mock_plugins.dart"; import 'dart:convert'; import 'dart:io'; @@ -9,6 +10,8 @@ import 'package:xworkmate/runtime/runtime_models.dart'; import 'package:xworkmate/runtime/secure_config_store.dart'; void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + mockPlugins(); group('SettingsController account sync', () { test( 'prefers managed bridge token over stale profile token for remote gateway auth',