diff --git a/.ci/targets/ios_platform_tests.yaml b/.ci/targets/ios_platform_tests.yaml index 262de31fb93f..08eaaf54c15a 100644 --- a/.ci/targets/ios_platform_tests.yaml +++ b/.ci/targets/ios_platform_tests.yaml @@ -7,7 +7,7 @@ tasks: infra_step: true # Note infra steps failing prevents "always" from running. - name: download Dart and iOS deps script: .ci/scripts/tool_runner.sh - args: ["fetch-deps", "--ios", "--supporting-target-platforms-only"] + args: ["fetch-deps", "--ios", "--supporting-target-platforms-only", "--swift-package-manager"] infra_step: true - name: build examples script: .ci/scripts/tool_runner.sh diff --git a/.ci/targets/macos_platform_tests.yaml b/.ci/targets/macos_platform_tests.yaml index 6756fa7e490f..ab8b033d09c6 100644 --- a/.ci/targets/macos_platform_tests.yaml +++ b/.ci/targets/macos_platform_tests.yaml @@ -4,7 +4,7 @@ tasks: infra_step: true # Note infra steps failing prevents "always" from running. - name: download Dart and macOS deps script: .ci/scripts/tool_runner.sh - args: ["fetch-deps", "--macos", "--supporting-target-platforms-only"] + args: ["fetch-deps", "--macos", "--supporting-target-platforms-only", "--swift-package-manager"] infra_step: true - name: build examples script: .ci/scripts/tool_runner.sh diff --git a/script/tool/lib/src/fetch_deps_command.dart b/script/tool/lib/src/fetch_deps_command.dart index 0645bd08836d..9243a10bc4fb 100644 --- a/script/tool/lib/src/fetch_deps_command.dart +++ b/script/tool/lib/src/fetch_deps_command.dart @@ -78,9 +78,11 @@ class FetchDepsCommand extends PackageLoopingCommand { 'Include packages with Windows examples when used with ' '--$_supportingTargetPlatformsOnlyFlag', ); + argParser.addFlag(_swiftPackageManagerFlag, defaultsTo: null); } static const String _dartFlag = 'dart'; + static const String _swiftPackageManagerFlag = 'swift-package-manager'; static const String _supportingTargetPlatformsOnlyFlag = 'supporting-target-platforms-only'; @@ -101,18 +103,24 @@ class FetchDepsCommand extends PackageLoopingCommand { @override Future initializeRun() async { - // `pod install` requires having the platform artifacts precached. See - // https://github.com/flutter/flutter/blob/fb7a763c640d247d090cbb373e4b3a0459ac171b/packages/flutter_tools/bin/podhelper.rb#L47 - // https://github.com/flutter/flutter/blob/fb7a763c640d247d090cbb373e4b3a0459ac171b/packages/flutter_tools/bin/podhelper.rb#L130 - final bool precacheIOS = getBoolArg(platformIOS); - final bool precacheMacOS = getBoolArg(platformMacOS); - if (precacheIOS || precacheMacOS) { + final bool includeIOS = getBoolArg(platformIOS); + final bool includeMacOS = getBoolArg(platformMacOS); + // TODO(stuartmorgan): Flip the default to true once SwiftPM is on by + // default on stable. For now this will have the wrong default on stable, + // but that's fine since we are usually providing an explicit flag for now. + final bool usesCocoaPods = + (includeIOS || includeMacOS) && + !(getNullableBoolArg(_swiftPackageManagerFlag) ?? false); + if (usesCocoaPods) { + // `pod install` requires having the platform artifacts precached. See + // https://github.com/flutter/flutter/blob/fb7a763c640d247d090cbb373e4b3a0459ac171b/packages/flutter_tools/bin/podhelper.rb#L47 + // https://github.com/flutter/flutter/blob/fb7a763c640d247d090cbb373e4b3a0459ac171b/packages/flutter_tools/bin/podhelper.rb#L130 final int precacheExitCode = await processRunner.runAndStream( flutterCommand, [ 'precache', - if (precacheIOS) '--ios', - if (precacheMacOS) '--macos', + if (includeIOS) '--ios', + if (includeMacOS) '--macos', ], ); if (precacheExitCode != 0) { @@ -128,6 +136,13 @@ class FetchDepsCommand extends PackageLoopingCommand { } } + bool? get _swiftPackageManagerFeatureConfig { + if (!getBoolArg(platformIOS) && !getBoolArg(platformMacOS)) { + return null; + } + return getNullableBoolArg(_swiftPackageManagerFlag); + } + @override Future runForPackage(RepositoryPackage package) async { var fetchedDeps = false; @@ -158,9 +173,40 @@ class FetchDepsCommand extends PackageLoopingCommand { case FlutterPlatform.android: result = await _fetchAndroidDeps(package); case FlutterPlatform.ios: - result = await _fetchDarwinDeps(package, platformIOS); case FlutterPlatform.macos: - result = await _fetchDarwinDeps(package, platformMacOS); + { + final bool? swiftPackageManagerOverride = + _swiftPackageManagerFeatureConfig; + final String platformString = platform == FlutterPlatform.ios + ? platformIOS + : platformMacOS; + // Rather than changing global config state, enable SwiftPM via a + // temporary package-level override. + if (swiftPackageManagerOverride != null) { + for (final RepositoryPackage example in package.getExamples()) { + print( + 'Overriding enable-swift-package-manager to ' + '$swiftPackageManagerOverride', + ); + setSwiftPackageManagerState( + example, + enabled: swiftPackageManagerOverride, + ); + } + } + + result = await _fetchDarwinDeps(package, platformString); + + // If an override was added, remove it. + if (swiftPackageManagerOverride != null) { + for (final RepositoryPackage example in package.getExamples()) { + print('Removing enable-swift-package-manager override'); + setSwiftPackageManagerState(example, enabled: null); + } + } + break; + } + case FlutterPlatform.linux: case FlutterPlatform.web: case FlutterPlatform.windows: diff --git a/script/tool/test/drive_examples_command_test.dart b/script/tool/test/drive_examples_command_test.dart index e9d1cc2e0826..f4aebdb569ac 100644 --- a/script/tool/test/drive_examples_command_test.dart +++ b/script/tool/test/drive_examples_command_test.dart @@ -48,8 +48,6 @@ void main() { ); runner.addCommand(command); - // TODO(dit): Clean this up, https://github.com/flutter/flutter/issues/151869 - mockPlatform.environment['CHANNEL'] = 'master'; mockPlatform.environment['FLUTTER_LOGS_DIR'] = '/path/to/logs'; }); diff --git a/script/tool/test/fetch_deps_command_test.dart b/script/tool/test/fetch_deps_command_test.dart index 57c3a8c277a1..8a59663e7ff7 100644 --- a/script/tool/test/fetch_deps_command_test.dart +++ b/script/tool/test/fetch_deps_command_test.dart @@ -525,7 +525,6 @@ void main() { mockPlatform, )] = [ FakeProcessInfo(MockProcess(), ['precache']), - FakeProcessInfo(MockProcess(), ['repo', 'update']), FakeProcessInfo(MockProcess(exitCode: 1), [ 'build', 'ios', @@ -650,7 +649,6 @@ void main() { mockPlatform, )] = [ FakeProcessInfo(MockProcess(), ['precache']), - FakeProcessInfo(MockProcess(), ['repo', 'update']), FakeProcessInfo(MockProcess(exitCode: 1), [ 'build', 'macos', @@ -716,5 +714,143 @@ void main() { ); }); }); + + group('swift-package-manager', () { + for (final platformName in [platformIOS, platformMacOS]) { + group(platformName, () { + test('is not set by default', () async { + mockPlatform.isMacOS = true; + final RepositoryPackage plugin = createFakePlugin( + 'plugin1', + packagesDir, + platformSupport: { + platformName: const PlatformDetails(PlatformSupport.inline), + }, + ); + final RepositoryPackage example = plugin.getExamples().first; + final String originalPubspecContents = example.pubspecFile + .readAsStringSync(); + String? buildTimePubspecContents; + processRunner.mockProcessesForExecutable[getFlutterCommand( + mockPlatform, + )] = [ + FakeProcessInfo(MockProcess(), ['precache']), + FakeProcessInfo(MockProcess(), ['build'], () { + buildTimePubspecContents = example.pubspecFile + .readAsStringSync(); + }), + ]; + + await runCapturingPrint(runner, [ + 'fetch-deps', + '--no-dart', + '--$platformName', + ]); + + // Ensure that SwiftPM was not set at build time. + expect( + buildTimePubspecContents, + isNot(contains('enable-swift-package-manager')), + ); + // And that the pubspec wasn't changed at all. + expect( + example.pubspecFile.readAsStringSync().trim(), + originalPubspecContents.trim(), + ); + }); + + test('can be enabled', () async { + mockPlatform.isMacOS = true; + final RepositoryPackage plugin = createFakePlugin( + 'plugin1', + packagesDir, + platformSupport: { + platformName: const PlatformDetails(PlatformSupport.inline), + }, + ); + final RepositoryPackage example = plugin.getExamples().first; + final String originalPubspecContents = example.pubspecFile + .readAsStringSync(); + String? buildTimePubspecContents; + processRunner.mockProcessesForExecutable[getFlutterCommand( + mockPlatform, + )] = [ + FakeProcessInfo(MockProcess(), ['build'], () { + buildTimePubspecContents = example.pubspecFile + .readAsStringSync(); + }), + ]; + + await runCapturingPrint(runner, [ + 'fetch-deps', + '--no-dart', + '--$platformName', + '--swift-package-manager', + ]); + + // Ensure that SwiftPM was enabled for the package. + expect( + originalPubspecContents, + isNot(contains('enable-swift-package-manager: true')), + ); + expect( + buildTimePubspecContents, + contains('enable-swift-package-manager: true'), + ); + // And that it was undone after. + expect( + example.pubspecFile.readAsStringSync().trim(), + originalPubspecContents.trim(), + ); + }); + + test('can be disabled', () async { + mockPlatform.isMacOS = true; + final RepositoryPackage plugin = createFakePlugin( + 'plugin1', + packagesDir, + platformSupport: { + platformName: const PlatformDetails(PlatformSupport.inline), + }, + ); + final RepositoryPackage example = plugin.getExamples().first; + final String originalPubspecContents = example.pubspecFile + .readAsStringSync(); + String? buildTimePubspecContents; + processRunner.mockProcessesForExecutable[getFlutterCommand( + mockPlatform, + )] = [ + FakeProcessInfo(MockProcess(), ['precache']), + FakeProcessInfo(MockProcess(), ['build'], () { + buildTimePubspecContents = example.pubspecFile + .readAsStringSync(); + }), + ]; + + await runCapturingPrint(runner, [ + 'fetch-deps', + '--no-dart', + '--$platformName', + '--no-swift-package-manager', + ]); + + // Ensure that SwiftPM was disabled for the package. + expect( + originalPubspecContents, + isNot(contains('enable-swift-package-manager: false')), + ); + expect( + buildTimePubspecContents, + contains('enable-swift-package-manager: false'), + ); + // And that it was undone after. + expect( + example.pubspecFile.readAsStringSync().trim(), + originalPubspecContents.trim(), + ); + }); + }); + } + }); }); }