From a529b0181984cc90f7a63be5567aae391aa10596 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Thu, 15 Oct 2026 18:12:38 -0500 Subject: [PATCH 1/2] chore: add strict linter rules, sync bot list, and clean activity dataset --- .../references/bots.txt | 44 ++++++ .github/workflows/validate.yml | 3 +- analysis_options.yaml | 12 ++ data/activity/2025-W44.json | 6 - data/activity/2025-W45.json | 6 - data/activity/2025-W46.json | 6 - data/activity/2025-W47.json | 6 - data/activity/2025-W49.json | 6 - data/activity/2025-W50.json | 6 - data/activity/2025-W51.json | 6 - data/activity/2026-W01.json | 6 - data/activity/2026-W02.json | 6 - data/activity/2026-W03.json | 6 - data/activity/2026-W04.json | 6 - data/activity/2026-W05.json | 6 - data/activity/2026-W06.json | 6 - data/activity/2026-W07.json | 6 - data/activity/2026-W08.json | 6 - data/activity/2026-W13.json | 6 - data/activity/2026-W14.json | 6 - data/activity/2026-W15.json | 6 - data/activity/2026-W16.json | 12 -- data/activity/2026-W17.json | 6 - data/activity/2026-W18.json | 6 - data/activity/2026-W19.json | 6 - data/activity/2026-W20.json | 12 -- data/activity/2026-W21.json | 6 - data/activity/2026-W24.json | 6 - data/activity/2026-W25.json | 6 - data/activity_summary.json | 12 -- test/activity_sync_test.dart | 4 + test/bots_test.dart | 21 +++ test/data_integrity_test.dart | 11 ++ test/github_client_test.dart | 4 + test/iso_week_test.dart | 4 + test/license_test.dart | 138 ++++++++++++++++++ tool/bots.dart | 6 + tool/github.dart | 4 + tool/sync_activity.dart | 5 + 39 files changed, 255 insertions(+), 181 deletions(-) create mode 100644 .agents/skills/quarterly-ladder-analysis/references/bots.txt create mode 100644 test/license_test.dart diff --git a/.agents/skills/quarterly-ladder-analysis/references/bots.txt b/.agents/skills/quarterly-ladder-analysis/references/bots.txt new file mode 100644 index 0000000..8c9f084 --- /dev/null +++ b/.agents/skills/quarterly-ladder-analysis/references/bots.txt @@ -0,0 +1,44 @@ +dependabot +dependabot[bot] +fluttergithubbot +google-oss-robot +google-oss-robot[bot] +github-actions +github-actions[bot] +engine-flutter-autoroll +engine-flutter-autoroll[bot] +skia-flutter-autoroll +skia-flutter-autoroll[bot] +flutter-autoroll +flutter-autoroll[bot] +auto-submit +auto-submit[bot] +google-cla +google-cla[bot] +googlebot +copybara-service +copybara-service[bot] +renovate +renovate[bot] +flutteractionsbot +flutter-pub-roller-bot +flutter-skills-sync-bot +flutter-intellij-kokoro +flutter-website-bot +fluttercerberus +flutterbuildbot +flutterdeploybot +fluttergalleryreleasebot +fluttermirroringbot +DartDevtoolWorkflowBot +buildbot +agentfu +kenzie-agent +reidbaker-agent +google-admin +google-admin-automation-1 +google-admin-automation-2 +google-admin-backup +google-ospo-team +gemini-code-assist +gemini-code-assist[bot] diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index a5afa5d..97c12ff 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -5,6 +5,7 @@ on: branches: [main] pull_request: branches: [main] + workflow_dispatch: permissions: contents: read @@ -32,7 +33,7 @@ jobs: run: dart format --output=none --set-exit-if-changed . - name: Analyze Dart code - run: dart analyze + run: dart analyze --fatal-infos - name: Run unit test suite run: dart test diff --git a/analysis_options.yaml b/analysis_options.yaml index d04adaf..9766c7c 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -5,3 +5,15 @@ analyzer: strict-casts: true strict-inference: true strict-raw-types: true + +linter: + rules: + - always_declare_return_types + - directives_ordering + - discarded_futures + - omit_local_variable_types + - only_throw_errors + - prefer_final_in_for_each + - prefer_final_locals + - prefer_single_quotes + - unawaited_futures diff --git a/data/activity/2025-W44.json b/data/activity/2025-W44.json index 52725ad..a9a9ac5 100644 --- a/data/activity/2025-W44.json +++ b/data/activity/2025-W44.json @@ -5,12 +5,6 @@ "reviews": 0, "total": 1 }, - "auto-submit": { - "merged_prs": 3, - "issues": 0, - "reviews": 0, - "total": 3 - }, "bleroux": { "merged_prs": 5, "issues": 2, diff --git a/data/activity/2025-W45.json b/data/activity/2025-W45.json index 8c64b07..62bbd43 100644 --- a/data/activity/2025-W45.json +++ b/data/activity/2025-W45.json @@ -17,12 +17,6 @@ "reviews": 0, "total": 3 }, - "auto-submit": { - "merged_prs": 4, - "issues": 0, - "reviews": 0, - "total": 4 - }, "autorejecttop": { "merged_prs": 1, "issues": 0, diff --git a/data/activity/2025-W46.json b/data/activity/2025-W46.json index 34b5169..0aa33fc 100644 --- a/data/activity/2025-W46.json +++ b/data/activity/2025-W46.json @@ -29,12 +29,6 @@ "reviews": 2, "total": 3 }, - "auto-submit": { - "merged_prs": 2, - "issues": 0, - "reviews": 0, - "total": 2 - }, "abdallahshaban557": { "merged_prs": 1, "issues": 0, diff --git a/data/activity/2025-W47.json b/data/activity/2025-W47.json index 571a660..434964b 100644 --- a/data/activity/2025-W47.json +++ b/data/activity/2025-W47.json @@ -1,10 +1,4 @@ { - "auto-submit": { - "merged_prs": 2, - "issues": 0, - "reviews": 0, - "total": 2 - }, "csells": { "merged_prs": 1, "issues": 0, diff --git a/data/activity/2025-W49.json b/data/activity/2025-W49.json index 1c0bdb7..f12e809 100644 --- a/data/activity/2025-W49.json +++ b/data/activity/2025-W49.json @@ -11,12 +11,6 @@ "reviews": 0, "total": 1 }, - "auto-submit": { - "merged_prs": 1, - "issues": 0, - "reviews": 0, - "total": 1 - }, "gaaclarke": { "merged_prs": 2, "issues": 2, diff --git a/data/activity/2025-W50.json b/data/activity/2025-W50.json index 34fd016..295ddc5 100644 --- a/data/activity/2025-W50.json +++ b/data/activity/2025-W50.json @@ -77,12 +77,6 @@ "reviews": 6, "total": 9 }, - "auto-submit": { - "merged_prs": 2, - "issues": 0, - "reviews": 0, - "total": 2 - }, "shindonghwi": { "merged_prs": 1, "issues": 0, diff --git a/data/activity/2025-W51.json b/data/activity/2025-W51.json index 8b51f3e..7eda886 100644 --- a/data/activity/2025-W51.json +++ b/data/activity/2025-W51.json @@ -11,12 +11,6 @@ "reviews": 0, "total": 2 }, - "auto-submit": { - "merged_prs": 1, - "issues": 0, - "reviews": 0, - "total": 1 - }, "LouiseHsu": { "merged_prs": 0, "issues": 0, diff --git a/data/activity/2026-W01.json b/data/activity/2026-W01.json index c12b20e..3bdef61 100644 --- a/data/activity/2026-W01.json +++ b/data/activity/2026-W01.json @@ -1,10 +1,4 @@ { - "auto-submit": { - "merged_prs": 3, - "issues": 0, - "reviews": 0, - "total": 3 - }, "gaaclarke": { "merged_prs": 3, "issues": 4, diff --git a/data/activity/2026-W02.json b/data/activity/2026-W02.json index 752e122..192e803 100644 --- a/data/activity/2026-W02.json +++ b/data/activity/2026-W02.json @@ -1,10 +1,4 @@ { - "auto-submit": { - "merged_prs": 5, - "issues": 0, - "reviews": 0, - "total": 5 - }, "csells": { "merged_prs": 0, "issues": 0, diff --git a/data/activity/2026-W03.json b/data/activity/2026-W03.json index 7a907f5..a8bf745 100644 --- a/data/activity/2026-W03.json +++ b/data/activity/2026-W03.json @@ -119,12 +119,6 @@ "reviews": 0, "total": 1 }, - "auto-submit": { - "merged_prs": 2, - "issues": 0, - "reviews": 0, - "total": 2 - }, "Gustl22": { "merged_prs": 1, "issues": 1, diff --git a/data/activity/2026-W04.json b/data/activity/2026-W04.json index ffe5497..e29bee8 100644 --- a/data/activity/2026-W04.json +++ b/data/activity/2026-W04.json @@ -29,12 +29,6 @@ "reviews": 1, "total": 7 }, - "auto-submit": { - "merged_prs": 2, - "issues": 0, - "reviews": 0, - "total": 2 - }, "ksokolovskyi": { "merged_prs": 2, "issues": 0, diff --git a/data/activity/2026-W05.json b/data/activity/2026-W05.json index a0eb54b..846de90 100644 --- a/data/activity/2026-W05.json +++ b/data/activity/2026-W05.json @@ -1,10 +1,4 @@ { - "auto-submit": { - "merged_prs": 1, - "issues": 0, - "reviews": 0, - "total": 1 - }, "jesswrd": { "merged_prs": 5, "issues": 0, diff --git a/data/activity/2026-W06.json b/data/activity/2026-W06.json index fecdd99..873f1a4 100644 --- a/data/activity/2026-W06.json +++ b/data/activity/2026-W06.json @@ -29,12 +29,6 @@ "reviews": 0, "total": 4 }, - "auto-submit": { - "merged_prs": 2, - "issues": 0, - "reviews": 0, - "total": 2 - }, "gmackall": { "merged_prs": 1, "issues": 0, diff --git a/data/activity/2026-W07.json b/data/activity/2026-W07.json index f592077..cbbb202 100644 --- a/data/activity/2026-W07.json +++ b/data/activity/2026-W07.json @@ -65,12 +65,6 @@ "reviews": 0, "total": 1 }, - "auto-submit": { - "merged_prs": 2, - "issues": 0, - "reviews": 0, - "total": 2 - }, "FMorschel": { "merged_prs": 1, "issues": 0, diff --git a/data/activity/2026-W08.json b/data/activity/2026-W08.json index c14c236..a7d434c 100644 --- a/data/activity/2026-W08.json +++ b/data/activity/2026-W08.json @@ -29,12 +29,6 @@ "reviews": 0, "total": 4 }, - "auto-submit": { - "merged_prs": 1, - "issues": 0, - "reviews": 0, - "total": 1 - }, "gurusai-voleti": { "merged_prs": 2, "issues": 0, diff --git a/data/activity/2026-W13.json b/data/activity/2026-W13.json index f77f579..7f04018 100644 --- a/data/activity/2026-W13.json +++ b/data/activity/2026-W13.json @@ -1,10 +1,4 @@ { - "auto-submit": { - "merged_prs": 2, - "issues": 0, - "reviews": 0, - "total": 2 - }, "xfce0": { "merged_prs": 1, "issues": 0, diff --git a/data/activity/2026-W14.json b/data/activity/2026-W14.json index 7daec76..dd7d637 100644 --- a/data/activity/2026-W14.json +++ b/data/activity/2026-W14.json @@ -1,10 +1,4 @@ { - "auto-submit": { - "merged_prs": 3, - "issues": 0, - "reviews": 0, - "total": 3 - }, "gmackall": { "merged_prs": 5, "issues": 1, diff --git a/data/activity/2026-W15.json b/data/activity/2026-W15.json index a2dc3d7..b99aae8 100644 --- a/data/activity/2026-W15.json +++ b/data/activity/2026-W15.json @@ -1,10 +1,4 @@ { - "auto-submit": { - "merged_prs": 6, - "issues": 0, - "reviews": 0, - "total": 6 - }, "chrisraygill": { "merged_prs": 1, "issues": 0, diff --git a/data/activity/2026-W16.json b/data/activity/2026-W16.json index 260ecc6..3648cba 100644 --- a/data/activity/2026-W16.json +++ b/data/activity/2026-W16.json @@ -5,12 +5,6 @@ "reviews": 22, "total": 34 }, - "auto-submit": { - "merged_prs": 4, - "issues": 0, - "reviews": 0, - "total": 4 - }, "andywolff": { "merged_prs": 2, "issues": 0, @@ -35,12 +29,6 @@ "reviews": 2, "total": 6 }, - "agentfu": { - "merged_prs": 0, - "issues": 1, - "reviews": 2, - "total": 3 - }, "khanak0509": { "merged_prs": 2, "issues": 0, diff --git a/data/activity/2026-W17.json b/data/activity/2026-W17.json index 316e73b..6f6e3cb 100644 --- a/data/activity/2026-W17.json +++ b/data/activity/2026-W17.json @@ -89,12 +89,6 @@ "reviews": 5, "total": 6 }, - "auto-submit": { - "merged_prs": 1, - "issues": 0, - "reviews": 0, - "total": 1 - }, "LouiseHsu": { "merged_prs": 0, "issues": 1, diff --git a/data/activity/2026-W18.json b/data/activity/2026-W18.json index e7fea3b..bc8d941 100644 --- a/data/activity/2026-W18.json +++ b/data/activity/2026-W18.json @@ -1,10 +1,4 @@ { - "auto-submit": { - "merged_prs": 2, - "issues": 0, - "reviews": 0, - "total": 2 - }, "gaaclarke": { "merged_prs": 2, "issues": 1, diff --git a/data/activity/2026-W19.json b/data/activity/2026-W19.json index 1445903..55512b1 100644 --- a/data/activity/2026-W19.json +++ b/data/activity/2026-W19.json @@ -1,10 +1,4 @@ { - "auto-submit": { - "merged_prs": 3, - "issues": 0, - "reviews": 0, - "total": 3 - }, "gaaclarke": { "merged_prs": 3, "issues": 2, diff --git a/data/activity/2026-W20.json b/data/activity/2026-W20.json index 4a46a57..d90ce69 100644 --- a/data/activity/2026-W20.json +++ b/data/activity/2026-W20.json @@ -29,24 +29,12 @@ "reviews": 0, "total": 1 }, - "auto-submit": { - "merged_prs": 1, - "issues": 0, - "reviews": 0, - "total": 1 - }, "jesswrd": { "merged_prs": 2, "issues": 0, "reviews": 0, "total": 2 }, - "agentfu": { - "merged_prs": 0, - "issues": 0, - "reviews": 1, - "total": 1 - }, "Eliezermga": { "merged_prs": 0, "issues": 0, diff --git a/data/activity/2026-W21.json b/data/activity/2026-W21.json index c512dcc..ed78163 100644 --- a/data/activity/2026-W21.json +++ b/data/activity/2026-W21.json @@ -17,12 +17,6 @@ "reviews": 0, "total": 2 }, - "auto-submit": { - "merged_prs": 1, - "issues": 0, - "reviews": 0, - "total": 1 - }, "albertoblue87-netizen": { "merged_prs": 0, "issues": 0, diff --git a/data/activity/2026-W24.json b/data/activity/2026-W24.json index ae85530..433a207 100644 --- a/data/activity/2026-W24.json +++ b/data/activity/2026-W24.json @@ -23,12 +23,6 @@ "reviews": 0, "total": 1 }, - "auto-submit": { - "merged_prs": 3, - "issues": 0, - "reviews": 0, - "total": 3 - }, "josemontespg": { "merged_prs": 0, "issues": 0, diff --git a/data/activity/2026-W25.json b/data/activity/2026-W25.json index 6bcf6a9..692b18c 100644 --- a/data/activity/2026-W25.json +++ b/data/activity/2026-W25.json @@ -29,12 +29,6 @@ "reviews": 0, "total": 1 }, - "auto-submit": { - "merged_prs": 1, - "issues": 0, - "reviews": 0, - "total": 1 - }, "derdilla": { "merged_prs": 2, "issues": 0, diff --git a/data/activity_summary.json b/data/activity_summary.json index f80fdeb..099ff53 100644 --- a/data/activity_summary.json +++ b/data/activity_summary.json @@ -6125,12 +6125,6 @@ "reviews": 0, "total": 1 }, - "agentfu": { - "merged_prs": 0, - "issues": 1, - "reviews": 3, - "total": 4 - }, "agrahariak": { "merged_prs": 0, "issues": 1, @@ -7157,12 +7151,6 @@ "reviews": 0, "total": 1 }, - "auto-submit": { - "merged_prs": 60, - "issues": 0, - "reviews": 0, - "total": 60 - }, "autorejecttop": { "merged_prs": 7, "issues": 1, diff --git a/test/activity_sync_test.dart b/test/activity_sync_test.dart index 7b06501..57b3358 100644 --- a/test/activity_sync_test.dart +++ b/test/activity_sync_test.dart @@ -1,3 +1,7 @@ +// Copyright 2014 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:convert'; import 'dart:io'; import 'package:http/http.dart' as http; diff --git a/test/bots_test.dart b/test/bots_test.dart index 3e068ce..c44649c 100644 --- a/test/bots_test.dart +++ b/test/bots_test.dart @@ -1,4 +1,9 @@ +// Copyright 2014 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:convert'; +import 'dart:io'; import 'package:http/http.dart' as http; import 'package:http/testing.dart'; import 'package:test/test.dart'; @@ -100,5 +105,21 @@ void main() { await loadRobotTeams(gh); expect(isBot('dynamic-team-robot-account'), isTrue); }); + + test('knownBots in tool/bots.dart stays in sync with references/bots.txt', + () { + final botsFile = + File('.agents/skills/quarterly-ladder-analysis/references/bots.txt'); + expect(botsFile.existsSync(), isTrue); + final fileBots = botsFile + .readAsLinesSync() + .map((l) => l.trim()) + .where((l) => l.isNotEmpty && !l.startsWith('#')) + .toSet(); + expect(knownBots, equals(fileBots)); + for (final bot in fileBots) { + expect(isExcludedAccount(bot), isTrue); + } + }); }); } diff --git a/test/data_integrity_test.dart b/test/data_integrity_test.dart index 327be29..d19ea33 100644 --- a/test/data_integrity_test.dart +++ b/test/data_integrity_test.dart @@ -1,6 +1,11 @@ +// Copyright 2014 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:convert'; import 'dart:io'; import 'package:test/test.dart'; +import '../tool/bots.dart'; void main() { group('Dataset Integrity', () { @@ -25,6 +30,9 @@ void main() { final stats = entry.value as Map; expect(user, isNotEmpty); + expect(isExcludedAccount(user), isFalse, + reason: + 'Excluded bot or ghost account "$user" found in ${file.path}'); final mergedPrs = stats['merged_prs'] as int?; final issues = stats['issues'] as int?; final reviews = stats['reviews'] as int?; @@ -91,6 +99,9 @@ void main() { for (final entry in expectedTotals.entries) { final user = entry.key; + expect(isExcludedAccount(user), isFalse, + reason: + 'Excluded bot or ghost account "$user" found in activity_summary.json'); final expected = entry.value; final actual = summaryContent[user] as Map?; diff --git a/test/github_client_test.dart b/test/github_client_test.dart index 09377eb..2d35514 100644 --- a/test/github_client_test.dart +++ b/test/github_client_test.dart @@ -1,3 +1,7 @@ +// Copyright 2014 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:convert'; import 'package:http/http.dart' as http; import 'package:http/testing.dart'; diff --git a/test/iso_week_test.dart b/test/iso_week_test.dart index e09d7e8..c9282f2 100644 --- a/test/iso_week_test.dart +++ b/test/iso_week_test.dart @@ -1,3 +1,7 @@ +// Copyright 2014 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 'package:test/test.dart'; import '../tool/sync_activity.dart'; diff --git a/test/license_test.dart b/test/license_test.dart new file mode 100644 index 0000000..940df85 --- /dev/null +++ b/test/license_test.dart @@ -0,0 +1,138 @@ +// Copyright 2014 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:test/test.dart'; + +String _generateLicense(String prefix) { + return '${prefix}Copyright 2014 The Flutter Authors. All rights reserved.\n' + '${prefix}Use of this source code is governed by a BSD-style license that can be\n' + '${prefix}found in the LICENSE file.'; +} + +final Map _extensionPrefixes = { + '.dart': '// ', + '.js': '// ', + '.cjs': '// ', + '.mjs': '// ', + '.ts': '// ', + '.java': '// ', + '.kt': '// ', + '.swift': '// ', + '.cc': '// ', + '.cpp': '// ', + '.h': '// ', + '.m': '// ', + '.gradle': '// ', + '.sh': '# ', + '.py': '# ', + '.ps1': '# ', + '.gn': '# ', + '.bat': 'REM ', +}; + +const Set _ignoredDirectories = { + '.git', + '.dart_tool', + '.gemini', + '.idea', + '.vscode', + 'build', + 'node_modules', +}; + +/// Returns all code files under [root] that are missing the Flutter license header. +List findFilesMissingLicense(Directory root) { + final missing = []; + final pending = [root]; + + while (pending.isNotEmpty) { + final dir = pending.removeLast(); + final entries = dir.listSync(followLinks: false) + ..sort((a, b) => a.path.compareTo(b.path)); + + for (final entity in entries) { + final name = entity.uri.pathSegments + .where((segment) => segment.isNotEmpty) + .lastOrNull; + if (name == null) continue; + + if (entity is Directory) { + if (_ignoredDirectories.contains(name)) continue; + pending.add(entity); + } else if (entity is File) { + final dotIndex = name.lastIndexOf('.'); + if (dotIndex == -1) continue; + final ext = name.substring(dotIndex); + final prefix = _extensionPrefixes[ext]; + if (prefix == null) continue; + + final contents = entity.readAsStringSync().replaceAll('\r\n', '\n'); + if (contents.isEmpty) continue; + + final expectedHeader = '${_generateLicense(prefix)}\n\n'; + final pattern = + RegExp('^(?:#![^\n]*\n)?${RegExp.escape(expectedHeader)}'); + if (!pattern.hasMatch(contents)) { + missing.add(entity.path); + } + } + } + } + + return missing..sort(); +} + +void main() { + group('License Headers', () { + test('root LICENSE file exists and is non-empty', () { + final licenseFile = File('LICENSE'); + expect(licenseFile.existsSync(), isTrue); + expect(licenseFile.readAsStringSync().trim(), isNotEmpty); + }); + + test('all code files in the repository have the Flutter license header', + () { + final missing = findFilesMissingLicense(Directory.current); + expect( + missing, + isEmpty, + reason: 'The following code files are missing the required Flutter ' + 'license header (followed by a blank line):\n' + ' ${missing.join('\n ')}\n\n' + 'Expected header:\n${_generateLicense('// ')}', + ); + }); + + test( + 'findFilesMissingLicense detects missing headers and accepts valid ones', + () { + final tempDir = Directory.systemTemp.createTempSync('license_test_'); + addTearDown(() { + if (tempDir.existsSync()) { + tempDir.deleteSync(recursive: true); + } + }); + + File('${tempDir.path}/valid.dart').writeAsStringSync( + '${_generateLicense('// ')}\n\nvoid main() {}\n', + ); + File('${tempDir.path}/valid_script.sh').writeAsStringSync( + '#!/usr/bin/env bash\n${_generateLicense('# ')}\n\necho "ok"\n', + ); + File('${tempDir.path}/missing.dart').writeAsStringSync( + 'void main() {}\n', + ); + File('${tempDir.path}/no_blank_line.dart').writeAsStringSync( + '${_generateLicense('// ')}\nvoid main() {}\n', + ); + File('${tempDir.path}/ignored.json').writeAsStringSync('{}\n'); + + final missing = findFilesMissingLicense(tempDir) + .map((p) => p.split('/').last) + .toList(); + expect(missing, equals(['missing.dart', 'no_blank_line.dart'])); + }); + }); +} diff --git a/tool/bots.dart b/tool/bots.dart index b2d7bbf..eaac81b 100644 --- a/tool/bots.dart +++ b/tool/bots.dart @@ -1,3 +1,7 @@ +// Copyright 2014 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 'github.dart'; /// Dynamic cache for members of the `@flutter/robots` and `@flutter/bots` GitHub teams. @@ -42,6 +46,8 @@ const Set knownBots = { 'renovate', 'renovate[bot]', 'flutteractionsbot', + 'flutter-pub-roller-bot', + 'flutter-skills-sync-bot', 'flutter-website-bot', 'flutter-intellij-kokoro', 'fluttercerberus', diff --git a/tool/github.dart b/tool/github.dart index ea62cac..8322647 100644 --- a/tool/github.dart +++ b/tool/github.dart @@ -1,3 +1,7 @@ +// Copyright 2014 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:convert'; import 'dart:io'; import 'package:http/http.dart' as http; diff --git a/tool/sync_activity.dart b/tool/sync_activity.dart index 5db2851..8fb9fb8 100644 --- a/tool/sync_activity.dart +++ b/tool/sync_activity.dart @@ -1,3 +1,7 @@ +// Copyright 2014 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:collection'; import 'dart:convert'; import 'dart:io'; @@ -92,6 +96,7 @@ void recomputeActivitySummary(Directory activityDir, {File? outputFile}) { jsonDecode(file.readAsStringSync()) as Map; for (final entry in content.entries) { final user = entry.key; + if (isExcludedAccount(user)) continue; final stats = entry.value as Map; summary.putIfAbsent( user, From c3eab7715797be43ad9ea7b121ad36d2d2ef6a19 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Mon, 19 Oct 2026 15:25:27 -0500 Subject: [PATCH 2/2] chore: address review nits in license_test.dart --- test/license_test.dart | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/test/license_test.dart b/test/license_test.dart index 940df85..7d67e0e 100644 --- a/test/license_test.dart +++ b/test/license_test.dart @@ -6,12 +6,13 @@ import 'dart:io'; import 'package:test/test.dart'; String _generateLicense(String prefix) { - return '${prefix}Copyright 2014 The Flutter Authors. All rights reserved.\n' - '${prefix}Use of this source code is governed by a BSD-style license that can be\n' - '${prefix}found in the LICENSE file.'; + return ''' +${prefix}Copyright 2014 The Flutter Authors. All rights reserved. +${prefix}Use of this source code is governed by a BSD-style license that can be +${prefix}found in the LICENSE file.'''; } -final Map _extensionPrefixes = { +const _extensionPrefixes = { '.dart': '// ', '.js': '// ', '.cjs': '// ', @@ -32,7 +33,7 @@ final Map _extensionPrefixes = { '.bat': 'REM ', }; -const Set _ignoredDirectories = { +const _ignoredDirectories = { '.git', '.dart_tool', '.gemini',