[codesign + recipe ] read passwords from a file (#2277)
diff --git a/codesign/bin/codesign.dart b/codesign/bin/codesign.dart
index 05a85ba..053282c 100644
--- a/codesign/bin/codesign.dart
+++ b/codesign/bin/codesign.dart
@@ -15,12 +15,11 @@
const String kHelpFlag = 'help';
const String kDryrunFlag = 'dryrun';
const String kCodesignCertNameOption = 'codesign-cert-name';
-const String kCodesignUserNameOption = 'codesign-username';
-const String kAppSpecificPasswordOption = 'app-specific-password';
-const String kCodesignAppStoreIdOption = 'codesign-appstore-id';
-const String kCodesignTeamIdOption = 'codesign-team-id';
const String kGcsDownloadPathOption = 'gcs-download-path';
const String kGcsUploadPathOption = 'gcs-upload-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';
/// Perform Mac code signing based on file paths.
///
@@ -34,12 +33,33 @@
/// 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 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
+/// 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
+///
+/// For [kAppSpecificPasswordOption], [kCodesignAppstoreIDOption] and [kCodesignTeamIDOption],
+/// they are file paths of the password files in the file system.
+/// Each of the file paths stores a single line of sensitive password.
+/// sensitive passwords include <CODESIGN_APPSTORE_ID>, <CODESIGN_TEAM_ID>, and <APP_SPECIFIC_PASSWORD>.
+/// For example, if a user supplies --app-specific-password-file-path=/tmp/passwords.txt,
+/// then we would be expecting a password file located at /tmp/passwords.txt.
+/// The password file should contain the password name APP-SPECIFIC-PASSWORD and its value, deliminated by a single colon.
+/// The content of a password file would look similar to:
+/// APP-SPECIFIC-PASSWORD:789
+///
+/// [kCodesignCertNameOption] is public information. For codesigning flutter artifacts,
+/// a user can provide values for this variable as shown in the example below.
///
/// Usage:
/// ```shell
-/// dart run bin/codesign.dart --[no-]dryrun --gcs-download-path=gs://flutter_infra_release/flutter/<commit>/android-arm-profile/artifacts.zip
+/// dart run bin/codesign.dart --[no-]dryrun
+/// --codesign-cert-name="FLUTTER.IO LLC"
+/// --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
/// ```
Future<void> main(List<String> args) async {
@@ -57,18 +77,6 @@
'the name of the certificate for flutter, for example, is: FLUTTER.IO LLC',
)
..addOption(
- kAppSpecificPasswordOption,
- help: 'Unique password specifically for codesigning the given application.',
- )
- ..addOption(
- kCodesignAppStoreIdOption,
- help: 'Apple developer account email used for authentication with notary service.',
- )
- ..addOption(
- kCodesignTeamIdOption,
- help: 'Team-id is used by notary service for xcode version 13+.',
- )
- ..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`'
@@ -80,6 +88,21 @@
'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',
)
+ ..addOption(
+ kAppSpecificPasswordOption,
+ help:
+ 'The file path of a password file in file system. The password file stores the sensitive password <APP-SPECIFIC-PASSWORD> \n',
+ )
+ ..addOption(
+ kCodesignAppstoreIDOption,
+ help:
+ 'The file path of a password file in file system. The password file stores the sensitive password <CODESIGN_APPSTORE_ID> \n',
+ )
+ ..addOption(
+ kCodesignTeamIDOption,
+ help:
+ 'The file path of a password file in file system. The password file stores the sensitive password <CODESIGN_TEAM_ID> \n',
+ )
..addFlag(
kDryrunFlag,
defaultsTo: true,
@@ -90,14 +113,12 @@
const Platform platform = LocalPlatform();
- final String codesignCertName = getValueFromEnvOrArgs(kCodesignCertNameOption, argResults, platform.environment)!;
- final String codesignUserName = getValueFromEnvOrArgs(kCodesignUserNameOption, argResults, platform.environment)!;
- final String appSpecificPassword =
- getValueFromEnvOrArgs(kAppSpecificPasswordOption, argResults, platform.environment)!;
- final String codesignAppstoreId = getValueFromEnvOrArgs(kCodesignAppStoreIdOption, argResults, platform.environment)!;
- final String codesignTeamId = getValueFromEnvOrArgs(kCodesignTeamIdOption, argResults, platform.environment)!;
- final String gCloudDownloadPath = getValueFromEnvOrArgs(kGcsDownloadPathOption, argResults, platform.environment)!;
- final String gCloudUploadPath = getValueFromEnvOrArgs(kGcsUploadPathOption, argResults, platform.environment)!;
+ final String codesignCertName = getValueFromArgs(kCodesignCertNameOption, argResults)!;
+ final String gCloudDownloadPath = getValueFromArgs(kGcsDownloadPathOption, argResults)!;
+ final String gCloudUploadPath = getValueFromArgs(kGcsUploadPathOption, argResults)!;
+ final String appSpecificPasswordFilePath = getValueFromArgs(kAppSpecificPasswordOption, argResults)!;
+ final String codesignAppstoreIDFilePath = getValueFromArgs(kCodesignAppstoreIDOption, argResults)!;
+ final String codesignTeamIDFilePath = getValueFromArgs(kCodesignTeamIDOption, argResults)!;
final bool dryrun = argResults[kDryrunFlag] as bool;
@@ -118,12 +139,11 @@
return FileCodesignVisitor(
codesignCertName: codesignCertName,
- codesignUserName: codesignUserName,
- appSpecificPassword: appSpecificPassword,
- codesignAppstoreId: codesignAppstoreId,
- codesignTeamId: codesignTeamId,
fileSystem: fileSystem,
rootDirectory: rootDirectory,
+ appSpecificPasswordFilePath: appSpecificPasswordFilePath,
+ codesignAppstoreIDFilePath: codesignAppstoreIDFilePath,
+ codesignTeamIDFilePath: codesignTeamIDFilePath,
processManager: processManager,
dryrun: dryrun,
gcsDownloadPath: gCloudDownloadPath,
diff --git a/codesign/lib/src/file_codesign_visitor.dart b/codesign/lib/src/file_codesign_visitor.dart
index 8d05f39..8581ef7 100644
--- a/codesign/lib/src/file_codesign_visitor.dart
+++ b/codesign/lib/src/file_codesign_visitor.dart
@@ -26,16 +26,15 @@
class FileCodesignVisitor {
FileCodesignVisitor({
required this.codesignCertName,
- required this.codesignUserName,
- required this.appSpecificPassword,
- required this.codesignAppstoreId,
- required this.codesignTeamId,
required this.fileSystem,
required this.rootDirectory,
required this.processManager,
required this.gcsDownloadPath,
required this.gcsUploadPath,
required this.googleCloudStorage,
+ required this.appSpecificPasswordFilePath,
+ required this.codesignAppstoreIDFilePath,
+ required this.codesignTeamIDFilePath,
this.dryrun = true,
this.notarizationTimerDuration = const Duration(seconds: 5),
}) {
@@ -53,19 +52,30 @@
final GoogleCloudStorage googleCloudStorage;
final String codesignCertName;
- final String codesignUserName;
- final String appSpecificPassword;
- final String codesignAppstoreId;
- final String codesignTeamId;
final String gcsDownloadPath;
final String gcsUploadPath;
+ final String appSpecificPasswordFilePath;
+ final String codesignAppstoreIDFilePath;
+ final String codesignTeamIDFilePath;
final bool dryrun;
final Duration notarizationTimerDuration;
+ // 'Apple developer account email used for authentication with notary service.'
+ late String codesignAppstoreId;
+ // Unique password of the apple developer account.'
+ late String appSpecificPassword;
+ // Team-id is used by notary service for xcode version 13+.
+ late String codesignTeamId;
+
Set<String> fileWithEntitlements = <String>{};
Set<String> fileWithoutEntitlements = <String>{};
Set<String> fileConsumed = <String>{};
Set<String> directoriesVisited = <String>{};
+ Map<String, String> availablePasswords = {
+ 'CODESIGN_APPSTORE_ID': '',
+ 'CODESIGN_TEAM_ID': '',
+ 'APP_SPECIFIC_PASSWORD': ''
+ };
late final File entitlementsFile;
late final Directory remoteDownloadsDir;
@@ -119,8 +129,50 @@
update these file paths accordingly.
''';
+ /// 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 {
+ if (!(await fileSystem.file(passwordFilePath).exists())) {
+ throw CodesignException('$passwordFilePath not found \n'
+ 'make sure you have provided codesign credentials in a file \n');
+ }
+
+ String passwordLine = await fileSystem.file(passwordFilePath).readAsString();
+ List<String> parsedPasswordLine = passwordLine.split(":");
+ if (parsedPasswordLine.length != 2) {
+ throw CodesignException('$passwordFilePath is not correctly formatted. \n'
+ 'please double check formatting \n');
+ }
+ String passwordName = parsedPasswordLine[0];
+ 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;
+ }
+
/// 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']!;
+
await processRemoteZip();
if (dryrun) {
diff --git a/codesign/lib/src/utils.dart b/codesign/lib/src/utils.dart
index 1c34a04..400ebce 100644
--- a/codesign/lib/src/utils.dart
+++ b/codesign/lib/src/utils.dart
@@ -89,39 +89,22 @@
String toString() => 'Exception: $message';
}
-/// Translate CLI arg names to env variable names.
+/// Return the command line argument by parsing [argResults].
///
-/// For example, 'state-file' -> 'STATE_FILE'.
-String fromArgToEnvName(String argName) {
- return argName.toUpperCase().replaceAll('-', '_');
-}
-
-/// Either return the value from [env] or fall back to [argResults].
-///
-/// If the key does not exist in either the environment or CLI args, throws a
-/// [ConductorException].
-///
-/// The environment is favored over CLI args since the latter can have a default
-/// value, which the environment should be able to override.
-String? getValueFromEnvOrArgs(
+/// If the key does not exist in CLI args, throws a [CodesignException].
+String? getValueFromArgs(
String name,
- ArgResults argResults,
- Map<String, String> env, {
+ ArgResults argResults, {
bool allowNull = false,
}) {
- final String envName = fromArgToEnvName(name);
- if (env[envName] != null) {
- return env[envName];
- }
final String? argValue = argResults[name] as String?;
if (argValue != null) {
return argValue;
}
-
if (allowNull) {
return null;
}
- throw CodesignException('Expected either the CLI arg --$name or the environment variable $envName '
+ throw CodesignException('Expected either the CLI arg --$name '
'to be provided!');
}
diff --git a/codesign/test/file_codesign_visitor_test.dart b/codesign/test/file_codesign_visitor_test.dart
index 29294ff..6a596d7 100644
--- a/codesign/test/file_codesign_visitor_test.dart
+++ b/codesign/test/file_codesign_visitor_test.dart
@@ -17,6 +17,9 @@
void main() {
const String randomString = 'abcd1234';
+ const String appSpecificPasswordFilePath = '/tmp/passwords.txt';
+ const String codesignAppstoreIDFilePath = '/tmp/appID.txt';
+ const String codesignTeamIDFilePath = '/tmp/teamID.txt';
final MemoryFileSystem fileSystem = MemoryFileSystem.test();
final List<LogRecord> records = <LogRecord>[];
@@ -26,6 +29,113 @@
Directory rootDirectory = fileSystem.systemTempDirectory.createTempSync('conductor_codesign');
+ 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',
+ notarizationTimerDuration: const Duration(seconds: 0),
+ dryrun: false,
+ );
+ codesignVisitor.directoriesVisited.clear();
+ records.clear();
+ 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,
+ );
+
+ 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>(),
+ ),
+ );
+ });
+
+ test('providing correctly formatted password returns normally', () async {
+ fileSystem.file(appSpecificPasswordFilePath)
+ ..createSync(recursive: true, exclusive: true)
+ ..writeAsStringSync(
+ 'APP_SPECIFIC_PASSWORD:123',
+ mode: FileMode.write,
+ encoding: utf8,
+ );
+
+ expect(() async {
+ await codesignVisitor.readPassword(appSpecificPasswordFilePath);
+ await fileSystem.file(appSpecificPasswordFilePath).delete();
+ }, returnsNormally);
+ });
+ });
+
group('test utils function to join virtual entitlement path: ', () {
test('omits slash for the first path', () async {
expect(joinEntitlementPaths("", randomString), randomString);
@@ -45,12 +155,11 @@
);
codesignVisitor = cs.FileCodesignVisitor(
codesignCertName: randomString,
- codesignUserName: randomString,
- appSpecificPassword: randomString,
- codesignAppstoreId: randomString,
- codesignTeamId: randomString,
googleCloudStorage: googleCloudStorage,
fileSystem: fileSystem,
+ appSpecificPasswordFilePath: appSpecificPasswordFilePath,
+ codesignAppstoreIDFilePath: codesignAppstoreIDFilePath,
+ codesignTeamIDFilePath: codesignTeamIDFilePath,
processManager: processManager,
rootDirectory: rootDirectory,
gcsDownloadPath: 'gs://flutter/$randomString/$randomString',
@@ -58,6 +167,9 @@
notarizationTimerDuration: const Duration(seconds: 0),
dryrun: false,
);
+ codesignVisitor.appSpecificPassword = randomString;
+ codesignVisitor.codesignAppstoreId = randomString;
+ codesignVisitor.codesignTeamId = randomString;
codesignVisitor.directoriesVisited.clear();
records.clear();
log.onRecord.listen((LogRecord record) => records.add(record));
@@ -311,18 +423,20 @@
);
codesignVisitor = cs.FileCodesignVisitor(
codesignCertName: randomString,
- codesignUserName: randomString,
- appSpecificPassword: randomString,
- codesignAppstoreId: randomString,
- codesignTeamId: 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',
notarizationTimerDuration: Duration.zero,
);
+ codesignVisitor.appSpecificPassword = randomString;
+ codesignVisitor.codesignAppstoreId = randomString;
+ codesignVisitor.codesignTeamId = randomString;
codesignVisitor.directoriesVisited.clear();
records.clear();
log.onRecord.listen((LogRecord record) => records.add(record));
@@ -582,12 +696,11 @@
test('visitBinary codesigns binary with / without entitlement', () async {
codesignVisitor = cs.FileCodesignVisitor(
codesignCertName: randomString,
- codesignUserName: randomString,
- appSpecificPassword: randomString,
- codesignAppstoreId: randomString,
- codesignTeamId: randomString,
googleCloudStorage: googleCloudStorage,
fileSystem: fileSystem,
+ appSpecificPasswordFilePath: appSpecificPasswordFilePath,
+ codesignAppstoreIDFilePath: codesignAppstoreIDFilePath,
+ codesignTeamIDFilePath: codesignTeamIDFilePath,
processManager: processManager,
rootDirectory: rootDirectory,
gcsDownloadPath: 'flutter/$randomString/FILEPATH',
@@ -595,6 +708,9 @@
dryrun: false,
notarizationTimerDuration: const Duration(seconds: 0),
);
+ codesignVisitor.appSpecificPassword = randomString;
+ codesignVisitor.codesignAppstoreId = randomString;
+ codesignVisitor.codesignTeamId = randomString;
codesignVisitor.fileWithEntitlements = <String>{'root/folder_a/file_a'};
codesignVisitor.fileWithoutEntitlements = <String>{'root/folder_b/file_b'};
fileSystem
@@ -672,17 +788,19 @@
);
codesignVisitor = cs.FileCodesignVisitor(
codesignCertName: randomString,
- codesignUserName: randomString,
- appSpecificPassword: randomString,
- codesignAppstoreId: randomString,
- codesignTeamId: randomString,
gcsDownloadPath: 'flutter/$randomString/FILEPATH',
gcsUploadPath: 'flutter/$randomString/FILEPATH',
googleCloudStorage: googleCloudStorage,
fileSystem: fileSystem,
+ appSpecificPasswordFilePath: appSpecificPasswordFilePath,
+ codesignAppstoreIDFilePath: codesignAppstoreIDFilePath,
+ codesignTeamIDFilePath: codesignTeamIDFilePath,
processManager: processManager,
rootDirectory: rootDirectory,
);
+ codesignVisitor.appSpecificPassword = randomString;
+ codesignVisitor.codesignAppstoreId = randomString;
+ codesignVisitor.codesignTeamId = randomString;
codesignVisitor.directoriesVisited.clear();
records.clear();
log.onRecord.listen((LogRecord record) => records.add(record));
@@ -775,17 +893,19 @@
);
codesignVisitor = cs.FileCodesignVisitor(
codesignCertName: randomString,
- codesignUserName: randomString,
- appSpecificPassword: randomString,
- codesignAppstoreId: randomString,
- codesignTeamId: randomString,
gcsDownloadPath: 'flutter/$randomString/FILEPATH',
gcsUploadPath: 'flutter/$randomString/FILEPATH',
googleCloudStorage: googleCloudStorage,
fileSystem: fileSystem,
+ appSpecificPasswordFilePath: appSpecificPasswordFilePath,
+ codesignAppstoreIDFilePath: codesignAppstoreIDFilePath,
+ codesignTeamIDFilePath: codesignTeamIDFilePath,
processManager: processManager,
rootDirectory: rootDirectory,
);
+ codesignVisitor.appSpecificPassword = randomString;
+ codesignVisitor.codesignAppstoreId = randomString;
+ codesignVisitor.codesignTeamId = randomString;
codesignVisitor.directoriesVisited.clear();
records.clear();
log.onRecord.listen((LogRecord record) => records.add(record));
@@ -1095,21 +1215,32 @@
);
codesignVisitor = cs.FileCodesignVisitor(
codesignCertName: randomString,
- codesignUserName: randomString,
- appSpecificPassword: randomString,
- codesignAppstoreId: randomString,
- codesignTeamId: randomString,
gcsDownloadPath: 'gs://ios-usb-dependencies/unsigned/libimobiledevice/$randomString/libimobiledevice.zip',
gcsUploadPath: 'gs://ios-usb-dependencies/libimobiledevice/$randomString/libimobiledevice.zip',
googleCloudStorage: googleCloudStorage,
fileSystem: fileSystem,
+ appSpecificPasswordFilePath: appSpecificPasswordFilePath,
+ codesignAppstoreIDFilePath: codesignAppstoreIDFilePath,
+ codesignTeamIDFilePath: codesignTeamIDFilePath,
processManager: processManager,
rootDirectory: rootDirectory,
notarizationTimerDuration: const Duration(seconds: 0),
);
+ codesignVisitor.appSpecificPassword = randomString;
+ codesignVisitor.codesignAppstoreId = randomString;
+ codesignVisitor.codesignTeamId = randomString;
codesignVisitor.directoriesVisited.clear();
records.clear();
log.onRecord.listen((LogRecord record) => records.add(record));
+ fileSystem.file(codesignAppstoreIDFilePath)
+ ..createSync(recursive: true)
+ ..writeAsStringSync('CODESIGN_APPSTORE_ID:$randomString');
+ fileSystem.file(codesignTeamIDFilePath)
+ ..createSync(recursive: true)
+ ..writeAsStringSync('CODESIGN_TEAM_ID:$randomString');
+ fileSystem.file(appSpecificPasswordFilePath)
+ ..createSync(recursive: true)
+ ..writeAsStringSync('APP_SPECIFIC_PASSWORD:$randomString');
});
test('codesign optional switches artifacts when dryrun is false', () async {
@@ -1261,19 +1392,21 @@
]);
codesignVisitor = cs.FileCodesignVisitor(
codesignCertName: randomString,
- codesignUserName: randomString,
- appSpecificPassword: randomString,
- codesignAppstoreId: randomString,
- codesignTeamId: randomString,
gcsDownloadPath: 'gs://ios-usb-dependencies/unsigned/libimobiledevice/$randomString/libimobiledevice.zip',
gcsUploadPath: 'gs://ios-usb-dependencies/libimobiledevice/$randomString/libimobiledevice.zip',
googleCloudStorage: googleCloudStorage,
fileSystem: fileSystem,
+ appSpecificPasswordFilePath: appSpecificPasswordFilePath,
+ codesignAppstoreIDFilePath: codesignAppstoreIDFilePath,
+ codesignTeamIDFilePath: codesignTeamIDFilePath,
processManager: processManager,
rootDirectory: rootDirectory,
notarizationTimerDuration: const Duration(seconds: 0),
dryrun: false,
);
+ codesignVisitor.appSpecificPassword = randomString;
+ codesignVisitor.codesignAppstoreId = randomString;
+ codesignVisitor.codesignTeamId = randomString;
codesignVisitor.directoriesVisited.clear();
await codesignVisitor.validateAll();
final Set<String> messages = records