Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CI steps to test iOS and macOS plugins with both CocoaPods and Swift Package Manager #6557

Merged
merged 6 commits into from
Apr 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .ci/targets/ios_platform_tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ tasks:
infra_step: true
- name: build examples
script: .ci/scripts/tool_runner.sh
args: ["build-examples", "--ios"]
args: ["build-examples", "--ios", "--swift-package-manager"]
- name: xcode analyze
script: .ci/scripts/tool_runner.sh
args: ["xcode-analyze", "--ios"]
Expand Down
2 changes: 1 addition & 1 deletion .ci/targets/macos_platform_tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ tasks:
infra_step: true
- name: build examples
script: .ci/scripts/tool_runner.sh
args: ["build-examples", "--macos"]
args: ["build-examples", "--macos", "--swift-package-manager"]
- name: xcode analyze
script: .ci/scripts/tool_runner.sh
args: ["xcode-analyze", "--macos"]
Expand Down
24 changes: 24 additions & 0 deletions script/tool/lib/src/build_examples_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ const String _flutterBuildTypeWindows = 'windows';

const String _flutterBuildTypeAndroidAlias = 'android';

/// Key for Swift Package Manager.
const String _swiftPackageManagerFlag = 'swift-package-manager';

/// A command to build the example applications for packages.
class BuildExamplesCommand extends PackageLoopingCommand {
/// Creates an instance of the build command.
Expand All @@ -58,6 +61,7 @@ class BuildExamplesCommand extends PackageLoopingCommand {
defaultsTo: '',
help: 'Enables the given Dart SDK experiments.',
);
argParser.addFlag(_swiftPackageManagerFlag);
}

// Maps the switch this command uses to identify a platform to information
Expand Down Expand Up @@ -111,6 +115,15 @@ class BuildExamplesCommand extends PackageLoopingCommand {
'single key "$_pluginToolsConfigGlobalKey" containing a list of build '
'arguments.';

/// Returns true if `--swift-package-manager` flag was passed along with
/// either `--ios` or `--macos`.
bool get usingSwiftPackageManager {
final List<String> platformFlags = _platforms.keys.toList();
return getBoolArg(_swiftPackageManagerFlag) &&
(platformFlags.contains(platformIOS) ||
platformFlags.contains(platformMacOS));
}

@override
Future<void> initializeRun() async {
final List<String> platformFlags = _platforms.keys.toList();
Expand All @@ -121,6 +134,17 @@ class BuildExamplesCommand extends PackageLoopingCommand {
'were specified. At least one platform must be provided.');
throw ToolExit(_exitNoPlatformFlags);
}

// TODO(vashworth): Enable on stable once Swift Package Manager feature is
// available on stable.
if (usingSwiftPackageManager &&
platform.environment['CHANNEL'] != 'stable') {
await processRunner.runAndStream(
flutterCommand,
<String>['config', '--enable-swift-package-manager'],
exitOnError: true,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will explode on our stable tests (which you aren't seeing in presubmit because we only run native stable tests on post-submit to reduce CI utilization). You'll need to gate either the whole call, or just exiting on failure, on a Platform.environment['CHANNEL'] != 'stable' check for now, with a TODO to enable it for stable once the flag is available there.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

);
}
}

@override
Expand Down
172 changes: 172 additions & 0 deletions script/tool/test/build_examples_command_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,98 @@ void main() {
]));
});

test('building for iOS with Swift Package Manager on master channel',
() async {
mockPlatform.isMacOS = true;
mockPlatform.environment['CHANNEL'] = 'master';

final RepositoryPackage plugin = createFakePlugin('plugin', packagesDir,
platformSupport: <String, PlatformDetails>{
platformIOS: const PlatformDetails(PlatformSupport.inline),
});

final Directory pluginExampleDirectory = getExampleDir(plugin);

final List<String> output = await runCapturingPrint(runner, <String>[
'build-examples',
'--ios',
'--enable-experiment=exp1',
'--swift-package-manager',
]);

expect(
output,
containsAllInOrder(<String>[
'\nBUILDING plugin/example for iOS',
]),
);

expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
ProcessCall(
getFlutterCommand(mockPlatform),
const <String>['config', '--enable-swift-package-manager'],
null,
),
ProcessCall(
getFlutterCommand(mockPlatform),
const <String>[
'build',
'ios',
'--no-codesign',
'--enable-experiment=exp1'
],
pluginExampleDirectory.path,
),
]),
);
});

test(
'building for iOS with Swift Package Manager on stable channel does not enable SPM',
() async {
mockPlatform.isMacOS = true;
mockPlatform.environment['CHANNEL'] = 'stable';

final RepositoryPackage plugin = createFakePlugin('plugin', packagesDir,
platformSupport: <String, PlatformDetails>{
platformIOS: const PlatformDetails(PlatformSupport.inline),
});

final Directory pluginExampleDirectory = getExampleDir(plugin);

final List<String> output = await runCapturingPrint(runner, <String>[
'build-examples',
'--ios',
'--enable-experiment=exp1',
'--swift-package-manager',
]);

expect(
output,
containsAllInOrder(<String>[
'\nBUILDING plugin/example for iOS',
]),
);

expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
ProcessCall(
getFlutterCommand(mockPlatform),
const <String>[
'build',
'ios',
'--no-codesign',
'--enable-experiment=exp1'
],
pluginExampleDirectory.path,
),
]),
);
});

test(
'building for Linux when plugin is not set up for Linux results in no-op',
() async {
Expand Down Expand Up @@ -261,6 +353,86 @@ void main() {
]));
});

test('building for macOS with Swift Package Manager on master channel',
() async {
mockPlatform.isMacOS = true;
mockPlatform.environment['CHANNEL'] = 'master';

final RepositoryPackage plugin = createFakePlugin('plugin', packagesDir,
platformSupport: <String, PlatformDetails>{
platformMacOS: const PlatformDetails(PlatformSupport.inline),
});

final Directory pluginExampleDirectory = getExampleDir(plugin);

final List<String> output = await runCapturingPrint(runner,
<String>['build-examples', '--macos', '--swift-package-manager']);

expect(
output,
containsAllInOrder(<String>[
'\nBUILDING plugin/example for macOS',
]),
);

expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
ProcessCall(
getFlutterCommand(mockPlatform),
const <String>['config', '--enable-swift-package-manager'],
null,
),
ProcessCall(
getFlutterCommand(mockPlatform),
const <String>[
'build',
'macos',
],
pluginExampleDirectory.path,
),
]),
);
});

test(
'building for macOS with Swift Package Manager on stable channel does not enable SPM',
() async {
mockPlatform.isMacOS = true;
mockPlatform.environment['CHANNEL'] = 'stable';

final RepositoryPackage plugin = createFakePlugin('plugin', packagesDir,
platformSupport: <String, PlatformDetails>{
platformMacOS: const PlatformDetails(PlatformSupport.inline),
});

final Directory pluginExampleDirectory = getExampleDir(plugin);

final List<String> output = await runCapturingPrint(runner,
<String>['build-examples', '--macos', '--swift-package-manager']);

expect(
output,
containsAllInOrder(<String>[
'\nBUILDING plugin/example for macOS',
]),
);

expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
ProcessCall(
getFlutterCommand(mockPlatform),
const <String>[
'build',
'macos',
],
pluginExampleDirectory.path,
),
]),
);
});

test('building for web with no implementation results in no-op', () async {
createFakePlugin('plugin', packagesDir);

Expand Down