-
-
Notifications
You must be signed in to change notification settings - Fork 277
chore: flutter symbol collector CLI tool #1673
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 47 commits
Commits
Show all changes
48 commits
Select commit
Hold shift + click to select a range
7bfcaf9
chore: flutter symbol collector CLI tool
vaind d1313bd
renames
vaind 7a0c73e
symbol collector CLI integration
vaind ac1c1c0
fixup getVersion()
vaind 7218df6
collector upload
vaind d394181
collect platform info with symbol archive
vaind 5e963aa
download and extract zip archives
vaind c4aa8a8
download via cli bin
vaind a7a80ea
upload via symbol-collector cli
vaind 667c144
add symbol collector CI
vaind 5390bcf
extract inner zip files
vaind 2bc4ed7
test symbol collector in CI
vaind ed79ef4
fix tests
vaind ff91b35
chore: update changelog
vaind 795e7a4
fix tests
vaind 816ae3e
fix tests
vaind 5170a46
upload android symbols
vaind caa9b62
fix duplicate upload
vaind 4724c81
upload symbols for all of 3.13.*
vaind b55becb
cache previous symbol collector successful uploads
vaind cb298d6
fix artifacts
vaind 57efb36
we need to use cache
vaind 8d686cb
cron
vaind bdfcfdc
test
vaind cee0761
use artifacts
vaind 611f636
run for all v3 flutter versions
vaind 321198c
fixup changelog
vaind 6834bc8
fixup changelog
vaind dfb8fee
refactor: move status cache to a separate file
vaind deca8fc
change artifact action to download from previous runs
vaind 12f6033
fix status cache
vaind 0dc96c3
fix status cache
vaind 3875129
register symbol collector CLI updater
vaind 6ba64f6
log status change
vaind d352c73
fix status caching
vaind 6d163a6
fix
vaind b7e4719
process all flutter v3 subversions
vaind 2edb9be
try to fix memory usage
vaind adf8f60
cleanup earlier
vaind 6529c4b
roll back changes after figuring out the issue is with symbol collect…
vaind 6f1fc8d
update symbol-collector to the latest version
vaind 7b9fb06
rename .successful to .cache
vaind e7a20f3
don't use version in the status cache
vaind 9461372
remove temp code
vaind 986f954
run cron every hour
vaind 9b74649
update symbol collector issue link
vaind 5edbf3d
Merge branch 'main' into feat/flutter-symbol-upload
vaind 0d8652b
minor fixes
vaind File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| name: Flutter symbols collection | ||
| on: | ||
| schedule: | ||
| # Run once an hour. It takes just a couple of minutes because of status caching. | ||
| - cron: "10 * * * *" | ||
| workflow_dispatch: | ||
| inputs: | ||
| flutter_version: | ||
| description: Flutter version, can be either a specific version (3.17.0) or a wildcard (3.2.*) | ||
| required: false | ||
| type: string | ||
| default: "3.*.*" | ||
|
|
||
| defaults: | ||
| run: | ||
| working-directory: scripts/flutter_symbol_collector | ||
|
|
||
| jobs: | ||
| test: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v3 | ||
|
|
||
| - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d # pin@v1 | ||
|
|
||
| - run: dart pub get | ||
|
|
||
| - run: dart test | ||
|
|
||
| run: | ||
| needs: [test] | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v3 | ||
|
|
||
| - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d # pin@v1 | ||
|
|
||
| - run: dart pub get | ||
|
|
||
| - name: Download status cache of previously processed files | ||
| run: | | ||
| gh run download --name 'flutter-symbol-collector-database' --dir .cache | ||
| grep -r "" .cache | ||
| continue-on-error: true | ||
| env: | ||
| GITHUB_TOKEN: ${{ github.token }} | ||
|
|
||
| - run: dart run bin/flutter_symbol_collector.dart --version=${{ inputs.flutter_version || '3.*.*' }} | ||
| timeout-minutes: 300 | ||
| env: | ||
| GITHUB_TOKEN: ${{ github.token }} | ||
|
|
||
| - name: Upload updated status cache of processed files | ||
| uses: actions/upload-artifact@v3 | ||
| if: always() | ||
| with: | ||
| name: flutter-symbol-collector-database | ||
| path: scripts/flutter_symbol_collector/.cache |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| # https://dart.dev/guides/libraries/private-files | ||
| # Created by `dart pub` | ||
| .dart_tool/ | ||
|
|
||
| .temp | ||
| .cache |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| # Flutter symbol collector | ||
|
|
||
| This is an internal tool to collect Flutter debug symbols and upload them to Sentry. | ||
| This application is not intended for public usage - we're uploading the symbols in CI automatically so you don't have to. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| include: package:lints/recommended.yaml | ||
|
|
||
| linter: | ||
| rules: | ||
| prefer_relative_imports: true | ||
| unnecessary_brace_in_string_interps: true | ||
| unawaited_futures: true |
96 changes: 96 additions & 0 deletions
96
scripts/flutter_symbol_collector/bin/flutter_symbol_collector.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| import 'package:args/args.dart'; | ||
| import 'package:file/local.dart'; | ||
| import 'package:flutter_symbol_collector/flutter_symbol_collector.dart'; | ||
| import 'package:github/github.dart'; | ||
| import 'package:logging/logging.dart'; | ||
|
|
||
| const githubToken = String.fromEnvironment('GITHUB_TOKEN'); | ||
| final githubAuth = githubToken.isEmpty | ||
| ? Authentication.anonymous() | ||
| : Authentication.withToken(githubToken); | ||
| final source = FlutterSymbolSource(githubAuth: githubAuth); | ||
| final fs = LocalFileSystem(); | ||
| final tempDir = fs.currentDirectory.childDirectory('.temp'); | ||
| final stateCache = | ||
| DirectoryStatusCache(fs.currentDirectory.childDirectory('.cache')); | ||
| late final SymbolCollectorCli collector; | ||
|
|
||
| void main(List<String> arguments) async { | ||
| Logger.root.level = Level.ALL; | ||
| Logger.root.onRecord.listen((record) { | ||
| print('${record.level.name}: ${record.time}: ${record.message}' | ||
| '${record.error == null ? '' : ': ${record.error}'}'); | ||
| }); | ||
|
|
||
| final parser = ArgParser()..addOption('version', defaultsTo: ''); | ||
| final args = parser.parse(arguments); | ||
| final argVersion = args['version'] as String; | ||
|
|
||
| collector = await SymbolCollectorCli.setup(tempDir); | ||
|
|
||
| // If a specific version was given, run just for this version. | ||
| if (argVersion.isNotEmpty && | ||
| !argVersion.contains('*') && | ||
| argVersion.split('.').length == 3) { | ||
| Logger.root.info('Running for a single flutter version: $argVersion'); | ||
| await processFlutterVerion(FlutterVersion(argVersion)); | ||
| } else { | ||
| // Otherwise, walk all the versions and run for the matching ones. | ||
| final versionRegex = RegExp(argVersion.isEmpty | ||
| ? '.*' | ||
| : '^${argVersion.replaceAll('.', '\\.').replaceAll('*', '.+')}\$'); | ||
| Logger.root.info('Running for all Flutter versions matching $versionRegex'); | ||
| final versions = await source | ||
| .listFlutterVersions() | ||
| .where((v) => !v.isPreRelease) | ||
| .where((v) => versionRegex.hasMatch(v.tagName)) | ||
| .toList(); | ||
| Logger.root.info( | ||
| 'Found ${versions.length} Flutter versions matching $versionRegex'); | ||
| for (var version in versions) { | ||
| await processFlutterVerion(version); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| Future<void> processFlutterVerion(FlutterVersion version) async { | ||
| if (bool.hasEnvironment('CI')) { | ||
| print('::group::Processing Flutter ${version.tagName}'); | ||
| } | ||
| Logger.root.info('Processing Flutter ${version.tagName}'); | ||
| Logger.root.info('Engine version: ${await version.engineVersion}'); | ||
|
|
||
| final archives = await source.listSymbolArchives(version); | ||
| final dir = tempDir.childDirectory(version.tagName); | ||
| for (final archive in archives) { | ||
| final status = await stateCache.getStatus(archive); | ||
| if (status == SymbolArchiveStatus.success) { | ||
| Logger.root | ||
| .info('Skipping ${archive.path} - already processed successfully'); | ||
| continue; | ||
| } | ||
|
|
||
| final archiveDir = dir.childDirectory(archive.platform.operatingSystem); | ||
| try { | ||
| if (await source.downloadAndExtractTo(archiveDir, archive.path)) { | ||
| if (await collector.upload(archiveDir, archive.platform, version)) { | ||
| await stateCache.setStatus(archive, SymbolArchiveStatus.success); | ||
| continue; | ||
| } | ||
| } | ||
| await stateCache.setStatus(archive, SymbolArchiveStatus.error); | ||
| } finally { | ||
| if (await archiveDir.exists()) { | ||
| await archiveDir.delete(recursive: true); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (await dir.exists()) { | ||
| await dir.delete(recursive: true); | ||
| } | ||
|
|
||
| if (bool.hasEnvironment('CI')) { | ||
| print('::endgroup::'); | ||
| } | ||
| } | ||
5 changes: 5 additions & 0 deletions
5
scripts/flutter_symbol_collector/lib/flutter_symbol_collector.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| export 'src/flutter_symbol_source.dart'; | ||
| export 'src/flutter_version.dart'; | ||
| export 'src/symbol_collector_cli.dart'; | ||
| export 'src/status_cache.dart'; | ||
| export 'src/symbol_archive.dart'; |
73 changes: 73 additions & 0 deletions
73
scripts/flutter_symbol_collector/lib/src/flutter_symbol_resolver.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| import 'package:gcloud/storage.dart'; | ||
| import 'package:platform/platform.dart'; | ||
|
|
||
| import 'symbol_archive.dart'; | ||
|
|
||
| abstract class FlutterSymbolResolver { | ||
| final String _prefix; | ||
| final Bucket _bucket; | ||
| final _resolvedFiles = List<SymbolArchive>.empty(growable: true); | ||
| Platform get platform; | ||
|
|
||
| FlutterSymbolResolver(this._bucket, String prefix) | ||
| : _prefix = prefix.endsWith('/') | ||
| ? prefix.substring(0, prefix.length - 1) | ||
| : prefix; | ||
|
|
||
| Future<void> tryResolve(String path) async { | ||
| path = '$_prefix/$path'; | ||
| final matches = await _bucket | ||
| .list(prefix: path) | ||
| .where((v) => v.isObject) | ||
| .where((v) => v.name == path) // because it's a prefix search | ||
| .map((v) => v.name) | ||
| .toList(); | ||
| if (matches.isNotEmpty) { | ||
| _resolvedFiles.add(SymbolArchive(matches.single, platform)); | ||
| } | ||
| } | ||
|
|
||
| Future<List<SymbolArchive>> listArchives(); | ||
| } | ||
|
|
||
| class IosSymbolResolver extends FlutterSymbolResolver { | ||
| IosSymbolResolver(super.bucket, super.prefix); | ||
|
|
||
| @override | ||
| final platform = FakePlatform(operatingSystem: Platform.iOS); | ||
|
|
||
| @override | ||
| Future<List<SymbolArchive>> listArchives() async { | ||
| await tryResolve('ios-release/Flutter.dSYM.zip'); | ||
| return _resolvedFiles; | ||
| } | ||
| } | ||
|
|
||
| class MacOSSymbolResolver extends FlutterSymbolResolver { | ||
| MacOSSymbolResolver(super.bucket, super.prefix); | ||
|
|
||
| @override | ||
| final platform = FakePlatform(operatingSystem: Platform.macOS); | ||
|
|
||
| @override | ||
| Future<List<SymbolArchive>> listArchives() async { | ||
| // darwin-x64-release directory contains a fat (arm64+x86_64) binary. | ||
| await tryResolve('darwin-x64-release/FlutterMacOS.dSYM.zip'); | ||
| return _resolvedFiles; | ||
| } | ||
| } | ||
|
|
||
| class AndroidSymbolResolver extends FlutterSymbolResolver { | ||
| final String architecture; | ||
|
|
||
| AndroidSymbolResolver(super.bucket, super.prefix, this.architecture); | ||
|
|
||
| @override | ||
| final platform = FakePlatform(operatingSystem: Platform.android); | ||
|
|
||
| @override | ||
| Future<List<SymbolArchive>> listArchives() async { | ||
| await tryResolve('android-$architecture-release/symbols.zip'); | ||
| return _resolvedFiles; | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.