diff --git a/app_dart/lib/src/request_handlers/file_flaky_issue_and_pr.dart b/app_dart/lib/src/request_handlers/file_flaky_issue_and_pr.dart index 10ab0bc95..6bca5d3cd 100644 --- a/app_dart/lib/src/request_handlers/file_flaky_issue_and_pr.dart +++ b/app_dart/lib/src/request_handlers/file_flaky_issue_and_pr.dart @@ -55,11 +55,7 @@ class FileFlakyIssueAndPR extends ApiRequestHandler { final Map nameToExistingPR = await getExistingPRs(gitHub, slug); int filedIssueAndPRCount = 0; for (final BuilderStatistic statistic in builderStatisticList) { - // Skip if ignore_flakiness is specified. - if (getIgnoreFlakiness(statistic.name, ciYaml)) { - continue; - } - if (statistic.flakyRate < _threshold) { + if (shouldSkip(statistic, ciYaml, targets)) { continue; } @@ -93,6 +89,22 @@ class FileFlakyIssueAndPR extends ApiRequestHandler { }); } + bool shouldSkip(BuilderStatistic statistic, CiYaml ciYaml, List targets) { + // Skips if the target has been removed from .ci.yaml. + if (!targets.map((e) => e.name).toList().contains(statistic.name)) { + return true; + } + // Skips if ignore_flakiness is specified. + if (getIgnoreFlakiness(statistic.name, ciYaml)) { + return true; + } + // Skips if the flaky percentage is below the threshold. + if (statistic.flakyRate < _threshold) { + return true; + } + return false; + } + double get _threshold => double.parse(request!.uri.queryParameters[kThresholdKey]!); Future _fileIssueAndPR( diff --git a/app_dart/test/request_handlers/file_flaky_issue_and_pr_test.dart b/app_dart/test/request_handlers/file_flaky_issue_and_pr_test.dart index f5ec497f2..1c44b27e8 100644 --- a/app_dart/test/request_handlers/file_flaky_issue_and_pr_test.dart +++ b/app_dart/test/request_handlers/file_flaky_issue_and_pr_test.dart @@ -672,6 +672,28 @@ void main() { expect(result['Status'], 'success'); }); + + test('skips when the target doesn not exist', () { + final YamlMap? ci = loadYaml(ciYamlContent) as YamlMap?; + final pb.SchedulerConfig unCheckedSchedulerConfig = pb.SchedulerConfig()..mergeFromProto3Json(ci); + final CiYaml ciYaml = CiYaml( + slug: Config.flutterSlug, + branch: Config.defaultBranch(Config.flutterSlug), + config: unCheckedSchedulerConfig, + ); + final BuilderStatistic builderStatistic = BuilderStatistic( + name: 'Mac_android test', + flakyRate: 0.5, + flakyBuilds: ['103', '102', '101'], + succeededBuilds: ['203', '202', '201'], + recentCommit: 'abc', + flakyBuildOfRecentCommit: '103', + flakyNumber: 3, + totalNumber: 6, + ); + final List targets = unCheckedSchedulerConfig.targets; + expect(handler.shouldSkip(builderStatistic, ciYaml, targets), true); + }); }); test('retrieveMetaTagsFromContent can work with different newlines', () async { diff --git a/cipd_packages/codesign/lib/src/file_codesign_visitor.dart b/cipd_packages/codesign/lib/src/file_codesign_visitor.dart index 31f7a6844..042c05185 100644 --- a/cipd_packages/codesign/lib/src/file_codesign_visitor.dart +++ b/cipd_packages/codesign/lib/src/file_codesign_visitor.dart @@ -255,6 +255,10 @@ update these file paths accordingly. } log.info('Child file of directory ${directory.basename} is ${entity.basename}'); } + final String directoryExtension = directory.basename.split('.').last; + if (directoryExtension == 'framework' || directoryExtension == 'xcframework') { + await codesignAtPath(binaryOrBundlePath: directory.absolute.path); + } } /// Unzip an [EmbeddedZip] and visit its children. @@ -314,17 +318,24 @@ update these file paths accordingly. if (dryrun) { return; } + await codesignAtPath(binaryOrBundlePath: binaryFile.absolute.path, entitlementCurrentPath: entitlementCurrentPath); + } + + Future codesignAtPath({ + required String binaryOrBundlePath, + String? entitlementCurrentPath, + }) async { final List args = [ '/usr/bin/codesign', '--keychain', 'build.keychain', // specify the keychain to look for cert - '-f', // force + '-f', // force. Needed to overwrite signature if major executable of bundle is already signed before bundle is signed. '-s', // use the cert provided by next argument codesignCertName, - binaryFile.absolute.path, + binaryOrBundlePath, '--timestamp', // add a secure timestamp '--options=runtime', // hardened runtime - if (fileWithEntitlements.contains(entitlementCurrentPath)) ...[ + if (entitlementCurrentPath != '' && fileWithEntitlements.contains(entitlementCurrentPath)) ...[ '--entitlements', entitlementsFile.absolute.path, ], @@ -338,7 +349,7 @@ update these file paths accordingly. } throw CodesignException( - 'Failed to codesign ${binaryFile.absolute.path} with args: ${args.join(' ')}\n' + 'Failed to codesign binary or bundle at $binaryOrBundlePath with args: ${args.join(' ')}\n' 'stdout:\n${(result.stdout as String).trim()}' 'stderr:\n${(result.stderr as String).trim()}', ); diff --git a/cipd_packages/codesign/test/file_codesign_visitor_test.dart b/cipd_packages/codesign/test/file_codesign_visitor_test.dart index 53a2ee5fa..31e0b677d 100644 --- a/cipd_packages/codesign/test/file_codesign_visitor_test.dart +++ b/cipd_packages/codesign/test/file_codesign_visitor_test.dart @@ -561,6 +561,87 @@ void main() { ); }); + test('visitDirectory codesigns framework bundle', () async { + fileSystem + ..file('${rootDirectory.path}/remote_zip_6/non_bundle/file_a').createSync(recursive: true) + ..file('${rootDirectory.path}/remote_zip_6/bundle.xcframework/bundle.framework/file_b') + .createSync(recursive: true); + final Directory testDirectory = fileSystem.directory('${rootDirectory.path}/remote_zip_6'); + processManager.addCommands([ + FakeCommand( + command: [ + 'file', + '--mime-type', + '-b', + '${rootDirectory.absolute.path}/remote_zip_6/non_bundle/file_a', + ], + stdout: 'other_files', + ), + FakeCommand( + command: [ + 'file', + '--mime-type', + '-b', + '${rootDirectory.absolute.path}/remote_zip_6/bundle.xcframework/bundle.framework/file_b', + ], + stdout: 'other_files', + ), + FakeCommand( + command: [ + '/usr/bin/codesign', + '--keychain', + 'build.keychain', + '-f', + '-s', + randomString, + '${rootDirectory.absolute.path}/remote_zip_6/bundle.xcframework/bundle.framework', + '--timestamp', + '--options=runtime', + ], + exitCode: 0, + ), + FakeCommand( + command: [ + '/usr/bin/codesign', + '--keychain', + 'build.keychain', + '-f', + '-s', + randomString, + '${rootDirectory.absolute.path}/remote_zip_6/bundle.xcframework', + '--timestamp', + '--options=runtime', + ], + exitCode: 0, + ), + ]); + await codesignVisitor.visitDirectory( + directory: testDirectory, + parentVirtualPath: '', + ); + final Set messages = records + .where((LogRecord record) => record.level == Level.INFO) + .map((LogRecord record) => record.message) + .toSet(); + expect(messages, contains('Visiting directory ${rootDirectory.path}/remote_zip_6/non_bundle')); + expect( + messages, + contains('Visiting directory ${rootDirectory.path}/remote_zip_6/bundle.xcframework/bundle.framework'), + ); + expect( + messages, + contains( + 'Executing: /usr/bin/codesign --keychain build.keychain -f -s $randomString ${rootDirectory.path}/remote_zip_6/bundle.xcframework/bundle.framework --timestamp --options=runtime\n', + ), + ); + expect( + messages, + contains( + 'Executing: /usr/bin/codesign --keychain build.keychain -f -s $randomString ${rootDirectory.path}/remote_zip_6/bundle.xcframework --timestamp --options=runtime\n', + ), + ); + }); + test('visitBinary codesigns binary with / without entitlement', () async { codesignVisitor = cs.FileCodesignVisitor( codesignCertName: randomString,