[codesign] the semi entry point of visiting files (#2125)
diff --git a/codesign/bin/codesign.dart b/codesign/bin/codesign.dart
index 84bdbd4..ec88c0d 100644
--- a/codesign/bin/codesign.dart
+++ b/codesign/bin/codesign.dart
@@ -104,8 +104,13 @@
}
const FileSystem fileSystem = LocalFileSystem();
- final Directory tempDir = fileSystem.systemTempDirectory.createTempSync('conductor_codesign');
+ final Directory rootDirectory = fileSystem.systemTempDirectory.createTempSync('conductor_codesign');
const ProcessManager processManager = LocalProcessManager();
+ final GoogleCloudStorage googleCloudStorage = GoogleCloudStorage(
+ processManager: processManager,
+ rootDirectory: rootDirectory,
+ commitHash: commit,
+ );
return FileCodesignVisitor(
codesignCertName: codesignCertName,
@@ -116,8 +121,9 @@
codesignTeamId: codesignTeamId,
codesignFilepaths: codesignFilepaths,
fileSystem: fileSystem,
- tempDir: tempDir,
+ rootDirectory: rootDirectory,
processManager: processManager,
production: production,
+ googleCloudStorage: googleCloudStorage,
).validateAll();
}
diff --git a/codesign/lib/codesign.dart b/codesign/lib/codesign.dart
index 54fe0c8..b814211 100644
--- a/codesign/lib/codesign.dart
+++ b/codesign/lib/codesign.dart
@@ -3,4 +3,5 @@
// 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 56f7d1e..f476a5f 100644
--- a/codesign/lib/src/file_codesign_visitor.dart
+++ b/codesign/lib/src/file_codesign_visitor.dart
@@ -8,6 +8,7 @@
import 'package:file/file.dart';
import 'package:process/process.dart';
+import 'google_cloud_storage.dart';
import 'log.dart';
import 'utils.dart';
@@ -32,21 +33,24 @@
required this.codesignTeamId,
required this.codesignFilepaths,
required this.fileSystem,
- required this.tempDir,
+ required this.rootDirectory,
required this.processManager,
+ required this.googleCloudStorage,
this.production = false,
+ this.notarizationTimerDuration = const Duration(seconds: 5),
}) {
- entitlementsFile = tempDir.childFile('Entitlements.plist')..writeAsStringSync(_entitlementsFileContents);
- remoteDownloadsDir = tempDir.childDirectory('downloads')..createSync();
- codesignedZipsDir = tempDir.childDirectory('codesigned_zips')..createSync();
+ 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.
///
/// This file will be deleted if [validateAll] completes successfully.
- final Directory tempDir;
+ final Directory rootDirectory;
final FileSystem fileSystem;
final ProcessManager processManager;
+ final GoogleCloudStorage googleCloudStorage;
final String commitHash;
final String codesignCertName;
@@ -55,6 +59,7 @@
final String codesignAppstoreId;
final String codesignTeamId;
final bool production;
+ final Duration notarizationTimerDuration;
// TODO(xilaizhang): add back utitlity in later splits
Set<String> fileWithEntitlements = <String>{};
@@ -90,7 +95,6 @@
</dict>
</plist>
''';
- static const Duration _notarizationTimerDuration = Duration(seconds: 45);
static final RegExp _notarytoolStatusCheckPattern = RegExp(r'[ ]*status: ([a-zA-z ]+)');
static final RegExp _notarytoolRequestPattern = RegExp(r'id: ([a-z0-9-]+)');
@@ -119,9 +123,61 @@
/// The entrance point of examining and code signing an engine artifact.
Future<void> validateAll() async {
await Future<void>.value(null);
- log.info('Codesigned all binaries in ${tempDir.path}');
+ log.info('Codesigned all binaries in ${rootDirectory.path}');
- await tempDir.delete(recursive: true);
+ await rootDirectory.delete(recursive: true);
+ }
+
+ /// Retrieve engine artifact from google cloud storage 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({
+ required String artifactFilePath,
+ required Directory parentDirectory,
+ }) async {
+ final FileSystem fs = rootDirectory.fileSystem;
+
+ // namespace by hashcode otherwise there will be collisions
+ final String localFilePath = '${artifactFilePath.hashCode}_${fs.path.basename(artifactFilePath)}';
+
+ // download the zip file
+ final File originalFile = await googleCloudStorage.downloadEngineArtifact(
+ from: artifactFilePath,
+ destination: remoteDownloadsDir.childFile(localFilePath).path,
+ );
+
+ await unzip(
+ inputZip: originalFile,
+ outDir: parentDirectory,
+ processManager: processManager,
+ );
+
+ //extract entitlements file.
+ fileWithEntitlements = await parseEntitlements(parentDirectory, true);
+ fileWithoutEntitlements = await parseEntitlements(parentDirectory, false);
+ log.info('parsed binaries with entitlements are $fileWithEntitlements');
+ log.info('parsed binaries without entitlements are $fileWithEntitlements');
+
+ // recursively visit extracted files
+ await visitDirectory(directory: parentDirectory, entitlementParentPath: artifactFilePath);
+
+ final File codesignedFile = codesignedZipsDir.childFile(localFilePath);
+
+ await zip(
+ inputDir: parentDirectory,
+ outputZip: codesignedFile,
+ processManager: processManager,
+ );
+
+ // notarize
+ await notarize(codesignedFile);
+
+ await googleCloudStorage.uploadEngineArtifact(
+ from: codesignedFile.path,
+ destination: artifactFilePath,
+ );
}
/// Visit a [Directory] type while examining the file system extracted from an artifact.
@@ -144,6 +200,9 @@
);
continue;
}
+ if (entity.basename == 'entitlements.txt' || entity.basename == 'without_entitlements.txt') {
+ continue;
+ }
final FileType childType = getFileType(
entity.absolute.path,
processManager,
@@ -167,7 +226,7 @@
}) async {
log.info('This embedded file is ${zipEntity.path} and entitlementParentPath is $entitlementParentPath');
final String currentFileName = zipEntity.basename;
- final Directory newDir = tempDir.childDirectory('embedded_zip_${zipEntity.absolute.path.hashCode}');
+ final Directory newDir = rootDirectory.childDirectory('embedded_zip_${zipEntity.absolute.path.hashCode}');
await unzip(
inputZip: zipEntity,
outDir: newDir,
@@ -268,7 +327,7 @@
// check on results
Timer.periodic(
- _notarizationTimerDuration,
+ notarizationTimerDuration,
callback,
);
await completer.future;
diff --git a/codesign/lib/src/google_cloud_storage.dart b/codesign/lib/src/google_cloud_storage.dart
new file mode 100644
index 0000000..4b33f5b
--- /dev/null
+++ b/codesign/lib/src/google_cloud_storage.dart
@@ -0,0 +1,55 @@
+// 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,
+ required this.commitHash,
+ });
+
+ final ProcessManager processManager;
+ final Directory rootDirectory;
+ final String commitHash;
+ final String gsCloudBaseUrl = 'gs://flutter_infra_release';
+
+ /// Method to upload code signed flutter engine artifact to google cloud bucket.
+ Future<void> uploadEngineArtifact({
+ required String from,
+ required String destination,
+ }) async {
+ final String destinationUrl = '$gsCloudBaseUrl/flutter/$commitHash/$destination';
+
+ final ProcessResult result = await processManager.run(
+ <String>['gsutil', 'cp', from, destinationUrl],
+ );
+
+ if (result.exitCode != 0) {
+ throw CodesignException('Failed to upload $from to $destinationUrl');
+ }
+ }
+
+ /// Method to download flutter engine artifact from google cloud bucket.
+ Future<File> downloadEngineArtifact({
+ required String from,
+ required String destination,
+ }) async {
+ final String sourceUrl = '$gsCloudBaseUrl/flutter/$commitHash/$from';
+ final ProcessResult result = await processManager.run(
+ <String>['gsutil', 'cp', sourceUrl, destination],
+ );
+ if (result.exitCode != 0) {
+ throw CodesignException('Failed to download from $sourceUrl');
+ }
+ return rootDirectory.fileSystem.file(destination);
+ }
+}
diff --git a/codesign/lib/src/utils.dart b/codesign/lib/src/utils.dart
index afe2008..9c946b1 100644
--- a/codesign/lib/src/utils.dart
+++ b/codesign/lib/src/utils.dart
@@ -5,6 +5,7 @@
import 'dart:io';
import 'package:args/args.dart';
+import 'package:file/file.dart';
import 'package:process/process.dart';
import 'log.dart';
diff --git a/codesign/test/file_codesign_visitor_test.dart b/codesign/test/file_codesign_visitor_test.dart
index 1b2bdb4..0c03690 100644
--- a/codesign/test/file_codesign_visitor_test.dart
+++ b/codesign/test/file_codesign_visitor_test.dart
@@ -5,28 +5,35 @@
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';
import 'package:file/memory.dart';
import 'package:logging/logging.dart';
import 'package:test/test.dart';
+
import './src/fake_process_manager.dart';
void main() {
const String randomString = 'abcd1234';
final MemoryFileSystem fileSystem = MemoryFileSystem.test();
const List<String> fakeFilepaths = <String>['a.zip', 'b.zip', 'c.zip'];
+ final Directory rootDirectory = fileSystem.systemTempDirectory.createTempSync('conductor_codesign');
late FakeProcessManager processManager;
- late Directory tempDir;
+ late GoogleCloudStorage googleCloudStorage;
late cs.FileCodesignVisitor codesignVisitor;
final List<LogRecord> records = <LogRecord>[];
- group('visit directory/zip api calls: ', () {
+ group('test google cloud storage and processRemoteZip workflow', () {
setUp(() {
- tempDir = fileSystem.systemTempDirectory.createTempSync('conductor_codesign');
processManager = FakeProcessManager.list(<FakeCommand>[]);
+ googleCloudStorage = GoogleCloudStorage(
+ processManager: processManager,
+ rootDirectory: rootDirectory,
+ commitHash: randomString,
+ );
codesignVisitor = cs.FileCodesignVisitor(
codesignCertName: randomString,
codesignUserName: randomString,
@@ -35,9 +42,286 @@
codesignTeamId: randomString,
codesignFilepaths: fakeFilepaths,
commitHash: randomString,
+ googleCloudStorage: googleCloudStorage,
fileSystem: fileSystem,
processManager: processManager,
- tempDir: tempDir,
+ rootDirectory: rootDirectory,
+ notarizationTimerDuration: const Duration(seconds: 0),
+ );
+ codesignVisitor.directoriesVisited.clear();
+ records.clear();
+ log.onRecord.listen((LogRecord record) => records.add(record));
+ });
+
+ test('download fails and upload succeeds throws exception', () async {
+ processManager.addCommands(<FakeCommand>[
+ FakeCommand(
+ command: <String>[
+ 'gsutil',
+ 'cp',
+ randomString,
+ '${googleCloudStorage.gsCloudBaseUrl}/flutter/$randomString/$randomString',
+ ],
+ exitCode: 0,
+ ),
+ ]);
+ expect(
+ () => googleCloudStorage.uploadEngineArtifact(
+ from: randomString,
+ destination: randomString,
+ ),
+ returnsNormally,
+ );
+ processManager.addCommands(<FakeCommand>[
+ FakeCommand(
+ command: <String>[
+ 'gsutil',
+ 'cp',
+ '${googleCloudStorage.gsCloudBaseUrl}/flutter/$randomString/$randomString',
+ randomString,
+ ],
+ exitCode: -1,
+ ),
+ ]);
+ expect(
+ () => googleCloudStorage.downloadEngineArtifact(
+ from: randomString,
+ destination: randomString,
+ ),
+ throwsA(
+ isA<CodesignException>(),
+ ),
+ );
+ });
+
+ test('download succeeds and upload fails throws exception', () async {
+ processManager.addCommands(<FakeCommand>[
+ FakeCommand(
+ command: <String>[
+ 'gsutil',
+ 'cp',
+ '${googleCloudStorage.gsCloudBaseUrl}/flutter/$randomString/$randomString',
+ randomString,
+ ],
+ exitCode: 0,
+ ),
+ ]);
+ expect(
+ () => googleCloudStorage.downloadEngineArtifact(
+ from: randomString,
+ destination: randomString,
+ ),
+ returnsNormally,
+ );
+ processManager.addCommands(<FakeCommand>[
+ FakeCommand(
+ command: <String>[
+ 'gsutil',
+ 'cp',
+ randomString,
+ '${googleCloudStorage.gsCloudBaseUrl}/flutter/$randomString/$randomString',
+ ],
+ exitCode: -1,
+ ),
+ ]);
+ expect(
+ () => googleCloudStorage.uploadEngineArtifact(
+ from: randomString,
+ destination: randomString,
+ ),
+ throwsA(
+ isA<CodesignException>(),
+ ),
+ );
+ });
+
+ test('download succeeds and upload succeeds returns normally', () async {
+ processManager.addCommands(<FakeCommand>[
+ FakeCommand(
+ command: <String>[
+ 'gsutil',
+ 'cp',
+ '${googleCloudStorage.gsCloudBaseUrl}/flutter/$randomString/$randomString',
+ randomString,
+ ],
+ exitCode: 0,
+ ),
+ ]);
+ expect(
+ () => googleCloudStorage.downloadEngineArtifact(
+ from: randomString,
+ destination: randomString,
+ ),
+ returnsNormally,
+ );
+ processManager.addCommands(<FakeCommand>[
+ FakeCommand(
+ command: <String>[
+ 'gsutil',
+ 'cp',
+ randomString,
+ '${googleCloudStorage.gsCloudBaseUrl}/flutter/$randomString/$randomString',
+ ],
+ exitCode: 0,
+ ),
+ ]);
+ expect(
+ () => googleCloudStorage.uploadEngineArtifact(
+ from: randomString,
+ destination: randomString,
+ ),
+ 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);
+ const String artifactFilePath = 'my/artifacts.zip';
+ final String artifactBaseName = rootDirectory.fileSystem.path.basename(artifactFilePath);
+ processManager.addCommands(<FakeCommand>[
+ FakeCommand(
+ command: <String>[
+ 'gsutil',
+ 'cp',
+ '${googleCloudStorage.gsCloudBaseUrl}/flutter/$randomString/$artifactFilePath',
+ '${rootDirectory.absolute.path}/downloads/${artifactFilePath.hashCode}_$artifactBaseName',
+ ],
+ ),
+ FakeCommand(
+ command: <String>[
+ 'unzip',
+ '${rootDirectory.absolute.path}/downloads/${artifactFilePath.hashCode}_$artifactBaseName',
+ '-d',
+ '${rootDirectory.absolute.path}/remote_zip_${artifactFilePath.hashCode}_$artifactBaseName',
+ ],
+ onRun: () => fileSystem
+ ..file('${rootDirectory.path}/remote_zip_${artifactFilePath.hashCode}_$artifactBaseName/entitlements.txt')
+ .createSync(recursive: true)
+ ..file('${rootDirectory.path}/remote_zip_${artifactFilePath.hashCode}_$artifactBaseName/without_entitlements.txt')
+ .createSync(recursive: true),
+ ),
+ FakeCommand(
+ command: <String>[
+ 'zip',
+ '--symlinks',
+ '--recurse-paths',
+ '${rootDirectory.absolute.path}/codesigned_zips/${artifactFilePath.hashCode}_$artifactBaseName',
+ '.',
+ '--include',
+ '*',
+ ],
+ ),
+ FakeCommand(
+ command: <String>[
+ 'xcrun',
+ 'notarytool',
+ 'submit',
+ '${rootDirectory.absolute.path}/codesigned_zips/${artifactFilePath.hashCode}_$artifactBaseName',
+ '--apple-id',
+ randomString,
+ '--password',
+ randomString,
+ '--team-id',
+ randomString,
+ ],
+ stdout: 'id: $randomString',
+ ),
+ const FakeCommand(
+ command: <String>[
+ 'xcrun',
+ 'notarytool',
+ 'info',
+ randomString,
+ '--password',
+ randomString,
+ '--apple-id',
+ randomString,
+ '--team-id',
+ randomString,
+ ],
+ stdout: 'status: Accepted',
+ ),
+ FakeCommand(
+ command: <String>[
+ 'gsutil',
+ 'cp',
+ '${rootDirectory.absolute.path}/codesigned_zips/${artifactFilePath.hashCode}_$artifactBaseName',
+ '${googleCloudStorage.gsCloudBaseUrl}/flutter/$randomString/$artifactFilePath',
+ ],
+ ),
+ ]);
+
+ await codesignVisitor.processRemoteZip(
+ artifactFilePath: artifactFilePath,
+ parentDirectory: rootDirectory.childDirectory('remote_zip_${artifactFilePath.hashCode}_$artifactBaseName'),
+ );
+ final Set<String> messages = records
+ .where((LogRecord record) => record.level == Level.INFO)
+ .map((LogRecord record) => record.message)
+ .toSet();
+ expect(
+ messages,
+ contains(
+ 'The downloaded file is unzipped from ${rootDirectory.absolute.path}/downloads/${artifactFilePath.hashCode}_$artifactBaseName to ${rootDirectory.path}/remote_zip_${artifactFilePath.hashCode}_$artifactBaseName'),
+ );
+ expect(
+ messages,
+ contains(
+ 'Visiting directory ${rootDirectory.absolute.path}/remote_zip_${artifactFilePath.hashCode}_$artifactBaseName'),
+ );
+ expect(
+ messages,
+ contains('parsed binaries with entitlements are {}'),
+ );
+ expect(
+ messages,
+ contains('parsed binaries without entitlements are {}'),
+ );
+ expect(
+ messages,
+ contains(
+ 'uploading xcrun notarytool submit ${rootDirectory.absolute.path}/codesigned_zips/${artifactFilePath.hashCode}_$artifactBaseName --apple-id $randomString --password $randomString --team-id $randomString'),
+ );
+ expect(
+ messages,
+ contains(
+ 'RequestUUID for ${rootDirectory.absolute.path}/codesigned_zips/${artifactFilePath.hashCode}_$artifactBaseName is: $randomString'),
+ );
+ expect(
+ messages,
+ contains(
+ 'checking notary status with xcrun notarytool info $randomString --password $randomString --apple-id $randomString --team-id $randomString'),
+ );
+ expect(
+ messages,
+ contains(
+ 'successfully notarized ${rootDirectory.absolute.path}/codesigned_zips/${artifactFilePath.hashCode}_$artifactBaseName'),
+ );
+ });
+ });
+
+ group('visit directory/zip api calls: ', () {
+ setUp(() {
+ processManager = FakeProcessManager.list(<FakeCommand>[]);
+ googleCloudStorage = GoogleCloudStorage(
+ processManager: processManager,
+ rootDirectory: rootDirectory,
+ commitHash: randomString,
+ );
+ codesignVisitor = cs.FileCodesignVisitor(
+ codesignCertName: randomString,
+ codesignUserName: randomString,
+ appSpecificPassword: randomString,
+ codesignAppstoreId: randomString,
+ codesignTeamId: randomString,
+ codesignFilepaths: fakeFilepaths,
+ commitHash: randomString,
+ googleCloudStorage: googleCloudStorage,
+ fileSystem: fileSystem,
+ processManager: processManager,
+ rootDirectory: rootDirectory,
+ notarizationTimerDuration: const Duration(seconds: 0),
);
codesignVisitor.directoriesVisited.clear();
records.clear();
@@ -46,16 +330,16 @@
test('visitDirectory correctly list files', () async {
fileSystem
- ..file('${tempDir.path}/remote_zip_0/file_a').createSync(recursive: true)
- ..file('${tempDir.path}/remote_zip_0/file_b').createSync(recursive: true)
- ..file('${tempDir.path}/remote_zip_0/file_c').createSync(recursive: true);
+ ..file('${rootDirectory.path}/remote_zip_0/file_a').createSync(recursive: true)
+ ..file('${rootDirectory.path}/remote_zip_0/file_b').createSync(recursive: true)
+ ..file('${rootDirectory.path}/remote_zip_0/file_c').createSync(recursive: true);
processManager.addCommands(<FakeCommand>[
FakeCommand(
command: <String>[
'file',
'--mime-type',
'-b',
- '${tempDir.absolute.path}/remote_zip_0/file_a',
+ '${rootDirectory.absolute.path}/remote_zip_0/file_a',
],
stdout: 'other_files',
),
@@ -64,7 +348,7 @@
'file',
'--mime-type',
'-b',
- '${tempDir.absolute.path}/remote_zip_0/file_b',
+ '${rootDirectory.absolute.path}/remote_zip_0/file_b',
],
stdout: 'other_files',
),
@@ -73,12 +357,12 @@
'file',
'--mime-type',
'-b',
- '${tempDir.absolute.path}/remote_zip_0/file_c',
+ '${rootDirectory.absolute.path}/remote_zip_0/file_c',
],
stdout: 'other_files',
),
]);
- final Directory testDirectory = fileSystem.directory('${tempDir.path}/remote_zip_0');
+ final Directory testDirectory = fileSystem.directory('${rootDirectory.path}/remote_zip_0');
await codesignVisitor.visitDirectory(
directory: testDirectory,
entitlementParentPath: 'a.zip',
@@ -87,7 +371,7 @@
.where((LogRecord record) => record.level == Level.INFO)
.map((LogRecord record) => record.message)
.toList();
- expect(messages, contains('Visiting directory ${tempDir.path}/remote_zip_0'));
+ expect(messages, contains('Visiting directory ${rootDirectory.path}/remote_zip_0'));
expect(messages, contains('Child file of directory remote_zip_0 is file_a'));
expect(messages, contains('Child file of directory remote_zip_0 is file_b'));
expect(messages, contains('Child file of directory remote_zip_0 is file_c'));
@@ -95,16 +379,16 @@
test('visitDirectory recursively visits directory', () async {
fileSystem
- ..file('${tempDir.path}/remote_zip_1/file_a').createSync(recursive: true)
- ..file('${tempDir.path}/remote_zip_1/folder_a/file_b').createSync(recursive: true);
- final Directory testDirectory = fileSystem.directory('${tempDir.path}/remote_zip_1');
+ ..file('${rootDirectory.path}/remote_zip_1/file_a').createSync(recursive: true)
+ ..file('${rootDirectory.path}/remote_zip_1/folder_a/file_b').createSync(recursive: true);
+ final Directory testDirectory = fileSystem.directory('${rootDirectory.path}/remote_zip_1');
processManager.addCommands(<FakeCommand>[
FakeCommand(
command: <String>[
'file',
'--mime-type',
'-b',
- '${tempDir.absolute.path}/remote_zip_1/file_a',
+ '${rootDirectory.absolute.path}/remote_zip_1/file_a',
],
stdout: 'other_files',
),
@@ -113,7 +397,7 @@
'file',
'--mime-type',
'-b',
- '${tempDir.absolute.path}/remote_zip_1/folder_a/file_b',
+ '${rootDirectory.absolute.path}/remote_zip_1/folder_a/file_b',
],
stdout: 'other_files',
),
@@ -126,32 +410,32 @@
.where((LogRecord record) => record.level == Level.INFO)
.map((LogRecord record) => record.message)
.toList();
- expect(messages, contains('Visiting directory ${tempDir.path}/remote_zip_1'));
- expect(messages, contains('Visiting directory ${tempDir.path}/remote_zip_1/folder_a'));
+ expect(messages, contains('Visiting directory ${rootDirectory.path}/remote_zip_1'));
+ expect(messages, contains('Visiting directory ${rootDirectory.path}/remote_zip_1/folder_a'));
expect(messages, contains('Child file of directory remote_zip_1 is file_a'));
expect(messages, contains('Child file of directory folder_a is file_b'));
});
test('visit directory inside a zip', () async {
- final String zipFileName = '${tempDir.path}/remote_zip_2/zip_1';
+ final String zipFileName = '${rootDirectory.path}/remote_zip_2/zip_1';
fileSystem.file(zipFileName).createSync(recursive: true);
processManager.addCommands(<FakeCommand>[
FakeCommand(
command: <String>[
'unzip',
- '${tempDir.absolute.path}/remote_zip_2/zip_1',
+ '${rootDirectory.absolute.path}/remote_zip_2/zip_1',
'-d',
- '${tempDir.absolute.path}/embedded_zip_${zipFileName.hashCode}',
+ '${rootDirectory.absolute.path}/embedded_zip_${zipFileName.hashCode}',
],
onRun: () => fileSystem
- ..file('${tempDir.path}/embedded_zip_${zipFileName.hashCode}/file_1').createSync(recursive: true)
- ..file('${tempDir.path}/embedded_zip_${zipFileName.hashCode}/file_2').createSync(recursive: true)),
+ ..file('${rootDirectory.path}/embedded_zip_${zipFileName.hashCode}/file_1').createSync(recursive: true)
+ ..file('${rootDirectory.path}/embedded_zip_${zipFileName.hashCode}/file_2').createSync(recursive: true)),
FakeCommand(
command: <String>[
'file',
'--mime-type',
'-b',
- '${tempDir.absolute.path}/embedded_zip_${zipFileName.hashCode}/file_1',
+ '${rootDirectory.absolute.path}/embedded_zip_${zipFileName.hashCode}/file_1',
],
stdout: 'other_files',
),
@@ -160,7 +444,7 @@
'file',
'--mime-type',
'-b',
- '${tempDir.absolute.path}/embedded_zip_${zipFileName.hashCode}/file_2',
+ '${rootDirectory.absolute.path}/embedded_zip_${zipFileName.hashCode}/file_2',
],
stdout: 'other_files',
),
@@ -169,17 +453,17 @@
'zip',
'--symlinks',
'--recurse-paths',
- '${tempDir.absolute.path}/remote_zip_2/zip_1',
+ '${rootDirectory.absolute.path}/remote_zip_2/zip_1',
'.',
'--include',
'*'
],
- onRun: () => fileSystem.file('${tempDir.path}/remote_zip_2/zip_1').createSync(recursive: true),
+ onRun: () => fileSystem.file('${rootDirectory.path}/remote_zip_2/zip_1').createSync(recursive: true),
),
]);
await codesignVisitor.visitEmbeddedZip(
- zipEntity: fileSystem.file('${tempDir.path}/remote_zip_2/zip_1'),
+ zipEntity: fileSystem.file('${rootDirectory.path}/remote_zip_2/zip_1'),
entitlementParentPath: 'a.zip',
);
final List<String> messages = records
@@ -189,14 +473,14 @@
expect(
messages,
contains(
- 'The downloaded file is unzipped from ${tempDir.path}/remote_zip_2/zip_1 to ${tempDir.path}/embedded_zip_${zipFileName.hashCode}'));
- expect(messages, contains('Visiting directory ${tempDir.path}/embedded_zip_${zipFileName.hashCode}'));
+ 'The downloaded file is unzipped from ${rootDirectory.path}/remote_zip_2/zip_1 to ${rootDirectory.path}/embedded_zip_${zipFileName.hashCode}'));
+ expect(messages, contains('Visiting directory ${rootDirectory.path}/embedded_zip_${zipFileName.hashCode}'));
expect(messages, contains('Child file of directory embedded_zip_${zipFileName.hashCode} is file_1'));
expect(messages, contains('Child file of directory embedded_zip_${zipFileName.hashCode} is file_2'));
});
test('visit zip inside a directory', () async {
- final String zipFileName = '${tempDir.path}/remote_zip_4/folder_1/zip_1';
+ final String zipFileName = '${rootDirectory.path}/remote_zip_4/folder_1/zip_1';
fileSystem.file(zipFileName).createSync(recursive: true);
processManager.addCommands(<FakeCommand>[
FakeCommand(
@@ -204,25 +488,26 @@
'file',
'--mime-type',
'-b',
- '${tempDir.absolute.path}/remote_zip_4/folder_1/zip_1',
+ '${rootDirectory.absolute.path}/remote_zip_4/folder_1/zip_1',
],
stdout: 'application/zip',
),
FakeCommand(
command: <String>[
'unzip',
- '${tempDir.absolute.path}/remote_zip_4/folder_1/zip_1',
+ '${rootDirectory.absolute.path}/remote_zip_4/folder_1/zip_1',
'-d',
- '${tempDir.absolute.path}/embedded_zip_${zipFileName.hashCode}',
+ '${rootDirectory.absolute.path}/embedded_zip_${zipFileName.hashCode}',
],
- onRun: () =>
- fileSystem.directory('${tempDir.path}/embedded_zip_${zipFileName.hashCode}').createSync(recursive: true),
+ onRun: () => fileSystem
+ .directory('${rootDirectory.path}/embedded_zip_${zipFileName.hashCode}')
+ .createSync(recursive: true),
),
FakeCommand(command: <String>[
'zip',
'--symlinks',
'--recurse-paths',
- '${tempDir.absolute.path}/remote_zip_4/folder_1/zip_1',
+ '${rootDirectory.absolute.path}/remote_zip_4/folder_1/zip_1',
'.',
'--include',
'*'
@@ -230,31 +515,32 @@
]);
await codesignVisitor.visitDirectory(
- directory: fileSystem.directory('${tempDir.path}/remote_zip_4'),
+ directory: fileSystem.directory('${rootDirectory.path}/remote_zip_4'),
entitlementParentPath: 'a.zip',
);
final List<String> messages = records
.where((LogRecord record) => record.level == Level.INFO)
.map((LogRecord record) => record.message)
.toList();
- expect(messages, contains('Visiting directory ${tempDir.absolute.path}/remote_zip_4'));
- expect(messages, contains('Visiting directory ${tempDir.absolute.path}/remote_zip_4/folder_1'));
+ expect(messages, contains('Visiting directory ${rootDirectory.absolute.path}/remote_zip_4'));
+ expect(messages, contains('Visiting directory ${rootDirectory.absolute.path}/remote_zip_4/folder_1'));
expect(
messages,
contains(
- 'The downloaded file is unzipped from ${tempDir.path}/remote_zip_4/folder_1/zip_1 to ${tempDir.path}/embedded_zip_${zipFileName.hashCode}'));
- expect(messages, contains('Visiting directory ${tempDir.absolute.path}/embedded_zip_${zipFileName.hashCode}'));
+ 'The downloaded file is unzipped from ${rootDirectory.path}/remote_zip_4/folder_1/zip_1 to ${rootDirectory.path}/embedded_zip_${zipFileName.hashCode}'));
+ expect(
+ messages, contains('Visiting directory ${rootDirectory.absolute.path}/embedded_zip_${zipFileName.hashCode}'));
});
test('throw exception when the same directory is visited', () async {
- fileSystem.file('${tempDir.path}/parent_1/child_1/file_1').createSync(recursive: true);
+ fileSystem.file('${rootDirectory.path}/parent_1/child_1/file_1').createSync(recursive: true);
processManager.addCommands(<FakeCommand>[
FakeCommand(
command: <String>[
'file',
'--mime-type',
'-b',
- '${tempDir.absolute.path}/parent_1/child_1/file_1',
+ '${rootDirectory.absolute.path}/parent_1/child_1/file_1',
],
stdout: 'other_files',
),
@@ -263,14 +549,14 @@
'file',
'--mime-type',
'-b',
- '${tempDir.absolute.path}/parent_1/child_1/file_1',
+ '${rootDirectory.absolute.path}/parent_1/child_1/file_1',
],
stdout: 'other_files',
),
]);
await codesignVisitor.visitDirectory(
- directory: fileSystem.directory('${tempDir.path}/parent_1/child_1'),
+ directory: fileSystem.directory('${rootDirectory.path}/parent_1/child_1'),
entitlementParentPath: 'a.zip',
);
List<String> warnings = records
@@ -280,7 +566,7 @@
expect(warnings, isEmpty);
await codesignVisitor.visitDirectory(
- directory: fileSystem.directory('${tempDir.path}/parent_1'),
+ directory: fileSystem.directory('${rootDirectory.path}/parent_1'),
entitlementParentPath: 'a.zip',
);
warnings = records
@@ -290,23 +576,23 @@
expect(
warnings,
contains(
- 'Warning! You are visiting a directory that has been visited before, the directory is ${tempDir.path}/parent_1/child_1'));
+ 'Warning! You are visiting a directory that has been visited before, the directory is ${rootDirectory.path}/parent_1/child_1'));
});
test('visitBinary codesigns binary with / without entitlement', () async {
codesignVisitor.fileWithEntitlements = <String>{'root/file_a'};
codesignVisitor.fileWithoutEntitlements = <String>{'root/file_b'};
fileSystem
- ..file('${tempDir.path}/remote_zip_1/file_a').createSync(recursive: true)
- ..file('${tempDir.path}/remote_zip_1/file_b').createSync(recursive: true);
- final Directory testDirectory = fileSystem.directory('${tempDir.path}/remote_zip_1');
+ ..file('${rootDirectory.path}/remote_zip_5/file_a').createSync(recursive: true)
+ ..file('${rootDirectory.path}/remote_zip_5/file_b').createSync(recursive: true);
+ final Directory testDirectory = fileSystem.directory('${rootDirectory.path}/remote_zip_5');
processManager.addCommands(<FakeCommand>[
FakeCommand(
command: <String>[
'file',
'--mime-type',
'-b',
- '${tempDir.absolute.path}/remote_zip_1/file_a',
+ '${rootDirectory.absolute.path}/remote_zip_5/file_a',
],
stdout: 'application/x-mach-binary',
),
@@ -316,11 +602,11 @@
'-f',
'-s',
randomString,
- '${tempDir.absolute.path}/remote_zip_1/file_a',
+ '${rootDirectory.absolute.path}/remote_zip_5/file_a',
'--timestamp',
'--options=runtime',
'--entitlements',
- '${tempDir.absolute.path}/Entitlements.plist'
+ '${rootDirectory.absolute.path}/Entitlements.plist'
],
),
FakeCommand(
@@ -328,7 +614,7 @@
'file',
'--mime-type',
'-b',
- '${tempDir.absolute.path}/remote_zip_1/file_b',
+ '${rootDirectory.absolute.path}/remote_zip_5/file_b',
],
stdout: 'application/x-mach-binary',
),
@@ -338,7 +624,7 @@
'-f',
'-s',
randomString,
- '${tempDir.absolute.path}/remote_zip_1/file_b',
+ '${rootDirectory.absolute.path}/remote_zip_5/file_b',
'--timestamp',
'--options=runtime',
],
@@ -352,11 +638,11 @@
.where((LogRecord record) => record.level == Level.INFO)
.map((LogRecord record) => record.message)
.toList();
- expect(messages, contains('signing file at path ${tempDir.absolute.path}/remote_zip_1/file_a'));
+ expect(messages, contains('signing file at path ${rootDirectory.absolute.path}/remote_zip_5/file_a'));
expect(messages, contains('the virtual entitlement path associated with file is root/file_a'));
expect(messages, contains('the decision to sign with entitlement is true'));
- expect(messages, contains('signing file at path ${tempDir.absolute.path}/remote_zip_1/file_b'));
+ expect(messages, contains('signing file at path ${rootDirectory.absolute.path}/remote_zip_5/file_b'));
expect(messages, contains('the virtual entitlement path associated with file is root/file_b'));
expect(messages, contains('the decision to sign with entitlement is false'));
});
@@ -364,8 +650,12 @@
group('parse entitlement configs: ', () {
setUp(() {
- tempDir = fileSystem.systemTempDirectory.createTempSync('conductor_codesign');
processManager = FakeProcessManager.list(<FakeCommand>[]);
+ googleCloudStorage = GoogleCloudStorage(
+ processManager: processManager,
+ rootDirectory: rootDirectory,
+ commitHash: randomString,
+ );
codesignVisitor = cs.FileCodesignVisitor(
codesignCertName: randomString,
codesignUserName: randomString,
@@ -374,9 +664,10 @@
codesignTeamId: randomString,
codesignFilepaths: fakeFilepaths,
commitHash: randomString,
+ googleCloudStorage: googleCloudStorage,
fileSystem: fileSystem,
processManager: processManager,
- tempDir: tempDir,
+ rootDirectory: rootDirectory,
);
codesignVisitor.directoriesVisited.clear();
records.clear();
@@ -384,7 +675,7 @@
});
test('correctly store file paths', () async {
- fileSystem.file('${tempDir.absolute.path}/test_entitlement/entitlements.txt')
+ fileSystem.file('${rootDirectory.absolute.path}/test_entitlement/entitlements.txt')
..createSync(recursive: true)
..writeAsStringSync(
'''file_a
@@ -394,7 +685,7 @@
encoding: utf8,
);
- fileSystem.file('${tempDir.absolute.path}/test_entitlement/without_entitlements.txt')
+ fileSystem.file('${rootDirectory.absolute.path}/test_entitlement/without_entitlements.txt')
..createSync(recursive: true)
..writeAsStringSync(
'''file_d
@@ -403,11 +694,11 @@
encoding: utf8,
);
final Set<String> fileWithEntitlements = await codesignVisitor.parseEntitlements(
- fileSystem.directory('${tempDir.absolute.path}/test_entitlement'),
+ fileSystem.directory('${rootDirectory.absolute.path}/test_entitlement'),
true,
);
final Set<String> fileWithoutEntitlements = await codesignVisitor.parseEntitlements(
- fileSystem.directory('${tempDir.absolute.path}/test_entitlement'),
+ fileSystem.directory('${rootDirectory.absolute.path}/test_entitlement'),
false,
);
expect(fileWithEntitlements.length, 3);
@@ -428,7 +719,7 @@
});
test('throw exception when configuration file is missing', () async {
- fileSystem.file('${tempDir.absolute.path}/test_entitlement/entitlements.txt')
+ fileSystem.file('${rootDirectory.absolute.path}/test_entitlement_2/entitlements.txt')
..createSync(recursive: true)
..writeAsStringSync(
'''file_a
@@ -439,7 +730,7 @@
);
final Set<String> fileWithEntitlements = await codesignVisitor.parseEntitlements(
- fileSystem.directory('${tempDir.absolute.path}/test_entitlement'),
+ fileSystem.directory('${rootDirectory.absolute.path}/test_entitlement_2'),
true,
);
expect(fileWithEntitlements.length, 3);
@@ -452,7 +743,7 @@
]));
expect(
() => codesignVisitor.parseEntitlements(
- fileSystem.directory('/Users/xilaizhang/Desktop/test_entitlement'),
+ fileSystem.directory('/Users/xilaizhang/Desktop/test_entitlement_2'),
false,
),
throwsA(
@@ -463,8 +754,12 @@
group('notarization tests: ', () {
setUp(() {
- tempDir = fileSystem.systemTempDirectory.createTempSync('conductor_codesign');
processManager = FakeProcessManager.list(<FakeCommand>[]);
+ googleCloudStorage = GoogleCloudStorage(
+ processManager: processManager,
+ rootDirectory: rootDirectory,
+ commitHash: randomString,
+ );
codesignVisitor = cs.FileCodesignVisitor(
codesignCertName: randomString,
codesignUserName: randomString,
@@ -473,9 +768,10 @@
codesignTeamId: randomString,
codesignFilepaths: fakeFilepaths,
commitHash: randomString,
+ googleCloudStorage: googleCloudStorage,
fileSystem: fileSystem,
processManager: processManager,
- tempDir: tempDir,
+ rootDirectory: rootDirectory,
);
codesignVisitor.directoriesVisited.clear();
records.clear();
@@ -601,14 +897,14 @@
});
test('upload notary retries upon failure', () async {
- fileSystem.file('${tempDir.absolute.path}/temp').createSync();
+ fileSystem.file('${rootDirectory.absolute.path}/temp').createSync();
processManager.addCommands(<FakeCommand>[
FakeCommand(
command: <String>[
'xcrun',
'notarytool',
'submit',
- '${tempDir.absolute.path}/temp',
+ '${rootDirectory.absolute.path}/temp',
'--apple-id',
randomString,
'--password',
@@ -625,7 +921,7 @@
'xcrun',
'notarytool',
'submit',
- '${tempDir.absolute.path}/temp',
+ '${rootDirectory.absolute.path}/temp',
'--apple-id',
randomString,
'--password',
@@ -640,7 +936,7 @@
]);
final String uuid = codesignVisitor.uploadZipToNotary(
- fileSystem.file('${tempDir.absolute.path}/temp'),
+ fileSystem.file('${rootDirectory.absolute.path}/temp'),
3,
0,
);
@@ -652,7 +948,7 @@
expect(
messages,
contains('Failed to upload to the notary service with args: '
- 'xcrun notarytool submit ${tempDir.absolute.path}/temp '
+ 'xcrun notarytool submit ${rootDirectory.absolute.path}/temp '
'--apple-id abcd1234 --password abcd1234 --team-id abcd1234'),
);
expect(
@@ -662,14 +958,14 @@
});
test('upload notary throws exception if exit code is unnormal', () async {
- fileSystem.file('${tempDir.absolute.path}/temp').createSync();
+ fileSystem.file('${rootDirectory.absolute.path}/temp').createSync();
processManager.addCommands(<FakeCommand>[
FakeCommand(
command: <String>[
'xcrun',
'notarytool',
'submit',
- '${tempDir.absolute.path}/temp',
+ '${rootDirectory.absolute.path}/temp',
'--apple-id',
randomString,
'--password',
@@ -686,7 +982,7 @@
expect(
() => codesignVisitor.uploadZipToNotary(
- fileSystem.file('${tempDir.absolute.path}/temp'),
+ fileSystem.file('${rootDirectory.absolute.path}/temp'),
1,
0,
),
@@ -697,14 +993,14 @@
});
test('upload notary throws exception after 3 default tries', () async {
- fileSystem.file('${tempDir.absolute.path}/temp').createSync();
+ fileSystem.file('${rootDirectory.absolute.path}/temp').createSync();
processManager.addCommands(<FakeCommand>[
FakeCommand(
command: <String>[
'xcrun',
'notarytool',
'submit',
- '${tempDir.absolute.path}/temp',
+ '${rootDirectory.absolute.path}/temp',
'--apple-id',
randomString,
'--password',
@@ -721,7 +1017,7 @@
'xcrun',
'notarytool',
'submit',
- '${tempDir.absolute.path}/temp',
+ '${rootDirectory.absolute.path}/temp',
'--apple-id',
randomString,
'--password',
@@ -738,7 +1034,7 @@
'xcrun',
'notarytool',
'submit',
- '${tempDir.absolute.path}/temp',
+ '${rootDirectory.absolute.path}/temp',
'--apple-id',
randomString,
'--password',
@@ -754,7 +1050,7 @@
expect(
() => codesignVisitor.uploadZipToNotary(
- fileSystem.file('${tempDir.absolute.path}/temp'),
+ fileSystem.file('${rootDirectory.absolute.path}/temp'),
3,
0,
),