findArtifact static method
Finds exactly one repository-contained Android App Bundle.
Implementation
static Future<String> findArtifact(
String projectRoot, {
String aabOutputPath = 'build/app/outputs/bundle/release',
}) async {
final normalizedRoot = p.normalize(p.absolute(projectRoot));
final configuredPath = p.normalize(
p.absolute(normalizedRoot, aabOutputPath),
);
SmfError.check(
p.equals(configuredPath, normalizedRoot) || p.isWithin(normalizedRoot, configuredPath),
'The configured aab_output_path must stay inside the Flutter app.',
SmfErrorCode.aabPathEscape,
);
final type = await FileSystemEntity.type(configuredPath);
SmfError.check(
type != FileSystemEntityType.notFound,
'The build command did not produce an AAB at $configuredPath.',
SmfErrorCode.aabNotFound,
);
final realRoot = await Directory(normalizedRoot).resolveSymbolicLinks();
final realConfiguredPath = await switch (type) {
FileSystemEntityType.file => File(configuredPath).resolveSymbolicLinks(),
FileSystemEntityType.directory => Directory(
configuredPath,
).resolveSymbolicLinks(),
_ => throw const SmfError(
'The configured aab_output_path must be a file or directory.',
SmfErrorCode.aabNotFound,
),
};
SmfError.check(
p.equals(realConfiguredPath, realRoot) || p.isWithin(realRoot, realConfiguredPath),
'The configured aab_output_path resolves outside the Flutter app.',
SmfErrorCode.aabPathEscape,
);
if (type == FileSystemEntityType.file) {
SmfError.check(
configuredPath.toLowerCase().endsWith('.aab'),
'The configured Android artifact file must have an .aab extension.',
SmfErrorCode.aabNotFound,
);
return configuredPath;
}
final artifactPaths = <String>[];
await for (final entity in Directory(configuredPath).list(recursive: true)) {
if (entity is! File || !entity.path.toLowerCase().endsWith('.aab')) {
continue;
}
final realFile = await entity.resolveSymbolicLinks();
SmfError.check(
p.isWithin(realRoot, realFile),
'An AAB in aab_output_path resolves outside the Flutter app.',
SmfErrorCode.aabPathEscape,
);
artifactPaths.add(entity.path);
}
artifactPaths.sort();
SmfError.check(
artifactPaths.length == 1,
'Expected exactly one AAB in $configuredPath, found ${artifactPaths.length}.',
SmfErrorCode.aabCount,
);
return artifactPaths.single;
}