ensure we always log all certificates

Bug: b/333426905
Change-Id: I13104465114db9d8f702f42b1b9e001e67f70e06
Reviewed-on: https://flutter-review.googlesource.com/c/recipes/+/57180
Reviewed-by: Xilai Zhang <xilaizhang@google.com>
Commit-Queue: Christopher Fujino <fujino@google.com>
diff --git a/recipe_modules/signing/resources/setup_keychain.sh b/recipe_modules/signing/resources/setup_keychain.sh
index e4f6634..97027fc 100755
--- a/recipe_modules/signing/resources/setup_keychain.sh
+++ b/recipe_modules/signing/resources/setup_keychain.sh
@@ -1,5 +1,4 @@
 #!/usr/bin/env dart
-
 // Helper script to import a flutter p12 identity.
 
 import 'dart:io' as io;
@@ -9,7 +8,8 @@
 const int totalRetryAttempts = 3;
 
 Future<void> main() async {
-  final io.File logFile = io.File(io.Platform.environment['SETUP_KEYCHAIN_LOGS_PATH']!);
+  final io.File logFile =
+      io.File(io.Platform.environment['SETUP_KEYCHAIN_LOGS_PATH']!);
   final logSink = logFile.openWrite();
   void log(String line) {
     logSink.writeln('$line\n');
@@ -38,7 +38,7 @@
   required String codesignPath,
   required void Function(String) log,
 }) async {
-  String security(List<String> args) {
+  String security(List<String> args, {bool allowNonzero = false}) {
     log('Executing ${<String>['/usr/bin/security', ...args]}');
 
     final io.ProcessResult result =
@@ -48,7 +48,7 @@
     log('STDOUT:\n\n${result.stdout}');
     log('STDERR:\n\n${result.stderr}');
 
-    if (result.exitCode != 0) {
+    if (!allowNonzero && result.exitCode != 0) {
       throw io.ProcessException(
           '/usr/bin/security', args, 'failed', result.exitCode);
     }
@@ -56,96 +56,99 @@
     return result.stdout as String;
   }
 
-  final String rawPassword = io.File(passwordPath).readAsStringSync();
+  try {
+    final String rawPassword = io.File(passwordPath).readAsStringSync();
 
-  // Only filepath with a .p12 suffix will be recognized
-  io.File(flutterP12Path).renameSync(p12SuffixFilePath);
+    // Only filepath with a .p12 suffix will be recognized
+    io.File(flutterP12Path).renameSync(p12SuffixFilePath);
 
-  // Delete build.keychain if it exists
-  security(const <String>['delete-keychain', keychainName]);
+    // Delete build.keychain if it exists
+    security(const <String>['delete-keychain', keychainName], allowNonzero: true);
 
-  // Create keychain.
-  security(const <String>[
-    'create-keychain',
-    '-p',
-    keychainPassword,
-    keychainName,
-  ]);
-
-  // Retrieve current list of keychains on the search list of current machine.
-  final keychains = security(const <String>['list-keychains', '-d', 'user'])
-      .split('\n')
-      .map<String?>((String line) {
-    final RegExp pattern = RegExp(r'^\s*".*\/([a-zA-Z0-9.]+)-db"');
-    final RegExpMatch? match = pattern.firstMatch(line);
-    if (match == null) {
-      return null;
-    }
-    // The first (and only) capture group is the name of the keychain
-    return match.group(1);
-  }).whereType<String>();
-
-  print('User keychains on this machine: $keychains');
-
-  // Add keychain name to search list.
-  // Without this, future commands such as `security import`,
-  // `security find-identity` and `codesign ...` will fail to find the cert
-  // in our newly created keychain.
-  security(<String>[
-    '-v',
-    'list-keychains',
-    // TODO(fujino): we probably don't need $keychains here, only keychainName should be required
-    '-s', ...keychains, keychainName,
-  ]);
-
-  // Set $keychainName as default.
-  security(<String>[
-    'default-keychain',
-    '-s',
-    keychainName,
-  ]);
-
-  // Unlock keychainName to allow sign commands to use its certs.
-  security(<String>['unlock-keychain', '-p', keychainPassword, keychainName]);
-
-  // This will be exponentially increased on retries
-  int sleepSeconds = 2;
-
-  for (int attempt = 0; attempt < totalRetryAttempts; attempt++) {
-    security(<String>[
-      'import',
-      p12SuffixFilePath,
-      '-k', keychainName,
-      '-P', rawPassword,
-      // -T allows the specified program to access this identity
-      '-T', codesignPath,
-      '-T', '/usr/bin/codesign',
-    ]);
-    security(<String>[
-      'set-key-partition-list',
-      '-S',
-      'apple-tool:,apple:,codesign:',
-      '-s',
-      '-k',
-      '',
+    // Create keychain.
+    security(const <String>[
+      'create-keychain',
+      '-p',
+      keychainPassword,
       keychainName,
     ]);
 
-    final String identities =
-        security(const <String>['find-identity', '-v', keychainName]);
-    if (identities.contains('FLUTTER.IO LLC')) {
-      log('successfully found a Flutter identity in the $keychainName keychain');
-      return 0;
+    // Retrieve current list of keychains on the search list of current machine.
+    final keychains = security(const <String>['list-keychains', '-d', 'user'])
+        .split('\n')
+        .map<String?>((String line) {
+      final RegExp pattern = RegExp(r'^\s*".*\/([a-zA-Z0-9.]+)-db"');
+      final RegExpMatch? match = pattern.firstMatch(line);
+      if (match == null) {
+        return null;
+      }
+      // The first (and only) capture group is the name of the keychain
+      return match.group(1);
+    }).whereType<String>();
+
+    print('User keychains on this machine: $keychains');
+
+    // Add keychain name to search list.
+    // Without this, future commands such as `security import`,
+    // `security find-identity` and `codesign ...` will fail to find the cert
+    // in our newly created keychain.
+    security(<String>[
+      '-v',
+      'list-keychains',
+      // TODO(fujino): we probably don't need $keychains here, only keychainName should be required
+      '-s', ...keychains, keychainName,
+    ]);
+
+    // Set $keychainName as default.
+    security(<String>[
+      'default-keychain',
+      '-s',
+      keychainName,
+    ]);
+
+    // Unlock keychainName to allow sign commands to use its certs.
+    security(<String>['unlock-keychain', '-p', keychainPassword, keychainName]);
+
+    // This will be exponentially increased on retries
+    int sleepSeconds = 2;
+
+    for (int attempt = 0; attempt < totalRetryAttempts; attempt++) {
+      security(<String>[
+        'import',
+        p12SuffixFilePath,
+        '-k', keychainName,
+        '-P', rawPassword,
+        // -T allows the specified program to access this identity
+        '-T', codesignPath,
+        '-T', '/usr/bin/codesign',
+      ]);
+      security(<String>[
+        'set-key-partition-list',
+        '-S',
+        'apple-tool:,apple:,codesign:',
+        '-s',
+        '-k',
+        '',
+        keychainName,
+      ]);
+
+      final String identities =
+          security(const <String>['find-identity', '-v', keychainName]);
+      if (identities.contains('FLUTTER.IO LLC')) {
+        log('successfully found a Flutter identity in the $keychainName keychain');
+        return 0;
+      }
+      log('failed to find a Flutter identity in the $keychainName keychain on attempt $attempt');
+      await Future<void>.delayed(Duration(seconds: sleepSeconds));
+      sleepSeconds *= sleepSeconds;
     }
-    log('failed to find a Flutter identity in the $keychainName keychain on attempt $attempt');
-    await Future<void>.delayed(Duration(seconds: sleepSeconds));
-    sleepSeconds *= sleepSeconds;
+  } finally {
+    security(const <String>[
+      'find-certificate',
+      // Find all matching certificates, not just the first
+      '-a',
+    ]);
   }
   log('failed to find a Flutter identity after $totalRetryAttempts attempts.');
-  security(const <String>[
-    'find-certificate',
-    // Find all matching certificates, not just the first
-    '-a',
-  ]);
   return 1;
 }