checkAppStoreTree function

List<ReleaseProblem> checkAppStoreTree(
  1. String path, {
  2. Set<String> requireScreenshotTypes = const {},
  3. Set<String> requireLocales = const {},
})

Loads the App Store metadata tree at path and reports what it refuses.

The loading is the check: loadMetadata validates text limits, URL schemes, category ids, screenshot dimensions and — the one that fires most often in practice — the alpha channel every simulator screen capture carries. Anything it throws becomes a problem here rather than an exception, so a caller sees it alongside whatever else is wrong.

requireScreenshotTypes covers the case the loader cannot know about on its own: a universal app declaring TARGETED_DEVICE_FAMILY = "1,2" must carry an iPad set as well as an iPhone one, and Apple refuses the submission if it does not. Which types are required is a property of the app, so the consumer names them.

Implementation

List<ReleaseProblem> checkAppStoreTree(
  String path, {
  Set<String> requireScreenshotTypes = const {},
  Set<String> requireLocales = const {},
}) {
  final AppStoreMetadata metadata;
  try {
    metadata = loadMetadata(path);
  } on MetadataException catch (e) {
    return [ReleaseProblem(path, e.message)];
  }

  final problems = <ReleaseProblem>[];

  if (metadata.locales.isEmpty) {
    problems.add(ReleaseProblem(path, 'no locales — nothing would publish'));
    return problems;
  }

  for (final locale in requireLocales) {
    if (!metadata.locales.any((l) => l.locale == locale)) {
      problems.add(
        ReleaseProblem(path, 'no listing for required locale $locale'),
      );
    }
  }

  for (final locale in metadata.locales) {
    if (requireLocales.isNotEmpty && !requireLocales.contains(locale.locale)) {
      continue;
    }
    for (final type in requireScreenshotTypes) {
      final shots = locale.screenshots[type];
      if (shots == null || shots.isEmpty) {
        problems.add(
          ReleaseProblem(
            '$path → ${locale.locale}',
            'no $type screenshots, which this app is required to carry',
          ),
        );
      }
    }
  }

  return problems;
}