[codesign + recipe] refactor gsutil and zip utilities  (#2289)

* refactor gsutil

* revert pubspec lock

* christopher's feedbacks

* try finally

* try block scope

* simplify passwords

* simplify cleanup
diff --git a/codesign/bin/codesign.dart b/codesign/bin/codesign.dart
index 937ac45..7197fde 100644
--- a/codesign/bin/codesign.dart
+++ b/codesign/bin/codesign.dart
@@ -15,8 +15,8 @@
 const String kHelpFlag = 'help';
 const String kDryrunFlag = 'dryrun';
 const String kCodesignCertNameOption = 'codesign-cert-name';
-const String kGcsDownloadPathOption = 'gcs-download-path';
-const String kGcsUploadPathOption = 'gcs-upload-path';
+const String kInputZipPathOption = 'input-zip-file-path';
+const String kOutputZipPathOption = 'output-zip-file-path';
 const String kAppSpecificPasswordOption = 'app-specific-password-file-path';
 const String kCodesignAppstoreIDOption = 'codesign-appstore-id-file-path';
 const String kCodesignTeamIDOption = 'codesign-team-id-file-path';
@@ -24,20 +24,20 @@
 /// Perform Mac code signing based on file paths.
 ///
 /// By default, if a user does not specify a dryrun flag, or selects dryrun
-/// mode by providing the `--dryrun` flag, then [kDryrunFlag] is set to true.
-/// In this case, code signed artifacts are not uploaded back to google cloud storage.
+/// mode by providing the `--dryrun` flag, then [kDryrunFlag] is set to true,
+/// a quick sanity check is performed and the notarization process is skipped.
 /// On the other hand, if a user provides the flag `--no-dryrun`, [kDryrunFlag]
-/// will be set to false, and code signed artifacts will be uploaded back to
-/// google cloud storage.
+/// will be set to false, and code signed artifacts will go through the notarization
+/// process.
 ///
-/// For [kGcsDownloadPathOption] and [kGcsUploadPathOption], they are required parameter to specify the google cloud bucket paths.
-/// [kGcsDownloadPathOption] is the google cloud bucket prefix to download the remote artifacts,
-/// [kGcsUploadPathOption] is the cloud bucket prefix to upload codesigned artifact to.
+/// For [kInputZipPathOption] and [kOutputZipPathOption], they are required parameter to specify the
+/// input and output locations.
+/// The codesign app will take the zip file located at the input location [kInputZipPathOption], and
+/// put codesigned zip at [kOutputZipPathOption]. The work of downloading and uploading the zip
+/// artifacts is delegated to recipe.
 /// For example, supply
-/// '--gcs-download-path=gs://flutter_infra_release/ios-usb-dependencies/unsigned/libimobiledevice/<commit>/libimobiledevice.zip',
-/// and code sign app will download the artifact at
-/// 'flutter_infra_release/ios-usb-dependencies/unsigned/libimobiledevice/<commit>/libimobiledevice.zip'
-/// on google cloud storage
+/// '--input-zip-file-path=/tmp/input.zip',
+/// and code sign app will code sign the artifacts located at /tmp/input.zip.
 ///
 /// For [kAppSpecificPasswordOption], [kCodesignAppstoreIDOption] and [kCodesignTeamIDOption],
 /// they are file paths of the password files in the file system.
@@ -59,8 +59,8 @@
 /// --codesign-team-id-file-path=/a/b/c.txt
 /// --codesign-appstore-id-file-path=/a/b/b.txt
 /// --app-specific-password-file-path=/a/b/a.txt
-/// --gcs-download-path=gs://flutter_infra_release/flutter/<commit>/android-arm-profile/artifacts.zip
-/// --gcs-upload-path=gs://flutter_infra_release/flutter/<commit>/android-arm-profile/artifacts.zip
+/// --input-zip-file-path=/a/input.zip
+/// --output-zip-file-path=/b/output.zip
 /// ```
 Future<void> main(List<String> args) async {
   final ArgParser parser = ArgParser();
@@ -81,36 +81,32 @@
           'the name of the certificate for flutter, for example, is: FLUTTER.IO LLC',
     )
     ..addOption(
-      kGcsDownloadPathOption,
-      help: 'The google cloud bucket path to download the artifact from\n'
-          'e.g. supply `--gcs-download-path=gs://flutter_infra_release/ios-usb-dependencies/unsigned/ios-deploy/<commit>/ios-deploy.zip`'
-          ' if you would like to codesign ios-deploy.zip, which has a google cloud bucket path of flutter_infra_release/ios-usb-dependencies/unsigned/ios-deploy/<commit>/ios-deploy.zip to be downloaded from \n',
+      kInputZipPathOption,
+      help: 'File path to the unsigned artifact zip file.',
     )
     ..addOption(
-      kGcsUploadPathOption,
-      help: 'The google cloud bucket path to upload the artifact to. \n'
-          'e.g. supply `--gcs-upload-path=gs://flutter_infra_release/ios-usb-dependencies/ios-deploy/<commit>/ios-deploy.zip`'
-          ' if you would like to codesign ios-deploy.zip, which has a google cloud bucket path of flutter_infra_release/ios-usb-dependencies/ios-deploy/<commit>/ios-deploy.zip to be uploaded to',
+      kOutputZipPathOption,
+      help: 'File path to codesigned artifact zip file for output.',
     )
     ..addOption(
       kAppSpecificPasswordOption,
       help:
-          'The file path of a password file in file system. The password file stores the sensitive password <APP-SPECIFIC-PASSWORD> \n',
+          'The file path of a password file in file system. The password file stores the sensitive password <APP-SPECIFIC-PASSWORD>.',
     )
     ..addOption(
       kCodesignAppstoreIDOption,
       help:
-          'The file path of a password file in file system. The password file stores the sensitive password <CODESIGN_APPSTORE_ID> \n',
+          'The file path of a password file in file system. The password file stores the sensitive password <CODESIGN_APPSTORE_ID>.',
     )
     ..addOption(
       kCodesignTeamIDOption,
       help:
-          'The file path of a password file in file system. The password file stores the sensitive password <CODESIGN_TEAM_ID> \n',
+          'The file path of a password file in file system. The password file stores the sensitive password <CODESIGN_TEAM_ID>.',
     )
     ..addFlag(
       kDryrunFlag,
       defaultsTo: true,
-      help: 'whether we are going to upload the artifacts back to GCS for dryrun',
+      help: 'whether we are going to skip the notarization process.',
     );
 
   final ArgResults argResults = parser.parse(args);
@@ -118,8 +114,8 @@
   const Platform platform = LocalPlatform();
 
   final String codesignCertName = getValueFromArgs(kCodesignCertNameOption, argResults)!;
-  final String gCloudDownloadPath = getValueFromArgs(kGcsDownloadPathOption, argResults)!;
-  final String gCloudUploadPath = getValueFromArgs(kGcsUploadPathOption, argResults)!;
+  final String inputZipPath = getValueFromArgs(kInputZipPathOption, argResults)!;
+  final String outputZipPath = getValueFromArgs(kOutputZipPathOption, argResults)!;
   final String appSpecificPasswordFilePath = getValueFromArgs(kAppSpecificPasswordOption, argResults)!;
   final String codesignAppstoreIDFilePath = getValueFromArgs(kCodesignAppstoreIDOption, argResults)!;
   final String codesignTeamIDFilePath = getValueFromArgs(kCodesignTeamIDOption, argResults)!;
@@ -136,10 +132,6 @@
   const FileSystem fileSystem = LocalFileSystem();
   final Directory rootDirectory = fileSystem.systemTempDirectory.createTempSync('conductor_codesign');
   const ProcessManager processManager = LocalProcessManager();
-  final GoogleCloudStorage googleCloudStorage = GoogleCloudStorage(
-    processManager: processManager,
-    rootDirectory: rootDirectory,
-  );
 
   return FileCodesignVisitor(
     codesignCertName: codesignCertName,
@@ -150,8 +142,7 @@
     codesignTeamIDFilePath: codesignTeamIDFilePath,
     processManager: processManager,
     dryrun: dryrun,
-    gcsDownloadPath: gCloudDownloadPath,
-    gcsUploadPath: gCloudUploadPath,
-    googleCloudStorage: googleCloudStorage,
+    inputZipPath: inputZipPath,
+    outputZipPath: outputZipPath,
   ).validateAll();
 }
diff --git a/codesign/lib/codesign.dart b/codesign/lib/codesign.dart
index b814211..54fe0c8 100644
--- a/codesign/lib/codesign.dart
+++ b/codesign/lib/codesign.dart
@@ -3,5 +3,4 @@
 // found in the LICENSE file.
 
 export 'src/file_codesign_visitor.dart';
-export 'src/google_cloud_storage.dart';
 export 'src/utils.dart';
diff --git a/codesign/lib/src/file_codesign_visitor.dart b/codesign/lib/src/file_codesign_visitor.dart
index cacaea8..124f639 100644
--- a/codesign/lib/src/file_codesign_visitor.dart
+++ b/codesign/lib/src/file_codesign_visitor.dart
@@ -8,7 +8,6 @@
 import 'package:file/file.dart';
 import 'package:process/process.dart';
 
-import 'google_cloud_storage.dart';
 import 'log.dart';
 import 'utils.dart';
 
@@ -29,9 +28,8 @@
     required this.fileSystem,
     required this.rootDirectory,
     required this.processManager,
-    required this.gcsDownloadPath,
-    required this.gcsUploadPath,
-    required this.googleCloudStorage,
+    required this.inputZipPath,
+    required this.outputZipPath,
     required this.appSpecificPasswordFilePath,
     required this.codesignAppstoreIDFilePath,
     required this.codesignTeamIDFilePath,
@@ -39,8 +37,6 @@
     this.notarizationTimerDuration = const Duration(seconds: 5),
   }) {
     entitlementsFile = rootDirectory.childFile('Entitlements.plist')..writeAsStringSync(_entitlementsFileContents);
-    remoteDownloadsDir = rootDirectory.childDirectory('downloads')..createSync();
-    codesignedZipsDir = rootDirectory.childDirectory('codesigned_zips')..createSync();
   }
 
   /// Temp [Directory] to download/extract files to.
@@ -49,11 +45,10 @@
   final Directory rootDirectory;
   final FileSystem fileSystem;
   final ProcessManager processManager;
-  final GoogleCloudStorage googleCloudStorage;
 
   final String codesignCertName;
-  final String gcsDownloadPath;
-  final String gcsUploadPath;
+  final String inputZipPath;
+  final String outputZipPath;
   final String appSpecificPasswordFilePath;
   final String codesignAppstoreIDFilePath;
   final String codesignTeamIDFilePath;
@@ -78,8 +73,6 @@
   };
 
   late final File entitlementsFile;
-  late final Directory remoteDownloadsDir;
-  late final Directory codesignedZipsDir;
 
   int _remoteDownloadIndex = 0;
   int get remoteDownloadIndex => _remoteDownloadIndex++;
@@ -130,75 +123,40 @@
 ''';
 
   /// Read a single line of password stored at [passwordFilePath].
-  ///
-  /// The password file should provide the password name and value, deliminated by a single colon.
-  /// The content of a password file would look similar to:
-  /// CODESIGN_APPSTORE_ID:123
-  Future<void> readPassword(String passwordFilePath) async {
+  Future<String> readPassword(String passwordFilePath) async {
     if (!(await fileSystem.file(passwordFilePath).exists())) {
       throw CodesignException('$passwordFilePath not found \n'
           'make sure you have provided codesign credentials in a file \n');
     }
-
-    final String passwordLine = await fileSystem.file(passwordFilePath).readAsString();
-    final List<String> parsedPasswordLine = passwordLine.split(":");
-    if (parsedPasswordLine.length != 2) {
-      throw CodesignException('$passwordFilePath is not correctly formatted. \n'
-          'please double check formatting \n');
-    }
-    final String passwordName = parsedPasswordLine[0];
-    final String passwordValue = parsedPasswordLine[1];
-    if (!availablePasswords.containsKey(passwordName)) {
-      throw CodesignException('$passwordName is not a password we can process. \n'
-          'please double check passwords.txt \n');
-    }
-    availablePasswords[passwordName] = passwordValue;
-    return;
+    return (await fileSystem.file(passwordFilePath).readAsString());
   }
 
   /// The entrance point of examining and code signing an engine artifact.
   Future<void> validateAll() async {
-    for (String passwordFilePath in [
-      codesignAppstoreIDFilePath,
-      codesignTeamIDFilePath,
-      appSpecificPasswordFilePath,
-    ]) {
-      await readPassword(passwordFilePath);
-    }
-    if (availablePasswords.containsValue('')) {
-      throw CodesignException('certian passwords are missing. \n'
-          'make sure you have provided <CODESIGN_APPSTORE_ID>, <CODESIGN_TEAM_ID>, and <APP_SPECIFIC_PASSWORD>');
-    }
-    codesignAppstoreId = availablePasswords['CODESIGN_APPSTORE_ID']!;
-    codesignTeamId = availablePasswords['CODESIGN_TEAM_ID']!;
-    appSpecificPassword = availablePasswords['APP_SPECIFIC_PASSWORD']!;
+    codesignAppstoreId = await readPassword(codesignAppstoreIDFilePath);
+    codesignTeamId = await readPassword(codesignTeamIDFilePath);
+    appSpecificPassword = await readPassword(appSpecificPasswordFilePath);
 
     await processRemoteZip();
 
+    log.info('Codesign completed. Codesigned zip is located at $outputZipPath.'
+        'If you have uploaded the artifacts back to google cloud storage, please delete'
+        ' the folder $outputZipPath and $inputZipPath.');
     if (dryrun) {
-      log.info('code signing dry run has completed, If you intend to upload the artifacts back to'
-          ' google cloud storage, please use the --dryrun=false flag to run code signing script.');
+      log.info('code signing dry run has completed, this is a quick sanity check without'
+          'going through the notary service. To run the full codesign process, use --no-dryrun flag.');
     }
-    log.info('Codesigned all binaries in ${rootDirectory.path}');
-
-    await rootDirectory.delete(recursive: true);
   }
 
-  /// Retrieve engine artifact from google cloud storage and kick start a
+  /// Process engine artifacts from [inputZipPath] and kick start a
   /// recursive visit of its contents.
   ///
   /// Invokes [visitDirectory] to recursively visit the contents of the remote
-  /// zip. Also downloads, notarizes and uploads the engine artifact.
-  Future<void> processRemoteZip() async {
-    // Name of the downloaded artifact.
-    // There won't be collisions since we are only signing one artifact at a time now
-    const String localFilePath = 'remote_artifact.zip';
-
+  /// zip. Notarizes the engine artifact if [dryrun] is false.
+  /// Returns null as result if [dryrun] is true.
+  Future<String?> processRemoteZip() async {
     // download the zip file
-    final File originalFile = await googleCloudStorage.downloadEngineArtifact(
-      from: gcsDownloadPath,
-      destination: remoteDownloadsDir.childFile(localFilePath).path,
-    );
+    final File originalFile = rootDirectory.fileSystem.file(inputZipPath);
 
     // This is the starting directory of the unzipped artifact.
     final Directory parentDirectory = rootDirectory.childDirectory('single_artifact');
@@ -218,24 +176,21 @@
     // recursively visit extracted files
     await visitDirectory(directory: parentDirectory, parentVirtualPath: "");
 
-    final File codesignedFile = codesignedZipsDir.childFile(localFilePath);
-
     await zip(
       inputDir: parentDirectory,
-      outputZip: codesignedFile,
+      outputZipPath: outputZipPath,
       processManager: processManager,
     );
 
-    // `dryrun` flag defaults to true to prevent uploading artifacts back to google cloud.
-    // This would help prevent https://github.com/flutter/flutter/issues/104387
-    if (!dryrun) {
-      await notarize(codesignedFile);
+    await parentDirectory.delete(recursive: true);
 
-      await googleCloudStorage.uploadEngineArtifact(
-        from: codesignedFile.path,
-        destination: gcsUploadPath,
-      );
+    // `dryrun` flag defaults to true to save time for a faster sanity check
+    if (!dryrun) {
+      await notarize(fileSystem.file(outputZipPath));
+
+      return outputZipPath;
     }
+    return null;
   }
 
   /// Visit a [Directory] type while examining the file system extracted from an artifact.
@@ -301,9 +256,10 @@
     await zipEntity.delete();
     await zip(
       inputDir: newDir,
-      outputZip: zipEntity,
+      outputZipPath: zipEntity.absolute.path,
       processManager: processManager,
     );
+    await newDir.delete(recursive: true);
   }
 
   /// Visit and codesign a binary with / without entitlement.
diff --git a/codesign/lib/src/google_cloud_storage.dart b/codesign/lib/src/google_cloud_storage.dart
deleted file mode 100644
index fd0fe58..0000000
--- a/codesign/lib/src/google_cloud_storage.dart
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2019 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import 'dart:io';
-
-import 'package:file/file.dart';
-import 'package:process/process.dart';
-
-import './utils.dart';
-
-/// A service to interact with google cloud storage through gsutil.
-class GoogleCloudStorage {
-  GoogleCloudStorage({
-    required this.processManager,
-    required this.rootDirectory,
-  });
-
-  final ProcessManager processManager;
-  final Directory rootDirectory;
-
-  /// Method to upload code signed flutter engine artifact to google cloud bucket.
-  Future<void> uploadEngineArtifact({
-    required String from,
-    required String destination,
-  }) async {
-    final ProcessResult result = await processManager.run(
-      <String>['gsutil', 'cp', from, destination],
-    );
-
-    if (result.exitCode != 0) {
-      throw CodesignException('Failed to upload $from to $destination');
-    }
-  }
-
-  /// Method to download flutter engine artifact from google cloud bucket.
-  Future<File> downloadEngineArtifact({
-    required String from,
-    required String destination,
-  }) async {
-    final ProcessResult result = await processManager.run(
-      <String>['gsutil', 'cp', from, destination],
-    );
-    if (result.exitCode != 0) {
-      throw CodesignException('Failed to download from $from');
-    }
-    return rootDirectory.fileSystem.file(destination);
-  }
-}
diff --git a/codesign/lib/src/utils.dart b/codesign/lib/src/utils.dart
index 400ebce..ad56517 100644
--- a/codesign/lib/src/utils.dart
+++ b/codesign/lib/src/utils.dart
@@ -48,7 +48,7 @@
 
 Future<void> zip({
   required Directory inputDir,
-  required FileSystemEntity outputZip,
+  required String outputZipPath,
   required ProcessManager processManager,
 }) async {
   await processManager.run(
@@ -56,7 +56,7 @@
       'zip',
       '--symlinks',
       '--recurse-paths',
-      outputZip.absolute.path,
+      outputZipPath,
       // use '.' so that the full absolute path is not encoded into the zip file
       '.',
       '--include',
diff --git a/codesign/test/file_codesign_visitor_test.dart b/codesign/test/file_codesign_visitor_test.dart
index b717b33..4a88bef 100644
--- a/codesign/test/file_codesign_visitor_test.dart
+++ b/codesign/test/file_codesign_visitor_test.dart
@@ -5,7 +5,6 @@
 import 'dart:convert';
 
 import 'package:codesign/codesign.dart' as cs;
-import 'package:codesign/src/google_cloud_storage.dart';
 import 'package:codesign/src/log.dart';
 import 'package:codesign/src/utils.dart';
 import 'package:file/file.dart';
@@ -20,11 +19,12 @@
   const String appSpecificPasswordFilePath = '/tmp/passwords.txt';
   const String codesignAppstoreIDFilePath = '/tmp/appID.txt';
   const String codesignTeamIDFilePath = '/tmp/teamID.txt';
+  const String inputZipPath = '/tmp/input.zip';
+  const String outputZipPath = '/tmp/output.zip';
   final MemoryFileSystem fileSystem = MemoryFileSystem.test();
   final List<LogRecord> records = <LogRecord>[];
 
   late FakeProcessManager processManager;
-  late GoogleCloudStorage googleCloudStorage;
   late cs.FileCodesignVisitor codesignVisitor;
 
   Directory rootDirectory = fileSystem.systemTempDirectory.createTempSync('conductor_codesign');
@@ -32,21 +32,16 @@
   group('test reading in passwords: ', () {
     setUp(() {
       processManager = FakeProcessManager.list(<FakeCommand>[]);
-      googleCloudStorage = GoogleCloudStorage(
-        processManager: processManager,
-        rootDirectory: rootDirectory,
-      );
       codesignVisitor = cs.FileCodesignVisitor(
         codesignCertName: randomString,
-        googleCloudStorage: googleCloudStorage,
         fileSystem: fileSystem,
         appSpecificPasswordFilePath: appSpecificPasswordFilePath,
         codesignAppstoreIDFilePath: codesignAppstoreIDFilePath,
         codesignTeamIDFilePath: codesignTeamIDFilePath,
         processManager: processManager,
         rootDirectory: rootDirectory,
-        gcsDownloadPath: 'gs://flutter/$randomString/$randomString',
-        gcsUploadPath: 'gs://flutter/$randomString/$randomString',
+        inputZipPath: inputZipPath,
+        outputZipPath: outputZipPath,
         notarizationTimerDuration: const Duration(seconds: 0),
         dryrun: false,
       );
@@ -55,64 +50,10 @@
       log.onRecord.listen((LogRecord record) => records.add(record));
     });
 
-    test('incorrectly formatted password file throws exception', () async {
-      fileSystem.file(appSpecificPasswordFilePath)
-        ..createSync(recursive: true)
-        ..writeAsStringSync(
-          'file_a',
-          mode: FileMode.write,
-          encoding: utf8,
-        );
-
+    test('lacking password file throws exception', () async {
       expect(
         () async {
           await codesignVisitor.readPassword(appSpecificPasswordFilePath);
-          fileSystem.file(appSpecificPasswordFilePath).deleteSync();
-        },
-        throwsA(
-          isA<CodesignException>(),
-        ),
-      );
-    });
-
-    test('unknown password name throws an exception', () async {
-      fileSystem.file(codesignTeamIDFilePath)
-        ..createSync(recursive: true, exclusive: true)
-        ..writeAsStringSync(
-          'dart:dart',
-          mode: FileMode.write,
-          encoding: utf8,
-        );
-
-      expect(
-        () async {
-          await codesignVisitor.readPassword(codesignTeamIDFilePath);
-          await fileSystem.file(codesignTeamIDFilePath).delete();
-        },
-        throwsA(
-          isA<CodesignException>(),
-        ),
-      );
-    });
-
-    test('lacking required passwords throws exception', () async {
-      codesignVisitor.availablePasswords = {
-        'CODESIGN_APPSTORE_ID': '',
-        'CODESIGN_TEAM_ID': '',
-        'APP-SPECIFIC-PASSWORD': ''
-      };
-      fileSystem.file(codesignAppstoreIDFilePath)
-        ..createSync(recursive: true)
-        ..writeAsStringSync(
-          'CODESIGN_APPSTORE_ID:123',
-          mode: FileMode.write,
-          encoding: utf8,
-        );
-
-      expect(
-        () async {
-          await codesignVisitor.validateAll();
-          await fileSystem.file(codesignAppstoreIDFilePath).delete();
         },
         throwsA(
           isA<CodesignException>(),
@@ -124,7 +65,7 @@
       fileSystem.file(appSpecificPasswordFilePath)
         ..createSync(recursive: true, exclusive: true)
         ..writeAsStringSync(
-          'APP_SPECIFIC_PASSWORD:123',
+          '123',
           mode: FileMode.write,
           encoding: utf8,
         );
@@ -152,23 +93,18 @@
   group('test google cloud storage and processRemoteZip workflow', () {
     setUp(() {
       processManager = FakeProcessManager.list(<FakeCommand>[]);
-      googleCloudStorage = GoogleCloudStorage(
-        processManager: processManager,
-        rootDirectory: rootDirectory,
-      );
       codesignVisitor = cs.FileCodesignVisitor(
         codesignCertName: randomString,
-        googleCloudStorage: googleCloudStorage,
         fileSystem: fileSystem,
         appSpecificPasswordFilePath: appSpecificPasswordFilePath,
         codesignAppstoreIDFilePath: codesignAppstoreIDFilePath,
         codesignTeamIDFilePath: codesignTeamIDFilePath,
         processManager: processManager,
         rootDirectory: rootDirectory,
-        gcsDownloadPath: 'gs://flutter/$randomString/$randomString',
-        gcsUploadPath: 'gs://flutter/$randomString/$randomString',
         notarizationTimerDuration: const Duration(seconds: 0),
         dryrun: false,
+        inputZipPath: inputZipPath,
+        outputZipPath: outputZipPath,
       );
       codesignVisitor.appSpecificPassword = randomString;
       codesignVisitor.codesignAppstoreId = randomString;
@@ -178,143 +114,14 @@
       log.onRecord.listen((LogRecord record) => records.add(record));
     });
 
-    test('download fails and upload succeeds throws exception', () async {
-      processManager.addCommands(<FakeCommand>[
-        const FakeCommand(
-          command: <String>[
-            'gsutil',
-            'cp',
-            randomString,
-            'gs://flutter/$randomString/$randomString',
-          ],
-          exitCode: 0,
-        ),
-      ]);
-      expect(
-        () => googleCloudStorage.uploadEngineArtifact(
-          from: randomString,
-          destination: codesignVisitor.gcsUploadPath,
-        ),
-        returnsNormally,
-      );
-      processManager.addCommands(<FakeCommand>[
-        const FakeCommand(
-          command: <String>[
-            'gsutil',
-            'cp',
-            'gs://flutter/$randomString/$randomString',
-            randomString,
-          ],
-          exitCode: -1,
-        ),
-      ]);
-      expect(
-        () => googleCloudStorage.downloadEngineArtifact(
-          destination: randomString,
-          from: codesignVisitor.gcsDownloadPath,
-        ),
-        throwsA(
-          isA<CodesignException>(),
-        ),
-      );
-    });
-
-    test('download succeeds and upload fails throws exception', () async {
-      processManager.addCommands(<FakeCommand>[
-        const FakeCommand(
-          command: <String>[
-            'gsutil',
-            'cp',
-            'gs://flutter/$randomString/$randomString',
-            randomString,
-          ],
-          exitCode: 0,
-        ),
-      ]);
-      expect(
-        () => googleCloudStorage.downloadEngineArtifact(
-          destination: randomString,
-          from: codesignVisitor.gcsDownloadPath,
-        ),
-        returnsNormally,
-      );
-      processManager.addCommands(<FakeCommand>[
-        const FakeCommand(
-          command: <String>[
-            'gsutil',
-            'cp',
-            randomString,
-            'gs://flutter/$randomString/$randomString',
-          ],
-          exitCode: -1,
-        ),
-      ]);
-      expect(
-        () => googleCloudStorage.uploadEngineArtifact(
-          from: randomString,
-          destination: codesignVisitor.gcsUploadPath,
-        ),
-        throwsA(
-          isA<CodesignException>(),
-        ),
-      );
-    });
-
-    test('download succeeds and upload succeeds returns normally', () async {
-      processManager.addCommands(<FakeCommand>[
-        const FakeCommand(
-          command: <String>[
-            'gsutil',
-            'cp',
-            'gs://flutter/$randomString/$randomString',
-            randomString,
-          ],
-          exitCode: 0,
-        ),
-      ]);
-      expect(
-        () => googleCloudStorage.downloadEngineArtifact(
-          destination: randomString,
-          from: codesignVisitor.gcsDownloadPath,
-        ),
-        returnsNormally,
-      );
-      processManager.addCommands(<FakeCommand>[
-        const FakeCommand(
-          command: <String>[
-            'gsutil',
-            'cp',
-            randomString,
-            'gs://flutter/$randomString/$randomString',
-          ],
-          exitCode: 0,
-        ),
-      ]);
-      expect(
-        () => googleCloudStorage.uploadEngineArtifact(
-          from: randomString,
-          destination: codesignVisitor.gcsUploadPath,
-        ),
-        returnsNormally,
-      );
-    });
-
     test('procesRemotezip triggers correct workflow', () async {
       final String zipFileName = '${rootDirectory.path}/remote_zip_4/folder_1/zip_1';
       fileSystem.file(zipFileName).createSync(recursive: true);
       processManager.addCommands(<FakeCommand>[
         FakeCommand(
           command: <String>[
-            'gsutil',
-            'cp',
-            'gs://flutter/$randomString/$randomString',
-            '${rootDirectory.absolute.path}/downloads/remote_artifact.zip',
-          ],
-        ),
-        FakeCommand(
-          command: <String>[
             'unzip',
-            '${rootDirectory.absolute.path}/downloads/remote_artifact.zip',
+            codesignVisitor.inputZipPath,
             '-d',
             '${rootDirectory.absolute.path}/single_artifact',
           ],
@@ -327,7 +134,7 @@
             'zip',
             '--symlinks',
             '--recurse-paths',
-            '${rootDirectory.absolute.path}/codesigned_zips/remote_artifact.zip',
+            codesignVisitor.outputZipPath,
             '.',
             '--include',
             '*',
@@ -338,7 +145,7 @@
             'xcrun',
             'notarytool',
             'submit',
-            '${rootDirectory.absolute.path}/codesigned_zips/remote_artifact.zip',
+            codesignVisitor.outputZipPath,
             '--apple-id',
             randomString,
             '--password',
@@ -363,14 +170,6 @@
           ],
           stdout: 'status: Accepted',
         ),
-        FakeCommand(
-          command: <String>[
-            'gsutil',
-            'cp',
-            '${rootDirectory.absolute.path}/codesigned_zips/remote_artifact.zip',
-            'gs://flutter/$randomString/$randomString',
-          ],
-        ),
       ]);
 
       await codesignVisitor.processRemoteZip();
@@ -381,7 +180,7 @@
       expect(
         messages,
         contains(
-          'The downloaded file is unzipped from ${rootDirectory.absolute.path}/downloads/remote_artifact.zip to ${rootDirectory.path}/single_artifact',
+          'The downloaded file is unzipped from ${codesignVisitor.inputZipPath} to ${rootDirectory.path}/single_artifact',
         ),
       );
       expect(
@@ -399,14 +198,12 @@
       expect(
         messages,
         contains(
-          'uploading xcrun notarytool submit ${rootDirectory.absolute.path}/codesigned_zips/remote_artifact.zip --apple-id $randomString --password $randomString --team-id $randomString',
+          'uploading xcrun notarytool submit ${codesignVisitor.outputZipPath} --apple-id $randomString --password $randomString --team-id $randomString',
         ),
       );
       expect(
         messages,
-        contains(
-          'RequestUUID for ${rootDirectory.absolute.path}/codesigned_zips/remote_artifact.zip is: $randomString',
-        ),
+        contains('RequestUUID for ${codesignVisitor.outputZipPath} is: $randomString'),
       );
       expect(
         messages,
@@ -416,7 +213,7 @@
       );
       expect(
         messages,
-        contains('successfully notarized ${rootDirectory.absolute.path}/codesigned_zips/remote_artifact.zip'),
+        contains('successfully notarized ${codesignVisitor.outputZipPath}'),
       );
     });
   });
@@ -424,21 +221,16 @@
   group('visit directory/zip api calls: ', () {
     setUp(() {
       processManager = FakeProcessManager.list(<FakeCommand>[]);
-      googleCloudStorage = GoogleCloudStorage(
-        processManager: processManager,
-        rootDirectory: rootDirectory,
-      );
       codesignVisitor = cs.FileCodesignVisitor(
         codesignCertName: randomString,
-        googleCloudStorage: googleCloudStorage,
         fileSystem: fileSystem,
         appSpecificPasswordFilePath: appSpecificPasswordFilePath,
         codesignAppstoreIDFilePath: codesignAppstoreIDFilePath,
         codesignTeamIDFilePath: codesignTeamIDFilePath,
         processManager: processManager,
         rootDirectory: rootDirectory,
-        gcsDownloadPath: 'gs://flutter/$randomString/FILEPATH',
-        gcsUploadPath: 'gs://flutter/$randomString/FILEPATH',
+        inputZipPath: inputZipPath,
+        outputZipPath: outputZipPath,
         notarizationTimerDuration: Duration.zero,
       );
       codesignVisitor.appSpecificPassword = randomString;
@@ -714,15 +506,14 @@
     test('visitBinary codesigns binary with / without entitlement', () async {
       codesignVisitor = cs.FileCodesignVisitor(
         codesignCertName: randomString,
-        googleCloudStorage: googleCloudStorage,
         fileSystem: fileSystem,
         appSpecificPasswordFilePath: appSpecificPasswordFilePath,
         codesignAppstoreIDFilePath: codesignAppstoreIDFilePath,
         codesignTeamIDFilePath: codesignTeamIDFilePath,
         processManager: processManager,
         rootDirectory: rootDirectory,
-        gcsDownloadPath: 'flutter/$randomString/FILEPATH',
-        gcsUploadPath: 'flutter/$randomString/FILEPATH',
+        inputZipPath: inputZipPath,
+        outputZipPath: outputZipPath,
         dryrun: false,
         notarizationTimerDuration: const Duration(seconds: 0),
       );
@@ -800,15 +591,10 @@
   group('parse entitlement configs: ', () {
     setUp(() {
       processManager = FakeProcessManager.list(<FakeCommand>[]);
-      googleCloudStorage = GoogleCloudStorage(
-        processManager: processManager,
-        rootDirectory: rootDirectory,
-      );
       codesignVisitor = cs.FileCodesignVisitor(
         codesignCertName: randomString,
-        gcsDownloadPath: 'flutter/$randomString/FILEPATH',
-        gcsUploadPath: 'flutter/$randomString/FILEPATH',
-        googleCloudStorage: googleCloudStorage,
+        inputZipPath: inputZipPath,
+        outputZipPath: outputZipPath,
         fileSystem: fileSystem,
         appSpecificPasswordFilePath: appSpecificPasswordFilePath,
         codesignAppstoreIDFilePath: codesignAppstoreIDFilePath,
@@ -909,15 +695,10 @@
   group('notarization tests: ', () {
     setUp(() {
       processManager = FakeProcessManager.list(<FakeCommand>[]);
-      googleCloudStorage = GoogleCloudStorage(
-        processManager: processManager,
-        rootDirectory: rootDirectory,
-      );
       codesignVisitor = cs.FileCodesignVisitor(
         codesignCertName: randomString,
-        gcsDownloadPath: 'flutter/$randomString/FILEPATH',
-        gcsUploadPath: 'flutter/$randomString/FILEPATH',
-        googleCloudStorage: googleCloudStorage,
+        inputZipPath: inputZipPath,
+        outputZipPath: outputZipPath,
         fileSystem: fileSystem,
         appSpecificPasswordFilePath: appSpecificPasswordFilePath,
         codesignAppstoreIDFilePath: codesignAppstoreIDFilePath,
@@ -1231,15 +1012,10 @@
     setUp(() {
       rootDirectory = fileSystem.systemTempDirectory.createTempSync('conductor_codesign');
       processManager = FakeProcessManager.list(<FakeCommand>[]);
-      googleCloudStorage = GoogleCloudStorage(
-        processManager: processManager,
-        rootDirectory: rootDirectory,
-      );
       codesignVisitor = cs.FileCodesignVisitor(
         codesignCertName: randomString,
-        gcsDownloadPath: 'gs://ios-usb-dependencies/unsigned/libimobiledevice/$randomString/libimobiledevice.zip',
-        gcsUploadPath: 'gs://ios-usb-dependencies/libimobiledevice/$randomString/libimobiledevice.zip',
-        googleCloudStorage: googleCloudStorage,
+        inputZipPath: inputZipPath,
+        outputZipPath: outputZipPath,
         fileSystem: fileSystem,
         appSpecificPasswordFilePath: appSpecificPasswordFilePath,
         codesignAppstoreIDFilePath: codesignAppstoreIDFilePath,
@@ -1256,29 +1032,21 @@
       log.onRecord.listen((LogRecord record) => records.add(record));
       fileSystem.file(codesignAppstoreIDFilePath)
         ..createSync(recursive: true)
-        ..writeAsStringSync('CODESIGN_APPSTORE_ID:$randomString');
+        ..writeAsStringSync(randomString);
       fileSystem.file(codesignTeamIDFilePath)
         ..createSync(recursive: true)
-        ..writeAsStringSync('CODESIGN_TEAM_ID:$randomString');
+        ..writeAsStringSync(randomString);
       fileSystem.file(appSpecificPasswordFilePath)
         ..createSync(recursive: true)
-        ..writeAsStringSync('APP_SPECIFIC_PASSWORD:$randomString');
+        ..writeAsStringSync(randomString);
     });
 
-    test('codesign optional switches artifacts when dryrun is false', () async {
+    test('codesign optional switches artifacts when dryrun is true', () async {
       processManager.addCommands(<FakeCommand>[
         FakeCommand(
           command: <String>[
-            'gsutil',
-            'cp',
-            'gs://ios-usb-dependencies/unsigned/libimobiledevice/abcd1234/libimobiledevice.zip',
-            '${rootDirectory.absolute.path}/downloads/remote_artifact.zip',
-          ],
-        ),
-        FakeCommand(
-          command: <String>[
             'unzip',
-            '${rootDirectory.absolute.path}/downloads/remote_artifact.zip',
+            codesignVisitor.inputZipPath,
             '-d',
             '${rootDirectory.absolute.path}/single_artifact'
           ],
@@ -1291,7 +1059,7 @@
             'zip',
             '--symlinks',
             '--recurse-paths',
-            '${rootDirectory.absolute.path}/codesigned_zips/remote_artifact.zip',
+            codesignVisitor.outputZipPath,
             '.',
             '--include',
             '*'
@@ -1302,7 +1070,7 @@
             'xcrun',
             'notarytool',
             'submit',
-            '${rootDirectory.absolute.path}/codesigned_zips/remote_zip',
+            codesignVisitor.outputZipPath,
             '--apple-id',
             randomString,
             '--password',
@@ -1335,26 +1103,18 @@
           .toList();
       expect(
         messages,
-        contains('code signing dry run has completed, If you intend to upload the artifacts back to'
-            ' google cloud storage, please use the --dryrun=false flag to run code signing script.'),
+        contains('code signing dry run has completed, this is a quick sanity check without'
+            'going through the notary service. To run the full codesign process, use --no-dryrun flag.'),
       );
       rootDirectory = fileSystem.systemTempDirectory.createTempSync('conductor_codesign');
     });
 
-    test('upload optional switch artifacts when dryrun is true', () async {
+    test('upload optional switch artifacts when dryrun is false', () async {
       processManager.addCommands(<FakeCommand>[
         FakeCommand(
           command: <String>[
-            'gsutil',
-            'cp',
-            'gs://ios-usb-dependencies/unsigned/libimobiledevice/abcd1234/libimobiledevice.zip',
-            '${rootDirectory.absolute.path}/downloads/remote_artifact.zip',
-          ],
-        ),
-        FakeCommand(
-          command: <String>[
             'unzip',
-            '${rootDirectory.absolute.path}/downloads/remote_artifact.zip',
+            codesignVisitor.inputZipPath,
             '-d',
             '${rootDirectory.absolute.path}/single_artifact'
           ],
@@ -1367,7 +1127,7 @@
             'zip',
             '--symlinks',
             '--recurse-paths',
-            '${rootDirectory.absolute.path}/codesigned_zips/remote_artifact.zip',
+            codesignVisitor.outputZipPath,
             '.',
             '--include',
             '*'
@@ -1378,7 +1138,7 @@
             'xcrun',
             'notarytool',
             'submit',
-            '${rootDirectory.absolute.path}/codesigned_zips/remote_artifact.zip',
+            codesignVisitor.outputZipPath,
             '--apple-id',
             randomString,
             '--password',
@@ -1403,20 +1163,11 @@
           ],
           stdout: 'status: Accepted',
         ),
-        FakeCommand(
-          command: <String>[
-            'gsutil',
-            'cp',
-            '${rootDirectory.absolute.path}/codesigned_zips/remote_artifact.zip',
-            'gs://ios-usb-dependencies/libimobiledevice/$randomString/libimobiledevice.zip',
-          ],
-        ),
       ]);
       codesignVisitor = cs.FileCodesignVisitor(
         codesignCertName: randomString,
-        gcsDownloadPath: 'gs://ios-usb-dependencies/unsigned/libimobiledevice/$randomString/libimobiledevice.zip',
-        gcsUploadPath: 'gs://ios-usb-dependencies/libimobiledevice/$randomString/libimobiledevice.zip',
-        googleCloudStorage: googleCloudStorage,
+        inputZipPath: inputZipPath,
+        outputZipPath: outputZipPath,
         fileSystem: fileSystem,
         appSpecificPasswordFilePath: appSpecificPasswordFilePath,
         codesignAppstoreIDFilePath: codesignAppstoreIDFilePath,
@@ -1437,14 +1188,16 @@
           .toSet();
       expect(
         messages,
-        isNot(
-          contains('code signing dry run has completed, If you intend to upload the artifacts back to'
-              ' google cloud storage, please use the --dryrun=false flag to run code signing script.'),
-        ),
+        contains('Codesign completed. Codesigned zip is located at ${codesignVisitor.outputZipPath}.'
+            'If you have uploaded the artifacts back to google cloud storage, please delete'
+            ' the folder ${codesignVisitor.outputZipPath} and ${codesignVisitor.inputZipPath}.'),
       );
       expect(
         messages,
-        contains('Codesigned all binaries in ${rootDirectory.path}'),
+        isNot(
+          contains('code signing dry run has completed, this is a quick sanity check without'
+              'going through the notary service. To run the full codesign process, use --no-dryrun flag.'),
+        ),
       );
       rootDirectory = fileSystem.systemTempDirectory.createTempSync('conductor_codesign');
     });