resolve static method
Future<AppleResolvedSigningAssets>
resolve({
- required AppleSigningCredentials credentials,
- required Set<
String> bundleIds, - required AppStoreConnectApi client,
- ProcessRunner processRunner = const SystemProcessRunner(),
- Directory? temporaryRoot,
- DateTime currentTime()?,
Finds or creates profiles through Apple's supported provisioning API.
Implementation
static Future<AppleResolvedSigningAssets> resolve({
required AppleSigningCredentials credentials,
required Set<String> bundleIds,
required AppStoreConnectApi client,
ProcessRunner processRunner = const SystemProcessRunner(),
Directory? temporaryRoot,
DateTime Function()? currentTime,
}) async {
SmfError.check(
bundleIds.isNotEmpty,
'No signed Apple bundle identifiers were discovered.',
SmfErrorCode.appleSigningTargetsNotFound,
);
final now = (currentTime ?? DateTime.now)().toUtc();
final validAfter = now.add(_minimumSigningValidity);
final certificateDer = await _certificateDer(
credentials,
processRunner: processRunner,
temporaryRoot: temporaryRoot,
);
final certificates = await client.listSigningCertificates();
final contentMatches = certificates.where((certificate) {
List<int> content;
try {
content = base64Decode(
certificate.certificateContent.replaceAll(RegExp(r'\s'), ''),
);
} on FormatException catch (error) {
throw SmfError(
'Apple returned malformed distribution-certificate content.',
SmfErrorCode.appStoreConnectResponse,
cause: error,
);
}
return _bytesEqual(certificateDer, content);
}).toList();
SmfError.check(
contentMatches.length == 1,
contentMatches.isEmpty
? 'The supplied .p12 certificate is not registered with this Apple '
'developer team.'
: 'Apple returned the supplied .p12 certificate more than once.',
SmfErrorCode.appleCertificateNotFound,
);
final certificate = contentMatches.single;
SmfError.check(
_distributionCertificateTypes.contains(certificate.certificateType),
'The supplied .p12 is ${certificate.certificateType}, not an Apple '
'Distribution certificate.',
SmfErrorCode.appleCertificateTypeMismatch,
);
SmfError.check(
certificate.isActivated && certificate.expirationDate.isAfter(validAfter),
'The supplied Apple Distribution certificate is inactive, expired, or '
'expires within 24 hours.',
SmfErrorCode.appleCertificateInvalid,
);
final registered = await client.listIosBundleIds();
final bundleResources = <String, AppleBundleIdentifierDto>{};
for (final bundleId in bundleIds) {
final matches = registered
.where(
(resource) => resource.platform == 'IOS' && resource.identifier == bundleId,
)
.toList();
SmfError.check(
matches.length == 1,
matches.isEmpty
? 'No registered iOS App ID matches $bundleId.'
: 'Apple returned more than one iOS App ID for $bundleId.',
SmfErrorCode.appleBundleIdNotFound,
);
bundleResources[bundleId] = matches.single;
}
final knownProfiles = List<AppleProvisioningProfileDto>.of(
await client.listAppStoreProfiles(),
);
final knownNames = knownProfiles.map((profile) => profile.name).toSet();
final encodedProfiles = <String, String>{};
final sortedBundleResources = bundleResources.entries.toList()
..sort((left, right) => left.key.compareTo(right.key));
for (final bundleEntry in sortedBundleResources) {
final bundleId = bundleEntry.key;
final bundleResource = bundleEntry.value;
var profile = _bestProfile(
knownProfiles,
bundleResource,
certificate,
validAfter,
);
if (profile == null) {
final profileName = _availableProfileName(
bundleId,
certificate.serialNumber,
knownNames,
);
knownNames.add(profileName);
profile = await _createOrRecoverProfile(
client: client,
name: profileName,
bundleId: bundleResource,
certificate: certificate,
validAfter: validAfter,
);
knownProfiles.add(profile);
}
_validateProfile(profile, bundleResource, certificate, validAfter);
encodedProfiles[bundleId] = _normalizedBase64Profile(
profile.profileContent,
bundleId,
);
}
return AppleResolvedSigningAssets(
credentials: credentials,
profilesByBundleId: Map<String, String>.unmodifiable(encodedProfiles),
);
}