Compare commits
2 Commits
main
...
pr/xcode27
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c89be591ad | ||
|
|
fe4c0ebe24 |
31
.github/workflows/build-and-release.yml
vendored
31
.github/workflows/build-and-release.yml
vendored
@ -30,6 +30,11 @@ on:
|
|||||||
- ".github/actions/setup-flutter-sdk/action.yml"
|
- ".github/actions/setup-flutter-sdk/action.yml"
|
||||||
- ".github/workflows/build-and-release.yml"
|
- ".github/workflows/build-and-release.yml"
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
enable_testflight:
|
||||||
|
description: "Build & upload TestFlight (macOS/iOS App Store) artifacts"
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
@ -49,6 +54,7 @@ jobs:
|
|||||||
contents: write
|
contents: write
|
||||||
outputs:
|
outputs:
|
||||||
should_release: ${{ steps.flags.outputs.should_release }}
|
should_release: ${{ steps.flags.outputs.should_release }}
|
||||||
|
testflight_enabled: ${{ steps.flags.outputs.testflight_enabled }}
|
||||||
release_tag: ${{ steps.meta.outputs.release_tag }}
|
release_tag: ${{ steps.meta.outputs.release_tag }}
|
||||||
release_title: ${{ steps.meta.outputs.release_title }}
|
release_title: ${{ steps.meta.outputs.release_title }}
|
||||||
release_notes: ${{ steps.meta.outputs.release_notes }}
|
release_notes: ${{ steps.meta.outputs.release_notes }}
|
||||||
@ -61,6 +67,9 @@ jobs:
|
|||||||
- name: Determine release mode
|
- name: Determine release mode
|
||||||
id: flags
|
id: flags
|
||||||
shell: bash
|
shell: bash
|
||||||
|
env:
|
||||||
|
ENABLE_TESTFLIGHT_INPUT: ${{ github.event.inputs.enable_testflight }}
|
||||||
|
ENABLE_TESTFLIGHT_VAR: ${{ vars.ENABLE_TESTFLIGHT }}
|
||||||
run: |
|
run: |
|
||||||
if [[ "${GITHUB_REF:-}" == refs/tags/v* || "${GITHUB_EVENT_NAME:-}" == "workflow_dispatch" || "${GITHUB_REF:-}" == "refs/heads/main" ]]; then
|
if [[ "${GITHUB_REF:-}" == refs/tags/v* || "${GITHUB_EVENT_NAME:-}" == "workflow_dispatch" || "${GITHUB_REF:-}" == "refs/heads/main" ]]; then
|
||||||
echo "should_release=true" >> "$GITHUB_OUTPUT"
|
echo "should_release=true" >> "$GITHUB_OUTPUT"
|
||||||
@ -68,6 +77,16 @@ jobs:
|
|||||||
echo "should_release=false" >> "$GITHUB_OUTPUT"
|
echo "should_release=false" >> "$GITHUB_OUTPUT"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# TestFlight is opt-in (default OFF). Enabled only when explicitly
|
||||||
|
# requested via the workflow_dispatch input or the ENABLE_TESTFLIGHT
|
||||||
|
# repo/org variable. Keeps missing Apple signing secrets from failing
|
||||||
|
# the normal DMG/IPA release path.
|
||||||
|
if [[ "${ENABLE_TESTFLIGHT_INPUT:-}" == "true" || "${ENABLE_TESTFLIGHT_VAR:-}" == "true" ]]; then
|
||||||
|
echo "testflight_enabled=true" >> "$GITHUB_OUTPUT"
|
||||||
|
else
|
||||||
|
echo "testflight_enabled=false" >> "$GITHUB_OUTPUT"
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Compute release metadata
|
- name: Compute release metadata
|
||||||
id: meta
|
id: meta
|
||||||
shell: bash
|
shell: bash
|
||||||
@ -257,12 +276,12 @@ jobs:
|
|||||||
go-version: "1.24.1"
|
go-version: "1.24.1"
|
||||||
|
|
||||||
- name: Build platform artifacts
|
- name: Build platform artifacts
|
||||||
if: ${{ steps.preflight.outputs.should_build_platform == 'true' && (matrix.release_only != 'true' || env.SHOULD_RELEASE == 'true') }}
|
if: ${{ steps.preflight.outputs.should_build_platform == 'true' && (matrix.release_only != 'true' || env.SHOULD_RELEASE == 'true') && (matrix.package != 'app-store-pkg' || needs.prepare.outputs.testflight_enabled == 'true') }}
|
||||||
shell: bash
|
shell: bash
|
||||||
run: bash ./scripts/ci/build_matrix_artifacts.sh "$PLATFORM" "$ARCH" "${{ matrix.package }}" "$SHOULD_RELEASE"
|
run: bash ./scripts/ci/build_matrix_artifacts.sh "$PLATFORM" "$ARCH" "${{ matrix.package }}" "$SHOULD_RELEASE"
|
||||||
|
|
||||||
- name: Upload build artifacts
|
- name: Upload build artifacts
|
||||||
if: ${{ steps.preflight.outputs.should_build_platform == 'true' && (matrix.release_only != 'true' || env.SHOULD_RELEASE == 'true') }}
|
if: ${{ steps.preflight.outputs.should_build_platform == 'true' && (matrix.release_only != 'true' || env.SHOULD_RELEASE == 'true') && (matrix.package != 'app-store-pkg' || needs.prepare.outputs.testflight_enabled == 'true') }}
|
||||||
uses: actions/upload-artifact@v7
|
uses: actions/upload-artifact@v7
|
||||||
with:
|
with:
|
||||||
name: ${{ matrix.artifact_name }}
|
name: ${{ matrix.artifact_name }}
|
||||||
@ -338,7 +357,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Load App Store Connect secrets
|
- name: Load App Store Connect secrets
|
||||||
id: vault
|
id: vault
|
||||||
if: ${{ matrix.target != 'github_release' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }}
|
if: ${{ matrix.target != 'github_release' && needs.prepare.outputs.testflight_enabled == 'true' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }}
|
||||||
uses: hashicorp/vault-action@v4
|
uses: hashicorp/vault-action@v4
|
||||||
with:
|
with:
|
||||||
url: ${{ env.VAULT_ADDR }}
|
url: ${{ env.VAULT_ADDR }}
|
||||||
@ -356,7 +375,7 @@ jobs:
|
|||||||
kv/data/github-actions/xworkmate-app APP_STORE_CONNECT_API_KEY_P8_BASE64 | APP_STORE_CONNECT_API_KEY_P8_BASE64
|
kv/data/github-actions/xworkmate-app APP_STORE_CONNECT_API_KEY_P8_BASE64 | APP_STORE_CONNECT_API_KEY_P8_BASE64
|
||||||
|
|
||||||
- name: Export App Store Connect secrets
|
- name: Export App Store Connect secrets
|
||||||
if: ${{ matrix.target != 'github_release' }}
|
if: ${{ matrix.target != 'github_release' && needs.prepare.outputs.testflight_enabled == 'true' }}
|
||||||
run: |
|
run: |
|
||||||
{
|
{
|
||||||
echo "APPLE_CERT_P12_BASE64=${{ steps.vault.outputs.APPLE_CERT_P12_BASE64 }}"
|
echo "APPLE_CERT_P12_BASE64=${{ steps.vault.outputs.APPLE_CERT_P12_BASE64 }}"
|
||||||
@ -385,13 +404,13 @@ jobs:
|
|||||||
RELEASE_NOTES: ${{ needs.prepare.outputs.release_notes }}
|
RELEASE_NOTES: ${{ needs.prepare.outputs.release_notes }}
|
||||||
|
|
||||||
- name: Download TestFlight artifact
|
- name: Download TestFlight artifact
|
||||||
if: ${{ matrix.target != 'github_release' }}
|
if: ${{ matrix.target != 'github_release' && needs.prepare.outputs.testflight_enabled == 'true' }}
|
||||||
uses: actions/download-artifact@v8
|
uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
name: ${{ matrix.artifact_name }}
|
name: ${{ matrix.artifact_name }}
|
||||||
path: ${{ matrix.artifact_path }}
|
path: ${{ matrix.artifact_path }}
|
||||||
|
|
||||||
- name: Upload to TestFlight
|
- name: Upload to TestFlight
|
||||||
if: ${{ matrix.target != 'github_release' }}
|
if: ${{ matrix.target != 'github_release' && needs.prepare.outputs.testflight_enabled == 'true' }}
|
||||||
shell: bash
|
shell: bash
|
||||||
run: bash ./scripts/ci/testflight_upload.sh "${{ matrix.testflight_platform }}" "${{ matrix.artifact_path }}"
|
run: bash ./scripts/ci/testflight_upload.sh "${{ matrix.testflight_platform }}" "${{ matrix.artifact_path }}"
|
||||||
|
|||||||
@ -39,6 +39,11 @@ post_install do |installer|
|
|||||||
installer.pods_project.targets.each do |target|
|
installer.pods_project.targets.each do |target|
|
||||||
flutter_additional_ios_build_settings(target)
|
flutter_additional_ios_build_settings(target)
|
||||||
|
|
||||||
|
target.build_configurations.each do |config|
|
||||||
|
# Xcode 27 rejects dependency targets below the app's iOS 15.5 minimum.
|
||||||
|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.5'
|
||||||
|
end
|
||||||
|
|
||||||
next unless ['Pods-Runner', 'Pods-RunnerTests'].include?(target.name)
|
next unless ['Pods-Runner', 'Pods-RunnerTests'].include?(target.name)
|
||||||
|
|
||||||
target.build_configurations.each do |config|
|
target.build_configurations.each do |config|
|
||||||
|
|||||||
@ -67,6 +67,6 @@ SPEC CHECKSUMS:
|
|||||||
super_native_extensions: b763c02dc3a8fd078389f410bf15149179020cb4
|
super_native_extensions: b763c02dc3a8fd078389f410bf15149179020cb4
|
||||||
WebRTC-SDK: 79942c006ea64f6fb48d7da8a4786dfc820bc1db
|
WebRTC-SDK: 79942c006ea64f6fb48d7da8a4786dfc820bc1db
|
||||||
|
|
||||||
PODFILE CHECKSUM: 5ab2a375a52a76f419425b2b219d2743259d6f1f
|
PODFILE CHECKSUM: ca16f6ef66890e172b6528d5f0eb390e0410291e
|
||||||
|
|
||||||
COCOAPODS: 1.16.2
|
COCOAPODS: 1.16.2
|
||||||
|
|||||||
@ -291,7 +291,7 @@
|
|||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
shellScript = "export PATH=\"$PROJECT_DIR/../scripts/xcode-tools:$PATH\"\n/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
||||||
};
|
};
|
||||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
@ -306,7 +306,7 @@
|
|||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
shellScript = "export PATH=\"$PROJECT_DIR/../scripts/xcode-tools:$PATH\"\n/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||||
};
|
};
|
||||||
BA47ED2B244B5E2B99043424 /* [CP] Check Pods Manifest.lock */ = {
|
BA47ED2B244B5E2B99043424 /* [CP] Check Pods Manifest.lock */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
platform :osx, '14.0'
|
platform :osx, '15.6'
|
||||||
|
|
||||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||||
@ -97,7 +97,8 @@ post_install do |installer|
|
|||||||
installer.pods_project.targets.each do |target|
|
installer.pods_project.targets.each do |target|
|
||||||
flutter_additional_macos_build_settings(target)
|
flutter_additional_macos_build_settings(target)
|
||||||
target.build_configurations.each do |config|
|
target.build_configurations.each do |config|
|
||||||
config.build_settings['MACOSX_DEPLOYMENT_TARGET'] = '14.0'
|
# Xcode 27 rejects dependency targets below the app's 15.6 minimum.
|
||||||
|
config.build_settings['MACOSX_DEPLOYMENT_TARGET'] = '15.6'
|
||||||
|
|
||||||
next unless ['Pods-Runner', 'Pods-RunnerTests', 'WebRTC-SDK', 'flutter_webrtc'].include?(target.name)
|
next unless ['Pods-Runner', 'Pods-RunnerTests', 'WebRTC-SDK', 'flutter_webrtc'].include?(target.name)
|
||||||
|
|
||||||
|
|||||||
@ -61,6 +61,6 @@ SPEC CHECKSUMS:
|
|||||||
super_native_extensions: c2795d6d9aedf4a79fae25cb6160b71b50549189
|
super_native_extensions: c2795d6d9aedf4a79fae25cb6160b71b50549189
|
||||||
WebRTC-SDK: 79942c006ea64f6fb48d7da8a4786dfc820bc1db
|
WebRTC-SDK: 79942c006ea64f6fb48d7da8a4786dfc820bc1db
|
||||||
|
|
||||||
PODFILE CHECKSUM: 1eb7d5d1472c632b8f775dd34562291c20ae818a
|
PODFILE CHECKSUM: 7804cba3ecbc9953edc70dee53b2ce2b4aeaa013
|
||||||
|
|
||||||
COCOAPODS: 1.16.2
|
COCOAPODS: 1.16.2
|
||||||
|
|||||||
@ -371,7 +371,7 @@
|
|||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n";
|
shellScript = "export PATH=\"$PROJECT_DIR/../scripts/xcode-tools:$PATH\"\necho \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n";
|
||||||
};
|
};
|
||||||
33CC111E2044C6BF0003C045 /* ShellScript */ = {
|
33CC111E2044C6BF0003C045 /* ShellScript */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
@ -392,7 +392,7 @@
|
|||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "if [[ \"${WORKSPACE_DIR:-}\" == *.xcodeproj ]]; then\n echo \"error: XWorkmate macOS builds with CocoaPods plugins must be launched from macos/Runner.xcworkspace, not Runner.xcodeproj.\" >&2\n echo \"error: Close this project, open macos/Runner.xcworkspace in Xcode, and build the shared Runner scheme for My Mac.\" >&2\n echo \"error: Pods targets appearing in the workspace are expected. Only configure signing on the Runner target.\" >&2\n echo \"error: For release packaging, run 'flutter build macos' from the repository root.\" >&2\n exit 1\nfi\n\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
|
shellScript = "export PATH=\"$PROJECT_DIR/../scripts/xcode-tools:$PATH\"\nif [[ \"${WORKSPACE_DIR:-}\" == *.xcodeproj ]]; then\n echo \"error: XWorkmate macOS builds with CocoaPods plugins must be launched from macos/Runner.xcworkspace, not Runner.xcodeproj.\" >&2\n echo \"error: Close this project, open macos/Runner.xcworkspace in Xcode, and build the shared Runner scheme for My Mac.\" >&2\n echo \"error: Pods targets appearing in the workspace are expected. Only configure signing on the Runner target.\" >&2\n echo \"error: For release packaging, run 'flutter build macos' from the repository root.\" >&2\n exit 1\nfi\n\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire";
|
||||||
};
|
};
|
||||||
8E8C2A3EBAA3461603096C04 /* [CP] Check Pods Manifest.lock */ = {
|
8E8C2A3EBAA3461603096C04 /* [CP] Check Pods Manifest.lock */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
@ -511,7 +511,7 @@
|
|||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MACOSX_DEPLOYMENT_TARGET = 14.0;
|
MACOSX_DEPLOYMENT_TARGET = 15.6;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
OTHER_CFLAGS = (
|
OTHER_CFLAGS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
@ -539,7 +539,7 @@
|
|||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MACOSX_DEPLOYMENT_TARGET = 14.0;
|
MACOSX_DEPLOYMENT_TARGET = 15.6;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
OTHER_CFLAGS = (
|
OTHER_CFLAGS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
@ -567,7 +567,7 @@
|
|||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MACOSX_DEPLOYMENT_TARGET = 14.0;
|
MACOSX_DEPLOYMENT_TARGET = 15.6;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
OTHER_CFLAGS = (
|
OTHER_CFLAGS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
@ -661,11 +661,13 @@
|
|||||||
ENABLE_RESOURCE_ACCESS_USB = NO;
|
ENABLE_RESOURCE_ACCESS_USB = NO;
|
||||||
ENABLE_USER_SELECTED_FILES = readonly;
|
ENABLE_USER_SELECTED_FILES = readonly;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = Xworkmate;
|
||||||
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/../Frameworks",
|
"@executable_path/../Frameworks",
|
||||||
);
|
);
|
||||||
MACOSX_DEPLOYMENT_TARGET = 14.0;
|
MACOSX_DEPLOYMENT_TARGET = 15.6;
|
||||||
OTHER_CFLAGS = (
|
OTHER_CFLAGS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"-Wno-ignored-attributes",
|
"-Wno-ignored-attributes",
|
||||||
@ -823,11 +825,13 @@
|
|||||||
ENABLE_RESOURCE_ACCESS_USB = NO;
|
ENABLE_RESOURCE_ACCESS_USB = NO;
|
||||||
ENABLE_USER_SELECTED_FILES = readonly;
|
ENABLE_USER_SELECTED_FILES = readonly;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = Xworkmate;
|
||||||
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/../Frameworks",
|
"@executable_path/../Frameworks",
|
||||||
);
|
);
|
||||||
MACOSX_DEPLOYMENT_TARGET = 14.0;
|
MACOSX_DEPLOYMENT_TARGET = 15.6;
|
||||||
OTHER_CFLAGS = (
|
OTHER_CFLAGS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"-Wno-ignored-attributes",
|
"-Wno-ignored-attributes",
|
||||||
@ -863,11 +867,13 @@
|
|||||||
ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;
|
ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;
|
||||||
ENABLE_USER_SELECTED_FILES = readonly;
|
ENABLE_USER_SELECTED_FILES = readonly;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = Xworkmate;
|
||||||
|
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/../Frameworks",
|
"@executable_path/../Frameworks",
|
||||||
);
|
);
|
||||||
MACOSX_DEPLOYMENT_TARGET = 14.0;
|
MACOSX_DEPLOYMENT_TARGET = 15.6;
|
||||||
OTHER_CFLAGS = (
|
OTHER_CFLAGS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"-Wno-ignored-attributes",
|
"-Wno-ignored-attributes",
|
||||||
|
|||||||
26
scripts/xcode-tools/lipo
Executable file
26
scripts/xcode-tools/lipo
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
real_lipo="$(xcrun --find lipo)"
|
||||||
|
args=("$@")
|
||||||
|
verify_index=-1
|
||||||
|
|
||||||
|
for ((index = 0; index < ${#args[@]}; index++)); do
|
||||||
|
if [[ "${args[index]}" == "-verify_arch" ]]; then
|
||||||
|
verify_index=$index
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Xcode 27 accepts one architecture per -verify_arch invocation. Flutter
|
||||||
|
# passes all requested architectures at once, so verify each one separately.
|
||||||
|
if ((verify_index >= 0 && ${#args[@]} - verify_index > 2)); then
|
||||||
|
command_prefix=("${args[@]:0:verify_index}")
|
||||||
|
architectures=("${args[@]:verify_index+1}")
|
||||||
|
for architecture in "${architectures[@]}"; do
|
||||||
|
"$real_lipo" "${command_prefix[@]}" -verify_arch "$architecture"
|
||||||
|
done
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$real_lipo" "$@"
|
||||||
@ -322,9 +322,7 @@ void main() {
|
|||||||
'xworkmate-no-runtime-main-home-',
|
'xworkmate-no-runtime-main-home-',
|
||||||
);
|
);
|
||||||
addTearDown(() async {
|
addTearDown(() async {
|
||||||
if (await localHome.exists()) {
|
await _resilientDelete(localHome);
|
||||||
await localHome.delete(recursive: true);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
final controller = _sandboxController(
|
final controller = _sandboxController(
|
||||||
environmentOverride: const <String, String>{},
|
environmentOverride: const <String, String>{},
|
||||||
@ -358,9 +356,7 @@ void main() {
|
|||||||
'xworkmate-refresh-no-session-one-',
|
'xworkmate-refresh-no-session-one-',
|
||||||
);
|
);
|
||||||
addTearDown(() async {
|
addTearDown(() async {
|
||||||
if (await localHome.exists()) {
|
await _resilientDelete(localHome);
|
||||||
await localHome.delete(recursive: true);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
final controller = _sandboxController(
|
final controller = _sandboxController(
|
||||||
environmentOverride: const <String, String>{},
|
environmentOverride: const <String, String>{},
|
||||||
@ -439,9 +435,7 @@ void main() {
|
|||||||
'xworkmate-stable-task-selection-home-',
|
'xworkmate-stable-task-selection-home-',
|
||||||
);
|
);
|
||||||
addTearDown(() async {
|
addTearDown(() async {
|
||||||
if (await localHome.exists()) {
|
await _resilientDelete(localHome);
|
||||||
await localHome.delete(recursive: true);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
final controller = _sandboxController(
|
final controller = _sandboxController(
|
||||||
environmentOverride: const <String, String>{},
|
environmentOverride: const <String, String>{},
|
||||||
@ -1716,9 +1710,7 @@ void main() {
|
|||||||
'xworkmate-acp-interrupt-artifacts-',
|
'xworkmate-acp-interrupt-artifacts-',
|
||||||
);
|
);
|
||||||
addTearDown(() async {
|
addTearDown(() async {
|
||||||
if (await localWorkspace.exists()) {
|
await _resilientDelete(localWorkspace);
|
||||||
await localWorkspace.delete(recursive: true);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
final fakeGoTaskService = _RecordingGoTaskServiceClient()
|
final fakeGoTaskService = _RecordingGoTaskServiceClient()
|
||||||
..onExecuteTask = ((request) async {
|
..onExecuteTask = ((request) async {
|
||||||
@ -2017,9 +2009,7 @@ void main() {
|
|||||||
'xworkmate-acp-handshake-interrupt-artifacts-',
|
'xworkmate-acp-handshake-interrupt-artifacts-',
|
||||||
);
|
);
|
||||||
addTearDown(() async {
|
addTearDown(() async {
|
||||||
if (await localWorkspace.exists()) {
|
await _resilientDelete(localWorkspace);
|
||||||
await localWorkspace.delete(recursive: true);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
final fakeGoTaskService = _RecordingGoTaskServiceClient()
|
final fakeGoTaskService = _RecordingGoTaskServiceClient()
|
||||||
..updatesBeforeNextOutcome.add(
|
..updatesBeforeNextOutcome.add(
|
||||||
@ -2383,9 +2373,7 @@ void main() {
|
|||||||
'xworkmate-background-completion-home-',
|
'xworkmate-background-completion-home-',
|
||||||
);
|
);
|
||||||
addTearDown(() async {
|
addTearDown(() async {
|
||||||
if (await localHome.exists()) {
|
await _resilientDelete(localHome);
|
||||||
await localHome.delete(recursive: true);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
final fakeGoTaskService = _BlockingGoTaskServiceClient();
|
final fakeGoTaskService = _BlockingGoTaskServiceClient();
|
||||||
final controller = _connectedController(
|
final controller = _connectedController(
|
||||||
@ -2508,9 +2496,7 @@ void main() {
|
|||||||
'xworkmate-same-prompt-home-',
|
'xworkmate-same-prompt-home-',
|
||||||
);
|
);
|
||||||
addTearDown(() async {
|
addTearDown(() async {
|
||||||
if (await localHome.exists()) {
|
await _resilientDelete(localHome);
|
||||||
await localHome.delete(recursive: true);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
final fakeGoTaskService = _BlockingGoTaskServiceClient();
|
final fakeGoTaskService = _BlockingGoTaskServiceClient();
|
||||||
final controller = _connectedController(
|
final controller = _connectedController(
|
||||||
@ -2683,9 +2669,7 @@ void main() {
|
|||||||
'xworkmate-same-prompt-empty-home-',
|
'xworkmate-same-prompt-empty-home-',
|
||||||
);
|
);
|
||||||
addTearDown(() async {
|
addTearDown(() async {
|
||||||
if (await localHome.exists()) {
|
await _resilientDelete(localHome);
|
||||||
await localHome.delete(recursive: true);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
final fakeGoTaskService = _BlockingGoTaskServiceClient();
|
final fakeGoTaskService = _BlockingGoTaskServiceClient();
|
||||||
final controller = _connectedController(
|
final controller = _connectedController(
|
||||||
@ -2707,9 +2691,7 @@ void main() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
final directory = Directory(workspace);
|
final directory = Directory(workspace);
|
||||||
if (await directory.exists()) {
|
await _resilientDelete(directory);
|
||||||
await directory.delete(recursive: true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -2845,9 +2827,7 @@ void main() {
|
|||||||
'xworkmate-terminal-failure-home-',
|
'xworkmate-terminal-failure-home-',
|
||||||
);
|
);
|
||||||
addTearDown(() async {
|
addTearDown(() async {
|
||||||
if (await localHome.exists()) {
|
await _resilientDelete(localHome);
|
||||||
await localHome.delete(recursive: true);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
final fakeGoTaskService = _BlockingGoTaskServiceClient();
|
final fakeGoTaskService = _BlockingGoTaskServiceClient();
|
||||||
final controller = _connectedController(
|
final controller = _connectedController(
|
||||||
@ -2925,9 +2905,7 @@ void main() {
|
|||||||
'xworkmate-empty-output-home-',
|
'xworkmate-empty-output-home-',
|
||||||
);
|
);
|
||||||
addTearDown(() async {
|
addTearDown(() async {
|
||||||
if (await localHome.exists()) {
|
await _resilientDelete(localHome);
|
||||||
await localHome.delete(recursive: true);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
final fakeGoTaskService = _BlockingGoTaskServiceClient();
|
final fakeGoTaskService = _BlockingGoTaskServiceClient();
|
||||||
final controller = _connectedController(
|
final controller = _connectedController(
|
||||||
@ -3297,9 +3275,7 @@ void main() {
|
|||||||
addTearDown(() async {
|
addTearDown(() async {
|
||||||
fakeGoTaskService.completeAll();
|
fakeGoTaskService.completeAll();
|
||||||
controller.dispose();
|
controller.dispose();
|
||||||
if (await localHome.exists()) {
|
await _resilientDelete(localHome);
|
||||||
await localHome.delete(recursive: true);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
for (
|
for (
|
||||||
@ -4902,19 +4878,28 @@ UiFeatureManifest _defaultDesktopManifest() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _resilientDelete(Directory dir) async {
|
Future<void> _resilientDelete(Directory dir) async {
|
||||||
|
for (var attempt = 0; attempt < 8; attempt++) {
|
||||||
if (!await dir.exists()) {
|
if (!await dir.exists()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (var attempt = 0; attempt < 8; attempt++) {
|
|
||||||
try {
|
try {
|
||||||
await dir.delete(recursive: true);
|
await dir.delete(recursive: true);
|
||||||
return;
|
return;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
// A background flush (e.g. controller dispose still persisting state)
|
||||||
|
// may keep writing into the temp dir, so a recursive delete can race
|
||||||
|
// and fail with "Directory not empty". Retry a few times.
|
||||||
debugPrint('Temporary directory delete retry: $error');
|
debugPrint('Temporary directory delete retry: $error');
|
||||||
await Future<void>.delayed(const Duration(milliseconds: 50));
|
await Future<void>.delayed(const Duration(milliseconds: 50));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Best-effort cleanup: never fail a test over leftover temp files; the OS
|
||||||
|
// reclaims the temp directory regardless.
|
||||||
|
try {
|
||||||
await dir.delete(recursive: true);
|
await dir.delete(recursive: true);
|
||||||
|
} catch (error) {
|
||||||
|
debugPrint('Giving up on temporary directory cleanup: $error');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AppController _sandboxController({
|
AppController _sandboxController({
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user