[SwiftPM] Add separate feature flag for the app migration (#158897)

<!--
Thanks for filing a pull request!
Reviewers are typically assigned within a week of filing a request.
To learn more about code review, see our documentation on Tree Hygiene:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
-->

### Overview

This splits the Swift Package Manager feature in two:

1. **SwiftPM feature**: This builds plugins using SwiftPM (if the app
supports it), and, uses the new app & plugin templates that support
SwiftPM
2. **SwiftPM app migration feature**: this updates an existing Flutter
iOS or macOS app to support Swift Package Manager. This feature requires
the SwiftPM feature - if SwiftPM is off, the app migration is also off.

For now, both features are off by default. We plan to turn on the first
feature in the next stable release. The app migration feature will be
stay off by default until we have higher confidence in the migration.

See this mini design doc:
https://github.com/flutter/flutter/issues/151567#issuecomment-2455941279

Here's the PR that updates the SwiftPM docs:
https://github.com/flutter/website/pull/11495

Part of https://github.com/flutter/flutter/issues/151567

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md

---------

Co-authored-by: Andrew Kolos <andrewrkolos@gmail.com>
This commit is contained in:
Loïc Sharma 2025-01-07 11:46:03 -08:00 committed by GitHub
parent 8273197bc7
commit e7a1b68086
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 434 additions and 13 deletions

View File

@ -54,6 +54,10 @@ abstract class FeatureFlags {
/// Whether Swift Package Manager dependency management is enabled.
bool get isSwiftPackageManagerEnabled => false;
/// Whether apps are automatically migrated to add Swift Package Manager
/// integration. Requires [isSwiftPackageManagerEnabled].
bool get isSwiftPackageManagerMigrationEnabled => false;
/// Whether explicit package dependency management is enabled.
bool get isExplicitPackageDependenciesEnabled => false;
@ -77,6 +81,7 @@ const List<Feature> allFeatures = <Feature>[
nativeAssets,
previewDevice,
swiftPackageManager,
swiftPackageManagerMigration,
explicitPackageDependencies,
];
@ -178,6 +183,16 @@ const Feature swiftPackageManager = Feature(
stable: FeatureChannelSetting(available: true),
);
/// Enable migrating iOS and macOS apps to add Swift Package Manager integration.
const Feature swiftPackageManagerMigration = Feature(
name: 'migrate iOS and macOS apps to add Swift Package Manager integration',
configSetting: 'enable-swift-package-manager-migration',
environmentOverride: 'FLUTTER_SWIFT_PACKAGE_MANAGER_MIGRATION',
master: FeatureChannelSetting(available: true),
beta: FeatureChannelSetting(available: true),
stable: FeatureChannelSetting(available: true),
);
/// Enable explicit resolution and generation of package dependencies.
const Feature explicitPackageDependencies = Feature(
name: 'support for dev_dependency plugins',

View File

@ -61,6 +61,15 @@ class FlutterFeatureFlags implements FeatureFlags {
@override
bool get isSwiftPackageManagerEnabled => isEnabled(swiftPackageManager);
@override
bool get isSwiftPackageManagerMigrationEnabled {
if (!isEnabled(swiftPackageManager)) {
return false;
}
return isEnabled(swiftPackageManagerMigration);
}
@override
bool get isExplicitPackageDependenciesEnabled => isEnabled(explicitPackageDependencies);

View File

@ -118,6 +118,14 @@ class SwiftPackageManagerIntegrationMigration extends ProjectMigrator {
return;
}
if (!_features.isSwiftPackageManagerMigrationEnabled) {
logger.printTrace(
'The migration to add Swift Package Manager integration is off. '
'Skipping...',
);
return;
}
if (!_xcodeProject.flutterPluginSwiftPackageManifest.existsSync()) {
logger.printTrace(
'The tool did not generate a Swift package. '

View File

@ -182,6 +182,15 @@ abstract class XcodeBasedProject extends FlutterProjectPlatform {
return false;
}
// If the project doesn't have Swift Package Manager integration yet,
// the SwiftPM migration feature is required (as that will add SwiftPM
// integration to the project).
if (!flutterPluginSwiftPackageInProjectSettings) {
if (!featureFlags.isSwiftPackageManagerMigrationEnabled) {
return false;
}
}
return true;
}

View File

@ -409,7 +409,7 @@ void main() {
});
group('Swift Package Manager feature', () {
test('availability and default enabled', () {
testWithoutContext('availability and default enabled', () {
expect(swiftPackageManager.master.enabledByDefault, false);
expect(swiftPackageManager.master.available, true);
expect(swiftPackageManager.beta.enabledByDefault, false);
@ -418,11 +418,52 @@ void main() {
expect(swiftPackageManager.stable.available, true);
});
test('can be enabled', () {
testWithoutContext('can be enabled', () {
platform.environment = <String, String>{'FLUTTER_SWIFT_PACKAGE_MANAGER': 'true'};
expect(featureFlags.isSwiftPackageManagerEnabled, isTrue);
});
});
group('Swift Package Manager app migration feature', () {
testWithoutContext('availability and default enabled', () {
expect(swiftPackageManagerMigration.master.enabledByDefault, false);
expect(swiftPackageManagerMigration.master.available, true);
expect(swiftPackageManagerMigration.beta.enabledByDefault, false);
expect(swiftPackageManagerMigration.beta.available, true);
expect(swiftPackageManagerMigration.stable.enabledByDefault, false);
expect(swiftPackageManagerMigration.stable.available, true);
});
testWithoutContext('requires Swift Package Manager feature', () {
platform.environment = <String, String>{
'FLUTTER_SWIFT_PACKAGE_MANAGER': 'false',
'FLUTTER_SWIFT_PACKAGE_MANAGER_MIGRATION': 'true',
};
expect(featureFlags.isSwiftPackageManagerEnabled, isFalse);
expect(featureFlags.isSwiftPackageManagerMigrationEnabled, isFalse);
});
testWithoutContext('is separate from the Swift Package Manager feature', () {
platform.environment = <String, String>{
'FLUTTER_SWIFT_PACKAGE_MANAGER': 'true',
'FLUTTER_SWIFT_PACKAGE_MANAGER_MIGRATION': 'false',
};
expect(featureFlags.isSwiftPackageManagerEnabled, isTrue);
expect(featureFlags.isSwiftPackageManagerMigrationEnabled, isFalse);
});
testWithoutContext('can be enabled', () {
platform.environment = <String, String>{
'FLUTTER_SWIFT_PACKAGE_MANAGER': 'true',
'FLUTTER_SWIFT_PACKAGE_MANAGER_MIGRATION': 'true',
};
expect(featureFlags.isSwiftPackageManagerEnabled, isTrue);
expect(featureFlags.isSwiftPackageManagerEnabled, isTrue);
});
});
});
}

View File

@ -566,7 +566,11 @@ void main() {
expect(fakeProcessManager, hasNoRemainingExpectations);
},
overrides: <Type, Generator>{
FeatureFlags: () => TestFeatureFlags(isSwiftPackageManagerEnabled: true),
FeatureFlags:
() => TestFeatureFlags(
isSwiftPackageManagerEnabled: true,
isSwiftPackageManagerMigrationEnabled: true,
),
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(version: Version(15, 0, 0)),
},
);

View File

@ -25,10 +25,11 @@ const List<SupportedPlatform> supportedPlatforms = <SupportedPlatform>[
void main() {
final TestFeatureFlags swiftPackageManagerFullyEnabledFlags = TestFeatureFlags(
isSwiftPackageManagerEnabled: true,
isSwiftPackageManagerMigrationEnabled: true,
);
group('Flutter Package Migration', () {
testWithoutContext('skips if swift package manager is off', () async {
testWithoutContext('skips if Swift Package Manager is off', () async {
final MemoryFileSystem memoryFileSystem = MemoryFileSystem();
final BufferLogger testLogger = BufferLogger.test();
@ -45,8 +46,9 @@ void main() {
logger: testLogger,
fileSystem: memoryFileSystem,
plistParser: FakePlistParser(),
features: TestFeatureFlags(),
features: TestFeatureFlags(isSwiftPackageManagerMigrationEnabled: true),
);
await projectMigration.migrate();
expect(
testLogger.traceText,
@ -55,6 +57,36 @@ void main() {
expect(testLogger.statusText, isEmpty);
});
testWithoutContext('skips if Swift Package Manager migration is off', () async {
final MemoryFileSystem memoryFileSystem = MemoryFileSystem();
final BufferLogger testLogger = BufferLogger.test();
final SwiftPackageManagerIntegrationMigration projectMigration =
SwiftPackageManagerIntegrationMigration(
FakeXcodeProject(
platform: SupportedPlatform.ios.name,
fileSystem: memoryFileSystem,
logger: testLogger,
),
SupportedPlatform.ios,
BuildInfo.debug,
xcodeProjectInterpreter: FakeXcodeProjectInterpreter(),
logger: testLogger,
fileSystem: memoryFileSystem,
plistParser: FakePlistParser(),
features: TestFeatureFlags(isSwiftPackageManagerEnabled: true),
);
await projectMigration.migrate();
expect(
testLogger.traceText,
contains(
'The migration to add Swift Package Manager integration is off. '
'Skipping...',
),
);
expect(testLogger.statusText, isEmpty);
});
testWithoutContext("skips if there's no generated swift package", () async {
final MemoryFileSystem memoryFileSystem = MemoryFileSystem();
final BufferLogger testLogger = BufferLogger.test();

View File

@ -122,7 +122,7 @@ void main() {
group('usesSwiftPackageManager', () {
testUsingContext(
'is true when iOS project exists',
'is true if the feature is on',
() async {
final MemoryFileSystem fs = MemoryFileSystem.test();
final Directory projectDirectory = fs.directory('path');
@ -131,6 +131,35 @@ void main() {
final FlutterProject project = FlutterProject(projectDirectory, manifest, manifest);
expect(project.ios.usesSwiftPackageManager, isTrue);
},
overrides: <Type, Generator>{
FeatureFlags:
() => TestFeatureFlags(
isSwiftPackageManagerEnabled: true,
isSwiftPackageManagerMigrationEnabled: true,
),
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(version: Version(15, 0, 0)),
},
);
testUsingContext(
'is true if migration feature is off but project is migrated',
() async {
final MemoryFileSystem fs = MemoryFileSystem.test();
final Directory projectDirectory = fs.directory('path');
projectDirectory.childDirectory('ios').createSync(recursive: true);
// Create an Xcode project that appears to have SwiftPM integration.
final File xcodeProjectFile = projectDirectory
.childDirectory('ios')
.childDirectory('Runner.xcodeproj')
.childFile('project.pbxproj');
xcodeProjectFile.createSync(recursive: true);
xcodeProjectFile.writeAsStringSync('FlutterGeneratedPluginSwiftPackage');
final FlutterManifest manifest = FakeFlutterManifest();
final FlutterProject project = FlutterProject(projectDirectory, manifest, manifest);
expect(project.ios.usesSwiftPackageManager, isTrue);
},
overrides: <Type, Generator>{
FeatureFlags: () => TestFeatureFlags(isSwiftPackageManagerEnabled: true),
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(version: Version(15, 0, 0)),
@ -254,7 +283,7 @@ void main() {
group('usesSwiftPackageManager', () {
testUsingContext(
'is true when macOS project exists',
'is true if feature on',
() async {
final MemoryFileSystem fs = MemoryFileSystem.test();
final Directory projectDirectory = fs.directory('path');
@ -263,6 +292,35 @@ void main() {
final FlutterProject project = FlutterProject(projectDirectory, manifest, manifest);
expect(project.macos.usesSwiftPackageManager, isTrue);
},
overrides: <Type, Generator>{
FeatureFlags:
() => TestFeatureFlags(
isSwiftPackageManagerEnabled: true,
isSwiftPackageManagerMigrationEnabled: true,
),
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(version: Version(15, 0, 0)),
},
);
testUsingContext(
'is true if migration feature is off but project is migrated',
() async {
final MemoryFileSystem fs = MemoryFileSystem.test();
final Directory projectDirectory = fs.directory('path');
projectDirectory.childDirectory('macos').createSync(recursive: true);
// Create an Xcode project that appears to have SwiftPM integration.
final File xcodeProjectFile = projectDirectory
.childDirectory('macos')
.childDirectory('Runner.xcodeproj')
.childFile('project.pbxproj');
xcodeProjectFile.createSync(recursive: true);
xcodeProjectFile.writeAsStringSync('FlutterGeneratedPluginSwiftPackage');
final FlutterManifest manifest = FakeFlutterManifest();
final FlutterProject project = FlutterProject(projectDirectory, manifest, manifest);
expect(project.macos.usesSwiftPackageManager, isTrue);
},
overrides: <Type, Generator>{
FeatureFlags: () => TestFeatureFlags(isSwiftPackageManagerEnabled: true),
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreter(version: Version(15, 0, 0)),

View File

@ -861,4 +861,210 @@ void main() {
expect(generatedManifest, contains(emptyDependencies));
expect(cocoaPodsPluginFramework, exists);
}, skip: !platform.isMacOS); // [intended] Swift Package Manager only works on macos.
test(
'App is not migrated if Swift Package Manager is turned on but not migration',
() async {
final Directory workingDirectory = fileSystem.systemTempDirectory.createTempSync(
'swift_package_manager_spm_on_migration_off_legacy_app.',
);
final String workingDirectoryPath = workingDirectory.path;
addTearDown(() async {
await SwiftPackageManagerUtils.disableSwiftPackageManager(flutterBin, workingDirectoryPath);
ErrorHandlingFileSystem.deleteIfExists(workingDirectory, recursive: true);
});
// Create an app that uses CocoaPods.
await SwiftPackageManagerUtils.disableSwiftPackageManager(flutterBin, workingDirectoryPath);
final String appDirectoryPath = await SwiftPackageManagerUtils.createApp(
flutterBin,
workingDirectoryPath,
iosLanguage: 'swift',
platform: 'ios',
options: <String>['--platforms=ios'],
);
final SwiftPackageManagerPlugin integrationTestPlugin =
SwiftPackageManagerUtils.integrationTestPlugin('ios');
SwiftPackageManagerUtils.addDependency(
appDirectoryPath: appDirectoryPath,
plugin: integrationTestPlugin,
);
await SwiftPackageManagerUtils.buildApp(
flutterBin,
appDirectoryPath,
options: <String>['ios', '--config-only', '-v'],
);
// Turn on the Swift Package Manager feature but not the app migration
// and build the app.
await SwiftPackageManagerUtils.cleanApp(flutterBin, appDirectoryPath);
await SwiftPackageManagerUtils.enableSwiftPackageManager(
flutterBin,
workingDirectoryPath,
enableMigration: false,
);
await SwiftPackageManagerUtils.buildApp(
flutterBin,
appDirectoryPath,
options: <String>['ios', '-v'],
);
// The app should be built using CocoaPods.
// The app should not have been migrated to add SwiftPM integration.
final File xcodeProjectFile = fileSystem
.directory(appDirectoryPath)
.childDirectory('ios')
.childDirectory('Runner.xcodeproj')
.childFile('project.pbxproj');
final File generatedManifestFile = fileSystem
.directory(appDirectoryPath)
.childDirectory('ios')
.childDirectory('Flutter')
.childDirectory('ephemeral')
.childDirectory('Packages')
.childDirectory('FlutterGeneratedPluginSwiftPackage')
.childFile('Package.swift');
final Directory cocoaPodsPluginFramework = fileSystem
.directory(appDirectoryPath)
.childDirectory('build')
.childDirectory('ios')
.childDirectory('iphoneos')
.childDirectory('Runner.app')
.childDirectory('Frameworks')
.childDirectory('${integrationTestPlugin.pluginName}.framework');
expect(xcodeProjectFile, exists);
expect(generatedManifestFile, isNot(exists));
expect(cocoaPodsPluginFramework, exists);
expect(
xcodeProjectFile.readAsStringSync(),
isNot(contains('FlutterGeneratedPluginSwiftPackage')),
);
},
skip: !platform.isMacOS, // [intended] Swift Package Manager only works on macos.
);
test('iOS can use Swift Package Manager while macOS uses CocoaPods', () async {
final Directory workingDirectory = fileSystem.systemTempDirectory.createTempSync(
'swift_package_manager_ios_on_cocoapods_macos_on_swiftpm.',
);
final String workingDirectoryPath = workingDirectory.path;
addTearDown(() async {
await SwiftPackageManagerUtils.disableSwiftPackageManager(flutterBin, workingDirectoryPath);
ErrorHandlingFileSystem.deleteIfExists(workingDirectory, recursive: true);
});
// Create an app that uses CocoaPods.
await SwiftPackageManagerUtils.disableSwiftPackageManager(flutterBin, workingDirectoryPath);
final String appDirectoryPath = await SwiftPackageManagerUtils.createApp(
flutterBin,
workingDirectoryPath,
iosLanguage: 'swift',
platform: 'ios',
options: <String>['--platforms=ios,macos'],
);
final SwiftPackageManagerPlugin integrationTestPlugin =
SwiftPackageManagerUtils.integrationTestPlugin('ios');
SwiftPackageManagerUtils.addDependency(
appDirectoryPath: appDirectoryPath,
plugin: integrationTestPlugin,
);
await SwiftPackageManagerUtils.buildApp(
flutterBin,
appDirectoryPath,
options: <String>['ios', '--config-only', '-v'],
);
// Turn on the Swift Package Manager feature and its migration and build
// the iOS app. This migrates the iOS app to Swift Package Manager - but not
// the macOS app!
await SwiftPackageManagerUtils.cleanApp(flutterBin, appDirectoryPath);
await SwiftPackageManagerUtils.enableSwiftPackageManager(flutterBin, workingDirectoryPath);
await SwiftPackageManagerUtils.buildApp(
flutterBin,
appDirectoryPath,
options: <String>['ios', '-v'],
);
// Turn off the migration but turn on the Swift Package Manager feature.
await SwiftPackageManagerUtils.cleanApp(flutterBin, appDirectoryPath);
await SwiftPackageManagerUtils.disableSwiftPackageManager(flutterBin, workingDirectoryPath);
await SwiftPackageManagerUtils.enableSwiftPackageManager(
flutterBin,
workingDirectoryPath,
enableMigration: false,
);
// Build the iOS and macOS apps. iOS should build using Swift Package Manager,
// macOS should build using CocoaPods.
await SwiftPackageManagerUtils.buildApp(
flutterBin,
appDirectoryPath,
options: <String>['ios', '--config-only', '-v'],
);
await SwiftPackageManagerUtils.buildApp(
flutterBin,
appDirectoryPath,
options: <String>['macos', '--config-only', '-v'],
);
final File flutterPluginsDependenciesFile = fileSystem
.directory(appDirectoryPath)
.childFile('.flutter-plugins-dependencies');
final File generatedSwiftPackageIos = fileSystem
.directory(appDirectoryPath)
.childDirectory('ios')
.childDirectory('Flutter')
.childDirectory('ephemeral')
.childDirectory('Packages')
.childDirectory('FlutterGeneratedPluginSwiftPackage')
.childFile('Package.swift');
final File generatedSwiftPackageMacos = fileSystem
.directory(appDirectoryPath)
.childDirectory('macos')
.childDirectory('Flutter')
.childDirectory('ephemeral')
.childDirectory('Packages')
.childDirectory('FlutterGeneratedPluginSwiftPackage')
.childFile('Package.swift');
final File xcodeProjectFileIos = fileSystem
.directory(appDirectoryPath)
.childDirectory('ios')
.childDirectory('Runner.xcodeproj')
.childFile('project.pbxproj');
final File xcodeProjectFileMacos = fileSystem
.directory(appDirectoryPath)
.childDirectory('macos')
.childDirectory('Runner.xcodeproj')
.childFile('project.pbxproj');
// The build should have used SwiftPM for iOS but CocoaPods for macOS.
expect(flutterPluginsDependenciesFile, exists);
expect(generatedSwiftPackageIos, exists);
expect(generatedSwiftPackageMacos, isNot(exists));
expect(xcodeProjectFileIos, exists);
expect(xcodeProjectFileMacos, exists);
final String dependenciesString = flutterPluginsDependenciesFile.readAsStringSync();
final Map<String, dynamic> dependenciesJson =
json.decode(dependenciesString) as Map<String, dynamic>;
expect(dependenciesJson['swift_package_manager_enabled'], <String, bool>{
'ios': true,
'macos': false,
});
expect(xcodeProjectFileIos.readAsStringSync(), contains('FlutterGeneratedPluginSwiftPackage'));
expect(
xcodeProjectFileMacos.readAsStringSync(),
isNot(contains('FlutterGeneratedPluginSwiftPackage')),
);
}, skip: !platform.isMacOS); // [intended] Swift Package Manager only works on macos.
}

View File

@ -6,43 +6,78 @@ import 'dart:convert';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/features.dart';
import '../src/common.dart';
import 'test_utils.dart';
class SwiftPackageManagerUtils {
static Future<void> enableSwiftPackageManager(String flutterBin, String workingDirectory) async {
static Future<void> enableSwiftPackageManager(
String flutterBin,
String workingDirectory, {
bool enableMigration = true,
}) async {
await _enableFeature(flutterBin, workingDirectory, swiftPackageManager);
if (enableMigration) {
await _enableFeature(flutterBin, workingDirectory, swiftPackageManagerMigration);
}
}
static Future<void> disableSwiftPackageManager(
String flutterBin,
String workingDirectory, {
bool disableMigration = true,
}) async {
if (disableMigration) {
await _disableFeature(flutterBin, workingDirectory, swiftPackageManagerMigration);
}
await _disableFeature(flutterBin, workingDirectory, swiftPackageManager);
}
static Future<void> _enableFeature(
String flutterBin,
String workingDirectory,
Feature feature,
) async {
final ProcessResult result = await processManager.run(<String>[
flutterBin,
...getLocalEngineArguments(),
'config',
'--enable-swift-package-manager',
'--${feature.configSetting}',
'-v',
], workingDirectory: workingDirectory);
expect(
result.exitCode,
0,
reason:
'Failed to enable Swift Package Manager: \n'
'Failed to enable feature "${feature.name}": \n'
'stdout: \n${result.stdout}\n'
'stderr: \n${result.stderr}\n',
verbose: true,
);
}
static Future<void> disableSwiftPackageManager(String flutterBin, String workingDirectory) async {
static Future<void> _disableFeature(
String flutterBin,
String workingDirectory,
Feature feature,
) async {
final ProcessResult result = await processManager.run(<String>[
flutterBin,
...getLocalEngineArguments(),
'config',
'--no-enable-swift-package-manager',
'--no-${feature.configSetting}',
'-v',
], workingDirectory: workingDirectory);
expect(
result.exitCode,
0,
reason:
'Failed to disable Swift Package Manager: \n'
'Failed to disable feature "${feature.name}": \n'
'stdout: \n${result.stdout}\n'
'stderr: \n${result.stderr}\n',
verbose: true,

View File

@ -489,6 +489,7 @@ class TestFeatureFlags implements FeatureFlags {
this.isNativeAssetsEnabled = false,
this.isPreviewDeviceEnabled = false,
this.isSwiftPackageManagerEnabled = false,
this.isSwiftPackageManagerMigrationEnabled = false,
this.isExplicitPackageDependenciesEnabled = false,
});
@ -528,6 +529,9 @@ class TestFeatureFlags implements FeatureFlags {
@override
final bool isSwiftPackageManagerEnabled;
@override
final bool isSwiftPackageManagerMigrationEnabled;
@override
final bool isExplicitPackageDependenciesEnabled;