├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── blast_repo.md │ ├── canary.md │ ├── corpus.md │ ├── dart_flutter_team_lints.md │ ├── firehose.md │ ├── repo_manage.md │ ├── repo_query.md │ ├── sdk_triage_bot.md │ └── trebuchet.md ├── dependabot.yaml ├── labeler.yml ├── test_repos │ └── repos.json └── workflows │ ├── blast_repo.yml │ ├── canary.yaml │ ├── canary_internal.yaml │ ├── canary_test.yml │ ├── corpus.yml │ ├── dart_flutter_team_lints.yml │ ├── firehose.yml │ ├── health.yaml │ ├── health_base.yaml │ ├── health_internal.yaml │ ├── no-response.yml │ ├── post_summaries.yaml │ ├── publish.yaml │ ├── publish_internal.yaml │ ├── pull_request_label.yml │ ├── puppy.yml │ ├── repo_manage.yml │ ├── sdk_triage_bot.yml │ └── trebuchet.yml ├── .gitignore ├── .vscode └── launch.json ├── CODEOWNERS ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── pkgs ├── blast_repo │ ├── .gitignore │ ├── AUTHORS │ ├── LICENSE │ ├── README.md │ ├── analysis_options.yaml │ ├── bin │ │ └── blast_repo.dart │ ├── lib │ │ └── src │ │ │ ├── action_version.dart │ │ │ ├── exact_file_tweak.dart │ │ │ ├── github.dart │ │ │ ├── github_action_resolver.dart │ │ │ ├── repo_tweak.dart │ │ │ ├── top_level.dart │ │ │ ├── tweaks │ │ │ ├── auto_publish_tweak.dart │ │ │ ├── dependabot_tweak.dart │ │ │ ├── drop_lint_tweak.dart │ │ │ ├── github_action_tweak.dart │ │ │ ├── mono_repo_tweak.dart │ │ │ └── no_reponse_tweak.dart │ │ │ └── utils.dart │ ├── pubspec.yaml │ ├── pubspec_overrides.yaml │ └── test │ │ ├── auto_publish_test.dart │ │ ├── dependabot_test.dart │ │ ├── drop_lint_test.dart │ │ ├── github_action_test.dart │ │ ├── mono_repo_test.dart │ │ ├── no_response_test.dart │ │ └── utils_test.dart ├── canary │ ├── .gitignore │ ├── LICENSE │ ├── README.md │ ├── analysis_options.yaml │ ├── bin │ │ └── canary.dart │ ├── pubspec.yaml │ ├── schema.json │ └── test │ │ └── canary_test.dart ├── corpus │ ├── .gitignore │ ├── AUTHORS │ ├── LICENSE │ ├── README.md │ ├── analysis_options.yaml │ ├── bin │ │ ├── deps.dart │ │ └── usage.dart │ ├── doc │ │ ├── dart_collection.md │ │ ├── matcher.csv │ │ └── package_collection.md │ ├── lib │ │ ├── api.dart │ │ ├── cache.dart │ │ ├── packages.dart │ │ ├── pub.dart │ │ ├── report.dart │ │ ├── surveyor.dart │ │ ├── usage.dart │ │ └── utils.dart │ ├── pubspec.yaml │ └── test │ │ ├── api_test.dart │ │ ├── data │ │ ├── class_references.dart │ │ ├── dart_extension_references.dart │ │ ├── dart_library_references.dart │ │ ├── dart_top_level_symbol_references.dart │ │ ├── extension_references.dart │ │ ├── library_references.dart │ │ └── top_level_symbol_references.dart │ │ ├── pub_test.dart │ │ └── visitor_test.dart ├── dart_flutter_team_lints │ ├── .gitignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── analysis_options.yaml │ ├── lib │ │ └── analysis_options.yaml │ ├── pubspec.yaml │ ├── test │ │ └── validate_test.dart │ └── tool │ │ └── dedup.dart ├── firehose │ ├── .gitignore │ ├── .pubignore │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── analysis_options.yaml │ ├── bin │ │ ├── firehose.dart │ │ └── health.dart │ ├── lib │ │ ├── firehose.dart │ │ └── src │ │ │ ├── changelog.dart │ │ │ ├── delayed_client.dart │ │ │ ├── github.dart │ │ │ ├── health │ │ │ ├── changelog.dart │ │ │ ├── coverage.dart │ │ │ ├── health.dart │ │ │ ├── lcov.dart │ │ │ └── license.dart │ │ │ ├── pub.dart │ │ │ ├── repo.dart │ │ │ └── utils.dart │ ├── pubspec.yaml │ ├── test │ │ ├── changelog_test.dart │ │ ├── coverage_test.dart │ │ ├── github_test.dart │ │ ├── health_test.dart │ │ ├── lcov.info │ │ ├── license_test.dart │ │ ├── pub_test.dart │ │ ├── repo_test.dart │ │ └── utils_test.dart │ └── test_data │ │ ├── base_test_repo │ │ └── pkgs │ │ │ ├── package1 │ │ │ ├── .gitignore │ │ │ ├── CHANGELOG.md │ │ │ ├── README.md │ │ │ ├── analysis_options.yaml │ │ │ ├── bin │ │ │ │ └── package1.dart │ │ │ ├── lib │ │ │ │ └── package1.dart │ │ │ ├── pubspec.yaml │ │ │ └── test │ │ │ │ └── package1_test.dart │ │ │ ├── package2 │ │ │ ├── .gitignore │ │ │ ├── CHANGELOG.md │ │ │ ├── README.md │ │ │ ├── analysis_options.yaml │ │ │ ├── bin │ │ │ │ └── package2.dart │ │ │ ├── lib │ │ │ │ └── package2.dart │ │ │ ├── pubspec.yaml │ │ │ └── test │ │ │ │ └── package2_test.dart │ │ │ ├── package3 │ │ │ ├── .gitignore │ │ │ ├── CHANGELOG.md │ │ │ ├── README.md │ │ │ ├── analysis_options.yaml │ │ │ ├── bin │ │ │ │ └── package3.dart │ │ │ ├── lib │ │ │ │ └── package3.dart │ │ │ ├── pubspec.yaml │ │ │ └── test │ │ │ │ └── package3_test.dart │ │ │ └── package5 │ │ │ ├── lib │ │ │ ├── package5.dart │ │ │ └── src │ │ │ │ └── package5_base.dart │ │ │ └── pubspec.yaml │ │ ├── golden │ │ ├── comment_breaking.md │ │ ├── comment_breaking_healthchanged.md │ │ ├── comment_breaking_ignore_package.md │ │ ├── comment_changelog.md │ │ ├── comment_changelog_healthchanged.md │ │ ├── comment_changelog_ignore_package.md │ │ ├── comment_coverage.md │ │ ├── comment_coverage_healthchanged.md │ │ ├── comment_coverage_ignore_package.md │ │ ├── comment_do-not-submit.md │ │ ├── comment_do-not-submit_healthchanged.md │ │ ├── comment_do-not-submit_ignore_package.md │ │ ├── comment_leaking.md │ │ ├── comment_leaking_healthchanged.md │ │ ├── comment_leaking_ignore_package.md │ │ ├── comment_license.md │ │ ├── comment_license_healthchanged.md │ │ ├── comment_license_ignore_license.md │ │ └── comment_license_ignore_package.md │ │ ├── root_unpublished_pkg │ │ ├── pkg_1 │ │ │ └── pubspec.yaml │ │ ├── pkg_2 │ │ │ └── pubspec.yaml │ │ └── pubspec.yaml │ │ ├── test_repo │ │ └── pkgs │ │ │ ├── package1 │ │ │ ├── .gitignore │ │ │ ├── CHANGELOG.md │ │ │ ├── README.md │ │ │ ├── analysis_options.yaml │ │ │ ├── bin │ │ │ │ └── package1.dart │ │ │ ├── lib │ │ │ │ └── package1.dart │ │ │ ├── pubspec.yaml │ │ │ └── test │ │ │ │ └── package1_test.dart │ │ │ ├── package2 │ │ │ ├── .gitignore │ │ │ ├── CHANGELOG.md │ │ │ ├── README.md │ │ │ ├── analysis_options.yaml │ │ │ ├── bin │ │ │ │ └── package2.dart │ │ │ ├── lib │ │ │ │ ├── anotherLib.dart │ │ │ │ └── package2.dart │ │ │ ├── pubspec.yaml │ │ │ ├── someImage.png │ │ │ └── test │ │ │ │ └── package2_test.dart │ │ │ ├── package3 │ │ │ ├── .gitignore │ │ │ ├── CHANGELOG.md │ │ │ ├── README.md │ │ │ ├── analysis_options.yaml │ │ │ ├── bin │ │ │ │ └── package3.dart │ │ │ ├── lib │ │ │ │ └── package3.dart │ │ │ ├── pubspec.yaml │ │ │ └── test │ │ │ │ └── package3_test.dart │ │ │ └── package5 │ │ │ ├── lib │ │ │ ├── package5.dart │ │ │ └── src │ │ │ │ └── package5_base.dart │ │ │ └── pubspec.yaml │ │ └── workspace_repo │ │ ├── pkg_1 │ │ └── pubspec.yaml │ │ ├── pkg_2 │ │ └── pubspec.yaml │ │ └── pubspec.yaml ├── puppy │ ├── README.md │ ├── analysis_options.yaml │ ├── bin │ │ └── puppy.dart │ ├── lib │ │ └── src │ │ │ ├── constants.dart │ │ │ ├── run_command.dart │ │ │ ├── run_command.g.dart │ │ │ └── utils.dart │ └── pubspec.yaml ├── repo_manage │ ├── .gitignore │ ├── README.md │ ├── analysis_options.yaml │ ├── bin │ │ └── report.dart │ ├── lib │ │ ├── branches.dart │ │ ├── contributors.dart │ │ ├── issue_transfer.dart │ │ ├── labels.dart │ │ ├── labels_update.dart │ │ ├── src │ │ │ └── common.dart │ │ └── weekly.dart │ └── pubspec.yaml ├── sdk_triage_bot │ ├── .gitignore │ ├── README.md │ ├── analysis_options.yaml │ ├── bin │ │ └── triage.dart │ ├── lib │ │ ├── src │ │ │ ├── common.dart │ │ │ ├── gemini.dart │ │ │ ├── github.dart │ │ │ └── prompts.dart │ │ └── triage.dart │ ├── pubspec.yaml │ ├── test │ │ ├── fakes.dart │ │ └── triage_test.dart │ └── tool │ │ ├── bench.dart │ │ ├── bench.md │ │ └── create_tuning_data.dart └── trebuchet │ ├── LICENSE │ ├── README.md │ ├── analysis_options.yaml │ ├── bin │ └── trebuchet.dart │ └── pubspec.yaml └── tool └── ci.sh /.gitattributes: -------------------------------------------------------------------------------- 1 | .github/workflows/dart.yml linguist-generated=true 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/blast_repo.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "package:blast_repo" 3 | about: "Create a bug or file a feature request against package:blast_repo." 4 | labels: "package:blast_repo" 5 | --- 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/canary.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "package:canary" 3 | about: "Create a bug or file a feature request against package:canary." 4 | labels: "package:canary" 5 | --- 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/corpus.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "package:corpus" 3 | about: "Create a bug or file a feature request against package:corpus." 4 | labels: "package:corpus" 5 | --- 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/dart_flutter_team_lints.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "package:dart_flutter_team_lints" 3 | about: "Create a bug or file a feature request against package:dart_flutter_team_lints." 4 | labels: "package:dart_flutter_team_lints" 5 | --- 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/firehose.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "package:firehose" 3 | about: "Create a bug or file a feature request against package:firehose." 4 | labels: "package:firehose" 5 | --- 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/repo_manage.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "package:repo_manage" 3 | about: "Create a bug or file a feature request against package:repo_manage." 4 | labels: "package:repo_manage" 5 | --- 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/repo_query.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "package:repo_manage" 3 | about: "Create a bug or file a feature request against package:repo_manage." 4 | labels: "package:repo_manage" 5 | --- 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/sdk_triage_bot.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "package:sdk_triage_bot" 3 | about: "Create a bug or file a feature request against package:sdk_triage_bot." 4 | labels: "package:sdk_triage_bot" 5 | --- 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/trebuchet.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "package:trebuchet" 3 | about: "Create a bug or file a feature request against package:trebuchet." 4 | labels: "package:trebuchet" 5 | --- 6 | -------------------------------------------------------------------------------- /.github/dependabot.yaml: -------------------------------------------------------------------------------- 1 | # Dependabot configuration file. 2 | version: 2 3 | 4 | updates: 5 | - package-ecosystem: github-actions 6 | directory: / 7 | schedule: 8 | interval: monthly 9 | labels: 10 | - autosubmit 11 | groups: 12 | github-actions: 13 | patterns: 14 | - "*" 15 | -------------------------------------------------------------------------------- /.github/labeler.yml: -------------------------------------------------------------------------------- 1 | # Configuration for .github/workflows/pull_request_label.yml. 2 | 3 | 'type-infra': 4 | - changed-files: 5 | - any-glob-to-any-file: '.github/**' 6 | 7 | 'package:blast_repo': 8 | - changed-files: 9 | - any-glob-to-any-file: 'pkgs/blast_repo/**' 10 | 11 | 'package:corpus': 12 | - changed-files: 13 | - any-glob-to-any-file: 'pkgs/corpus/**' 14 | 15 | 'package:dart_flutter_team_lints': 16 | - changed-files: 17 | - any-glob-to-any-file: 'pkgs/dart_flutter_team_lints/**' 18 | 19 | 'package:firehose': 20 | - changed-files: 21 | - any-glob-to-any-file: 'pkgs/firehose/**' 22 | 23 | 'package:repo_manage': 24 | - changed-files: 25 | - any-glob-to-any-file: 'pkgs/repo_manage/**' 26 | 27 | 'package:puppy': 28 | - changed-files: 29 | - any-glob-to-any-file: 'pkgs/puppy/**' 30 | 31 | 'package:sdk_triage_bot': 32 | - changed-files: 33 | - any-glob-to-any-file: 'pkgs/sdk_triage_bot/**' 34 | 35 | 'package:trebuchet': 36 | - changed-files: 37 | - any-glob-to-any-file: 'pkgs/trebuchet/**' 38 | -------------------------------------------------------------------------------- /.github/test_repos/repos.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../pkgs/canary/schema.json", 3 | "https://github.com/mosuem/my_app_old_web": { 4 | "level": "analyze" 5 | }, 6 | "https://github.com/mosuem/my_app_new_web": { 7 | "level": "test", 8 | "packages": { 9 | "exclude": "intl4x" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /.github/workflows/blast_repo.yml: -------------------------------------------------------------------------------- 1 | name: package:blast_repo 2 | 3 | permissions: read-all 4 | 5 | on: 6 | pull_request: 7 | branches: [ main ] 8 | paths: 9 | - '.github/workflows/blast_repo.yml' 10 | - 'pkgs/blast_repo/**' 11 | push: 12 | branches: [ main ] 13 | paths: 14 | - '.github/workflows/blast_repo.yml' 15 | - 'pkgs/blast_repo/**' 16 | schedule: 17 | - cron: '0 0 * * 0' # weekly 18 | 19 | defaults: 20 | run: 21 | working-directory: pkgs/blast_repo 22 | 23 | jobs: 24 | build: 25 | runs-on: ubuntu-latest 26 | strategy: 27 | fail-fast: false 28 | matrix: 29 | sdk: [stable, dev] 30 | steps: 31 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 32 | - uses: dart-lang/setup-dart@e51d8e571e22473a2ddebf0ef8a2123f0ab2c02c 33 | with: 34 | sdk: ${{ matrix.sdk }} 35 | 36 | - run: dart pub get 37 | 38 | - run: dart analyze --fatal-infos 39 | 40 | - run: dart format --output=none --set-exit-if-changed . 41 | if: ${{ matrix.sdk == 'stable' }} 42 | 43 | - run: dart test 44 | -------------------------------------------------------------------------------- /.github/workflows/canary.yaml: -------------------------------------------------------------------------------- 1 | name: Canary 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | repos_file: 7 | description: 'Path to the file containing the list of repository names' 8 | type: string 9 | required: true 10 | local_debug: 11 | description: Whether to use a local version of ecosystem testing - only for debug 12 | default: false 13 | type: boolean 14 | required: false 15 | 16 | jobs: 17 | test: 18 | runs-on: ubuntu-latest 19 | steps: 20 | - name: Checkout repository 21 | uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 22 | with: 23 | token: ${{ secrets.GITHUB_TOKEN }} 24 | 25 | - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff 26 | with: 27 | channel: main 28 | 29 | - run: echo "${{ toJSON(github.event.pull_request.labels.*.name) }}" 30 | 31 | - name: Install local version of `package:canary` 32 | run: dart pub global activate -s path pkgs/canary 33 | if: ${{ inputs.local_debug }} 34 | 35 | - run: dart pub global activate -s git https://github.com/dart-lang/ecosystem.git --git-ref main --git-path pkgs/canary 36 | if: ${{ !inputs.local_debug }} 37 | 38 | - name: Update package and test 39 | run: | 40 | dart pub global run canary ${{ inputs.repos_file }} ${{ github.repositoryUrl }} ${{ github.head_ref || github.ref_name }} "${{ toJSON(github.event.pull_request.labels.*.name) }}" 41 | env: 42 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 43 | 44 | - name: Output issue number 45 | run: | 46 | mkdir -p output 47 | echo ${{ github.event.number }} > output/issueNumber 48 | 49 | - name: Find Comment 50 | uses: peter-evans/find-comment@9735ba2ed6a47d05499d9b653e05f347f3031e89 51 | id: fc 52 | with: 53 | issue-number: ${{ github.event.number }} 54 | comment-author: github-actions[bot] 55 | body-includes: '## Ecosystem testing' 56 | 57 | - name: Write comment id to file 58 | if: ${{ steps.fc.outputs.comment-id != 0 }} 59 | run: echo ${{ steps.fc.outputs.comment-id }} >> output/commentId 60 | 61 | - name: Upload markdown 62 | if: success() || failure() 63 | uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 64 | with: 65 | name: output 66 | path: output/ 67 | -------------------------------------------------------------------------------- /.github/workflows/canary_internal.yaml: -------------------------------------------------------------------------------- 1 | name: Canary:Internal 2 | 3 | on: 4 | pull_request: 5 | branches: [ main ] 6 | types: [opened, synchronize, reopened, labeled, unlabeled] 7 | 8 | jobs: 9 | test_ecosystem: 10 | uses: ./.github/workflows/canary.yaml 11 | with: 12 | repos_file: .github/test_repos/repos.json 13 | local_debug: true 14 | -------------------------------------------------------------------------------- /.github/workflows/canary_test.yml: -------------------------------------------------------------------------------- 1 | name: package:canary 2 | 3 | permissions: read-all 4 | 5 | on: 6 | pull_request: 7 | branches: [ main ] 8 | paths: 9 | - '.github/workflows/canary.yml' 10 | - 'pkgs/canary/**' 11 | push: 12 | branches: [ main ] 13 | paths: 14 | - '.github/workflows/canary.yml' 15 | - 'pkgs/canary/**' 16 | schedule: 17 | - cron: '0 0 * * 0' # weekly 18 | 19 | defaults: 20 | run: 21 | working-directory: pkgs/canary 22 | 23 | env: 24 | GH_TOKEN: ${{ github.token }} 25 | 26 | jobs: 27 | build: 28 | runs-on: ubuntu-latest 29 | steps: 30 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 31 | - uses: subosito/flutter-action@f2c4f6686ca8e8d6e6d0f28410eeef506ed66aff 32 | with: 33 | channel: main 34 | 35 | - run: dart pub get 36 | 37 | - run: dart analyze --fatal-infos 38 | 39 | - run: dart format --output=none --set-exit-if-changed . 40 | 41 | - run: dart test 42 | -------------------------------------------------------------------------------- /.github/workflows/corpus.yml: -------------------------------------------------------------------------------- 1 | name: package:corpus 2 | 3 | permissions: read-all 4 | 5 | on: 6 | pull_request: 7 | branches: [ main ] 8 | paths: 9 | - '.github/workflows/corpus.yml' 10 | - 'pkgs/corpus/**' 11 | push: 12 | branches: [ main ] 13 | paths: 14 | - '.github/workflows/corpus.yml' 15 | - 'pkgs/corpus/**' 16 | schedule: 17 | - cron: '0 0 * * 0' # weekly 18 | 19 | defaults: 20 | run: 21 | working-directory: pkgs/corpus 22 | 23 | jobs: 24 | build: 25 | runs-on: ubuntu-latest 26 | strategy: 27 | fail-fast: false 28 | matrix: 29 | sdk: [3.6, dev] 30 | steps: 31 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 32 | - uses: dart-lang/setup-dart@e51d8e571e22473a2ddebf0ef8a2123f0ab2c02c 33 | with: 34 | sdk: ${{ matrix.sdk }} 35 | 36 | - run: dart pub get 37 | 38 | - run: dart analyze --fatal-infos 39 | 40 | - run: dart format --output=none --set-exit-if-changed . 41 | if: ${{ matrix.sdk == 'dev' }} 42 | 43 | - run: dart test 44 | -------------------------------------------------------------------------------- /.github/workflows/dart_flutter_team_lints.yml: -------------------------------------------------------------------------------- 1 | name: package:dart_flutter_team_lints 2 | 3 | permissions: read-all 4 | 5 | on: 6 | pull_request: 7 | branches: [ main ] 8 | paths: 9 | - '.github/workflows/dart_flutter_team_lints.yml' 10 | - 'pkgs/dart_flutter_team_lints/**' 11 | push: 12 | branches: [ main ] 13 | paths: 14 | - '.github/workflows/dart_flutter_team_lints.yml' 15 | - 'pkgs/dart_flutter_team_lints/**' 16 | schedule: 17 | - cron: '0 0 * * 0' # weekly 18 | 19 | defaults: 20 | run: 21 | working-directory: pkgs/dart_flutter_team_lints 22 | 23 | jobs: 24 | build: 25 | runs-on: ubuntu-latest 26 | strategy: 27 | fail-fast: false 28 | matrix: 29 | sdk: [3.8, dev] 30 | steps: 31 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 32 | - uses: dart-lang/setup-dart@e51d8e571e22473a2ddebf0ef8a2123f0ab2c02c 33 | with: 34 | sdk: ${{ matrix.sdk }} 35 | 36 | - run: dart pub get 37 | 38 | - run: dart analyze --fatal-infos 39 | 40 | - run: dart format --output=none --set-exit-if-changed . 41 | if: ${{ matrix.sdk == 'dev' }} 42 | 43 | - run: dart test 44 | -------------------------------------------------------------------------------- /.github/workflows/firehose.yml: -------------------------------------------------------------------------------- 1 | name: package:firehose 2 | 3 | permissions: read-all 4 | 5 | on: 6 | pull_request: 7 | branches: [ main ] 8 | paths: 9 | - '.github/workflows/firehose.yml' 10 | - 'pkgs/firehose/**' 11 | push: 12 | branches: [ main ] 13 | paths: 14 | - '.github/workflows/firehose.yml' 15 | - 'pkgs/firehose/**' 16 | schedule: 17 | - cron: '0 0 * * 0' # weekly 18 | 19 | defaults: 20 | run: 21 | working-directory: pkgs/firehose 22 | 23 | jobs: 24 | build: 25 | runs-on: ubuntu-latest 26 | strategy: 27 | fail-fast: false 28 | matrix: 29 | sdk: [stable, dev] 30 | steps: 31 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 32 | - uses: dart-lang/setup-dart@e51d8e571e22473a2ddebf0ef8a2123f0ab2c02c 33 | with: 34 | sdk: ${{ matrix.sdk }} 35 | 36 | - run: dart pub get 37 | 38 | - run: dart analyze --fatal-infos 39 | 40 | - run: dart format --output=none --set-exit-if-changed . 41 | if: ${{ matrix.sdk == 'stable' }} 42 | 43 | - run: dart test 44 | -------------------------------------------------------------------------------- /.github/workflows/health_internal.yaml: -------------------------------------------------------------------------------- 1 | # A CI configuration to check PR health. 2 | 3 | name: Health:Internal 4 | 5 | on: 6 | pull_request: 7 | branches: [ main ] 8 | types: [opened, synchronize, reopened, labeled, unlabeled] 9 | 10 | jobs: 11 | health: 12 | uses: ./.github/workflows/health.yaml 13 | with: 14 | sdk: dev 15 | local_debug: true 16 | coverage_web: false 17 | upload_coverage: false 18 | checks: changelog,license,coverage,breaking,do-not-submit,leaking 19 | fail_on: changelog,do-not-submit 20 | warn_on: license,coverage,breaking,leaking 21 | ignore_license: 'pkgs/firehose/test_data' 22 | ignore_coverage: 'pkgs/firehose/bin,pkgs/firehose/test_data' 23 | permissions: 24 | pull-requests: write 25 | -------------------------------------------------------------------------------- /.github/workflows/no-response.yml: -------------------------------------------------------------------------------- 1 | # A workflow to close issues where the author hasn't responded to a request for 2 | # more information; see https://github.com/actions/stale. 3 | 4 | name: No Response 5 | 6 | # Run as a daily cron. 7 | on: 8 | schedule: 9 | # Every day at 8am 10 | - cron: '0 8 * * *' 11 | 12 | # All permissions not specified are set to 'none'. 13 | permissions: 14 | issues: write 15 | pull-requests: write 16 | 17 | jobs: 18 | no-response: 19 | runs-on: ubuntu-latest 20 | if: ${{ github.repository_owner == 'dart-lang' }} 21 | steps: 22 | - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 23 | with: 24 | days-before-stale: -1 25 | days-before-close: 14 26 | stale-issue-label: "needs-info" 27 | close-issue-message: > 28 | Without additional information we're not able to resolve this issue. 29 | Feel free to add more info or respond to any questions above and we 30 | can reopen the case. Thanks for your contribution! 31 | stale-pr-label: "needs-info" 32 | close-pr-message: > 33 | Without additional information we're not able to resolve this PR. 34 | Feel free to add more info or respond to any questions above. 35 | Thanks for your contribution! 36 | -------------------------------------------------------------------------------- /.github/workflows/publish_internal.yaml: -------------------------------------------------------------------------------- 1 | # A CI configuration to auto-publish pub packages from dart-lang/ecosystem. 2 | 3 | # We don't use the regular publish.yaml script here in order to dogfood the 4 | # publishing code at head. 5 | 6 | name: Publish:Internal 7 | 8 | on: 9 | pull_request: 10 | branches: [ main ] 11 | types: [opened, synchronize, reopened, labeled, unlabeled] 12 | push: 13 | tags: [ '[A-z0-9]+-v[0-9]+.[0-9]+.[0-9]+*' ] 14 | 15 | jobs: 16 | publish: 17 | uses: ./.github/workflows/publish.yaml 18 | with: 19 | local_debug: true 20 | use-flutter: false 21 | write-comments: false 22 | sdk: dev 23 | permissions: 24 | id-token: write 25 | pull-requests: write 26 | -------------------------------------------------------------------------------- /.github/workflows/pull_request_label.yml: -------------------------------------------------------------------------------- 1 | # This workflow applies labels to pull requests based on the paths that are 2 | # modified in the pull request. 3 | # 4 | # Edit `.github/labeler.yml` to configure labels. For more information, see 5 | # https://github.com/actions/labeler. 6 | 7 | name: Pull Request Labeler 8 | permissions: read-all 9 | 10 | on: 11 | pull_request_target 12 | 13 | jobs: 14 | label: 15 | permissions: 16 | pull-requests: write 17 | runs-on: ubuntu-latest 18 | steps: 19 | - uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 20 | with: 21 | repo-token: "${{ secrets.GITHUB_TOKEN }}" 22 | sync-labels: true 23 | -------------------------------------------------------------------------------- /.github/workflows/puppy.yml: -------------------------------------------------------------------------------- 1 | name: package:puppy 2 | 3 | permissions: read-all 4 | 5 | on: 6 | pull_request: 7 | branches: [ main ] 8 | paths: 9 | - '.github/workflows/puppy.yml' 10 | - 'pkgs/puppy/**' 11 | push: 12 | branches: [ main ] 13 | paths: 14 | - '.github/workflows/puppy.yml' 15 | - 'pkgs/puppy/**' 16 | schedule: 17 | - cron: '0 0 * * 0' # weekly 18 | 19 | defaults: 20 | run: 21 | working-directory: pkgs/puppy 22 | 23 | jobs: 24 | build: 25 | runs-on: ubuntu-latest 26 | strategy: 27 | fail-fast: false 28 | matrix: 29 | sdk: [3.6, dev] 30 | steps: 31 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 32 | - uses: dart-lang/setup-dart@e51d8e571e22473a2ddebf0ef8a2123f0ab2c02c 33 | with: 34 | sdk: ${{ matrix.sdk }} 35 | 36 | - run: dart pub get 37 | - run: dart analyze --fatal-infos 38 | - run: dart format --output=none --set-exit-if-changed . 39 | if: ${{ matrix.sdk == 'dev' }} 40 | # TODO: enable when there are tests! 41 | #- run: dart test 42 | -------------------------------------------------------------------------------- /.github/workflows/repo_manage.yml: -------------------------------------------------------------------------------- 1 | name: package:repo_manage 2 | 3 | permissions: read-all 4 | 5 | on: 6 | pull_request: 7 | branches: [ main ] 8 | paths: 9 | - '.github/workflows/repo_manage.yml' 10 | - 'pkgs/repo_manage/**' 11 | push: 12 | branches: [ main ] 13 | paths: 14 | - '.github/workflows/repo_manage.yml' 15 | - 'pkgs/repo_manage/**' 16 | schedule: 17 | - cron: '0 0 * * 0' # weekly 18 | 19 | defaults: 20 | run: 21 | working-directory: pkgs/repo_manage 22 | 23 | jobs: 24 | build: 25 | runs-on: ubuntu-latest 26 | strategy: 27 | fail-fast: false 28 | matrix: 29 | sdk: [stable, dev] 30 | steps: 31 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 32 | - uses: dart-lang/setup-dart@e51d8e571e22473a2ddebf0ef8a2123f0ab2c02c 33 | with: 34 | sdk: ${{ matrix.sdk }} 35 | 36 | - run: dart pub get 37 | 38 | - run: dart analyze --fatal-infos 39 | 40 | - run: dart format --output=none --set-exit-if-changed . 41 | if: ${{ matrix.sdk == 'stable' }} 42 | -------------------------------------------------------------------------------- /.github/workflows/sdk_triage_bot.yml: -------------------------------------------------------------------------------- 1 | name: package:sdk_triage_bot 2 | 3 | permissions: read-all 4 | 5 | on: 6 | pull_request: 7 | branches: [ main ] 8 | paths: 9 | - '.github/workflows/sdk_triage_bot.yml' 10 | - 'pkgs/sdk_triage_bot/**' 11 | push: 12 | branches: [ main ] 13 | paths: 14 | - '.github/workflows/sdk_triage_bot.yml' 15 | - 'pkgs/sdk_triage_bot/**' 16 | schedule: 17 | - cron: '0 0 * * 0' # weekly 18 | 19 | defaults: 20 | run: 21 | working-directory: pkgs/sdk_triage_bot 22 | 23 | jobs: 24 | build: 25 | runs-on: ubuntu-latest 26 | strategy: 27 | fail-fast: false 28 | matrix: 29 | sdk: [stable, dev] 30 | steps: 31 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 32 | - uses: dart-lang/setup-dart@e51d8e571e22473a2ddebf0ef8a2123f0ab2c02c 33 | with: 34 | sdk: ${{ matrix.sdk }} 35 | 36 | - run: dart pub get 37 | 38 | - run: dart analyze --fatal-infos 39 | 40 | - run: dart format --output=none --set-exit-if-changed . 41 | if: ${{ matrix.sdk == 'stable' }} 42 | 43 | - run: dart test 44 | -------------------------------------------------------------------------------- /.github/workflows/trebuchet.yml: -------------------------------------------------------------------------------- 1 | name: package:trebuchet 2 | 3 | permissions: read-all 4 | 5 | on: 6 | pull_request: 7 | branches: [ main ] 8 | paths: 9 | - '.github/workflows/trebuchet.yml' 10 | - 'pkgs/trebuchet/**' 11 | push: 12 | branches: [ main ] 13 | paths: 14 | - '.github/workflows/trebuchet.yml' 15 | - 'pkgs/trebuchet/**' 16 | schedule: 17 | - cron: '0 0 * * 0' # weekly 18 | 19 | defaults: 20 | run: 21 | working-directory: pkgs/trebuchet 22 | 23 | jobs: 24 | build: 25 | runs-on: ubuntu-latest 26 | strategy: 27 | fail-fast: false 28 | matrix: 29 | sdk: [stable, dev] 30 | steps: 31 | - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 32 | - uses: dart-lang/setup-dart@e51d8e571e22473a2ddebf0ef8a2123f0ab2c02c 33 | with: 34 | sdk: ${{ matrix.sdk }} 35 | 36 | - run: dart pub get 37 | 38 | - run: dart analyze --fatal-infos 39 | 40 | - run: dart format --output=none --set-exit-if-changed . 41 | if: ${{ matrix.sdk == 'stable' }} 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Files and directories created by pub. 2 | .dart_tool/ 3 | .packages 4 | 5 | # Conventional directory for build outputs. 6 | build/ 7 | 8 | # Omit committing pubspec.lock for library packages; see 9 | # https://dart.dev/guides/libraries/private-files#pubspeclock. 10 | pubspec.lock 11 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "health", 9 | "program": "${workspaceFolder}/pkgs/firehose/bin/health.dart", 10 | "request": "launch", 11 | "type": "dart", 12 | "env": { 13 | "GITHUB_REPOSITORY": "dart-lang/ecosystem", 14 | "ISSUE_NUMBER": "173", 15 | "GITHUB_SHA": "null", 16 | "GITHUB_STEP_SUMMARY": "/tmp/github_step_summary_mock.md", 17 | }, 18 | "args": [ 19 | "--check", 20 | "breaking" 21 | ], 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Below are suggested reviewers for PRs to packages in this repository. 2 | # 3 | # These are suggestions; it is fine to have your changes reviewed by someone 4 | # else. 5 | 6 | /pkgs/blast_repo/ @kevmoo 7 | /pkgs/canary/ @mosuem 8 | /pkgs/corpus/ @devoncarew 9 | /pkgs/dart_flutter_team_lints/ @devoncarew @natebosch 10 | /pkgs/firehose/ @devoncarew @mosuem 11 | /pkgs/repo_manage/ @devoncarew @mosuem 12 | /pkgs/sdk_triage_bot/ @devoncarew 13 | /pkgs/trebuchet/ @mosuem 14 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement (CLA). You (or your employer) retain the copyright to your 10 | contribution; this simply gives us permission to use and redistribute your 11 | contributions as part of the project. Head over to 12 | to see your current agreements on file or 13 | to sign a new one. 14 | 15 | You generally only need to submit a CLA once, so if you've already submitted one 16 | (even if it was for a different project), you probably don't need to do it 17 | again. 18 | 19 | ## Code Reviews 20 | 21 | All submissions, including submissions by project members, require review. We 22 | use GitHub pull requests for this purpose. Consult 23 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 24 | information on using pull requests. 25 | 26 | ## Coding style 27 | 28 | The Dart source code in this repo follows the: 29 | 30 | * [Dart style guide](https://dart.dev/guides/language/effective-dart/style) 31 | 32 | You should familiarize yourself with those guidelines. 33 | 34 | ## File headers 35 | 36 | All files in the Dart project must start with the following header; if you add a 37 | new file please also add this. The year should be a single number stating the 38 | year the file was created (don't use a range like "2011-2012"). Additionally, if 39 | you edit an existing file, you shouldn't update the year. 40 | 41 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 42 | // for details. All rights reserved. Use of this source code is governed by a 43 | // BSD-style license that can be found in the LICENSE file. 44 | 45 | ## Community Guidelines 46 | 47 | This project follows 48 | [Google's Open Source Community Guidelines](https://opensource.google/conduct/). 49 | 50 | We pledge to maintain an open and welcoming environment. For details, see our 51 | [code of conduct](https://dart.dev/code-of-conduct). 52 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2022, the Dart project authors. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following 11 | disclaimer in the documentation and/or other materials provided 12 | with the distribution. 13 | * Neither the name of Google LLC nor the names of its 14 | contributors may be used to endorse or promote products derived 15 | from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Overview 2 | 3 | This repository is home to general Dart Ecosystem tools and packages. 4 | 5 | ## Packages 6 | 7 | | Package | Description | Version | 8 | | --- | --- | --- | 9 | | [blast_repo](pkgs/blast_repo/) | A tool to bulk validate and fix GitHub repos. | | 10 | | [canary](pkgs/canary/) | Test package upgrades against the ecosystem. | | 11 | | [corpus](pkgs/corpus/) | A tool to calculate the API usage for a package. | | 12 | | [dart_flutter_team_lints](pkgs/dart_flutter_team_lints/) | An analysis rule set used by the Dart and Flutter teams. | [![pub package](https://img.shields.io/pub/v/dart_flutter_team_lints.svg)](https://pub.dev/packages/dart_flutter_team_lints) | 13 | | [firehose](pkgs/firehose/) | A tool to automate publishing of Pub packages from GitHub actions. | [![pub package](https://img.shields.io/pub/v/firehose.svg)](https://pub.dev/packages/firehose) | 14 | | [puppy](pkgs/puppy/) | A grab bag of CLI tools for managing Dart code. | | 15 | | [repo_manage](pkgs/repo_manage/) | Miscellaneous issue, repo, and PR query tools. | | 16 | | [sdk_triage_bot](pkgs/sdk_triage_bot/) | A triage automation tool for dart-lang/sdk issues. | | 17 | | [trebuchet](pkgs/trebuchet/) | A tool for moving existing packages into monorepos. | | 18 | 19 | ## Publishing automation 20 | 21 | For information about our publishing automation and release process, see 22 | https://github.com/dart-lang/ecosystem/wiki/Publishing-automation. 23 | 24 | For additional information about contributing, see our 25 | [contributing](CONTRIBUTING.md) page. 26 | -------------------------------------------------------------------------------- /pkgs/blast_repo/.gitignore: -------------------------------------------------------------------------------- 1 | # https://dart.dev/guides/libraries/private-files 2 | pubspec.lock 3 | -------------------------------------------------------------------------------- /pkgs/blast_repo/AUTHORS: -------------------------------------------------------------------------------- 1 | # Below is a list of people and organizations that have contributed 2 | # to the project. Names should be added to the list like so: 3 | # 4 | # Name/Organization 5 | 6 | Google Inc. 7 | -------------------------------------------------------------------------------- /pkgs/blast_repo/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2022, the Dart project authors. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following 11 | disclaimer in the documentation and/or other materials provided 12 | with the distribution. 13 | * Neither the name of Google LLC nor the names of its 14 | contributors may be used to endorse or promote products derived 15 | from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /pkgs/blast_repo/README.md: -------------------------------------------------------------------------------- 1 | A tool to bulk validate and fix GitHub repos. 2 | 3 | ## blast_repo 4 | 5 | ``` 6 | Usage: blast_repo [org/repo] 7 | 8 | --keep-temp Don't delete the temporary repo clone. 9 | --tweaks= Optionally list the specific tweaks to run (defaults to all applicable tweaks). 10 | [auto-publish, dependabot, github-actions, monorepo, no-response] 11 | --reviewer= Specify the GitHub handle for the desired reviewer. 12 | -h, --help Prints out usage and exits. 13 | 14 | available tweaks: 15 | auto-publish: configure a github action to enable package auto-publishing 16 | dependabot: ensure ".github/dependabot.yml" exists and has the correct content 17 | github-actions: ensure GitHub actions use the latest versions and are keyed by SHA 18 | monorepo: regenerate the latest configuration files for package:mono_repo 19 | no-response: configure a 'no response' bot to handle needs-info labels 20 | ``` 21 | -------------------------------------------------------------------------------- /pkgs/blast_repo/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:dart_flutter_team_lints/analysis_options.yaml 2 | 3 | analyzer: 4 | language: 5 | strict-inference: true 6 | strict-raw-types: true 7 | -------------------------------------------------------------------------------- /pkgs/blast_repo/bin/blast_repo.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:io'; 6 | 7 | import 'package:args/args.dart'; 8 | import 'package:blast_repo/src/top_level.dart'; 9 | import 'package:blast_repo/src/utils.dart'; 10 | import 'package:io/io.dart'; 11 | import 'package:stack_trace/stack_trace.dart'; 12 | 13 | Future main(List args) async { 14 | final parser = ArgParser() 15 | ..addFlag( 16 | 'dry-run', 17 | aliases: ['keep-temp'], 18 | help: "Don't create a PR or delete the temporary repo clone.", 19 | negatable: false, 20 | ) 21 | ..addMultiOption('tweaks', 22 | help: 'Optionally list the specific tweaks to run (defaults to all ' 23 | 'applicable tweaks).', 24 | allowed: allTweaks.map((t) => t.id), 25 | valueHelp: 'tweak1,tweak2') 26 | ..addOption( 27 | 'reviewer', 28 | aliases: ['pr-reviewer'], 29 | valueHelp: 'github-id', 30 | help: 'Specify the GitHub handle for the desired reviewer.', 31 | ) 32 | ..addMultiOption( 33 | 'labels', 34 | help: 'Specify labels to apply to the PR.', 35 | ) 36 | ..addFlag( 37 | 'help', 38 | abbr: 'h', 39 | negatable: false, 40 | help: 'Prints out usage and exits.', 41 | ); 42 | 43 | void printUsage() { 44 | print('Usage: $packageName [org/repo]\n'); 45 | print(parser.usage); 46 | print('\navailable tweaks:'); 47 | for (var tweak in allTweaks) { 48 | print(' ${tweak.id}: ${tweak.description}'); 49 | } 50 | } 51 | 52 | final ArgResults argResults; 53 | try { 54 | argResults = parser.parse(args); 55 | } on FormatException catch (e) { 56 | printError(e.message); 57 | printUsage(); 58 | exitCode = ExitCode.usage.code; 59 | return; 60 | } 61 | 62 | if (argResults.flag('help') || argResults.rest.isEmpty) { 63 | printUsage(); 64 | return; 65 | } 66 | 67 | final slug = argResults.rest.single; 68 | 69 | final dryRun = argResults.flag('dry-run'); 70 | 71 | final reviewer = argResults.option('reviewer'); 72 | final explicitTweakIds = argResults.multiOption('tweaks'); 73 | final explicitTweaks = explicitTweakIds.isEmpty 74 | ? null 75 | : explicitTweakIds 76 | .map((id) => allTweaks.firstWhere((t) => t.id == id)) 77 | .toList(); 78 | 79 | final labels = argResults.multiOption('labels'); 80 | 81 | try { 82 | await runFix( 83 | slug: slug, 84 | deleteTemp: !dryRun, 85 | tweaks: explicitTweaks, 86 | reviewer: reviewer, 87 | labels: labels, 88 | dryRun: dryRun, 89 | ); 90 | } catch (error, stack) { 91 | final chain = Chain.forTrace(stack); 92 | print('Error type: ${error.runtimeType}'); 93 | print(error); 94 | print(chain.terse.toString().trim()); 95 | exitCode = 1; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /pkgs/blast_repo/lib/src/action_version.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:path/path.dart' as p; 6 | 7 | class ActionVersion { 8 | ActionVersion({ 9 | required this.org, 10 | required this.repo, 11 | required this.path, 12 | required this.version, 13 | }); 14 | 15 | factory ActionVersion.parse(String value) { 16 | final atSplit = value.split('@'); 17 | if (atSplit.length != 2) { 18 | throw ArgumentError.value( 19 | value, 20 | 'value', 21 | 'Should have two halves seperated by "@".', 22 | ); 23 | } 24 | 25 | final pathSegments = p.url.split(atSplit[0]); 26 | 27 | if (pathSegments.length < 2) { 28 | throw ArgumentError.value( 29 | value, 30 | 'value', 31 | 'Should have at least two initial path segments.', 32 | ); 33 | } 34 | 35 | final path = 36 | pathSegments.length > 2 ? pathSegments.skip(2).join('/') : null; 37 | 38 | return ActionVersion( 39 | org: pathSegments[0], 40 | repo: pathSegments[1], 41 | path: path, 42 | version: atSplit[1], 43 | ); 44 | } 45 | 46 | final String org; 47 | final String repo; 48 | final String? path; 49 | final String version; 50 | 51 | String get fullRepo => '$org/$repo'; 52 | 53 | @override 54 | String toString() => 55 | '${[org, repo, if (path != null) path].join('/')}@$version'; 56 | 57 | @override 58 | bool operator ==(Object other) => 59 | other is ActionVersion && 60 | org == other.org && 61 | repo == other.repo && 62 | path == other.path && 63 | version == other.version; 64 | 65 | @override 66 | int get hashCode => Object.hash(org, repo, path, version); 67 | } 68 | -------------------------------------------------------------------------------- /pkgs/blast_repo/lib/src/exact_file_tweak.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:async'; 6 | import 'dart:io'; 7 | 8 | import 'package:path/path.dart' as p; 9 | 10 | import 'repo_tweak.dart'; 11 | 12 | abstract class ExactFileTweak extends RepoTweak { 13 | ExactFileTweak({ 14 | required this.filePath, 15 | required super.id, 16 | required super.description, 17 | this.alternateFilePaths = const {}, 18 | }) : assert(p.isRelative(filePath)) { 19 | if (!p.isRelative(filePath)) { 20 | throw ArgumentError.value( 21 | filePath, 22 | 'filePath', 23 | 'Must be a relative path!', 24 | ); 25 | } 26 | 27 | for (var entry in alternateFilePaths) { 28 | if (p.equals(entry, filePath)) { 29 | throw ArgumentError.value( 30 | alternateFilePaths, 31 | 'alternateFilePaths', 32 | 'Should not contain `filePath` ($filePath).', 33 | ); 34 | } 35 | if (!p.isRelative(entry)) { 36 | throw ArgumentError.value( 37 | alternateFilePaths, 38 | 'alternateFilePaths', 39 | 'Must be a relative path ($entry)', 40 | ); 41 | } 42 | } 43 | } 44 | 45 | final String filePath; 46 | final Set alternateFilePaths; 47 | 48 | String expectedContent(Directory checkout, String repoSlug); 49 | 50 | @override 51 | FutureOr fix(Directory checkout, String repoSlug) { 52 | final file = _targetFile(checkout); 53 | 54 | var fixResults = []; 55 | 56 | final newContent = expectedContent(checkout, repoSlug); 57 | if (!file.existsSync()) { 58 | file.writeAsStringSync(newContent); 59 | fixResults.add('$filePath has been created.'); 60 | } else if (file.readAsStringSync() != newContent) { 61 | file.writeAsStringSync(newContent); 62 | fixResults.add('$filePath has been updated.'); 63 | } 64 | 65 | return fixResults.isEmpty 66 | ? FixResult.noFixesMade 67 | : FixResult(fixes: fixResults); 68 | } 69 | 70 | File _targetFile(Directory checkout) { 71 | assert(checkout.existsSync()); 72 | 73 | for (var option in [filePath, ...alternateFilePaths]) { 74 | final realPath = p.join(checkout.path, option); 75 | 76 | final realFile = File(realPath); 77 | if (realFile.existsSync()) { 78 | return realFile; 79 | } 80 | } 81 | 82 | return File(p.join(checkout.path, filePath)); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /pkgs/blast_repo/lib/src/github.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:io'; 6 | 7 | import 'package:github/github.dart'; 8 | 9 | GitHub createGitHubClient() => GitHub( 10 | auth: Authentication.withToken(Platform.environment['GITHUB_TOKEN']), 11 | ); 12 | -------------------------------------------------------------------------------- /pkgs/blast_repo/lib/src/repo_tweak.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:async'; 6 | import 'dart:io'; 7 | 8 | abstract class RepoTweak { 9 | const RepoTweak({ 10 | required this.id, 11 | required this.description, 12 | }); 13 | 14 | final String id; 15 | final String description; 16 | 17 | /// Returns whether this tweak should run for the given repository by default. 18 | /// 19 | /// Some tweaks may only run by default in the presence of a file in the repo, 20 | /// or only if the repo is a mono repo. 21 | bool shouldRunByDefault(Directory checkout, String repoSlug); 22 | 23 | /// Checks to see if the [checkout] needs to be fixed. 24 | /// 25 | /// If no fix is needed, nothing happens and `false` is returned. 26 | /// 27 | /// If a fix is needed, the fix is run and `true` is returned. 28 | /// 29 | /// If the repo cannot be checked or if a required fix cannot be applied, 30 | /// an error is thrown. 31 | FutureOr fix(Directory checkout, String repoSlug); 32 | 33 | @override 34 | String toString() => id; 35 | } 36 | 37 | class CheckResult { 38 | static const noFixNeeded = CheckResult._(); 39 | 40 | const CheckResult._() : neededFixes = const []; 41 | 42 | CheckResult({required this.neededFixes}) { 43 | neededFixes.forEach(_validateItem); 44 | } 45 | 46 | final List neededFixes; 47 | 48 | bool get fixNeeded => neededFixes.isNotEmpty; 49 | } 50 | 51 | class FixResult { 52 | static const noFixesMade = FixResult._(); 53 | 54 | const FixResult._() : fixes = const []; 55 | 56 | FixResult({required this.fixes}) { 57 | fixes.forEach(_validateItem); 58 | } 59 | 60 | final List fixes; 61 | } 62 | 63 | void _validateItem(Object item) { 64 | if (item is String) { 65 | if (item.trim().isEmpty) { 66 | throw ArgumentError('Bad item! Cannot be trimmed empty!'); 67 | } 68 | return; 69 | } 70 | 71 | if (item is Map) { 72 | if (item.length != 1) { 73 | throw ArgumentError('Item must be a single item map'); 74 | } 75 | final entry = item.entries.single; 76 | if (entry.key is! String) { 77 | throw ArgumentError('Map key must be a String'); 78 | } 79 | final value = entry.value; 80 | if (value is List) { 81 | value.cast().forEach(_validateItem); 82 | return; 83 | } 84 | throw ArgumentError( 85 | 'Map value must be a List it was ${value.runtimeType}.', 86 | ); 87 | } 88 | 89 | throw ArgumentError('We do not support ${item.runtimeType}'); 90 | } 91 | -------------------------------------------------------------------------------- /pkgs/blast_repo/lib/src/tweaks/auto_publish_tweak.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:io'; 6 | 7 | import '../exact_file_tweak.dart'; 8 | import '../utils.dart'; 9 | 10 | final _instance = AutoPublishTweak._(); 11 | 12 | class AutoPublishTweak extends ExactFileTweak { 13 | factory AutoPublishTweak() => _instance; 14 | 15 | AutoPublishTweak._() 16 | : super( 17 | id: 'auto-publish', 18 | description: 19 | 'configure a github action to enable package auto-publishing', 20 | filePath: '.github/workflows/publish.yaml', 21 | ); 22 | 23 | @override 24 | bool shouldRunByDefault(Directory checkout, String repoSlug) => 25 | monoRepo(checkout, repoSlug); 26 | 27 | @override 28 | String expectedContent(Directory checkout, String repoSlug) { 29 | final org = repoSlug.split('/').first; 30 | final branch = gitDefaultBranch(checkout) ?? 'main'; 31 | final glob = singlePackageRepo(checkout) 32 | ? "'v[0-9]+.[0-9]+.[0-9]+'" 33 | : "'[A-z]+-v[0-9]+.[0-9]+.[0-9]+'"; 34 | 35 | // Substitute for the github org, default branch, and glob pattern values. 36 | return publishContents 37 | .replaceAll('{org}', org) 38 | .replaceAll('{branch}', branch) 39 | .replaceAll('{glob}', glob); 40 | } 41 | } 42 | 43 | const publishContents = r''' 44 | # A CI configuration to auto-publish pub packages. 45 | 46 | name: Publish 47 | 48 | on: 49 | pull_request: 50 | branches: [ {branch} ] 51 | push: 52 | tags: [ {glob} ] 53 | 54 | jobs: 55 | publish: 56 | if: ${{ github.repository_owner == '{org}' }} 57 | uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main 58 | permissions: 59 | id-token: write # Required for authentication using OIDC 60 | pull-requests: write # Required for writing the pull request note 61 | '''; 62 | -------------------------------------------------------------------------------- /pkgs/blast_repo/lib/src/tweaks/drop_lint_tweak.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:async'; 6 | import 'dart:io'; 7 | 8 | import 'package:collection/collection.dart'; 9 | import 'package:path/path.dart' as p; 10 | import 'package:yaml/yaml.dart'; 11 | import 'package:yaml_edit/yaml_edit.dart'; 12 | 13 | import '../repo_tweak.dart'; 14 | 15 | final _instance = DropLintTweak._(); 16 | 17 | class DropLintTweak extends RepoTweak { 18 | factory DropLintTweak() => _instance; 19 | 20 | DropLintTweak._() 21 | : super( 22 | id: 'drop-lint', 23 | description: 'Drop deprecated lints from analysis_options.yaml', 24 | ); 25 | 26 | @override 27 | bool shouldRunByDefault(Directory checkout, String repoSlug) => true; 28 | 29 | @override 30 | FutureOr fix(Directory checkout, String repoSlug) async { 31 | final analysisOptionsFile = 32 | File(p.join(checkout.path, 'analysis_options.yaml')); 33 | 34 | if (!analysisOptionsFile.existsSync()) { 35 | return FixResult.noFixesMade; 36 | } 37 | 38 | final yamlSource = loadYaml( 39 | analysisOptionsFile.readAsStringSync(), 40 | sourceUrl: analysisOptionsFile.uri, 41 | ); 42 | 43 | if (yamlSource is YamlMap) { 44 | final linterNode = yamlSource['linter']; 45 | if (linterNode is YamlMap) { 46 | final rules = linterNode['rules']; 47 | 48 | if (rules is YamlList) { 49 | final fixes = {}; 50 | final badIndexes = rules 51 | .mapIndexed((index, value) { 52 | if (_deprecatedLints.contains(value)) { 53 | fixes.add('Removed "$value".'); 54 | return index; 55 | } 56 | return -1; 57 | }) 58 | .where((e) => e >= 0) 59 | .toList(); 60 | 61 | final editor = YamlEditor(analysisOptionsFile.readAsStringSync()); 62 | for (var index in badIndexes.reversed) { 63 | editor.remove(['linter', 'rules', index]); 64 | } 65 | 66 | analysisOptionsFile.writeAsStringSync(editor.toString(), 67 | mode: FileMode.writeOnly); 68 | 69 | return FixResult(fixes: fixes.toList()..sort()); 70 | } 71 | 72 | if (rules == null) { 73 | return FixResult(fixes: []); 74 | } 75 | 76 | throw UnimplementedError('not sure what to do with $rules'); 77 | } 78 | } 79 | 80 | return FixResult(fixes: []); 81 | } 82 | } 83 | 84 | final _deprecatedLints = { 85 | 'avoid_null_checks_in_equality_operators', 86 | 'package_api_docs', 87 | 'unsafe_html', 88 | }; 89 | -------------------------------------------------------------------------------- /pkgs/blast_repo/lib/src/tweaks/mono_repo_tweak.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:async'; 6 | import 'dart:io'; 7 | 8 | import 'package:path/path.dart' as p; 9 | 10 | import '../repo_tweak.dart'; 11 | import '../utils.dart'; 12 | 13 | final _instance = MonoRepoTweak._(); 14 | 15 | /// Regenerate the latest configuration files for package:mono_repo. 16 | class MonoRepoTweak extends RepoTweak { 17 | factory MonoRepoTweak() => _instance; 18 | 19 | MonoRepoTweak._() 20 | : super( 21 | id: 'monorepo', 22 | description: 23 | 'regenerate the latest configuration files for package:mono_repo', 24 | ); 25 | 26 | @override 27 | bool shouldRunByDefault(Directory checkout, String repoSlug) { 28 | return File(p.join(checkout.path, 'mono_repo.yaml')).existsSync(); 29 | } 30 | 31 | @override 32 | FutureOr fix(Directory checkout, String repoSlug) async { 33 | // get the latest mono_repo 34 | await runProc( 35 | 'activating mono_repo', 36 | Platform.resolvedExecutable, 37 | ['pub', 'global', 'activate', 'mono_repo'], 38 | workingDirectory: checkout.path, 39 | ); 40 | 41 | // record the current values for the files 42 | final files = { 43 | '.github/workflows/dart.yml', 44 | 'tool/ci.sh', 45 | }; 46 | final existingContent = { 47 | for (var path in files) 48 | path: File(p.join(checkout.path, path)).existsSync() 49 | ? File(p.join(checkout.path, path)).readAsStringSync() 50 | : '', 51 | }; 52 | 53 | // run mono_repo generate 54 | await runProc( 55 | 'run mono_repo generate', 56 | Platform.resolvedExecutable, 57 | ['pub', 'global', 'run', 'mono_repo', 'generate'], 58 | workingDirectory: checkout.path, 59 | ); 60 | 61 | // return the results 62 | final fixes = []; 63 | 64 | for (var entry in existingContent.entries) { 65 | final file = File(p.join(checkout.path, entry.key)); 66 | if (file.readAsStringSync() != entry.value) { 67 | fixes.add('updated ${entry.key}'); 68 | } 69 | } 70 | 71 | return fixes.isEmpty ? FixResult.noFixesMade : FixResult(fixes: fixes); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /pkgs/blast_repo/lib/src/tweaks/no_reponse_tweak.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:io'; 6 | 7 | import '../exact_file_tweak.dart'; 8 | import '../utils.dart'; 9 | 10 | final _instance = NoResponseTweak._(); 11 | 12 | class NoResponseTweak extends ExactFileTweak { 13 | factory NoResponseTweak() => _instance; 14 | 15 | NoResponseTweak._() 16 | : super( 17 | id: 'no-response', 18 | description: 19 | "configure a 'no response' bot to handle needs-info labels", 20 | filePath: filePath, 21 | ); 22 | 23 | @override 24 | bool shouldRunByDefault(Directory checkout, String repoSlug) => 25 | monoRepo(checkout, repoSlug); 26 | 27 | @override 28 | String expectedContent(Directory checkout, String repoSlug) { 29 | final org = repoSlug.split('/').first; 30 | 31 | // Substitute for the github org value. 32 | return noResponseContent.replaceAll('{org}', org); 33 | } 34 | } 35 | 36 | const filePath = '.github/workflows/no-response.yml'; 37 | 38 | const noResponseContent = r''' 39 | # A workflow to close issues where the author hasn't responded to a request for 40 | # more information; see https://github.com/actions/stale. 41 | 42 | name: No Response 43 | 44 | # Run as a daily cron. 45 | on: 46 | schedule: 47 | # Every day at 8am 48 | - cron: '0 8 * * *' 49 | 50 | # All permissions not specified are set to 'none'. 51 | permissions: 52 | issues: write 53 | pull-requests: write 54 | 55 | jobs: 56 | no-response: 57 | runs-on: ubuntu-latest 58 | if: ${{ github.repository_owner == '{org}' }} 59 | steps: 60 | - uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 61 | with: 62 | # Don't automatically mark inactive issues+PRs as stale. 63 | days-before-stale: -1 64 | # Close needs-info issues and PRs after 14 days of inactivity. 65 | days-before-close: 14 66 | stale-issue-label: "needs-info" 67 | close-issue-message: > 68 | Without additional information we're not able to resolve this issue. 69 | Feel free to add more info or respond to any questions above and we 70 | can reopen the case. Thanks for your contribution! 71 | stale-pr-label: "needs-info" 72 | close-pr-message: > 73 | Without additional information we're not able to resolve this PR. 74 | Feel free to add more info or respond to any questions above. 75 | Thanks for your contribution! 76 | '''; 77 | -------------------------------------------------------------------------------- /pkgs/blast_repo/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: blast_repo 2 | description: A tool to bulk validate and fix GitHub repos. 3 | 4 | publish_to: none 5 | 6 | environment: 7 | sdk: ^3.1.0 8 | 9 | dependencies: 10 | args: ^2.4.0 11 | collection: ^1.17.0 12 | git: ^2.2.0 13 | github: ^9.6.0 14 | io: ^1.0.0 15 | meta: ^1.8.0 16 | path: ^1.8.2 17 | pub_semver: ^2.1.2 18 | stack_trace: ^1.11.0 19 | yaml: ^3.1.0 20 | yaml_edit: ^2.1.0 21 | 22 | dev_dependencies: 23 | dart_flutter_team_lints: ^3.0.0 24 | test: ^1.22.0 25 | test_descriptor: ^2.0.0 26 | 27 | executables: 28 | blast_repo: 29 | -------------------------------------------------------------------------------- /pkgs/blast_repo/pubspec_overrides.yaml: -------------------------------------------------------------------------------- 1 | dependency_overrides: 2 | dart_flutter_team_lints: 3 | path: ../dart_flutter_team_lints 4 | -------------------------------------------------------------------------------- /pkgs/blast_repo/test/auto_publish_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:io' as io; 6 | 7 | import 'package:blast_repo/src/tweaks/auto_publish_tweak.dart'; 8 | import 'package:test/test.dart'; 9 | import 'package:test_descriptor/test_descriptor.dart' as d; 10 | 11 | void main() { 12 | late AutoPublishTweak tweak; 13 | late io.Directory dir; 14 | 15 | setUp(() async { 16 | tweak = AutoPublishTweak(); 17 | await d.dir('foo', [ 18 | d.file('README.md', '# package name\n\n'), 19 | d.dir('.github', [ 20 | d.dir('workflows', [ 21 | d.file('build.yaml', '# hello world'), 22 | ]), 23 | ]) 24 | ]).create(); 25 | dir = d.dir('foo').io; 26 | }); 27 | 28 | test('customized to github org', () async { 29 | var results = await tweak.fix(dir, 'my_org/my_repo'); 30 | expect(results.fixes, isNotEmpty); 31 | 32 | await d.dir('foo', [ 33 | d.dir('.github', [ 34 | d.dir('workflows', [ 35 | d.file('publish.yaml', contains('my_org')), 36 | ]), 37 | ]) 38 | ]).validate(); 39 | }); 40 | 41 | test('detects mono-repo', () async { 42 | var results = await tweak.fix(dir, 'my_org/my_repo'); 43 | expect(results.fixes, isNotEmpty); 44 | 45 | await d.dir('foo', [ 46 | d.dir('.github', [ 47 | d.dir('workflows', [ 48 | d.file('publish.yaml', contains('[A-z]+-v')), 49 | ]), 50 | ]) 51 | ]).validate(); 52 | }); 53 | } 54 | -------------------------------------------------------------------------------- /pkgs/blast_repo/test/dependabot_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:blast_repo/src/tweaks/dependabot_tweak.dart'; 6 | import 'package:test/test.dart'; 7 | 8 | void main() { 9 | group('bad cases', () { 10 | const values = { 11 | 'not a map': '"bob"', 12 | 'no version': 'no_version: bob', 13 | 'just a version': 'version: 2', 14 | 'updates null': ''' 15 | version: 2 16 | updates: 17 | ''', 18 | 'updates not a list': ''' 19 | version: 2 20 | updates: "bob" 21 | ''', 22 | }; 23 | 24 | for (var entry in values.entries) { 25 | test(entry.key, () { 26 | expect(() => doDependabotFix(entry.value), throwsException); 27 | }); 28 | } 29 | }); 30 | 31 | test('updates missing package-ecosystem', () { 32 | final result = doDependabotFix(r''' 33 | #some comment 34 | version: 2 35 | 36 | updates: 37 | - package-ecosystem: "pub" 38 | directory: "/" 39 | schedule: 40 | interval: "monthly" 41 | '''); 42 | 43 | expect(result, r''' 44 | #some comment 45 | version: 2 46 | 47 | updates: 48 | - package-ecosystem: "pub" 49 | directory: "/" 50 | schedule: 51 | interval: "monthly" 52 | - package-ecosystem: github-actions 53 | directory: / 54 | schedule: 55 | interval: monthly 56 | labels: 57 | - autosubmit 58 | groups: 59 | github-actions: 60 | patterns: 61 | - "*" 62 | '''); 63 | }); 64 | 65 | group('allow more frequent updates', () { 66 | for (var frequency in dependabotAllowedFrequencies) { 67 | test(frequency, () { 68 | final input = ''' 69 | # Random header is cool! 70 | version: 2 71 | 72 | # Random comment is cool 73 | 74 | updates: 75 | - package-ecosystem: "github-actions" 76 | directory: "/" 77 | schedule: 78 | interval: "$frequency" 79 | labels: 80 | - autosubmit 81 | groups: 82 | github-actions: 83 | patterns: 84 | - "*" 85 | '''; 86 | final result = doDependabotFix(input); 87 | 88 | expect(result, input); 89 | }); 90 | } 91 | }); 92 | 93 | test('dependabotDefaultContent', () { 94 | expect(dependabotDefaultContent, _expectedDependabotContent); 95 | }); 96 | 97 | test('default content should be a no-op', () { 98 | final result = doDependabotFix(dependabotDefaultContent); 99 | expect(result, dependabotDefaultContent); 100 | }); 101 | } 102 | 103 | const _expectedDependabotContent = ''' 104 | # Dependabot configuration file. 105 | # See https://docs.github.com/en/code-security/dependabot/dependabot-version-updates 106 | 107 | version: 2 108 | updates: 109 | - package-ecosystem: github-actions 110 | directory: / 111 | schedule: 112 | interval: monthly 113 | labels: 114 | - autosubmit 115 | groups: 116 | github-actions: 117 | patterns: 118 | - "*" 119 | '''; 120 | -------------------------------------------------------------------------------- /pkgs/blast_repo/test/mono_repo_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:io' as io; 6 | 7 | import 'package:blast_repo/src/tweaks/mono_repo_tweak.dart'; 8 | import 'package:test/test.dart'; 9 | import 'package:test_descriptor/test_descriptor.dart' as d; 10 | 11 | void main() { 12 | late MonoRepoTweak tweak; 13 | late io.Directory dir; 14 | 15 | setUp(() async { 16 | tweak = MonoRepoTweak(); 17 | await d.dir('foo', [ 18 | d.file('mono_repo.yaml', '# foo bar\n'), 19 | ]).create(); 20 | dir = d.dir('foo').io; 21 | }); 22 | 23 | test('recognizes mono_repo repo', () async { 24 | expect(tweak.shouldRunByDefault(dir, 'my_org/my_repo'), true); 25 | }); 26 | 27 | test('ignores non-managed repo', () async { 28 | await d.dir('foo', [ 29 | d.file('README.md', '# package name\n\n'), 30 | ]).create(); 31 | dir = d.dir('foo').io; 32 | 33 | expect(tweak.shouldRunByDefault(dir, 'my_org/my_repo'), true); 34 | }); 35 | } 36 | -------------------------------------------------------------------------------- /pkgs/blast_repo/test/no_response_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:io' as io; 6 | 7 | import 'package:blast_repo/src/tweaks/no_reponse_tweak.dart'; 8 | import 'package:test/test.dart'; 9 | import 'package:test_descriptor/test_descriptor.dart' as d; 10 | 11 | void main() { 12 | late NoResponseTweak tweak; 13 | late io.Directory dir; 14 | 15 | setUp(() async { 16 | tweak = NoResponseTweak(); 17 | await d.dir('foo', [ 18 | d.file('README.md', '# package name\n\n'), 19 | d.dir('.github', [ 20 | d.dir('workflows', [ 21 | d.file('build.yaml', '# hello world'), 22 | ]), 23 | ]) 24 | ]).create(); 25 | dir = d.dir('foo').io; 26 | }); 27 | 28 | test('creates file', () async { 29 | var results = await tweak.fix(dir, 'my_org/my_repo'); 30 | expect(results.fixes, isNotEmpty); 31 | 32 | await d.dir('foo', [ 33 | d.dir('.github', [ 34 | d.dir('workflows', [ 35 | d.file('no-response.yml', contains('my_org')), 36 | d.file('no-response.yml', contains('actions/stale')), 37 | d.file('no-response.yml', contains('"needs-info"')), 38 | ]), 39 | ]) 40 | ]).validate(); 41 | }); 42 | } 43 | -------------------------------------------------------------------------------- /pkgs/blast_repo/test/utils_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:io' as io; 6 | 7 | import 'package:blast_repo/src/utils.dart'; 8 | import 'package:pub_semver/pub_semver.dart'; 9 | import 'package:test/test.dart'; 10 | 11 | void main() { 12 | // We skip this test on github actions as that typically does a shallow clone. 13 | test('gitDefaultBranch', () { 14 | final result = gitDefaultBranch(io.Directory.current.parent.parent); 15 | 16 | expect(result, 'main'); 17 | }, skip: io.Platform.environment['GITHUB_ACTIONS'] == 'true'); 18 | 19 | test('latestStableVersion', () { 20 | expect(latestStableVersion([]), isNull); 21 | 22 | expect( 23 | latestStableVersion([Version.parse('1.0.0')]), 24 | Version.parse('1.0.0'), 25 | ); 26 | 27 | expect( 28 | latestStableVersion([Version.parse('1.0.0'), Version.parse('2.0.0')]), 29 | Version.parse('2.0.0'), 30 | ); 31 | 32 | expect( 33 | latestStableVersion([Version.parse('2.0.0'), Version.parse('1.0.0')]), 34 | Version.parse('2.0.0'), 35 | ); 36 | 37 | expect( 38 | latestStableVersion([ 39 | Version.parse('1.0.0'), 40 | Version.parse('2.0.0'), 41 | Version.parse('3.0.0-dev'), 42 | ]), 43 | Version.parse('2.0.0'), 44 | ); 45 | }); 46 | } 47 | -------------------------------------------------------------------------------- /pkgs/canary/.gitignore: -------------------------------------------------------------------------------- 1 | # https://dart.dev/guides/libraries/private-files 2 | # Created by `dart pub` 3 | .dart_tool/ 4 | -------------------------------------------------------------------------------- /pkgs/canary/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2024, the Dart project authors. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following 11 | disclaimer in the documentation and/or other materials provided 12 | with the distribution. 13 | * Neither the name of Google LLC nor the names of its 14 | contributors may be used to endorse or promote products derived 15 | from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /pkgs/canary/README.md: -------------------------------------------------------------------------------- 1 | # Canary: Ecosystem Testing for Dart Packages 2 | Before publishing, send a canary out to test a package against a suite of applications. This helps identify potential breaking changes introduced by package updates, ensuring seamless integration across the ecosystem. 3 | 4 | ## What does it do? 5 | It checks if your package upgrade would result in failures in the ecosystem. This is achieved by running the following pseudocode: 6 | ```dart 7 | for (final app in applicationSuite) { 8 | if (app.dependencies.contains(package)) { 9 | pubGet(app); 10 | analyze(app); 11 | test(app); 12 | 13 | upgradePackage(app); 14 | 15 | pubGet(app); 16 | analyze(app); 17 | test(app); 18 | } 19 | } 20 | ``` 21 | 22 | ## How do I use it? 23 | 1. Create a suite of repositories to test against at `.github/test_repos/repos.json`. Follow the schema specified [here](schema.json). 24 | ```json 25 | { 26 | "https://github.com/mosuem/my_app_old_web": { 27 | "level": "analyze" 28 | }, 29 | "https://github.com/mosuem/my_app_new_web": { 30 | "level": "test", 31 | "packages": { 32 | "exclude": "intl4x" 33 | } 34 | } 35 | } 36 | ``` 37 | 38 | 2. Add a workflow file `canary.yaml` with the following contents: 39 | ```yaml 40 | name: Canary 41 | 42 | on: 43 | pull_request: 44 | branches: [ main ] 45 | types: [opened, synchronize, reopened, labeled, unlabeled] 46 | 47 | jobs: 48 | test_ecosystem: 49 | uses: dart-lang/ecosystem/.github/workflows/canary.yaml@main 50 | with: 51 | repos_file: .github/test_repos/repos.json 52 | ``` 53 | 54 | 3. To show the markdown result as a comment, also add a workflow file `post_summaries.yaml` 55 | ```yaml 56 | name: Comment on the pull request 57 | 58 | on: 59 | # Trigger this workflow after the Health workflow completes. This workflow will have permissions to 60 | # do things like create comments on the PR, even if the original workflow couldn't. 61 | workflow_run: 62 | workflows: 63 | - Canary 64 | types: 65 | - completed 66 | 67 | jobs: 68 | upload: 69 | uses: dart-lang/ecosystem/.github/workflows/post_summaries.yaml@main 70 | permissions: 71 | pull-requests: write 72 | ``` 73 | 74 | 4. Profit! 75 | 76 | # Contributing 77 | Contributions are welcome! Please see the [contribution guidelines](../../CONTRIBUTING.md). 78 | -------------------------------------------------------------------------------- /pkgs/canary/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:dart_flutter_team_lints/analysis_options.yaml 2 | 3 | linter: 4 | rules: 5 | - prefer_final_locals 6 | -------------------------------------------------------------------------------- /pkgs/canary/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: canary 2 | description: Test package upgrades against the ecosystem. 3 | repository: https://github.com/dart-lang/ecosystem/tree/main/pkgs/canary 4 | 5 | publish_to: none 6 | 7 | environment: 8 | sdk: ^3.5.0 9 | 10 | dependencies: 11 | collection: ^1.19.1 12 | firehose: ^0.9.3 13 | io: ^1.0.4 14 | path: ^1.9.1 15 | 16 | dev_dependencies: 17 | dart_flutter_team_lints: ^3.0.0 18 | test: ^1.24.0 19 | -------------------------------------------------------------------------------- /pkgs/canary/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "http://json-schema.org/draft-07/schema#", 3 | "title": "Repository Configuration", 4 | "description": "Schema for repositories for ecosystem testing", 5 | "type": "object", 6 | "patternProperties": { 7 | "^https:\\/\\/github\\.com\\/[^\\/]+\\/[^\\/]+$": { 8 | "type": "object", 9 | "properties": { 10 | "level": { 11 | "type": "string", 12 | "description": "Level of testing depth.", 13 | "enum": [ 14 | "solve", 15 | "analyze", 16 | "test" 17 | ] 18 | }, 19 | "packages": { 20 | "type": "object", 21 | "description": "Packages which are tested using this repository", 22 | "properties": { 23 | "exclude": { 24 | "type": "string", 25 | "description": "Packages to exclude from the analysis" 26 | } 27 | } 28 | } 29 | }, 30 | "required": [ 31 | "level" 32 | ] 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /pkgs/canary/test/canary_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:convert'; 6 | import 'dart:io'; 7 | 8 | import 'package:path/path.dart' as p; 9 | import 'package:test/test.dart'; 10 | 11 | import '../bin/canary.dart'; 12 | 13 | void main() { 14 | test('test name', () async { 15 | final temp = await Directory.systemTemp.createTemp(); 16 | final repoFile = await File(p.join(temp.path, 'repos.json')).create(); 17 | await repoFile.writeAsString( 18 | jsonEncode({ 19 | 'https://github.com/mosuem/my_app_old_web': {'level': 'analyze'}, 20 | 'https://github.com/mosuem/my_app_new_web': {'level': 'test'}, 21 | }), 22 | ); 23 | 24 | final mineAirQuality = await Canary( 25 | 'intl', 26 | 'intl:{"git":{"url":"https://github.com/mosuem/i18n","ref":"pr","path":"pkgs/intl"}}', 27 | repoFile.path, 28 | ).intoTheMine(); 29 | 30 | final comment = createComment(mineAirQuality); 31 | expect(comment, startsWith(goldenComment)); 32 | await temp.delete(recursive: true); 33 | }, timeout: const Timeout(Duration(minutes: 5))); 34 | } 35 | 36 | final goldenComment = ''' 37 | ## Ecosystem testing 38 | 39 | | Package | Solve | Analyze | Test | 40 | | ------- | ----- | ------- | ---- | 41 | | my_app_old_web | $checkEmoji/$crossEmoji | $checkEmoji/$checkEmoji | -/- | 42 | | my_app_new_web | $checkEmoji/$checkEmoji | $checkEmoji/$checkEmoji | $checkEmoji/$checkEmoji | 43 | '''; 44 | -------------------------------------------------------------------------------- /pkgs/corpus/.gitignore: -------------------------------------------------------------------------------- 1 | cache/ 2 | reports/ 3 | -------------------------------------------------------------------------------- /pkgs/corpus/AUTHORS: -------------------------------------------------------------------------------- 1 | # Below is a list of people and organizations that have contributed 2 | # to the project. Names should be added to the list like so: 3 | # 4 | # Name/Organization 5 | 6 | Google Inc. 7 | -------------------------------------------------------------------------------- /pkgs/corpus/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2022, the Dart project authors. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following 11 | disclaimer in the documentation and/or other materials provided 12 | with the distribution. 13 | * Neither the name of Google LLC nor the names of its 14 | contributors may be used to endorse or promote products derived 15 | from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /pkgs/corpus/README.md: -------------------------------------------------------------------------------- 1 | Welcome! There are two tools in this repo - a `deps` tool and a `usage` tool. To 2 | use them, clone this repo, cd to `pkgs/corpus`, and run one of the two tools 3 | below. 4 | 5 | ## bin/deps.dart 6 | 7 | This is a tool to calculate information about which packages depend on a target 8 | package. 9 | 10 | It queries pub.dev for the packages that use `` and generates a 11 | `.csv` file with the dependent information. This is useful for things like 12 | understanding which packages might be impacted by version changes to the target 13 | package. For an example of the dependency report, see 14 | [matcher.csv](doc/matcher.csv). 15 | 16 | ### Usage 17 | 18 | ``` 19 | usage: dart bin/deps.dart [options] 20 | 21 | options: 22 | -h, --help Print this usage information. 23 | --package-limit= Limit the number of packages to return data for. 24 | --include-old Include packages that haven't been published in the last year. 25 | --include-dev-deps Include usages from dev dependencies. 26 | ``` 27 | 28 | ## bin/usage.dart 29 | 30 | This is a tool to calculate the API usage for a package - what parts of a 31 | package's API are typically used by other Dart packages and applications. 32 | 33 | It queries pub.dev for the packages that use ``, downloads the 34 | referencing packages, analyzes them, and determines which portions of the target 35 | package's API are used. For an example usage report, see 36 | [collection.md](doc/collection.md). 37 | 38 | ### Usage 39 | 40 | ``` 41 | usage: dart bin/usage.dart [options] 42 | 43 | options: 44 | -h, --help Print this usage information. 45 | --package-limit= Limit the number of packages usage data is collected from. 46 | (defaults to "100") 47 | --show-src-references Report specific references to src/ libraries. 48 | ``` 49 | -------------------------------------------------------------------------------- /pkgs/corpus/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:dart_flutter_team_lints/analysis_options.yaml 2 | 3 | analyzer: 4 | exclude: 5 | - cache/** 6 | -------------------------------------------------------------------------------- /pkgs/corpus/bin/usage.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:io'; 6 | 7 | import 'package:args/args.dart'; 8 | import 'package:corpus/usage.dart'; 9 | 10 | void main(List args) async { 11 | var argParser = _createArgParser(); 12 | 13 | ArgResults argResults; 14 | try { 15 | argResults = argParser.parse(args); 16 | } on FormatException catch (e) { 17 | print(e.message); 18 | print(''); 19 | _printUsage(argParser); 20 | exit(64); 21 | } 22 | 23 | if (argResults.rest.length != 1 || argResults['help'] as bool) { 24 | _printUsage(argParser); 25 | exit(1); 26 | } 27 | 28 | final packageName = argResults.rest.first; 29 | final packageLimit = int.parse(argResults['package-limit'] as String); 30 | var showSrcReferences = argResults['show-src-references'] as bool; 31 | 32 | await analyzeUsage( 33 | packageName: packageName, 34 | packageLimit: packageLimit, 35 | showSrcReferences: showSrcReferences, 36 | ); 37 | } 38 | 39 | ArgParser _createArgParser() { 40 | var parser = ArgParser(); 41 | parser.addFlag( 42 | 'help', 43 | abbr: 'h', 44 | negatable: false, 45 | help: 'Print this usage information.', 46 | ); 47 | parser.addOption( 48 | 'package-limit', 49 | defaultsTo: '100', 50 | aliases: ['limit'], 51 | help: 'Limit the number of packages usage data is collected from.', 52 | valueHelp: 'count', 53 | ); 54 | parser.addFlag( 55 | 'show-src-references', 56 | negatable: false, 57 | help: 'Report specific references to src/ libraries.', 58 | ); 59 | return parser; 60 | } 61 | 62 | void _printUsage(ArgParser argParser) { 63 | print('usage: dart bin/usage.dart [options] '); 64 | print(''); 65 | print('options:'); 66 | print(argParser.usage); 67 | } 68 | -------------------------------------------------------------------------------- /pkgs/corpus/doc/dart_collection.md: -------------------------------------------------------------------------------- 1 | # Report for dart:collection 2 | 3 | ## General info 4 | 5 | https://api.dart.dev/dart-collection/dart-collection-library.html 6 | 7 | Stats for dart:collection v2.19.0 pulled from 10 packages. 8 | 9 | ## Library references 10 | 11 | ### Library references from packages 12 | 13 | | Library | Package references | % | 14 | | --- | ---: | ---: | 15 | | dart:collection | 10 | 100% | 16 | 17 | ### Library references from libraries 18 | 19 | | Library | Library references | % | 20 | | --- | ---: | ---: | 21 | | dart:collection | 24 | 75% | 22 | 23 | ## Class references 24 | 25 | ### Class references from packages 26 | 27 | | Class | Package references | % | 28 | | --- | ---: | ---: | 29 | | UnmodifiableMapView | 3 | 30% | 30 | | LinkedHashMap | 3 | 30% | 31 | | ListMixin | 2 | 20% | 32 | | HashMap | 2 | 20% | 33 | | MapView | 2 | 20% | 34 | | LinkedHashSet | 2 | 20% | 35 | | MapBase | 2 | 20% | 36 | | ListBase | 2 | 20% | 37 | | MapMixin | 1 | 10% | 38 | | SetMixin | 1 | 10% | 39 | | HashSet | 1 | 10% | 40 | | IterableBase | 1 | 10% | 41 | | Queue | 1 | 10% | 42 | | SetBase | 1 | 10% | 43 | | LinkedList | 1 | 10% | 44 | | LinkedListEntry | 1 | 10% | 45 | | SplayTreeMap | 1 | 10% | 46 | 47 | ### Class references from libraries 48 | 49 | | Class | Library references | % | 50 | | --- | ---: | ---: | 51 | | MapBase | 5 | 16% | 52 | | MapMixin | 4 | 13% | 53 | | UnmodifiableMapView | 4 | 13% | 54 | | ListMixin | 3 | 9% | 55 | | HashMap | 3 | 9% | 56 | | MapView | 3 | 9% | 57 | | LinkedHashMap | 3 | 9% | 58 | | LinkedHashSet | 3 | 9% | 59 | | ListBase | 3 | 9% | 60 | | SetMixin | 1 | 3% | 61 | | HashSet | 1 | 3% | 62 | | IterableBase | 1 | 3% | 63 | | Queue | 1 | 3% | 64 | | SetBase | 1 | 3% | 65 | | LinkedList | 1 | 3% | 66 | | LinkedListEntry | 1 | 3% | 67 | | SplayTreeMap | 1 | 3% | 68 | 69 | ## Corpus packages 70 | 71 | - get v4.6.5 72 | - path v1.8.2 73 | - table_calendar v3.0.8 74 | - pdf v3.8.4 75 | - freezed v2.2.1 76 | - flutter_hooks v0.18.5+1 77 | - logging v1.1.0 78 | - shelf v1.4.0 79 | - awesome_notifications v0.7.4+1 80 | - googleapis v9.2.0 81 | -------------------------------------------------------------------------------- /pkgs/corpus/doc/matcher.csv: -------------------------------------------------------------------------------- 1 | matcher 0.12.14 2 | 3 | Package,Version,Publish Days,Score,Popularity,Likes,Constraint,Dep Type,SDK,Repo 4 | mockito,5.3.2,140,93,99,930,^0.12.10,regular,>=2.17.0-0 <3.0.0,https://github.com/dart-lang/mockito 5 | mocktail,0.3.0,344,100,98,698,^0.12.10,regular,>=2.12.0 <3.0.0,https://github.com/felangel/mocktail 6 | quiver,3.2.1,50,93,99,434,^0.12.10,regular,>=2.17.0 <3.0.0,https://github.com/google/quiver-dart 7 | dcli,2.0.1,5,93,91,166,^0.12.14,regular,>=2.19.0 <3.0.0,https://github.com/onepub-dev/dcli 8 | code_builder,4.4.0,50,100,96,154,^0.12.10,regular,>=2.17.0 <3.0.0,https://github.com/dart-lang/code_builder 9 | mockingjay,0.3.0,310,100,93,67,^0.12.10,regular,>=2.12.0 <3.0.0,https://github.com/VeryGoodOpenSource/mockingjay 10 | leak_tracker,2.0.1,13,93,88,54,^0.12.13,regular,>=2.18.0 <3.0.0,https://github.com/dart-lang/leak_tracker 11 | webdriver,3.0.2,22,79,100,35,^0.12.10,regular,>=2.18.0 <3.0.0,https://github.com/google/webdriver.dart 12 | gherkin,3.1.0,223,93,86,33,^0.12.11,regular,>=2.15.0 <3.0.0,https://github.com/jonsamwell/dart_gherkin 13 | angel3_framework,7.0.3,126,93,77,33,^0.12.10,regular,>=2.17.0 <3.0.0,https://github.com/dukefirehawk/angel/tree/master/packages/framework 14 | test_api,0.4.18,28,86,99,10,>=0.12.11 <0.12.15,regular,>=2.18.0 <3.0.0,https://github.com/dart-lang/test/tree/master/pkgs/test_api 15 | rx,0.2.0,4,100,78,8,^0.12.0,regular,>=2.17.0 <3.0.0,https://github.com/renggli/dart-rx 16 | build_test,2.1.6,20,86,93,8,^0.12.0,regular,>=2.18.0 <3.0.0,https://github.com/dart-lang/build/tree/master/build_test 17 | typed_result,1.0.0,21,100,54,4,^0.12.14,regular,>=2.18.2 <3.0.0,https://github.com/lucastsantos/typed_result 18 | flutter_lwa,2.1.0,46,93,82,3,^0.12.10,regular,>=2.12.0 <3.0.0,https://github.com/ayvazj/flutter_lwa 19 | built_value_test,8.4.3,29,93,58,3,^0.12.0,regular,>=2.12.0 <3.0.0,https://github.com/google/built_value.dart/tree/master/built_value_test 20 | angel3_validate,7.0.1,68,100,71,2,^0.12.0,regular,>=2.17.0 <3.0.0,https://github.com/dukefirehawk/angel/tree/master/packages/validate 21 | conduit_test,4.2.2,8,100,70,2,^0.12.12,regular,>=2.19.0 <3.0.0,https://github.com/conduit-dart/conduit 22 | test_descriptor,2.0.1,113,79,83,2,^0.12.10,regular,>=2.12.0 <3.0.0,https://github.com/dart-lang/test_descriptor 23 | ngpageloader,5.0.0,184,86,6,2,^0.12.10,regular,>=2.17.0 <3.0.0,https://github.com/angulardart-community/ngpageloader 24 | test_core,0.4.23,1,93,100,1,any,regular,>=2.18.0 <3.0.0,https://github.com/dart-lang/test/tree/master/pkgs/test_core 25 | jael3,7.0.0,165,93,57,1,^0.12.10,regular,>=2.17.0 <3.0.0,https://github.com/dukefirehawk/angel/tree/master/packages/jael/jael 26 | dartbag,0.6.0,8,93,31,1,^0.12.14,regular,>=2.19.0 <3.0.0,https://github.com/jamesderlin/dartbag 27 | critical_test,7.0.1,85,64,0,1,0.12.13,regular,>=2.18.0 <3.0.0,https://github.com/bsutton/critical_tester 28 | dev_test,0.15.7+1,14,100,79,0,>=0.12.10 <2.0.0,regular,>=2.18.0 <3.0.0,https://github.com/tekartik/dev_test.dart/tree/master/dev_test 29 | mock_exceptions,0.8.2,37,100,69,0,^0.12.12,regular,>=2.18.6 <3.0.0,https://github.com/atn832/mock_exceptions 30 | belatuk_combinator,4.0.0,218,100,49,0,^0.12.10,regular,>=2.17.0 <3.0.0,https://github.com/dart-backend/belatuk-common-utilities/tree/main/packages/combinator 31 | angel3_test,7.0.0,166,100,39,0,^0.12.10,regular,>=2.17.0 <3.0.0,https://github.com/dukefirehawk/angel/tree/master/packages/test 32 | tridev_test,1.0.0,109,93,0,0,>=0.12.3 <0.14.0,regular,>=2.12.0 <3.0.0,https://github.com/tridev-dart/tridev 33 | flutter_lwa_platform_interface,2.1.0,46,71,41,0,^0.12.10,regular,>=2.12.0 <3.0.0,https://github.com/ayvazj/flutter_lwa 34 | endaft_core,0.0.3-dev.45,97,71,22,0,^0.12.12,regular,>=2.18.0 <3.0.0,https://github.com/endaft/endaft-core 35 | -------------------------------------------------------------------------------- /pkgs/corpus/lib/cache.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:io'; 6 | 7 | import 'package:path/path.dart' as path; 8 | 9 | class Cache { 10 | final Directory cacheDir = Directory('cache'); 11 | 12 | Directory getCreateCacheDirectory(String name) { 13 | var dir = Directory(path.join(cacheDir.path, name)); 14 | if (!dir.existsSync()) { 15 | dir.createSync(recursive: true); 16 | } 17 | return dir; 18 | } 19 | 20 | Directory get archivesDir => getCreateCacheDirectory('archives'); 21 | 22 | Directory get packagesDir => getCreateCacheDirectory('packages'); 23 | 24 | Directory get usageDir => getCreateCacheDirectory('usage'); 25 | } 26 | -------------------------------------------------------------------------------- /pkgs/corpus/lib/surveyor.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:io' as io; 6 | 7 | import 'package:analyzer/dart/analysis/analysis_context.dart'; 8 | import 'package:analyzer/dart/analysis/analysis_context_collection.dart'; 9 | import 'package:analyzer/dart/analysis/results.dart'; 10 | import 'package:analyzer/dart/ast/ast.dart'; 11 | import 'package:analyzer/file_system/physical_file_system.dart'; 12 | import 'package:path/path.dart' as path; 13 | 14 | const bool _silent = true; 15 | 16 | class Surveyor { 17 | final SurveyorVisitor visitor; 18 | final List sourcePaths; 19 | final List excludedPaths; 20 | 21 | Surveyor.fromDirs({ 22 | required this.visitor, 23 | required List directories, 24 | this.excludedPaths = const [], 25 | }) : sourcePaths = directories 26 | .map((directory) => path.normalize(directory.absolute.path)) 27 | .toList() { 28 | assert(sourcePaths.isNotEmpty); 29 | } 30 | 31 | Future analyze() async { 32 | for (var directory in sourcePaths) { 33 | await _analyzeDirectory(directory); 34 | } 35 | } 36 | 37 | Future _analyzeDirectory(String directory) async { 38 | var analysisContextCollection = AnalysisContextCollection( 39 | includedPaths: [directory], 40 | excludedPaths: excludedPaths, 41 | resourceProvider: PhysicalResourceProvider.INSTANCE, 42 | ); 43 | 44 | for (var analysisContext in analysisContextCollection.contexts) { 45 | var dir = analysisContext.contextRoot.root.path; 46 | var surveyorContext = SurveyorContext(analysisContext); 47 | 48 | visitor.preAnalysis(surveyorContext, subDir: dir != directory); 49 | 50 | for (var filePath in analysisContext.contextRoot.analyzedFiles()) { 51 | if (!_isDartFileName(filePath)) continue; 52 | 53 | surveyorContext._updateCurrentFilePath(filePath); 54 | 55 | try { 56 | var resolvedUnitResult = await analysisContext.currentSession 57 | .getResolvedUnit(filePath) as ResolvedUnitResult; 58 | resolvedUnitResult.unit.accept(visitor); 59 | } catch (e) { 60 | if (!_silent) { 61 | print('Exception caught analyzing: $filePath\n$e'); 62 | } 63 | } 64 | 65 | surveyorContext._updateCurrentFilePath(null); 66 | } 67 | 68 | visitor.postAnalysis(surveyorContext); 69 | } 70 | } 71 | } 72 | 73 | abstract class SurveyorVisitor implements AstVisitor { 74 | void preAnalysis(SurveyorContext context, {required bool subDir}); 75 | void postAnalysis(SurveyorContext context); 76 | } 77 | 78 | class SurveyorContext { 79 | final AnalysisContext analysisContext; 80 | String? _currentFilePath; 81 | 82 | SurveyorContext(this.analysisContext); 83 | 84 | String get currentFilePath => _currentFilePath!; 85 | 86 | void _updateCurrentFilePath(String? filePath) { 87 | _currentFilePath = filePath; 88 | } 89 | } 90 | 91 | bool _isDartFileName(String filePath) => filePath.endsWith('.dart'); 92 | -------------------------------------------------------------------------------- /pkgs/corpus/lib/utils.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:io'; 6 | 7 | import 'package:cli_util/cli_logging.dart'; 8 | 9 | String percent(int val, int count) { 10 | return '${(val * 100 / count).round()}%'; 11 | } 12 | 13 | String pluralize(int count, String word, {String? plural}) { 14 | return count == 1 ? word : (plural ?? '${word}s'); 15 | } 16 | 17 | Future runProcess( 18 | String executable, 19 | List arguments, { 20 | String? workingDirectory, 21 | bool verbose = false, 22 | Logger? logger, 23 | }) async { 24 | if (verbose) { 25 | print('$executable ${arguments.join(' ')}'); 26 | } 27 | 28 | var result = await Process.run( 29 | executable, 30 | arguments, 31 | workingDirectory: workingDirectory, 32 | ); 33 | if (result.exitCode != 0) { 34 | var out = result.stdout as String; 35 | if (out.isNotEmpty) { 36 | logger == null ? print(out.trimRight()) : logger.stdout(out.trimRight()); 37 | } 38 | out = result.stderr as String; 39 | if (out.isNotEmpty) { 40 | logger == null ? print(out.trimRight()) : logger.stderr(out.trimRight()); 41 | } 42 | } 43 | return result; 44 | } 45 | -------------------------------------------------------------------------------- /pkgs/corpus/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: corpus 2 | description: A tool to calculate the API usage for a package. 3 | 4 | publish_to: none 5 | 6 | environment: 7 | sdk: ^3.6.0 8 | 9 | dependencies: 10 | analyzer: ^7.0.0 11 | args: ^2.1.0 12 | cli_util: ^0.4.0 13 | collection: ^1.19.0 14 | http: ^1.0.0 15 | path: ^1.9.0 16 | pub_semver: ^2.1.4 17 | yaml: ^3.0.0 18 | 19 | dev_dependencies: 20 | checks: ^0.3.0 21 | dart_flutter_team_lints: ^3.0.0 22 | test: ^1.25.9 23 | test_descriptor: ^2.0.0 24 | -------------------------------------------------------------------------------- /pkgs/corpus/test/data/class_references.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:path/path.dart'; 6 | import 'package:path/src/style/posix.dart'; 7 | 8 | void main() { 9 | print(PosixStyle()); 10 | print(Style.posix); 11 | } 12 | -------------------------------------------------------------------------------- /pkgs/corpus/test/data/dart_extension_references.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:async'; 6 | 7 | void main() { 8 | Future? future; 9 | // ignore: dead_code 10 | print(future?..ignore()); 11 | } 12 | -------------------------------------------------------------------------------- /pkgs/corpus/test/data/dart_library_references.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:collection'; 6 | 7 | void main() { 8 | var map = SplayTreeMap(); 9 | map['one'] = 1; 10 | map['two'] = 2; 11 | map['three'] = 3; 12 | print(map); 13 | 14 | var local = Queue(); 15 | Queue.castFrom(local); 16 | } 17 | -------------------------------------------------------------------------------- /pkgs/corpus/test/data/dart_top_level_symbol_references.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:convert'; 6 | 7 | void main() { 8 | print(base64); 9 | print(jsonDecode('{}')); 10 | } 11 | -------------------------------------------------------------------------------- /pkgs/corpus/test/data/extension_references.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:collection/collection.dart'; 6 | 7 | void main() { 8 | // firstWhereOrNull is on the extension IterableExtension. 9 | var foo = ['one', 'two', 'three']; 10 | print(foo.firstWhereOrNull((item) => item == 'four')); 11 | } 12 | -------------------------------------------------------------------------------- /pkgs/corpus/test/data/library_references.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:path/path.dart' as path; 6 | 7 | void main() { 8 | print(path.join('one', 'two')); 9 | } 10 | -------------------------------------------------------------------------------- /pkgs/corpus/test/data/top_level_symbol_references.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:path/path.dart' as path; 6 | 7 | void main() { 8 | print(path.join('one', 'two')); 9 | print(path.basename); 10 | } 11 | -------------------------------------------------------------------------------- /pkgs/corpus/test/pub_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:convert'; 6 | 7 | import 'package:checks/checks.dart'; 8 | import 'package:checks/context.dart'; 9 | import 'package:corpus/pub.dart'; 10 | import 'package:pub_semver/pub_semver.dart'; 11 | import 'package:test/test.dart'; 12 | 13 | void main() { 14 | group('PackageInfo', () { 15 | test('parse pub.dev results', () { 16 | var packageInfo = 17 | PackageInfo.from(jsonDecode(_pubSampleData) as Map); 18 | 19 | check(packageInfo.name).equals('usage'); 20 | check(packageInfo.version).equals('4.0.2'); 21 | check(packageInfo.archiveUrl).isNotNull(); 22 | check(packageInfo.publishedDate).isNotNull(); 23 | 24 | check(packageInfo.constraintFor('path')).isNotNull().allows('1.8.0'); 25 | check(packageInfo.constraintFor('test')).isNotNull().allows('1.16.0'); 26 | }); 27 | }); 28 | } 29 | 30 | extension VersionConstraintChecks on Subject { 31 | void allows(String version) { 32 | context.expect(() => const ['allows'], (VersionConstraint actual) { 33 | final ver = Version.parse(version); 34 | if (!actual.allows(ver)) return Rejection(actual: ['$actual']); 35 | return null; 36 | }); 37 | } 38 | } 39 | 40 | final String _pubSampleData = ''' 41 | { 42 | "name": "usage", 43 | "latest": { 44 | "version": "4.0.2", 45 | "pubspec": { 46 | "name": "usage", 47 | "version": "4.0.2", 48 | "description": "A Google Analytics wrapper for command-line, web, and Flutter apps.", 49 | "repository": "https://github.com/dart-lang/wasm", 50 | "environment": { 51 | "sdk":">=2.12.0-0 <3.0.0" 52 | }, 53 | "dependencies": { 54 | "path":"^1.8.0" 55 | }, 56 | "dev_dependencies": { 57 | "pedantic":"^1.9.0", 58 | "test":"^1.16.0" 59 | } 60 | }, 61 | "archive_url": "https://pub.dartlang.org/packages/usage/versions/4.0.2.tar.gz", 62 | "published": "2021-03-30T17:44:54.093423Z" 63 | } 64 | } 65 | '''; 66 | -------------------------------------------------------------------------------- /pkgs/dart_flutter_team_lints/.gitignore: -------------------------------------------------------------------------------- 1 | # Files and directories created by pub. 2 | .dart_tool/ 3 | .packages 4 | 5 | # Conventional directory for build output. 6 | build/ 7 | 8 | pubspec.lock 9 | -------------------------------------------------------------------------------- /pkgs/dart_flutter_team_lints/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 3.5.2 2 | 3 | - Depend on the `6.0.0` release of `package:lints`. 4 | - Require Dart `3.8` 5 | 6 | ## 3.5.1 7 | 8 | - Removed `discarded_futures`; this produced more results than expected. 9 | 10 | ## 3.5.0 11 | 12 | - Added `discarded_futures`. 13 | 14 | ## 3.4.0 15 | 16 | - Added `unnecessary_underscores`. 17 | 18 | ## 3.3.0 19 | 20 | - Added `strict_top_level_inference`. 21 | - Require Dart `3.7`. 22 | 23 | ## 3.2.1 24 | 25 | - Depend on the `5.0.0` release of `package:lints`. 26 | - Removed duplicated lints: `unnecessary_library_name`, 27 | `invalid_runtime_check_with_js_interop_types`, and 28 | `unintended_html_in_doc_comment` 29 | 30 | ## 3.2.0 31 | 32 | - Contributed a (brief) change policy to the readme. 33 | - Added `invalid_runtime_check_with_js_interop_types`. 34 | - Added `unintended_html_in_doc_comment`. 35 | - Require Dart `3.5`. 36 | 37 | ## 3.1.0 38 | 39 | - Added `unnecessary_library_name`. 40 | - Require Dart `3.4`. 41 | 42 | ## 3.0.0 43 | 44 | - Depend on the `4.0.0` release of `package:lints`, adding the 45 | `no_wildcard_variable_uses` lint. 46 | - Require Dart `3.1.0` or later. 47 | 48 | ## 2.1.1 49 | 50 | - Depend on the `3.0.0` release version of package:lints. 51 | 52 | ## 2.1.0 53 | 54 | - Updated to the preview `3.0.0-beta` version of package:lints/recommended.yaml. 55 | - Removed lints duplicated from package:lints/core.yaml and 56 | package:lints/recommended.yaml. 57 | 58 | ## 2.0.0 59 | 60 | - Enable `strict-inference`. 61 | - Added `comment_references`. 62 | - Added `conditional_uri_does_not_exist`. 63 | - Added `prefer_const_constructors`. 64 | - Added `prefer_relative_imports`. 65 | - Added `test_types_in_equals`. 66 | - Added `use_super_parameters`. 67 | 68 | ## 1.0.0 69 | 70 | - Added `collection_methods_unrelated_type`. 71 | - Added `combinators_ordering`. 72 | - Added `dangling_library_doc_comments`. 73 | - Added `implicit_call_tearoffs`. 74 | - Added `library_annotations`. 75 | - Added `unnecessary_library_directive`. 76 | - Added `unreachable_from_main`. 77 | - Added `use_string_in_part_of_directives`. 78 | - Require Dart `2.19.0`. 79 | 80 | ## 0.1.0 81 | 82 | - Turn on `strict-casts: true`. 83 | 84 | ## 0.1.0-dev 85 | 86 | - Initial version. 87 | -------------------------------------------------------------------------------- /pkgs/dart_flutter_team_lints/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2022, the Dart project authors. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following 11 | disclaimer in the documentation and/or other materials provided 12 | with the distribution. 13 | * Neither the name of Google LLC nor the names of its 14 | contributors may be used to endorse or promote products derived 15 | from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /pkgs/dart_flutter_team_lints/README.md: -------------------------------------------------------------------------------- 1 | [![pub package](https://img.shields.io/pub/v/dart_flutter_team_lints.svg)](https://pub.dev/packages/dart_flutter_team_lints) 2 | [![package publisher](https://img.shields.io/pub/publisher/dart_flutter_team_lints.svg)](https://pub.dev/packages/dart_flutter_team_lints/publisher) 3 | 4 | ## What is this? 5 | 6 | This is a set of lints used by the Dart and Flutter teams to analyze their 7 | packages and repositories; it's built on top of 8 | `package:lints/recommended.yaml`. 9 | 10 | This package is not meant to be a recommendation for analysis settings for the 11 | wider ecosystem. For our community recommendations, see `package:lints` and 12 | `package:flutter_lints`. 13 | 14 | For documentation about customizing static analysis for your project, see 15 | https://dart.dev/tools/analysis. 16 | 17 | ## Using the Lints 18 | 19 | To use the lints, add the package as a dev dependency 20 | in your `pubspec.yaml` file: 21 | 22 | ```bash 23 | dart pub add dev:dart_flutter_team_lints 24 | ``` 25 | 26 | then, add an `analysis_options.yaml` file to your project: 27 | 28 | ```yaml 29 | include: package:dart_flutter_team_lints/analysis_options.yaml 30 | ``` 31 | 32 | ## Suggesting changes to the lint set 33 | 34 | In order to suggest a change to the `package:dart_flutter_team_lints` lint set, 35 | please [file an issue](https://github.com/dart-lang/ecosystem/issues/new?template=dart_flutter_team_lints.md) 36 | against the package. A representative group of Dart and Flutter team members, 37 | along with interested parties, will then discuss the lint addition or removal. 38 | 39 | Changes to the lint set may be batched up in order to minimize churn for 40 | downstream codebases. 41 | 42 | Lint additions may go out in new package major versions. `package:lints` only 43 | ships lint additions in major versions as new lints are effectively breaking 44 | changes for repo CI systems. The packages downstream from this lint set are 45 | more scoped and better known however, so we have more room for flexibility for 46 | changes to `package:dart_flutter_team_lints`. 47 | -------------------------------------------------------------------------------- /pkgs/dart_flutter_team_lints/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:dart_flutter_team_lints/analysis_options.yaml 2 | -------------------------------------------------------------------------------- /pkgs/dart_flutter_team_lints/lib/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | # for details. All rights reserved. Use of this source code is governed by a 3 | # BSD-style license that can be found in the LICENSE file. 4 | 5 | # This set of lints builds on top of `package:lints/recommended.yaml`; it's 6 | # used by the Dart and Flutter teams when analyzing their packages and 7 | # repositories. 8 | # 9 | # This package is not meant to be a recommendation for analysis settings for 10 | # the wider ecosystem. For our community recommendations, see `package:lints` 11 | # and `package:flutter_lints`. 12 | # 13 | # For documentation about customizing static analysis for your project, see 14 | # https://dart.dev/tools/analysis. 15 | 16 | include: package:lints/recommended.yaml 17 | 18 | analyzer: 19 | language: 20 | strict-casts: true 21 | strict-inference: true 22 | 23 | linter: 24 | rules: 25 | # consistency 26 | - combinators_ordering 27 | - directives_ordering 28 | - lines_longer_than_80_chars 29 | - omit_local_variable_types 30 | - prefer_asserts_in_initializer_lists 31 | - prefer_const_constructors 32 | - prefer_relative_imports 33 | - prefer_single_quotes 34 | - sort_pub_dependencies 35 | - unnecessary_lambdas 36 | - unnecessary_library_directive 37 | - unnecessary_parenthesis 38 | - unnecessary_statements 39 | - use_is_even_rather_than_modulo 40 | 41 | # correctness 42 | - always_declare_return_types 43 | - avoid_catching_errors 44 | - avoid_dynamic_calls 45 | - comment_references 46 | - conditional_uri_does_not_exist 47 | - only_throw_errors 48 | - test_types_in_equals 49 | - throw_in_finally 50 | - type_annotate_public_apis 51 | - unawaited_futures 52 | - unreachable_from_main 53 | -------------------------------------------------------------------------------- /pkgs/dart_flutter_team_lints/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: dart_flutter_team_lints 2 | description: An analysis rule set used by the Dart and Flutter teams. 3 | version: 3.5.2 4 | repository: https://github.com/dart-lang/ecosystem/tree/main/pkgs/dart_flutter_team_lints 5 | issue_tracker: https://github.com/dart-lang/ecosystem/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Adart_flutter_team_lints 6 | 7 | environment: 8 | sdk: ^3.8.0 9 | 10 | dependencies: 11 | lints: ^6.0.0 12 | 13 | dev_dependencies: 14 | checks: ^0.3.0 15 | path: ^1.8.0 16 | test: ^1.24.0 17 | yaml: ^3.0.0 18 | -------------------------------------------------------------------------------- /pkgs/dart_flutter_team_lints/test/validate_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:io'; 6 | 7 | import 'package:checks/checks.dart'; 8 | import 'package:test/test.dart'; 9 | import 'package:yaml/yaml.dart' as yaml; 10 | 11 | void main() { 12 | late String content; 13 | 14 | setUp(() { 15 | return content = File('lib/analysis_options.yaml').readAsStringSync(); 16 | }); 17 | 18 | test('well-formed', () { 19 | var result = yaml.loadYaml(content); 20 | check(result).isA(); 21 | }); 22 | 23 | test('references recommended', () { 24 | var result = yaml.loadYaml(content) as yaml.YamlMap; 25 | check(result['include']).equals('package:lints/recommended.yaml'); 26 | }); 27 | 28 | test('defines linter rules', () { 29 | var result = yaml.loadYaml(content) as yaml.YamlMap; 30 | check((result['linter'] as Map)['rules'] as List).isNotEmpty(); 31 | }); 32 | } 33 | -------------------------------------------------------------------------------- /pkgs/firehose/.gitignore: -------------------------------------------------------------------------------- 1 | # Files and directories created by pub. 2 | .dart_tool/ 3 | 4 | # Conventional directory for build outputs. 5 | build/ 6 | 7 | # Omit committing pubspec.lock for library packages; see 8 | # https://dart.dev/guides/libraries/private-files#pubspeclock. 9 | pubspec.lock 10 | 11 | coverage/ 12 | -------------------------------------------------------------------------------- /pkgs/firehose/.pubignore: -------------------------------------------------------------------------------- 1 | test_data/ 2 | -------------------------------------------------------------------------------- /pkgs/firehose/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2022, the Dart project authors. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following 11 | disclaimer in the documentation and/or other materials provided 12 | with the distribution. 13 | * Neither the name of Google LLC nor the names of its 14 | contributors may be used to endorse or promote products derived 15 | from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /pkgs/firehose/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:dart_flutter_team_lints/analysis_options.yaml 2 | 3 | analyzer: 4 | exclude: 5 | - test_data/* 6 | -------------------------------------------------------------------------------- /pkgs/firehose/bin/firehose.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:io'; 6 | 7 | import 'package:args/args.dart'; 8 | import 'package:firehose/firehose.dart'; 9 | import 'package:glob/glob.dart'; 10 | 11 | const helpFlag = 'help'; 12 | const validateFlag = 'validate'; 13 | const publishFlag = 'publish'; 14 | const useFlutterFlag = 'use-flutter'; 15 | 16 | void main(List arguments) async { 17 | var argParser = _createArgs(); 18 | try { 19 | final argResults = argParser.parse(arguments); 20 | 21 | if (argResults[helpFlag] as bool) { 22 | _usage(argParser); 23 | return; 24 | } 25 | 26 | final validate = argResults[validateFlag] as bool; 27 | final publish = argResults[publishFlag] as bool; 28 | final useFlutter = argResults[useFlutterFlag] as bool; 29 | final ignoredPackages = (argResults['ignore-packages'] as List) 30 | .where((pattern) => pattern.isNotEmpty) 31 | .map((pattern) => Glob(pattern, recursive: true)) 32 | .toList(); 33 | 34 | if (!validate && !publish) { 35 | _usage(argParser, 36 | error: 'Error: one of --validate or --publish must be specified.'); 37 | exitCode = 1; 38 | return; 39 | } 40 | 41 | final github = GithubApi(); 42 | if (publish && !github.inGithubContext) { 43 | _usage(argParser, 44 | error: 'Error: --publish can only be executed from within a GitHub ' 45 | 'action.'); 46 | exitCode = 1; 47 | return; 48 | } 49 | 50 | final firehose = Firehose(Directory.current, useFlutter, ignoredPackages); 51 | 52 | if (validate) { 53 | await firehose.validate(); 54 | } else if (publish) { 55 | await firehose.publish(); 56 | } 57 | } on ArgParserException catch (e) { 58 | _usage(argParser, error: e.message); 59 | exitCode = 1; 60 | return; 61 | } 62 | } 63 | 64 | void _usage(ArgParser argParser, {String? error}) { 65 | if (error != null) { 66 | stderr.writeln(error); 67 | stderr.writeln(); 68 | } 69 | 70 | print('usage: dart bin/firehose.dart '); 71 | print(''); 72 | print(argParser.usage); 73 | } 74 | 75 | ArgParser _createArgs() { 76 | return ArgParser() 77 | ..addFlag( 78 | helpFlag, 79 | abbr: 'h', 80 | negatable: false, 81 | help: 'Print tool help.', 82 | ) 83 | ..addFlag( 84 | validateFlag, 85 | negatable: false, 86 | help: 'Validate packages and indicate whether --publish would publish ' 87 | 'anything.', 88 | ) 89 | ..addFlag( 90 | publishFlag, 91 | negatable: false, 92 | help: 'Publish any changed packages.', 93 | ) 94 | ..addFlag( 95 | useFlutterFlag, 96 | negatable: true, 97 | help: 'Whether this is a Flutter project.', 98 | ) 99 | ..addMultiOption( 100 | 'ignore-packages', 101 | help: 'Which packages to ignore.', 102 | ); 103 | } 104 | -------------------------------------------------------------------------------- /pkgs/firehose/bin/health.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:io'; 6 | 7 | import 'package:args/args.dart'; 8 | import 'package:firehose/src/github.dart'; 9 | import 'package:firehose/src/health/health.dart'; 10 | 11 | void main(List arguments) async { 12 | var checkTypes = Check.values.map((c) => c.displayName); 13 | var argParser = ArgParser() 14 | ..addOption( 15 | 'check', 16 | allowed: checkTypes, 17 | help: 'Check PR health.', 18 | ) 19 | ..addMultiOption( 20 | 'ignore_packages', 21 | defaultsTo: [], 22 | help: 'Which packages to ignore.', 23 | ) 24 | ..addMultiOption( 25 | 'warn_on', 26 | allowed: checkTypes, 27 | help: 'Which checks to display warnings on', 28 | ) 29 | ..addMultiOption( 30 | 'fail_on', 31 | allowed: checkTypes, 32 | help: 'Which checks should lead to workflow failure', 33 | ) 34 | ..addMultiOption( 35 | 'experiments', 36 | help: 'Which experiments should be enabled for Dart', 37 | ) 38 | ..addFlag( 39 | 'coverage_web', 40 | help: 'Whether to run web tests for coverage', 41 | ) 42 | ..addMultiOption( 43 | 'flutter_packages', 44 | defaultsTo: [], 45 | help: 'The Flutter packages in this repo', 46 | ); 47 | for (var check in Check.values) { 48 | argParser.addMultiOption( 49 | 'ignore_${check.name}', 50 | defaultsTo: [], 51 | help: 'Which files to ignore for the ${check.displayName} check.', 52 | ); 53 | } 54 | final parsedArgs = argParser.parse(arguments); 55 | final checkStr = parsedArgs.option('check'); 56 | final check = Check.values.firstWhere((c) => c.displayName == checkStr); 57 | final warnOn = parsedArgs.multiOption('warn_on'); 58 | final failOn = parsedArgs.multiOption('fail_on'); 59 | final flutterPackages = _listNonEmpty(parsedArgs, 'flutter_packages'); 60 | final ignorePackages = _listNonEmpty(parsedArgs, 'ignore_packages'); 61 | final ignoredFor = Map.fromEntries(Check.values 62 | .map((c) => MapEntry(c, _listNonEmpty(parsedArgs, 'ignore_${c.name}')))); 63 | final experiments = _listNonEmpty(parsedArgs, 'experiments'); 64 | final coverageWeb = parsedArgs.flag('coverage_web'); 65 | if (warnOn.toSet().intersection(failOn.toSet()).isNotEmpty) { 66 | throw ArgumentError('The checks for which warnings are displayed and the ' 67 | 'checks which lead to failure must be disjoint.'); 68 | } 69 | await Health( 70 | Directory.current, 71 | check, 72 | warnOn, 73 | failOn, 74 | coverageWeb, 75 | ignorePackages, 76 | ignoredFor, 77 | experiments, 78 | GithubApi(), 79 | flutterPackages, 80 | ).healthCheck(); 81 | } 82 | 83 | List _listNonEmpty(ArgResults parsedArgs, String key) => 84 | (parsedArgs[key] as List).where((e) => e.isNotEmpty).toList(); 85 | -------------------------------------------------------------------------------- /pkgs/firehose/lib/src/changelog.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:io'; 6 | 7 | class Changelog { 8 | static const _headerLinePrefix = '## '; 9 | 10 | final File file; 11 | final bool exists; 12 | final List<_Section> _sections; 13 | 14 | /// Reads [file] and parses it into sections. 15 | factory Changelog(File file) { 16 | if (!file.existsSync()) { 17 | return Changelog._(file, false, const <_Section>[]); 18 | } 19 | var lines = file.readAsLinesSync(); 20 | var sections = _parseSections(lines); 21 | return Changelog._(file, true, sections); 22 | } 23 | 24 | Changelog._(this.file, this.exists, this._sections); 25 | 26 | /// Pattern recognizing some SemVer formats. 27 | /// 28 | /// Accepts: 29 | /// 30 | /// > digits '.' digits '.' digits 31 | /// 32 | /// optionally followed by `-` or `+` character and one of more non-whitespace 33 | /// characters, without validating them as valid semver. 34 | /// 35 | /// This is not all complete SemVer version strings but it should be enough 36 | /// for the user-cases we need it for in this package. 37 | static final _versionRegex = RegExp(r'\d+\.\d+\.\d+(?:[+\-]\S*)?'); 38 | 39 | String? get latestVersion { 40 | var input = latestHeading; 41 | 42 | if (input != null) { 43 | var match = _versionRegex.firstMatch(input); 44 | if (match != null) { 45 | var version = match[0]; 46 | return version; 47 | } 48 | } 49 | 50 | return null; 51 | } 52 | 53 | String? get latestHeading { 54 | var section = _sections.firstOrNull; 55 | if (section == null) return null; 56 | // Remove the leading `_headerLinePrefix`, then trim left-over whitespace. 57 | var title = section.title; 58 | assert(title.startsWith(_headerLinePrefix)); 59 | return title.substring(_headerLinePrefix.length).trim(); 60 | } 61 | 62 | List get latestChangeEntries => 63 | _sections.firstOrNull?.entries ?? const []; 64 | 65 | static List<_Section> _parseSections(List lines) { 66 | var sections = <_Section>[]; 67 | 68 | _Section? section; 69 | 70 | for (var line in lines) { 71 | if (line.isEmpty) continue; 72 | if (line.startsWith(_headerLinePrefix)) { 73 | if (section != null) sections.add(section); 74 | section = _Section(line); 75 | } else { 76 | section?.entries.add(line); 77 | } 78 | } 79 | if (section != null) sections.add(section); 80 | 81 | return sections; 82 | } 83 | 84 | String get describeLatestChanges => latestChangeEntries.join('\n'); 85 | } 86 | 87 | class _Section { 88 | final String title; 89 | final List entries = []; 90 | 91 | _Section(this.title); 92 | } 93 | -------------------------------------------------------------------------------- /pkgs/firehose/lib/src/delayed_client.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:convert'; 6 | 7 | import 'dart:typed_data'; 8 | 9 | import 'package:http/http.dart' as http; 10 | 11 | class DelayedClient implements http.Client { 12 | final http.Client _client; 13 | final Duration duration; 14 | 15 | factory DelayedClient(Duration duration) => DelayedClient._( 16 | client: http.Client(), 17 | duration: duration, 18 | ); 19 | 20 | DelayedClient._({required this.duration, required http.Client client}) 21 | : _client = client; 22 | 23 | @override 24 | void close() => _client.close(); 25 | 26 | @override 27 | Future delete(Uri url, 28 | {Map? headers, Object? body, Encoding? encoding}) => 29 | Future.delayed( 30 | duration, 31 | () => _client.delete(url, 32 | body: body, encoding: encoding, headers: headers)); 33 | 34 | @override 35 | Future get(Uri url, {Map? headers}) => 36 | Future.delayed(duration, () => _client.get(url, headers: headers)); 37 | 38 | @override 39 | Future head(Uri url, {Map? headers}) => 40 | Future.delayed(duration, () => _client.head(url, headers: headers)); 41 | 42 | @override 43 | Future patch(Uri url, 44 | {Map? headers, Object? body, Encoding? encoding}) => 45 | Future.delayed( 46 | duration, 47 | () => _client.patch(url, 48 | headers: headers, body: body, encoding: encoding)); 49 | 50 | @override 51 | Future post(Uri url, 52 | {Map? headers, Object? body, Encoding? encoding}) => 53 | Future.delayed( 54 | duration, 55 | () => _client.post(url, 56 | headers: headers, body: body, encoding: encoding)); 57 | @override 58 | Future put(Uri url, 59 | {Map? headers, Object? body, Encoding? encoding}) => 60 | Future.delayed( 61 | duration, 62 | () => _client.put(url, 63 | headers: headers, body: body, encoding: encoding)); 64 | @override 65 | Future read(Uri url, {Map? headers}) => 66 | Future.delayed(duration, () => _client.read(url, headers: headers)); 67 | 68 | @override 69 | Future readBytes(Uri url, {Map? headers}) => 70 | Future.delayed(duration, () => _client.readBytes(url, headers: headers)); 71 | 72 | @override 73 | Future send(http.BaseRequest request) => 74 | Future.delayed(duration, () => _client.send(request)); 75 | } 76 | -------------------------------------------------------------------------------- /pkgs/firehose/lib/src/health/changelog.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:io'; 6 | 7 | import 'package:glob/glob.dart'; 8 | import 'package:path/path.dart' as path; 9 | 10 | import '../github.dart'; 11 | import '../repo.dart'; 12 | 13 | Future>> packagesWithoutChangelog( 14 | GithubApi github, 15 | List ignored, 16 | Directory directory, 17 | ) async { 18 | final repo = Repository(directory); 19 | final packages = repo.locatePackages(ignore: ignored); 20 | final files = await github.listFilesForPR(directory, ignored); 21 | 22 | var packagesWithoutChangedChangelog = collectPackagesWithoutChangelogChanges( 23 | packages, 24 | files, 25 | directory, 26 | ); 27 | 28 | print('Collecting files without license headers in those packages:'); 29 | var packagesWithChanges = >{}; 30 | for (final file in files) { 31 | for (final package in packagesWithoutChangedChangelog) { 32 | if (fileNeedsEntryInChangelog(package, file.filename, directory)) { 33 | print(file); 34 | packagesWithChanges.update( 35 | package, 36 | (changedFiles) => [...changedFiles, file], 37 | ifAbsent: () => [file], 38 | ); 39 | } 40 | } 41 | } 42 | print(''' 43 | Done, found ${packagesWithChanges.length} packages with a need for a changelog.'''); 44 | return packagesWithChanges; 45 | } 46 | 47 | List collectPackagesWithoutChangelogChanges( 48 | List packages, 49 | List files, 50 | Directory directory, 51 | ) { 52 | print('Collecting packages without changed changelogs:'); 53 | final packagesWithoutChangedChangelog = 54 | packages.where((package) => package.changelog.exists).where((package) { 55 | return !files 56 | .map((e) => e.pathInRepository) 57 | .contains(package.changelog.file.path); 58 | }).toList(); 59 | print('Done, found ${packagesWithoutChangedChangelog.length} packages.'); 60 | return packagesWithoutChangedChangelog; 61 | } 62 | 63 | bool fileNeedsEntryInChangelog(Package package, String file, Directory d) { 64 | final directoryPath = package.directory.path; 65 | final directory = path.relative(directoryPath, from: d.path); 66 | final isInPackage = path.isWithin(directory, file); 67 | final isInLib = path.isWithin(path.join(directory, 'lib'), file); 68 | final isInBin = path.isWithin(path.join(directory, 'bin'), file); 69 | final isPubspec = file.endsWith('pubspec.yaml'); 70 | final isReadme = file.endsWith('README.md'); 71 | return isInPackage && (isInLib || isInBin || isPubspec || isReadme); 72 | } 73 | -------------------------------------------------------------------------------- /pkgs/firehose/lib/src/health/lcov.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:io'; 6 | import 'package:path/path.dart' as path; 7 | 8 | Map parseLCOV( 9 | String lcovPath, { 10 | required String relativeTo, 11 | }) { 12 | var file = File(lcovPath); 13 | List lines; 14 | if (file.existsSync()) { 15 | lines = file.readAsLinesSync(); 16 | } else { 17 | print('LCOV file not found at $lcovPath.'); 18 | return {}; 19 | } 20 | var coveragePerFile = {}; 21 | String? fileName; 22 | int? numberLines; 23 | int? coveredLines; 24 | for (var line in lines) { 25 | if (line.startsWith('SF:')) { 26 | fileName = line.substring('SF:'.length); 27 | } else if (line.startsWith('LF:')) { 28 | numberLines = int.parse(line.substring('LF:'.length)); 29 | } else if (line.startsWith('LH:')) { 30 | coveredLines = int.parse(line.substring('LH:'.length)); 31 | } else if (line.startsWith('end_of_record')) { 32 | if (numberLines != null) { 33 | var change = (coveredLines ?? 0) / numberLines; 34 | coveragePerFile[path.relative(fileName!, from: relativeTo)] = change; 35 | } 36 | } 37 | } 38 | print('Found coverage for ${coveragePerFile.length} files.'); 39 | return coveragePerFile; 40 | } 41 | -------------------------------------------------------------------------------- /pkgs/firehose/lib/src/health/license.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:io'; 6 | 7 | import 'package:collection/collection.dart'; 8 | import 'package:glob/glob.dart'; 9 | import 'package:path/path.dart' as path; 10 | 11 | final license = ''' 12 | // Copyright (c) ${DateTime.now().year}, the Dart project authors. Please see the AUTHORS file 13 | // for details. All rights reserved. Use of this source code is governed by a 14 | // BSD-style license that can be found in the LICENSE file.'''; 15 | 16 | Future> getFilesWithoutLicenses( 17 | Directory repositoryDir, List ignored) async { 18 | var dartFiles = await repositoryDir 19 | .list(recursive: true) 20 | .where((file) => file.path.endsWith('.dart')) 21 | .toList(); 22 | print('Collecting files without license headers:'); 23 | var filesWithoutLicenses = dartFiles 24 | .map((file) { 25 | var relativePath = path.relative(file.path, from: repositoryDir.path); 26 | if (ignored.none((glob) => 27 | glob.matches(path.relative(file.path, from: repositoryDir.path)))) { 28 | var fileContents = File(file.path).readAsStringSync(); 29 | if (!fileIsGenerated(fileContents, file.path) && 30 | !fileContainsCopyright(fileContents)) { 31 | print(relativePath); 32 | return relativePath; 33 | } 34 | } 35 | }) 36 | .whereType() 37 | .sortedBy((fileName) => fileName) 38 | .toList(); 39 | print(''' 40 | Done, found ${filesWithoutLicenses.length} files without license headers'''); 41 | return filesWithoutLicenses; 42 | } 43 | 44 | bool fileIsGenerated(String fileContents, String path) => 45 | path.endsWith('.g.dart') || 46 | fileContents 47 | .split('\n') 48 | .takeWhile((line) => line.startsWith('//') || line.isEmpty) 49 | .any((line) => line.toLowerCase().contains('generate')); 50 | 51 | bool fileContainsCopyright(String fileContents) => 52 | fileContents.contains('// Copyright (c)'); 53 | -------------------------------------------------------------------------------- /pkgs/firehose/lib/src/pub.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:convert'; 6 | 7 | import 'package:http/http.dart' as http; 8 | import 'package:pub_semver/pub_semver.dart'; 9 | 10 | class Pub { 11 | http.Client? _httpClient; 12 | 13 | http.Client get httpClient => _httpClient ??= http.Client(); 14 | 15 | Future hasPublishedVersion(String name, String version) async { 16 | var uri = Uri.parse('https://pub.dev/api/packages/$name'); 17 | var response = await getCall(uri, retries: 3); 18 | if (response.statusCode != 200) { 19 | return false; 20 | } 21 | 22 | var json = jsonDecode(response.body) as Map; 23 | return (json['versions'] as List) 24 | .map((versionObject) => 25 | (versionObject as Map)['version']) 26 | .contains(version); 27 | } 28 | 29 | Future getCall(Uri uri, {required int retries}) async { 30 | for (var i = 0; i < retries + 1; i++) { 31 | try { 32 | var response = await httpClient.get(uri); 33 | return response; 34 | } catch (e) { 35 | if (i >= retries) { 36 | rethrow; 37 | } 38 | } 39 | } 40 | throw AssertionError('This should be unreachable'); 41 | } 42 | 43 | void close() { 44 | _httpClient?.close(); 45 | } 46 | } 47 | 48 | extension VersionExtension on Version { 49 | bool get wip { 50 | return isPreRelease && preRelease.length == 1 && preRelease.first == 'wip'; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /pkgs/firehose/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: firehose 2 | description: A tool to automate publishing of Pub packages from GitHub actions. 3 | version: 0.10.5 4 | repository: https://github.com/dart-lang/ecosystem/tree/main/pkgs/firehose 5 | 6 | environment: 7 | sdk: ^3.5.0 8 | 9 | executables: 10 | firehose: firehose 11 | health: health 12 | 13 | dependencies: 14 | args: ^2.3.0 15 | collection: ^1.17.2 16 | github: ^9.20.0 17 | glob: ^2.1.2 18 | http: ^1.0.0 19 | path: ^1.8.0 20 | pub_semver: ^2.1.0 21 | pubspec_parse: ^1.2.3 22 | yaml: ^3.1.0 23 | 24 | dev_dependencies: 25 | dart_flutter_team_lints: ^3.0.0 26 | test: ^1.21.0 27 | -------------------------------------------------------------------------------- /pkgs/firehose/test/coverage_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | @TestOn('vm') 6 | library; 7 | 8 | import 'dart:io'; 9 | 10 | import 'package:firehose/src/github.dart'; 11 | import 'package:firehose/src/health/coverage.dart'; 12 | import 'package:firehose/src/health/lcov.dart'; 13 | import 'package:firehose/src/repo.dart'; 14 | import 'package:test/test.dart'; 15 | 16 | void main() { 17 | test('LCOV parser', () { 18 | var parsed = 19 | parseLCOV('test/lcov.info', relativeTo: Directory.current.path); 20 | expect( 21 | parsed.values, 22 | orderedEquals([ 23 | 1.0, 24 | 0.02857142857142857, 25 | 0.8, 26 | 0.8333333333333334, 27 | 0.40625, 28 | 0.0, 29 | 1.0, 30 | 0.0, 31 | ]), 32 | ); 33 | }); 34 | test('Compare coverage', () async { 35 | var coverages = FakeHealth().compareCoveragesFor( 36 | [GitFile('testfile.dart', FileStatus.modified, Directory.current)], 37 | Directory('base_path_does_not_exist'), 38 | ); 39 | 40 | expect(coverages.coveragePerFile, 41 | {'testfile.dart': Change(newCoverage: 0.7, oldCoverage: 0.5)}); 42 | }); 43 | } 44 | 45 | class FakeHealth extends Coverage { 46 | FakeHealth() : super(true, [], Directory.current, [], 'dart'); 47 | 48 | @override 49 | Map getCoverage(Package? package) { 50 | Map result; 51 | if (package == null) { 52 | // as 'base_path_does_not_exist' 53 | result = {'testfile.dart': 0.5}; 54 | } else { 55 | result = {'testfile.dart': 0.7}; 56 | } 57 | return result; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /pkgs/firehose/test/github_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:io'; 6 | 7 | import 'package:firehose/src/github.dart'; 8 | import 'package:github/github.dart'; 9 | import 'package:test/test.dart'; 10 | 11 | Future main() async { 12 | var github = GithubApi( 13 | repoSlug: RepositorySlug('dart-lang', 'ecosystem'), 14 | issueNumber: 148, 15 | ); 16 | test('Fetching pull request description', () async { 17 | var pullrequestDescription = await github.pullrequestBody(); 18 | expect( 19 | pullrequestDescription, 20 | startsWith( 21 | 'Bumps [actions/labeler](https://github.com/actions/labeler) from 4.0.4 to 4.3.0.\n')); 22 | }); 23 | test('Listing files for PR', () async { 24 | var files = await github.listFilesForPR(Directory.current); 25 | expect(files, [ 26 | GitFile( 27 | '.github/workflows/pull_request_label.yml', 28 | FileStatus.modified, 29 | Directory.current, 30 | ), 31 | ]); 32 | }); 33 | test('Find comment', () async { 34 | var commentId = await github.findCommentId(user: 'auto-submit[bot]'); 35 | expect(commentId, 1660891263); 36 | }); 37 | test('Find comment with searchterm', () async { 38 | var commentId = await github.findCommentId( 39 | user: 'auto-submit[bot]', 40 | searchTerm: 'before re-applying this label.', 41 | ); 42 | expect(commentId, 1660891263); 43 | }); 44 | test('Find comment with searchterm', () async { 45 | var commentId = await github.findCommentId( 46 | user: 'auto-submit[bot]', 47 | searchTerm: 'some string not in the comment', 48 | ); 49 | expect(commentId, isNull); 50 | }); 51 | 52 | tearDownAll(() => github.close()); 53 | } 54 | -------------------------------------------------------------------------------- /pkgs/firehose/test/license_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | @TestOn('vm') 6 | library; 7 | 8 | import 'dart:io'; 9 | 10 | import 'package:firehose/src/health/license.dart'; 11 | import 'package:path/path.dart' as path; 12 | import 'package:test/test.dart'; 13 | 14 | void main() { 15 | var fileWithLicense = File('test/fileWithLicense.dart'); 16 | var fileWithoutLicense = File('test/fileWithoutLicense.dart'); 17 | 18 | setUp(() async { 19 | await fileWithLicense.writeAsString(license); 20 | await fileWithoutLicense.writeAsString(''); 21 | }); 22 | 23 | test('Check for licenses', () async { 24 | var directory = Directory('test/'); 25 | var filesWithoutLicenses = await getFilesWithoutLicenses(directory, []); 26 | expect(filesWithoutLicenses, 27 | [path.relative(fileWithoutLicense.path, from: directory.path)]); 28 | }); 29 | 30 | tearDown(() async { 31 | await fileWithLicense.delete(); 32 | await fileWithoutLicense.delete(); 33 | }); 34 | } 35 | -------------------------------------------------------------------------------- /pkgs/firehose/test/pub_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | @TestOn('vm') 6 | library; 7 | 8 | import 'package:firehose/src/pub.dart'; 9 | import 'package:pub_semver/pub_semver.dart'; 10 | import 'package:test/test.dart'; 11 | 12 | void main() { 13 | group('pub', () { 14 | late Pub pub; 15 | 16 | setUp(() { 17 | pub = Pub(); 18 | }); 19 | 20 | tearDown(() { 21 | pub.close(); 22 | }); 23 | 24 | test('version exists', () async { 25 | var result = await pub.hasPublishedVersion('path', '1.8.0'); 26 | expect(result, true); 27 | }); 28 | 29 | test('version doesn\'t exist', () async { 30 | var result = await pub.hasPublishedVersion('path', '1.7.1'); 31 | expect(result, false); 32 | }); 33 | 34 | test('package not published exists', () async { 35 | var result = await pub.hasPublishedVersion( 36 | 'foo_bar_not_published_package', '1.8.0'); 37 | expect(result, false); 38 | }); 39 | }); 40 | 41 | group('VersionExtension', () { 42 | test('wip no pre-release', () async { 43 | final version = Version.parse('1.2.3'); 44 | expect(version.wip, false); 45 | }); 46 | 47 | test('wip pre-release', () async { 48 | final version = Version.parse('1.2.3-dev'); 49 | expect(version.wip, false); 50 | }); 51 | 52 | test('wip pre-release wip', () async { 53 | final version = Version.parse('1.2.3-wip'); 54 | expect(version.wip, true); 55 | }); 56 | }); 57 | } 58 | -------------------------------------------------------------------------------- /pkgs/firehose/test/repo_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | @TestOn('vm') 6 | library; 7 | 8 | import 'dart:io'; 9 | import 'dart:isolate'; 10 | 11 | import 'package:firehose/src/github.dart'; 12 | import 'package:firehose/src/repo.dart'; 13 | import 'package:github/github.dart' show RepositorySlug; 14 | import 'package:test/test.dart'; 15 | 16 | void main() { 17 | late Repository packages; 18 | late Uri packageRoot; 19 | 20 | setUpAll(() async { 21 | packageRoot = (await Isolate.resolvePackageUri( 22 | Uri.parse('package:firehose/test.dart')))! 23 | .resolve('../'); 24 | }); 25 | 26 | group('repo', () { 27 | setUp(() { 28 | // Look up two levels from the package directory to get the repo dir. 29 | packages = Repository(Directory.fromUri(packageRoot.resolve('../../'))); 30 | }); 31 | 32 | test('isSinglePackageRepo', () { 33 | var result = packages.isSinglePackageRepo; 34 | expect(result, false); 35 | }); 36 | 37 | test('locatePackages', () { 38 | var result = packages.locatePackages(); 39 | expect(result, isNotEmpty); 40 | }); 41 | 42 | test('validate sorted', () { 43 | var result = packages.locatePackages(); 44 | var sorted = true; 45 | for (var i = 1; i < result.length; i++) { 46 | final a = result[i - 1]; 47 | final b = result[i]; 48 | 49 | sorted &= a.name.compareTo(b.name) <= 0; 50 | } 51 | expect(sorted, isTrue); 52 | }); 53 | 54 | test('github release link', () { 55 | final github = GithubApi( 56 | repoSlug: RepositorySlug.full('dart-lang/ecosystem'), 57 | ); 58 | final package = packages.locatePackages().first; 59 | final releaseUri = packages.calculateReleaseUri(package, github); 60 | expect(releaseUri.path, '/${github.repoSlug}/releases/new'); 61 | 62 | final queryParams = releaseUri.queryParameters; 63 | expect(queryParams['tag'], packages.calculateRepoTag(package)); 64 | expect(queryParams['title'], 65 | allOf(contains(package.name), contains(package.version.toString()))); 66 | expect(queryParams['body'], package.changelog.describeLatestChanges); 67 | }); 68 | }); 69 | 70 | group('pub workspace repo', () { 71 | setUp(() { 72 | packages = Repository( 73 | Directory.fromUri(packageRoot.resolve('test_data/workspace_repo'))); 74 | }); 75 | 76 | test('locatePackages', () { 77 | var result = packages.locatePackages(); 78 | expect( 79 | result, 80 | equals([ 81 | isA().having((p) => p.name, 'name', 'pkg_1'), 82 | isA().having((p) => p.name, 'name', 'pkg_2'), 83 | ])); 84 | }); 85 | }); 86 | 87 | group('repo with an unpublished root package', () { 88 | setUp(() { 89 | packages = Repository(Directory.fromUri( 90 | packageRoot.resolve('test_data/root_unpublished_pkg'))); 91 | }); 92 | 93 | test('locatePackages', () { 94 | var result = packages.locatePackages(); 95 | expect( 96 | result, 97 | equals([ 98 | isA().having((p) => p.name, 'name', 'pkg_1'), 99 | isA().having((p) => p.name, 'name', 'pkg_2'), 100 | ])); 101 | }); 102 | }); 103 | } 104 | -------------------------------------------------------------------------------- /pkgs/firehose/test/utils_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:firehose/src/utils.dart'; 6 | import 'package:test/test.dart'; 7 | 8 | void main() { 9 | group('Tag', () { 10 | test('invalid', () { 11 | var tag = Tag('1.2.4'); 12 | expect(tag.valid, false); 13 | }); 14 | 15 | test('invalid 2', () { 16 | var tag = Tag('v1.2'); 17 | expect(tag.valid, false); 18 | }); 19 | 20 | test('single package repo', () { 21 | var tag = Tag('v1.2.3'); 22 | expect(tag.version, '1.2.3'); 23 | }); 24 | 25 | test('pre-release package repo', () { 26 | var tag = Tag('v1.2.3-beta'); 27 | expect(tag.version, '1.2.3-beta'); 28 | }); 29 | 30 | test('service release', () { 31 | var tag = Tag('v1.2.3+1'); 32 | expect(tag.version, '1.2.3+1'); 33 | }); 34 | 35 | test('mono repo', () { 36 | var tag = Tag('foobar-v1.2.3'); 37 | expect(tag.package, 'foobar'); 38 | expect(tag.version, '1.2.3'); 39 | }); 40 | 41 | test('mono repo 2', () { 42 | var tag = Tag('foo_bar-v1.2.3'); 43 | expect(tag.package, 'foo_bar'); 44 | expect(tag.version, '1.2.3'); 45 | }); 46 | 47 | test('mono repo pre-release', () { 48 | var tag = Tag('foo_bar-v1.2.3-dev.1'); 49 | expect(tag.package, 'foo_bar'); 50 | expect(tag.version, '1.2.3-dev.1'); 51 | }); 52 | 53 | test('mono repo bad', () { 54 | var tag = Tag('foobar_v1.2.3'); 55 | expect(tag.valid, false); 56 | }); 57 | 58 | test('mono repo bad 2', () { 59 | var tag = Tag('foobar_1.2.3'); 60 | expect(tag.valid, false); 61 | 62 | tag = Tag('foobar-1.2.3'); 63 | expect(tag.valid, false); 64 | }); 65 | }); 66 | } 67 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/base_test_repo/pkgs/package1/.gitignore: -------------------------------------------------------------------------------- 1 | # https://dart.dev/guides/libraries/private-files 2 | # Created by `dart pub` 3 | .dart_tool/ 4 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/base_test_repo/pkgs/package1/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.0.0 2 | 3 | - Initial version. 4 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/base_test_repo/pkgs/package1/README.md: -------------------------------------------------------------------------------- 1 | A sample command-line application with an entrypoint in `bin/`, library code 2 | in `lib/`, and example unit test in `test/`. 3 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/base_test_repo/pkgs/package1/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the static analysis results for your project (errors, 2 | # warnings, and lints). 3 | # 4 | # This enables the 'recommended' set of lints from `package:lints`. 5 | # This set helps identify many issues that may lead to problems when running 6 | # or consuming Dart code, and enforces writing Dart using a single, idiomatic 7 | # style and format. 8 | # 9 | # If you want a smaller set of lints you can change this to specify 10 | # 'package:lints/core.yaml'. These are just the most critical lints 11 | # (the recommended set includes the core lints). 12 | # The core lints are also what is used by pub.dev for scoring packages. 13 | 14 | include: package:lints/recommended.yaml 15 | 16 | # Uncomment the following section to specify additional rules. 17 | 18 | # linter: 19 | # rules: 20 | # - camel_case_types 21 | 22 | # analyzer: 23 | # exclude: 24 | # - path/to/excluded/files/** 25 | 26 | # For more information about the core and recommended set of lints, see 27 | # https://dart.dev/go/core-lints 28 | 29 | # For additional information about configuring this file, see 30 | # https://dart.dev/guides/language/analysis-options 31 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/base_test_repo/pkgs/package1/bin/package1.dart: -------------------------------------------------------------------------------- 1 | import 'package:package1/package1.dart' as package1; 2 | 3 | void main(List arguments) { 4 | print('Hello world: ${package1.calculate()}!'); 5 | } 6 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/base_test_repo/pkgs/package1/lib/package1.dart: -------------------------------------------------------------------------------- 1 | int calculate() { 2 | return 6 * 7; 3 | } 4 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/base_test_repo/pkgs/package1/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: package1 2 | description: A sample command-line application. 3 | version: 1.0.0 4 | # repository: https://github.com/my_org/my_repo 5 | 6 | environment: 7 | sdk: ^3.1.0 8 | 9 | # Add regular dependencies here. 10 | dependencies: 11 | # path: ^1.8.0 12 | 13 | dev_dependencies: 14 | lints: ^3.0.0 15 | test: ^1.24.0 16 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/base_test_repo/pkgs/package1/test/package1_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:package1/package1.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | test('calculate', () { 6 | expect(calculate(), 42); 7 | }); 8 | } 9 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/base_test_repo/pkgs/package2/.gitignore: -------------------------------------------------------------------------------- 1 | # https://dart.dev/guides/libraries/private-files 2 | # Created by `dart pub` 3 | .dart_tool/ 4 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/base_test_repo/pkgs/package2/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.0.0 2 | 3 | - Initial version. 4 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/base_test_repo/pkgs/package2/README.md: -------------------------------------------------------------------------------- 1 | A sample command-line application with an entrypoint in `bin/`, library code 2 | in `lib/`, and example unit test in `test/`. 3 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/base_test_repo/pkgs/package2/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the static analysis results for your project (errors, 2 | # warnings, and lints). 3 | # 4 | # This enables the 'recommended' set of lints from `package:lints`. 5 | # This set helps identify many issues that may lead to problems when running 6 | # or consuming Dart code, and enforces writing Dart using a single, idiomatic 7 | # style and format. 8 | # 9 | # If you want a smaller set of lints you can change this to specify 10 | # 'package:lints/core.yaml'. These are just the most critical lints 11 | # (the recommended set includes the core lints). 12 | # The core lints are also what is used by pub.dev for scoring packages. 13 | 14 | include: package:lints/recommended.yaml 15 | 16 | # Uncomment the following section to specify additional rules. 17 | 18 | # linter: 19 | # rules: 20 | # - camel_case_types 21 | 22 | # analyzer: 23 | # exclude: 24 | # - path/to/excluded/files/** 25 | 26 | # For more information about the core and recommended set of lints, see 27 | # https://dart.dev/go/core-lints 28 | 29 | # For additional information about configuring this file, see 30 | # https://dart.dev/guides/language/analysis-options 31 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/base_test_repo/pkgs/package2/bin/package2.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:package2/package2.dart' as package2; 6 | 7 | void main(List arguments) { 8 | print('Hello world: ${package2.calculate()}!'); 9 | } 10 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/base_test_repo/pkgs/package2/lib/package2.dart: -------------------------------------------------------------------------------- 1 | int calculate() { 2 | return 6 * 7; 3 | } 4 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/base_test_repo/pkgs/package2/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: package2 2 | description: A sample command-line application. 3 | version: 1.0.0 4 | # repository: https://github.com/my_org/my_repo 5 | 6 | environment: 7 | sdk: ^3.1.0 8 | 9 | # Add regular dependencies here. 10 | dependencies: 11 | # path: ^1.8.0 12 | 13 | dev_dependencies: 14 | lints: ^3.0.0 15 | test: ^1.24.0 16 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/base_test_repo/pkgs/package2/test/package2_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:package2/package2.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | test('calculate', () { 6 | expect(calculate(), 42); 7 | }); 8 | } 9 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/base_test_repo/pkgs/package3/.gitignore: -------------------------------------------------------------------------------- 1 | # https://dart.dev/guides/libraries/private-files 2 | # Created by `dart pub` 3 | .dart_tool/ 4 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/base_test_repo/pkgs/package3/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.0.0 2 | 3 | - Initial version. 4 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/base_test_repo/pkgs/package3/README.md: -------------------------------------------------------------------------------- 1 | A sample command-line application with an entrypoint in `bin/`, library code 2 | in `lib/`, and example unit test in `test/`. 3 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/base_test_repo/pkgs/package3/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the static analysis results for your project (errors, 2 | # warnings, and lints). 3 | # 4 | # This enables the 'recommended' set of lints from `package:lints`. 5 | # This set helps identify many issues that may lead to problems when running 6 | # or consuming Dart code, and enforces writing Dart using a single, idiomatic 7 | # style and format. 8 | # 9 | # If you want a smaller set of lints you can change this to specify 10 | # 'package:lints/core.yaml'. These are just the most critical lints 11 | # (the recommended set includes the core lints). 12 | # The core lints are also what is used by pub.dev for scoring packages. 13 | 14 | include: package:lints/recommended.yaml 15 | 16 | # Uncomment the following section to specify additional rules. 17 | 18 | # linter: 19 | # rules: 20 | # - camel_case_types 21 | 22 | # analyzer: 23 | # exclude: 24 | # - path/to/excluded/files/** 25 | 26 | # For more information about the core and recommended set of lints, see 27 | # https://dart.dev/go/core-lints 28 | 29 | # For additional information about configuring this file, see 30 | # https://dart.dev/guides/language/analysis-options 31 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/base_test_repo/pkgs/package3/bin/package3.dart: -------------------------------------------------------------------------------- 1 | import 'package:package3/package3.dart' as package3; 2 | 3 | void main(List arguments) { 4 | print('Hello world: ${package3.calculate()}!'); 5 | } 6 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/base_test_repo/pkgs/package3/lib/package3.dart: -------------------------------------------------------------------------------- 1 | int calculate() { 2 | return 6 * 7; 3 | } 4 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/base_test_repo/pkgs/package3/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: package3 2 | description: A sample command-line application. 3 | version: 1.0.0 4 | # repository: https://github.com/my_org/my_repo 5 | 6 | environment: 7 | sdk: ^3.1.0 8 | 9 | # Add regular dependencies here. 10 | dependencies: 11 | # path: ^1.8.0 12 | 13 | dev_dependencies: 14 | lints: ^3.0.0 15 | test: ^1.24.0 16 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/base_test_repo/pkgs/package3/test/package3_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:package3/package3.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | test('calculate', () { 6 | expect(calculate(), 42); 7 | }); 8 | } 9 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/base_test_repo/pkgs/package5/lib/package5.dart: -------------------------------------------------------------------------------- 1 | /// Support for doing something awesome. 2 | /// 3 | /// More dartdocs go here. 4 | library; 5 | 6 | export 'src/package5_base.dart' show Awesome; 7 | 8 | // TODO: Export any libraries intended for clients of this package. 9 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/base_test_repo/pkgs/package5/lib/src/package5_base.dart: -------------------------------------------------------------------------------- 1 | // TODO: Put public facing types in this file. 2 | 3 | /// Checks if you are awesome. Spoiler: you are. 4 | class Awesome { 5 | bool get isAwesome => true; 6 | } 7 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/base_test_repo/pkgs/package5/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: package5 2 | description: A starting point for Dart libraries or applications. 3 | version: 1.0.0 4 | # repository: https://github.com/my_org/my_repo 5 | 6 | environment: 7 | sdk: ^3.1.0 8 | 9 | # Add regular dependencies here. 10 | dependencies: 11 | # path: ^1.8.0 12 | 13 | dev_dependencies: 14 | lints: ^3.0.0 15 | test: ^1.24.0 16 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/golden/comment_breaking.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | Breaking changes :warning: 4 | 5 | 6 | | Package | Change | Current Version | New Version | Needed Version | Looking good? | 7 | | :--- | :--- | ---: | ---: | ---: | ---: | 8 | |package1|None|1.0.0|1.0.0|1.0.0|:heavy_check_mark:| 9 | |package2|Non-Breaking|1.0.0|1.0.0|**1.1.0**
Got "1.0.0" expected >= "1.1.0" (non-breaking changes)|:warning:| 10 | |package5|Non-Breaking|1.0.0|1.2.0|1.1.0|:heavy_check_mark:| 11 | 12 | 13 | This check can be disabled by tagging the PR with `skip-breaking-check`. 14 |
15 | 16 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/golden/comment_breaking_healthchanged.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | Breaking changes :warning: 4 | 5 | 6 | | Package | Change | Current Version | New Version | Needed Version | Looking good? | 7 | | :--- | :--- | ---: | ---: | ---: | ---: | 8 | |package1|None|1.0.0|1.0.0|1.0.0|:heavy_check_mark:| 9 | |package2|Non-Breaking|1.0.0|1.0.0|**1.1.0**
Got "1.0.0" expected >= "1.1.0" (non-breaking changes)|:warning:| 10 | |package3|None|1.0.0|1.0.0|1.0.0|:heavy_check_mark:| 11 | |package5|Non-Breaking|1.0.0|1.2.0|1.1.0|:heavy_check_mark:| 12 | 13 | 14 | This check can be disabled by tagging the PR with `skip-breaking-check`. 15 |
16 | 17 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/golden/comment_breaking_ignore_package.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | Breaking changes :warning: 4 | 5 | 6 | | Package | Change | Current Version | New Version | Needed Version | Looking good? | 7 | | :--- | :--- | ---: | ---: | ---: | ---: | 8 | |package2|Non-Breaking|1.0.0|1.0.0|**1.1.0**
Got "1.0.0" expected >= "1.1.0" (non-breaking changes)|:warning:| 9 | |package5|Non-Breaking|1.0.0|1.2.0|1.1.0|:heavy_check_mark:| 10 | 11 | 12 | This check can be disabled by tagging the PR with `skip-breaking-check`. 13 |
14 | 15 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/golden/comment_changelog.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | Changelog Entry :exclamation: 4 | 5 | 6 | | Package | Changed Files | 7 | | :--- | :--- | 8 | | package:package1 | pkgs/package1/bin/package1.dart | 9 | | package:package2 | pkgs/package2/lib/anotherLib.dart | 10 | 11 | Changes to files need to be [accounted for](https://github.com/dart-lang/ecosystem/wiki/Changelog) in their respective changelogs. 12 | 13 | 14 | This check can be disabled by tagging the PR with `skip-changelog-check`. 15 |
16 | 17 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/golden/comment_changelog_healthchanged.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | Changelog Entry :exclamation: 4 | 5 | 6 | | Package | Changed Files | 7 | | :--- | :--- | 8 | | package:package1 | pkgs/package1/bin/package1.dart | 9 | | package:package2 | pkgs/package2/lib/anotherLib.dart | 10 | 11 | Changes to files need to be [accounted for](https://github.com/dart-lang/ecosystem/wiki/Changelog) in their respective changelogs. 12 | 13 | 14 | This check can be disabled by tagging the PR with `skip-changelog-check`. 15 |
16 | 17 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/golden/comment_changelog_ignore_package.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | Changelog Entry :exclamation: 4 | 5 | 6 | | Package | Changed Files | 7 | | :--- | :--- | 8 | | package:package2 | pkgs/package2/lib/anotherLib.dart | 9 | 10 | Changes to files need to be [accounted for](https://github.com/dart-lang/ecosystem/wiki/Changelog) in their respective changelogs. 11 | 12 | 13 | This check can be disabled by tagging the PR with `skip-changelog-check`. 14 |
15 | 16 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/golden/comment_coverage.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | Coverage :warning: 4 | 5 | 6 | | File | Coverage | 7 | | :--- | :--- | 8 | |pkgs/package1/bin/package1.dart| :broken_heart: Not covered | 9 | |pkgs/package2/lib/anotherLib.dart| :green_heart: 100 % | 10 | |pkgs/package5/lib/src/package5_base.dart| :broken_heart: Not covered | 11 | 12 | This check for [test coverage](https://github.com/dart-lang/ecosystem/wiki/Test-Coverage) is informational (issues shown here will not fail the PR). 13 | 14 | 15 | This check can be disabled by tagging the PR with `skip-coverage-check`. 16 |
17 | 18 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/golden/comment_coverage_healthchanged.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | Coverage :warning: 4 | 5 | 6 | | File | Coverage | 7 | | :--- | :--- | 8 | |pkgs/package1/bin/package1.dart| :broken_heart: Not covered | 9 | |pkgs/package1/lib/package1.dart| :green_heart: 100 % | 10 | |pkgs/package2/bin/package2.dart| :broken_heart: Not covered | 11 | |pkgs/package2/lib/anotherLib.dart| :green_heart: 100 % | 12 | |pkgs/package2/lib/package2.dart| :green_heart: 100 % | 13 | |pkgs/package3/bin/package3.dart| :broken_heart: Not covered | 14 | |pkgs/package3/lib/package3.dart| :green_heart: 100 % | 15 | |pkgs/package5/lib/package5.dart| :broken_heart: Not covered | 16 | |pkgs/package5/lib/src/package5_base.dart| :broken_heart: Not covered | 17 | 18 | This check for [test coverage](https://github.com/dart-lang/ecosystem/wiki/Test-Coverage) is informational (issues shown here will not fail the PR). 19 | 20 | 21 | This check can be disabled by tagging the PR with `skip-coverage-check`. 22 |
23 | 24 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/golden/comment_coverage_ignore_package.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | Coverage :warning: 4 | 5 | 6 | | File | Coverage | 7 | | :--- | :--- | 8 | |pkgs/package2/lib/anotherLib.dart| :green_heart: 100 % | 9 | |pkgs/package5/lib/src/package5_base.dart| :broken_heart: Not covered | 10 | 11 | This check for [test coverage](https://github.com/dart-lang/ecosystem/wiki/Test-Coverage) is informational (issues shown here will not fail the PR). 12 | 13 | 14 | This check can be disabled by tagging the PR with `skip-coverage-check`. 15 |
16 | 17 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/golden/comment_do-not-submit.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | Do Not Submit :exclamation: 4 | 5 | 6 | Body contains `DO_NOT_SUBMIT`: false 7 | 8 | | Files with `DO_NOT_SUBMIT` | 9 | | :--- | 10 | |pkgs/package1/bin/package1.dart| 11 | 12 | 13 | This check can be disabled by tagging the PR with `skip-do-not-submit-check`. 14 |
15 | 16 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/golden/comment_do-not-submit_healthchanged.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | Do Not Submit :exclamation: 4 | 5 | 6 | Body contains `DO_NOT_SUBMIT`: false 7 | 8 | | Files with `DO_NOT_SUBMIT` | 9 | | :--- | 10 | |pkgs/package1/bin/package1.dart| 11 | 12 | 13 | This check can be disabled by tagging the PR with `skip-do-not-submit-check`. 14 |
15 | 16 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/golden/comment_do-not-submit_ignore_package.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dart-lang/ecosystem/64aac3a9c4606950bcf6c8729f01ed8548b9ed87/pkgs/firehose/test_data/golden/comment_do-not-submit_ignore_package.md -------------------------------------------------------------------------------- /pkgs/firehose/test_data/golden/comment_leaking.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | API leaks :warning: 4 | 5 | 6 | The following packages contain symbols visible in the public API, but not exported by the library. Export these symbols or remove them from your publicly visible API. 7 | 8 | | Package | Leaked API symbols | 9 | | :--- | :--- | 10 | |package5|NonExported
NonExported2
TransitiveNonExported| 11 | 12 | 13 | This check can be disabled by tagging the PR with `skip-leaking-check`. 14 |
15 | 16 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/golden/comment_leaking_healthchanged.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | API leaks :warning: 4 | 5 | 6 | The following packages contain symbols visible in the public API, but not exported by the library. Export these symbols or remove them from your publicly visible API. 7 | 8 | | Package | Leaked API symbols | 9 | | :--- | :--- | 10 | |package5|NonExported
NonExported2
TransitiveNonExported| 11 | 12 | 13 | This check can be disabled by tagging the PR with `skip-leaking-check`. 14 |
15 | 16 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/golden/comment_leaking_ignore_package.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | API leaks :warning: 4 | 5 | 6 | The following packages contain symbols visible in the public API, but not exported by the library. Export these symbols or remove them from your publicly visible API. 7 | 8 | | Package | Leaked API symbols | 9 | | :--- | :--- | 10 | |package5|NonExported
NonExported2
TransitiveNonExported| 11 | 12 | 13 | This check can be disabled by tagging the PR with `skip-leaking-check`. 14 |
15 | 16 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/golden/comment_license.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | License Headers :exclamation: 4 | 5 | 6 | ``` 7 | // Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file 8 | // for details. All rights reserved. Use of this source code is governed by a 9 | // BSD-style license that can be found in the LICENSE file. 10 | ``` 11 | 12 | | Files | 13 | | :--- | 14 | |pkgs/package1/bin/package1.dart| 15 | |pkgs/package5/lib/src/package5_base.dart| 16 | 17 | All source files should start with a [license header](https://github.com/dart-lang/ecosystem/wiki/License-Header). 18 | 19 |
20 | 21 | Unrelated files missing license headers 22 | 23 | 24 | | Files | 25 | | :--- | 26 | |pkgs/package1/lib/package1.dart| 27 | |pkgs/package1/test/package1_test.dart| 28 | |pkgs/package2/lib/package2.dart| 29 | |pkgs/package2/test/package2_test.dart| 30 | |pkgs/package3/bin/package3.dart| 31 | |pkgs/package3/lib/package3.dart| 32 | |pkgs/package3/test/package3_test.dart| 33 | |pkgs/package5/lib/package5.dart| 34 |
35 | 36 | 37 | 38 | 39 | This check can be disabled by tagging the PR with `skip-license-check`. 40 |
41 | 42 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/golden/comment_license_healthchanged.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | License Headers :exclamation: 4 | 5 | 6 | ``` 7 | // Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file 8 | // for details. All rights reserved. Use of this source code is governed by a 9 | // BSD-style license that can be found in the LICENSE file. 10 | ``` 11 | 12 | | Files | 13 | | :--- | 14 | |pkgs/package1/bin/package1.dart| 15 | |pkgs/package1/lib/package1.dart| 16 | |pkgs/package1/test/package1_test.dart| 17 | |pkgs/package2/lib/package2.dart| 18 | |pkgs/package2/test/package2_test.dart| 19 | |pkgs/package3/bin/package3.dart| 20 | |pkgs/package3/lib/package3.dart| 21 | |pkgs/package3/test/package3_test.dart| 22 | |pkgs/package5/lib/package5.dart| 23 | |pkgs/package5/lib/src/package5_base.dart| 24 | 25 | All source files should start with a [license header](https://github.com/dart-lang/ecosystem/wiki/License-Header). 26 | 27 | 28 | 29 | 30 | 31 | This check can be disabled by tagging the PR with `skip-license-check`. 32 |
33 | 34 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/golden/comment_license_ignore_license.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | License Headers :exclamation: 4 | 5 | 6 | ``` 7 | // Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file 8 | // for details. All rights reserved. Use of this source code is governed by a 9 | // BSD-style license that can be found in the LICENSE file. 10 | ``` 11 | 12 | | Files | 13 | | :--- | 14 | |pkgs/package1/bin/package1.dart| 15 | |pkgs/package5/lib/src/package5_base.dart| 16 | 17 | All source files should start with a [license header](https://github.com/dart-lang/ecosystem/wiki/License-Header). 18 | 19 |
20 | 21 | Unrelated files missing license headers 22 | 23 | 24 | | Files | 25 | | :--- | 26 | |pkgs/package1/lib/package1.dart| 27 | |pkgs/package1/test/package1_test.dart| 28 | |pkgs/package2/lib/package2.dart| 29 | |pkgs/package2/test/package2_test.dart| 30 | |pkgs/package5/lib/package5.dart| 31 |
32 | 33 | 34 | 35 | 36 | This check can be disabled by tagging the PR with `skip-license-check`. 37 |
38 | 39 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/golden/comment_license_ignore_package.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | License Headers :exclamation: 4 | 5 | 6 | ``` 7 | // Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file 8 | // for details. All rights reserved. Use of this source code is governed by a 9 | // BSD-style license that can be found in the LICENSE file. 10 | ``` 11 | 12 | | Files | 13 | | :--- | 14 | |pkgs/package5/lib/src/package5_base.dart| 15 | 16 | All source files should start with a [license header](https://github.com/dart-lang/ecosystem/wiki/License-Header). 17 | 18 |
19 | 20 | Unrelated files missing license headers 21 | 22 | 23 | | Files | 24 | | :--- | 25 | |pkgs/package2/lib/package2.dart| 26 | |pkgs/package2/test/package2_test.dart| 27 | |pkgs/package3/bin/package3.dart| 28 | |pkgs/package3/lib/package3.dart| 29 | |pkgs/package3/test/package3_test.dart| 30 | |pkgs/package5/lib/package5.dart| 31 |
32 | 33 | 34 | 35 | 36 | This check can be disabled by tagging the PR with `skip-license-check`. 37 |
38 | 39 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/root_unpublished_pkg/pkg_1/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: pkg_1 2 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/root_unpublished_pkg/pkg_2/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: pkg_2 2 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/root_unpublished_pkg/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: root 2 | publish_to: none 3 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/test_repo/pkgs/package1/.gitignore: -------------------------------------------------------------------------------- 1 | # https://dart.dev/guides/libraries/private-files 2 | # Created by `dart pub` 3 | .dart_tool/ 4 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/test_repo/pkgs/package1/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.0.0 2 | 3 | - Initial version. 4 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/test_repo/pkgs/package1/README.md: -------------------------------------------------------------------------------- 1 | A sample command-line application with an entrypoint in `bin/`, library code 2 | in `lib/`, and example unit test in `test/`. 3 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/test_repo/pkgs/package1/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the static analysis results for your project (errors, 2 | # warnings, and lints). 3 | # 4 | # This enables the 'recommended' set of lints from `package:lints`. 5 | # This set helps identify many issues that may lead to problems when running 6 | # or consuming Dart code, and enforces writing Dart using a single, idiomatic 7 | # style and format. 8 | # 9 | # If you want a smaller set of lints you can change this to specify 10 | # 'package:lints/core.yaml'. These are just the most critical lints 11 | # (the recommended set includes the core lints). 12 | # The core lints are also what is used by pub.dev for scoring packages. 13 | 14 | include: package:lints/recommended.yaml 15 | 16 | # Uncomment the following section to specify additional rules. 17 | 18 | # linter: 19 | # rules: 20 | # - camel_case_types 21 | 22 | # analyzer: 23 | # exclude: 24 | # - path/to/excluded/files/** 25 | 26 | # For more information about the core and recommended set of lints, see 27 | # https://dart.dev/go/core-lints 28 | 29 | # For additional information about configuring this file, see 30 | # https://dart.dev/guides/language/analysis-options 31 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/test_repo/pkgs/package1/bin/package1.dart: -------------------------------------------------------------------------------- 1 | import 'package:package1/package1.dart' as package1; 2 | 3 | void main(List arguments) { 4 | // Add a comment DO_NOT_SUBMIT 5 | print('Hello world: ${package1.calculate()}!'); 6 | } 7 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/test_repo/pkgs/package1/lib/package1.dart: -------------------------------------------------------------------------------- 1 | int calculate() { 2 | return 6 * 7; 3 | } 4 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/test_repo/pkgs/package1/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: package1 2 | description: A sample command-line application. 3 | version: 1.0.0 4 | # repository: https://github.com/my_org/my_repo 5 | 6 | environment: 7 | sdk: ^3.1.0 8 | 9 | # Add regular dependencies here. 10 | dependencies: 11 | # path: ^1.8.0 12 | 13 | dev_dependencies: 14 | lints: ^3.0.0 15 | test: ^1.24.0 16 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/test_repo/pkgs/package1/test/package1_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:package1/package1.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | test('calculate', () { 6 | expect(calculate(), 42); 7 | }); 8 | } 9 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/test_repo/pkgs/package2/.gitignore: -------------------------------------------------------------------------------- 1 | # https://dart.dev/guides/libraries/private-files 2 | # Created by `dart pub` 3 | .dart_tool/ 4 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/test_repo/pkgs/package2/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.0.0 2 | 3 | - Initial version. 4 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/test_repo/pkgs/package2/README.md: -------------------------------------------------------------------------------- 1 | A sample command-line application with an entrypoint in `bin/`, library code 2 | in `lib/`, and example unit test in `test/`. 3 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/test_repo/pkgs/package2/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the static analysis results for your project (errors, 2 | # warnings, and lints). 3 | # 4 | # This enables the 'recommended' set of lints from `package:lints`. 5 | # This set helps identify many issues that may lead to problems when running 6 | # or consuming Dart code, and enforces writing Dart using a single, idiomatic 7 | # style and format. 8 | # 9 | # If you want a smaller set of lints you can change this to specify 10 | # 'package:lints/core.yaml'. These are just the most critical lints 11 | # (the recommended set includes the core lints). 12 | # The core lints are also what is used by pub.dev for scoring packages. 13 | 14 | include: package:lints/recommended.yaml 15 | 16 | # Uncomment the following section to specify additional rules. 17 | 18 | # linter: 19 | # rules: 20 | # - camel_case_types 21 | 22 | # analyzer: 23 | # exclude: 24 | # - path/to/excluded/files/** 25 | 26 | # For more information about the core and recommended set of lints, see 27 | # https://dart.dev/go/core-lints 28 | 29 | # For additional information about configuring this file, see 30 | # https://dart.dev/guides/language/analysis-options 31 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/test_repo/pkgs/package2/bin/package2.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:package2/package2.dart' as package2; 6 | 7 | void main(List arguments) { 8 | print('Hello world: ${package2.calculate()}!'); 9 | } 10 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/test_repo/pkgs/package2/lib/anotherLib.dart: -------------------------------------------------------------------------------- 1 | // SOME COMMENT 2 | // THIS IS A GENERATED FILE 3 | 4 | int calculateUnused() { 5 | return 6 * 7; 6 | } 7 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/test_repo/pkgs/package2/lib/package2.dart: -------------------------------------------------------------------------------- 1 | int calculate() { 2 | return 6 * 7; 3 | } 4 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/test_repo/pkgs/package2/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: package2 2 | description: A sample command-line application. 3 | version: 1.0.0 4 | # repository: https://github.com/my_org/my_repo 5 | 6 | environment: 7 | sdk: ^3.1.0 8 | 9 | # Add regular dependencies here. 10 | dependencies: 11 | # path: ^1.8.0 12 | 13 | dev_dependencies: 14 | lints: ^3.0.0 15 | test: ^1.24.0 16 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/test_repo/pkgs/package2/someImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dart-lang/ecosystem/64aac3a9c4606950bcf6c8729f01ed8548b9ed87/pkgs/firehose/test_data/test_repo/pkgs/package2/someImage.png -------------------------------------------------------------------------------- /pkgs/firehose/test_data/test_repo/pkgs/package2/test/package2_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:package2/anotherLib.dart' as anotherLib; 2 | import 'package:package2/package2.dart' as p2; 3 | import 'package:test/test.dart'; 4 | 5 | void main() { 6 | test('calculate', () { 7 | expect(p2.calculate(), 42); 8 | }); 9 | test('calculate anotherlib', () { 10 | expect(anotherLib.calculateUnused(), 42); 11 | }); 12 | } 13 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/test_repo/pkgs/package3/.gitignore: -------------------------------------------------------------------------------- 1 | # https://dart.dev/guides/libraries/private-files 2 | # Created by `dart pub` 3 | .dart_tool/ 4 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/test_repo/pkgs/package3/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.0.0 2 | 3 | - Initial version. 4 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/test_repo/pkgs/package3/README.md: -------------------------------------------------------------------------------- 1 | A sample command-line application with an entrypoint in `bin/`, library code 2 | in `lib/`, and example unit test in `test/`. 3 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/test_repo/pkgs/package3/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the static analysis results for your project (errors, 2 | # warnings, and lints). 3 | # 4 | # This enables the 'recommended' set of lints from `package:lints`. 5 | # This set helps identify many issues that may lead to problems when running 6 | # or consuming Dart code, and enforces writing Dart using a single, idiomatic 7 | # style and format. 8 | # 9 | # If you want a smaller set of lints you can change this to specify 10 | # 'package:lints/core.yaml'. These are just the most critical lints 11 | # (the recommended set includes the core lints). 12 | # The core lints are also what is used by pub.dev for scoring packages. 13 | 14 | include: package:lints/recommended.yaml 15 | 16 | # Uncomment the following section to specify additional rules. 17 | 18 | # linter: 19 | # rules: 20 | # - camel_case_types 21 | 22 | # analyzer: 23 | # exclude: 24 | # - path/to/excluded/files/** 25 | 26 | # For more information about the core and recommended set of lints, see 27 | # https://dart.dev/go/core-lints 28 | 29 | # For additional information about configuring this file, see 30 | # https://dart.dev/guides/language/analysis-options 31 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/test_repo/pkgs/package3/bin/package3.dart: -------------------------------------------------------------------------------- 1 | import 'package:package3/package3.dart' as package3; 2 | 3 | void main(List arguments) { 4 | print('Hello world: ${package3.calculate()}!'); 5 | } 6 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/test_repo/pkgs/package3/lib/package3.dart: -------------------------------------------------------------------------------- 1 | int calculate() { 2 | return 6 * 7; 3 | } 4 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/test_repo/pkgs/package3/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: package3 2 | description: A sample command-line application. 3 | version: 1.0.0 4 | # repository: https://github.com/my_org/my_repo 5 | 6 | environment: 7 | sdk: ^3.1.0 8 | 9 | # Add regular dependencies here. 10 | dependencies: 11 | # path: ^1.8.0 12 | 13 | dev_dependencies: 14 | lints: ^3.0.0 15 | test: ^1.24.0 16 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/test_repo/pkgs/package3/test/package3_test.dart: -------------------------------------------------------------------------------- 1 | import 'package:package3/package3.dart'; 2 | import 'package:test/test.dart'; 3 | 4 | void main() { 5 | test('calculate', () { 6 | expect(calculate(), 42); 7 | }); 8 | } 9 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/test_repo/pkgs/package5/lib/package5.dart: -------------------------------------------------------------------------------- 1 | /// Support for doing something awesome. 2 | /// 3 | /// More dartdocs go here. 4 | library; 5 | 6 | export 'src/package5_base.dart' show Awesome; 7 | 8 | // TODO: Export any libraries intended for clients of this package. 9 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/test_repo/pkgs/package5/lib/src/package5_base.dart: -------------------------------------------------------------------------------- 1 | // TODO: Put public facing types in this file. 2 | 3 | /// Checks if you are awesome. Spoiler: you are. 4 | class Awesome { 5 | bool get isAwesome => true; 6 | 7 | NonExported get myClass => NonExported(); 8 | NonExported2 get myClass2 => NonExported2(); 9 | } 10 | 11 | class NonExported {} 12 | 13 | class NonExported2 { 14 | TransitiveNonExported get myClass => TransitiveNonExported(); 15 | } 16 | 17 | class TransitiveNonExported {} 18 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/test_repo/pkgs/package5/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: package5 2 | description: A starting point for Dart libraries or applications. 3 | version: 1.2.0 4 | # repository: https://github.com/my_org/my_repo 5 | 6 | environment: 7 | sdk: ^3.1.0 8 | 9 | # Add regular dependencies here. 10 | dependencies: 11 | # path: ^1.8.0 12 | 13 | dev_dependencies: 14 | lints: ^3.0.0 15 | test: ^1.24.0 16 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/workspace_repo/pkg_1/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: pkg_1 2 | resolution: workspace 3 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/workspace_repo/pkg_2/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: pkg_2 2 | resolution: workspace 3 | -------------------------------------------------------------------------------- /pkgs/firehose/test_data/workspace_repo/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: workspace 2 | workspace: 3 | - pkg_1 4 | - pkg_2 5 | -------------------------------------------------------------------------------- /pkgs/puppy/README.md: -------------------------------------------------------------------------------- 1 | ## What's this? 2 | 3 | A package for miscellaneous Dart CLI tools. 4 | 5 | ### Running 6 | 7 | Activate locally using: 8 | 9 | ```console 10 | cd 11 | dart pub global activate --source=path . 12 | ``` 13 | 14 | ### Commands 15 | 16 | - `run`: runs a command in every directory containing `pubspec.yaml`. 17 | -------------------------------------------------------------------------------- /pkgs/puppy/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:dart_flutter_team_lints/analysis_options.yaml 2 | -------------------------------------------------------------------------------- /pkgs/puppy/bin/puppy.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:args/command_runner.dart'; 6 | import 'package:puppy/src/constants.dart'; 7 | import 'package:puppy/src/run_command.dart'; 8 | 9 | Future main(List args) async { 10 | var runner = CommandRunner(cmdName, 'Dart repository management tools.') 11 | ..addCommand(RunCommand()); 12 | 13 | await runner.run(args); 14 | } 15 | -------------------------------------------------------------------------------- /pkgs/puppy/lib/src/constants.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | const cmdName = 'puppy'; 6 | -------------------------------------------------------------------------------- /pkgs/puppy/lib/src/run_command.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:async'; 6 | import 'dart:io'; 7 | 8 | import 'package:args/command_runner.dart'; 9 | import 'package:build_cli_annotations/build_cli_annotations.dart'; 10 | import 'package:io/ansi.dart'; 11 | import 'package:path/path.dart' as p; 12 | 13 | import 'constants.dart'; 14 | import 'utils.dart'; 15 | 16 | part 'run_command.g.dart'; 17 | 18 | class RunCommand extends _$RunArgsCommand { 19 | @override 20 | String get description => 21 | 'Run the provided command in each subdirectory containing ' 22 | '`pubspec.yaml`.'; 23 | 24 | @override 25 | String get name => 'run'; 26 | 27 | @override 28 | Future? run() async { 29 | final args = _options; 30 | 31 | final exe = args.rest.first; 32 | final extraArgs = args.rest.skip(1).toList(); 33 | 34 | final packages = findPackages(Directory.current, deep: args.deep); 35 | final exits = {}; 36 | 37 | var count = 0; 38 | for (final packageDir in packages) { 39 | final relative = p.relative(packageDir.path); 40 | 41 | print( 42 | green.wrap('$relative (${++count} of ${packages.length})'), 43 | ); 44 | final proc = await Process.start( 45 | exe, 46 | extraArgs, 47 | mode: ProcessStartMode.inheritStdio, 48 | workingDirectory: packageDir.path, 49 | ); 50 | 51 | // TODO(kevmoo): display a summary of results on completion 52 | exits[packageDir.path] = await proc.exitCode; 53 | 54 | print(''); 55 | } 56 | } 57 | } 58 | 59 | @CliOptions(createCommand: true) 60 | class RunArgs { 61 | @CliOption(abbr: 'd', help: 'Keep looking for "nested" pubspec files.') 62 | final bool deep; 63 | 64 | final List rest; 65 | 66 | RunArgs({ 67 | this.deep = false, 68 | required this.rest, 69 | }) { 70 | if (rest.isEmpty) { 71 | throw UsageException( 72 | 'Missing command to invoke!', 73 | '$cmdName map [--deep] ', 74 | ); 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /pkgs/puppy/lib/src/run_command.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'run_command.dart'; 4 | 5 | // ************************************************************************** 6 | // CliGenerator 7 | // ************************************************************************** 8 | 9 | RunArgs _$parseRunArgsResult(ArgResults result) => RunArgs( 10 | deep: result['deep'] as bool, 11 | rest: result.rest, 12 | ); 13 | 14 | ArgParser _$populateRunArgsParser(ArgParser parser) => parser 15 | ..addFlag( 16 | 'deep', 17 | abbr: 'd', 18 | help: 'Keep looking for "nested" pubspec files.', 19 | ); 20 | 21 | final _$parserForRunArgs = _$populateRunArgsParser(ArgParser()); 22 | 23 | RunArgs parseRunArgs(List args) { 24 | final result = _$parserForRunArgs.parse(args); 25 | return _$parseRunArgsResult(result); 26 | } 27 | 28 | abstract class _$RunArgsCommand extends Command { 29 | _$RunArgsCommand() { 30 | _$populateRunArgsParser(argParser); 31 | } 32 | 33 | late final _options = _$parseRunArgsResult(argResults!); 34 | } 35 | -------------------------------------------------------------------------------- /pkgs/puppy/lib/src/utils.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:io'; 6 | 7 | List findPackages(Directory root, {bool deep = false}) { 8 | final results = []; 9 | 10 | void traverse(Directory dir, {required bool deep}) { 11 | final pubspecs = dir 12 | .listSync() 13 | .whereType() 14 | .where((element) => element.uri.pathSegments.last == 'pubspec.yaml') 15 | .toList(); 16 | 17 | if (pubspecs.isNotEmpty) { 18 | results.add(dir); 19 | } 20 | 21 | if (!pubspecs.isNotEmpty || deep) { 22 | for (var subDir in dir.listSync().whereType().where( 23 | (element) => !element.uri.pathSegments 24 | .any((element) => element.startsWith('.')))) { 25 | traverse(subDir, deep: deep); 26 | } 27 | } 28 | } 29 | 30 | traverse(Directory.current, deep: deep); 31 | 32 | results.sort((a, b) => a.path.compareTo(b.path)); 33 | 34 | return results; 35 | } 36 | -------------------------------------------------------------------------------- /pkgs/puppy/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: puppy 2 | description: A package for miscellaneous Dart CLI tools. 3 | publish_to: none 4 | 5 | environment: 6 | sdk: ^3.6.0 7 | 8 | dependencies: 9 | args: ^2.6.0 10 | build_cli_annotations: ^2.1.0 11 | io: ^1.0.5 12 | path: ^1.9.1 13 | 14 | dev_dependencies: 15 | build_cli: ^2.2.4 16 | build_runner: ^2.4.14 17 | dart_flutter_team_lints: ^3.0.0 18 | 19 | executables: 20 | puppy: 21 | -------------------------------------------------------------------------------- /pkgs/repo_manage/.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | -------------------------------------------------------------------------------- /pkgs/repo_manage/README.md: -------------------------------------------------------------------------------- 1 | Various and miscellaneous commands to query dart-lang github repos. 2 | 3 | ## Usage 4 | 5 | ``` 6 | Run various reports on Dart and Flutter related repositories. 7 | 8 | Usage: report [arguments] 9 | 10 | Global options: 11 | -h, --help Print this usage information. 12 | 13 | Available commands: 14 | branches Show the default branch names of Dart and Flutter repos. 15 | labels Report on the various labels in use by dart-lang repos. 16 | labels-update Audit and update the labels used by dart-lang repos. 17 | transfer-issues Bulk transfer issues from one repo to another. 18 | weekly Run a week-based report on repo status and activity. 19 | 20 | Run "report help " for more information about a command. 21 | ``` 22 | 23 | ## Useful dart-lang GitHub searches 24 | 25 | dart-lang P0 issues: 26 | 27 | - https://github.com/issues?q=is%3Aopen+is%3Aissue+archived%3Afalse+org%3Adart-lang+label%3AP0 28 | 29 | dart-lang P1 issues: 30 | - https://github.com/issues?q=is%3Aopen+is%3Aissue+archived%3Afalse+org%3Adart-lang+label%3AP1 31 | 32 | dart-lang PRs with no review: 33 | - https://github.com/pulls?q=is%3Aopen+is%3Apr+archived%3Afalse+org%3Adart-lang+review%3Anone 34 | 35 | dart-lang issues with more than 75 reactions: 36 | - https://github.com/issues?q=is%3Aopen+is%3Aissue+archived%3Afalse+org%3Adart-lang+reactions%3A%3E75+sort%3Areactions-%2B1-desc+ 37 | 38 | dart-lang issues with no label: 39 | - https://github.com/issues?q=is%3Aopen+is%3Aissue+archived%3Afalse+org%3Adart-lang+no%3Alabel 40 | -------------------------------------------------------------------------------- /pkgs/repo_manage/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:dart_flutter_team_lints/analysis_options.yaml 2 | -------------------------------------------------------------------------------- /pkgs/repo_manage/bin/report.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:io'; 6 | 7 | import 'package:repo_manage/src/common.dart'; 8 | 9 | void main(List args) async { 10 | final runner = ReportCommandRunner(); 11 | exit(await runner.run(args) ?? 0); 12 | } 13 | -------------------------------------------------------------------------------- /pkgs/repo_manage/lib/branches.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'src/common.dart'; 6 | 7 | class BranchesCommand extends ReportCommand { 8 | BranchesCommand() 9 | : super('branches', 10 | 'Show the default branch names of Dart and Flutter repos.'); 11 | 12 | @override 13 | Future run() async { 14 | print('Repository, Default branch, Stars'); 15 | 16 | for (var org in ['dart-lang', 'flutter']) { 17 | var repos = await getReposForOrg(org); 18 | 19 | for (var repo in repos) { 20 | print('$org/${repo.name}, ${repo.defaultBranch}, ' 21 | '${repo.stargazersCount}'); 22 | } 23 | } 24 | 25 | return 0; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /pkgs/repo_manage/lib/labels.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:math'; 6 | 7 | import 'package:github/github.dart'; 8 | 9 | import 'src/common.dart'; 10 | 11 | class LabelsCommand extends ReportCommand { 12 | LabelsCommand() 13 | : super('labels', 14 | 'Report on the various labels in use by dart-lang repos.'); 15 | 16 | @override 17 | Future run() async { 18 | var repos = await getReposForOrg('dart-lang'); 19 | 20 | var results = >{}; 21 | 22 | for (var repo in repos) { 23 | var labels = 24 | await reportRunner.github.issues.listLabels(repo.slug()).toList(); 25 | 26 | results[repo] = labels; 27 | 28 | print('${repo.slug()} has ${results[repo]!.length} labels ' 29 | '(${repo.openIssuesCount} issues, ${repo.stargazersCount} stars).'); 30 | } 31 | 32 | print(''); 33 | 34 | // calculate label usage 35 | var labels = {}; 36 | 37 | for (var entry in results.entries) { 38 | var repo = entry.key; 39 | var openIssues = repo.openIssuesCount; 40 | 41 | // If a repo doesn't have very many issues, we don't want to give too much 42 | // weight to how it's using labels (fewer issues means less need for a 43 | // mature labeling strategy). 44 | if (openIssues < 30) continue; 45 | 46 | for (var label in entry.value) { 47 | var labelInfo = 48 | labels.putIfAbsent(label.name, () => _LabelInfo(label.name)); 49 | 50 | labelInfo.repos.add(repo.name); 51 | labelInfo.weight += log(openIssues); 52 | } 53 | } 54 | 55 | print('Label,Count,Weighted Repo,Repos'); 56 | 57 | var labelUsage = labels.values.toList() 58 | ..sort((a, b) => b.repoCount - a.repoCount); 59 | 60 | for (var info in labelUsage) { 61 | print('${info.name},${info.repoCount},${info.weight.toStringAsFixed(1)},' 62 | '"${info.repoNames}"'); 63 | } 64 | 65 | return 0; 66 | } 67 | } 68 | 69 | class _LabelInfo { 70 | final String name; 71 | final Set repos = {}; 72 | 73 | double weight = 0.0; 74 | 75 | _LabelInfo(this.name); 76 | 77 | int get repoCount => repos.length; 78 | 79 | String get repoNames => (repos.toList()..sort()).join(','); 80 | } 81 | -------------------------------------------------------------------------------- /pkgs/repo_manage/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: repo_manage 2 | description: Miscellaneous issue, repo, and PR query tools. 3 | 4 | publish_to: none 5 | 6 | environment: 7 | sdk: ^3.3.0 8 | 9 | dependencies: 10 | args: ^2.4.0 11 | collection: ^1.17.0 12 | github: ^9.11.0 13 | graphql: ^5.0.0 14 | path: ^1.8.0 15 | 16 | dev_dependencies: 17 | dart_flutter_team_lints: ^3.0.0 18 | -------------------------------------------------------------------------------- /pkgs/sdk_triage_bot/.gitignore: -------------------------------------------------------------------------------- 1 | # https://dart.dev/guides/libraries/private-files 2 | 3 | # Created by `dart pub` 4 | .dart_tool/ 5 | pubspec.lock 6 | 7 | .env 8 | 9 | tool/training.csv 10 | tool/training.jsonl 11 | tool/training.txt 12 | -------------------------------------------------------------------------------- /pkgs/sdk_triage_bot/README.md: -------------------------------------------------------------------------------- 1 | ## What's this? 2 | 3 | A LLM based triage automation system for the dart-lang/sdk repo. It processes 4 | new issues filed against the repo and triages them in the same manner that a 5 | human would. This includes: 6 | 7 | - re-summarizing the issue for clarity 8 | - assigning the issues to an `area-` label (first line triage) 9 | 10 | ## Bot trigger and entry-point 11 | 12 | This bot is generally triggered by a GitHub workflow listening for new issues 13 | on the dart-lang/sdk repo. 14 | 15 | See https://github.com/dart-lang/sdk/blob/main/.github/workflows/issue-triage.yml. 16 | 17 | ## Overview 18 | 19 | The general workflow of the tool is: 20 | 21 | - download the issue information (existing labels, title, first comment) 22 | - ask Gemini to summarize the issue (see [prompts](lib/src/prompts.dart)) 23 | - ask Gemini to classify the issue (see [prompts](lib/src/prompts.dart)) 24 | - create a comment on the issue (`@dart-github-bot`) with the summary; 25 | apply any labels produced as part of the classification 26 | 27 | ## Tuning 28 | 29 | We create a tuned Gemini model in order to improve the performance of 30 | classification. This involves: 31 | 32 | - downloading recent, already triaged issues (~800 issues) 33 | - writing them in a format suitable for tuning (either .csv or .jsonl) 34 | - tuning via the Gemini APIs; this gives us a new model name to use when 35 | calling Gemini (e.g., `model: 'tunedModels/sdk-triage-tuned-prompt-1l96e2n'`) 36 | 37 | See [tool/create_tuning_data.dart](tool/create_tuning_data.dart). 38 | -------------------------------------------------------------------------------- /pkgs/sdk_triage_bot/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:dart_flutter_team_lints/analysis_options.yaml 2 | -------------------------------------------------------------------------------- /pkgs/sdk_triage_bot/bin/triage.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:io' as io; 6 | 7 | import 'package:args/args.dart'; 8 | import 'package:github/github.dart'; 9 | import 'package:http/http.dart' as http; 10 | import 'package:sdk_triage_bot/src/common.dart'; 11 | import 'package:sdk_triage_bot/src/gemini.dart'; 12 | import 'package:sdk_triage_bot/src/github.dart'; 13 | import 'package:sdk_triage_bot/triage.dart'; 14 | 15 | void main(List arguments) async { 16 | final argParser = ArgParser(); 17 | argParser.addFlag('dry-run', 18 | negatable: false, 19 | help: 'Perform triage but don\'t make any actual changes to the issue.'); 20 | argParser.addFlag('force', 21 | negatable: false, 22 | help: 'Make changes to the issue even if it already looks triaged.'); 23 | argParser.addFlag('help', 24 | abbr: 'h', negatable: false, help: 'Print this usage information.'); 25 | 26 | final ArgResults results; 27 | try { 28 | results = argParser.parse(arguments); 29 | } on ArgParserException catch (e) { 30 | print(e.message); 31 | print(''); 32 | print(usage); 33 | print(''); 34 | print(argParser.usage); 35 | io.exit(64); 36 | } 37 | 38 | if (results.flag('help') || results.rest.isEmpty) { 39 | print(usage); 40 | print(''); 41 | print(argParser.usage); 42 | io.exit(results.flag('help') ? 0 : 64); 43 | } 44 | 45 | var issue = results.rest.first; 46 | final dryRun = results.flag('dry-run'); 47 | final forceTriage = results.flag('force'); 48 | 49 | // Accept either an issue number or a url (i.e., 50 | // https://github.com/dart-lang/sdk/issues/55816). 51 | const sdkToken = 'dart-lang/sdk/issues/'; 52 | if (issue.contains(sdkToken)) { 53 | issue = issue.substring(issue.indexOf(sdkToken) + sdkToken.length); 54 | } 55 | 56 | final client = http.Client(); 57 | 58 | final github = GitHub( 59 | auth: Authentication.withToken(githubToken), 60 | client: client, 61 | ); 62 | final githubService = GithubService(github: github); 63 | 64 | final geminiService = GeminiService( 65 | apiKey: geminiKey, 66 | httpClient: client, 67 | ); 68 | 69 | await triage( 70 | int.parse(issue), 71 | dryRun: dryRun, 72 | forceTriage: forceTriage, 73 | githubService: githubService, 74 | geminiService: geminiService, 75 | logger: Logger(), 76 | ); 77 | 78 | client.close(); 79 | } 80 | 81 | const String usage = ''' 82 | A tool to triage issues from https://github.com/dart-lang/sdk. 83 | 84 | usage: dart bin/triage.dart [options] '''; 85 | -------------------------------------------------------------------------------- /pkgs/sdk_triage_bot/lib/src/common.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:io'; 6 | 7 | String? _envFileTokenOrEnvironment({required String key}) { 8 | final envFile = File('.env'); 9 | if (envFile.existsSync()) { 10 | final env = {}; 11 | for (var line in envFile.readAsLinesSync().map((line) => line.trim())) { 12 | if (line.isEmpty || line.startsWith('#')) continue; 13 | var split = line.indexOf('='); 14 | env[line.substring(0, split).trim()] = line.substring(split + 1).trim(); 15 | } 16 | return env[key]; 17 | } else { 18 | return Platform.environment[key]; 19 | } 20 | } 21 | 22 | String get githubToken { 23 | var token = _envFileTokenOrEnvironment(key: 'GITHUB_TOKEN'); 24 | if (token == null) { 25 | throw StateError('This tool expects a github access token in the ' 26 | 'GITHUB_TOKEN environment variable.'); 27 | } 28 | return token; 29 | } 30 | 31 | String get geminiKey { 32 | var token = _envFileTokenOrEnvironment(key: 'GOOGLE_API_KEY'); 33 | if (token == null) { 34 | throw StateError('This tool expects a gemini api key in the ' 35 | 'GOOGLE_API_KEY environment variable.'); 36 | } 37 | return token; 38 | } 39 | 40 | /// Maximal length of body used for querying. 41 | const bodyLengthLimit = 10 * 1024; 42 | 43 | /// The [body], truncated if larger than [bodyLengthLimit]. 44 | String trimmedBody(String body) { 45 | return body.length > bodyLengthLimit 46 | ? body = body.substring(0, bodyLengthLimit) 47 | : body; 48 | } 49 | 50 | class Logger { 51 | void log(String message) { 52 | print(message); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /pkgs/sdk_triage_bot/lib/src/gemini.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:google_generative_ai/google_generative_ai.dart'; 6 | import 'package:http/http.dart' as http; 7 | 8 | class GeminiService { 9 | // Possible values for models: gemini-1.5-pro-latest, gemini-1.5-flash-latest, 10 | // gemini-1.0-pro-latest, gemini-1.5-flash-exp-0827. 11 | static const String classificationModel = 'models/gemini-1.5-flash-latest'; 12 | static const String summarizationModel = 'models/gemini-1.5-flash-latest'; 13 | 14 | final GenerativeModel _summarizeModel; 15 | final GenerativeModel _classifyModel; 16 | 17 | GeminiService({ 18 | required String apiKey, 19 | required http.Client httpClient, 20 | }) : _summarizeModel = GenerativeModel( 21 | model: summarizationModel, 22 | apiKey: apiKey, 23 | generationConfig: GenerationConfig(temperature: 0.2), 24 | httpClient: httpClient, 25 | ), 26 | _classifyModel = GenerativeModel( 27 | // TODO(devoncarew): substitute our tuned model 28 | // model: 'tunedModels/autotune-sdk-triage-tuned-prompt-1l96e2n', 29 | model: classificationModel, 30 | apiKey: apiKey, 31 | generationConfig: GenerationConfig(temperature: 0.2), 32 | httpClient: httpClient, 33 | ); 34 | 35 | /// Call the summarize model with the given prompt. 36 | /// 37 | /// On failures, this will throw a [GenerativeAIException]. 38 | Future summarize(String prompt) { 39 | return _query(_summarizeModel, prompt); 40 | } 41 | 42 | /// Call the classify model with the given prompt. 43 | /// 44 | /// On failures, this will throw a [GenerativeAIException]. 45 | Future> classify(String prompt) async { 46 | final result = await _query(_classifyModel, prompt); 47 | final labels = result.split(',').map((l) => l.trim()).toList()..sort(); 48 | return labels; 49 | } 50 | 51 | Future _query(GenerativeModel model, String prompt) async { 52 | final response = await model.generateContent([Content.text(prompt)]); 53 | return (response.text ?? '').trim(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /pkgs/sdk_triage_bot/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: sdk_triage_bot 2 | description: A triage automation tool for dart-lang/sdk issues. 3 | 4 | publish_to: none 5 | 6 | environment: 7 | sdk: ^3.4.0 8 | 9 | dependencies: 10 | args: ^2.5.0 11 | github: ^9.0.0 12 | google_generative_ai: ^0.4.0 13 | graphql: ^5.1.0 14 | http: ^1.2.0 15 | 16 | dev_dependencies: 17 | dart_flutter_team_lints: ^3.1.0 18 | test: ^1.24.0 19 | -------------------------------------------------------------------------------- /pkgs/sdk_triage_bot/test/fakes.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:github/github.dart'; 6 | import 'package:sdk_triage_bot/src/common.dart'; 7 | import 'package:sdk_triage_bot/src/gemini.dart'; 8 | import 'package:sdk_triage_bot/src/github.dart'; 9 | import 'package:test/test.dart'; 10 | 11 | const int mockIssueNumber = 123; 12 | 13 | class GithubServiceMock implements GithubService { 14 | @override 15 | Future> getAllLabels(RepositorySlug repoSlug) async { 16 | return ['area-analyzer', 'area-vm', 'type-enhancement', 'type-bug']; 17 | } 18 | 19 | Issue returnedIssue = Issue( 20 | url: 'https://github.com/dart-lang/sdk/issues/55869', 21 | title: 'Add full support for service ID zones', 22 | number: mockIssueNumber, 23 | body: 'Lorem ipsum.', 24 | labels: [], 25 | ); 26 | 27 | @override 28 | Future fetchIssue(RepositorySlug sdkSlug, int issueNumber) async { 29 | return returnedIssue; 30 | } 31 | 32 | @override 33 | Future> fetchIssueComments( 34 | RepositorySlug slug, Issue issue) { 35 | return Future.value([]); 36 | } 37 | 38 | String? updatedComment; 39 | 40 | @override 41 | Future createComment( 42 | RepositorySlug sdkSlug, int issueNumber, String comment) async { 43 | updatedComment = comment; 44 | } 45 | 46 | List? updatedLabels; 47 | 48 | @override 49 | Future addLabelsToIssue( 50 | RepositorySlug sdkSlug, int issueNumber, List newLabels) async { 51 | updatedLabels = newLabels; 52 | } 53 | } 54 | 55 | class GeminiServiceStub implements GeminiService { 56 | @override 57 | Future summarize(String prompt) async { 58 | return 'Lorem ipsum.'; 59 | } 60 | 61 | @override 62 | Future> classify(String prompt) async { 63 | return ['area-vm', 'type-bug']; 64 | } 65 | } 66 | 67 | class TestLogger implements Logger { 68 | @override 69 | void log(String message) { 70 | printOnFailure(message); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /pkgs/sdk_triage_bot/test/triage_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'package:github/github.dart'; 6 | import 'package:sdk_triage_bot/triage.dart'; 7 | import 'package:test/test.dart'; 8 | 9 | import 'fakes.dart'; 10 | 11 | void main() { 12 | test('triages issue', () async { 13 | final githubService = GithubServiceMock(); 14 | final geminiService = GeminiServiceStub(); 15 | 16 | await triage( 17 | mockIssueNumber, 18 | githubService: githubService, 19 | geminiService: geminiService, 20 | logger: TestLogger(), 21 | ); 22 | 23 | expect(githubService.updatedComment, isNotEmpty); 24 | expect(githubService.updatedComment, contains('Lorem ipsum')); 25 | expect(githubService.updatedLabels, contains(startsWith('area-'))); 26 | expect(githubService.updatedLabels, contains('triage-automation')); 27 | }); 28 | 29 | test('skips triaged issues', () async { 30 | final githubService = GithubServiceMock(); 31 | final geminiService = GeminiServiceStub(); 32 | 33 | githubService.returnedIssue = Issue( 34 | url: 'https://github.com/dart-lang/sdk/issues/55869', 35 | title: 'Add full support for service ID zones', 36 | number: mockIssueNumber, 37 | body: 'Lorem ipsum.', 38 | labels: [IssueLabel(name: 'area-vm')], 39 | ); 40 | 41 | await triage( 42 | mockIssueNumber, 43 | githubService: githubService, 44 | geminiService: geminiService, 45 | logger: TestLogger(), 46 | ); 47 | 48 | expect(githubService.updatedComment, isNull); 49 | expect(githubService.updatedLabels, isNull); 50 | }); 51 | 52 | test('respects --force flag', () async { 53 | final githubService = GithubServiceMock(); 54 | final geminiService = GeminiServiceStub(); 55 | 56 | githubService.returnedIssue = Issue( 57 | url: 'https://github.com/dart-lang/sdk/issues/55869', 58 | title: 'Add full support for service ID zones', 59 | number: mockIssueNumber, 60 | body: 'Lorem ipsum.', 61 | labels: [IssueLabel(name: 'area-vm')], 62 | ); 63 | 64 | await triage( 65 | mockIssueNumber, 66 | forceTriage: true, 67 | githubService: githubService, 68 | geminiService: geminiService, 69 | logger: TestLogger(), 70 | ); 71 | 72 | expect(githubService.updatedComment, isNotEmpty); 73 | expect(githubService.updatedComment, contains('Lorem ipsum')); 74 | expect(githubService.updatedLabels, contains(startsWith('area-'))); 75 | expect(githubService.updatedLabels, contains('triage-automation')); 76 | }); 77 | 78 | test('ignore redundant type labels', () async { 79 | final githubService = GithubServiceMock(); 80 | final geminiService = GeminiServiceStub(); 81 | 82 | githubService.returnedIssue = Issue( 83 | url: 'https://github.com/dart-lang/sdk/issues/55869', 84 | title: 'Add full support for service ID zones', 85 | number: mockIssueNumber, 86 | body: 'Lorem ipsum.', 87 | labels: [IssueLabel(name: 'type-enhancement')], 88 | ); 89 | 90 | await triage( 91 | mockIssueNumber, 92 | githubService: githubService, 93 | geminiService: geminiService, 94 | logger: TestLogger(), 95 | ); 96 | 97 | expect(githubService.updatedLabels, ['area-vm', 'triage-automation']); 98 | }); 99 | } 100 | -------------------------------------------------------------------------------- /pkgs/trebuchet/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2024, the Dart project authors. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following 11 | disclaimer in the documentation and/or other materials provided 12 | with the distribution. 13 | * Neither the name of Google LLC nor the names of its 14 | contributors may be used to endorse or promote products derived 15 | from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /pkgs/trebuchet/README.md: -------------------------------------------------------------------------------- 1 | ## What's this? 2 | 3 | This is a tool to move existing packages into monorepos. 4 | 5 | ## Running the tool 6 | 7 | ```bash 8 | dart run bin/trebuchet.dart \ 9 | --input-name coverage \ 10 | --input-branch-name main \ 11 | --target-branch-name main \ 12 | --input-path ~/projects/coverage/ \ 13 | --target tools \ 14 | --target-path ~/projects/tools/ \ 15 | --git-filter-repo ~/tools/git-filter-repo \ 16 | --dry-run 17 | ``` 18 | 19 | This script automates portions of the instructions at 20 | https://github.com/dart-lang/ecosystem/wiki/Merging-existing-repos-into-a-monorepo. 21 | -------------------------------------------------------------------------------- /pkgs/trebuchet/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:dart_flutter_team_lints/analysis_options.yaml 2 | 3 | linter: 4 | rules: 5 | - prefer_final_locals 6 | -------------------------------------------------------------------------------- /pkgs/trebuchet/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: trebuchet 2 | description: A tool for hurling packages into monorepos. 3 | repository: https://github.com/dart-lang/ecosystem/tree/main/pkgs/trebuchet 4 | 5 | publish_to: none 6 | 7 | environment: 8 | sdk: ^3.3.0 9 | 10 | dependencies: 11 | args: ^2.5.0 12 | path: ^1.9.0 13 | pubspec_parse: ^1.3.0 14 | 15 | dev_dependencies: 16 | dart_flutter_team_lints: ^3.2.0 17 | test: ^1.24.0 18 | -------------------------------------------------------------------------------- /tool/ci.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Created with package:mono_repo v6.6.2 3 | 4 | # Support built in commands on windows out of the box. 5 | 6 | # When it is a flutter repo (check the pubspec.yaml for "sdk: flutter") 7 | # then "flutter pub" is called instead of "dart pub". 8 | # This assumes that the Flutter SDK has been installed in a previous step. 9 | function pub() { 10 | if grep -Fq "sdk: flutter" "${PWD}/pubspec.yaml"; then 11 | command flutter pub "$@" 12 | else 13 | command dart pub "$@" 14 | fi 15 | } 16 | 17 | function format() { 18 | command dart format "$@" 19 | } 20 | 21 | # When it is a flutter repo (check the pubspec.yaml for "sdk: flutter") 22 | # then "flutter analyze" is called instead of "dart analyze". 23 | # This assumes that the Flutter SDK has been installed in a previous step. 24 | function analyze() { 25 | if grep -Fq "sdk: flutter" "${PWD}/pubspec.yaml"; then 26 | command flutter analyze "$@" 27 | else 28 | command dart analyze "$@" 29 | fi 30 | } 31 | 32 | if [[ -z ${PKGS} ]]; then 33 | echo -e '\033[31mPKGS environment variable must be set! - TERMINATING JOB\033[0m' 34 | exit 64 35 | fi 36 | 37 | if [[ "$#" == "0" ]]; then 38 | echo -e '\033[31mAt least one task argument must be provided! - TERMINATING JOB\033[0m' 39 | exit 64 40 | fi 41 | 42 | SUCCESS_COUNT=0 43 | declare -a FAILURES 44 | 45 | for PKG in ${PKGS}; do 46 | echo -e "\033[1mPKG: ${PKG}\033[22m" 47 | EXIT_CODE=0 48 | pushd "${PKG}" >/dev/null || EXIT_CODE=$? 49 | 50 | if [[ ${EXIT_CODE} -ne 0 ]]; then 51 | echo -e "\033[31mPKG: '${PKG}' does not exist - TERMINATING JOB\033[0m" 52 | exit 64 53 | fi 54 | 55 | dart pub upgrade || EXIT_CODE=$? 56 | 57 | if [[ ${EXIT_CODE} -ne 0 ]]; then 58 | echo -e "\033[31mPKG: ${PKG}; 'dart pub upgrade' - FAILED (${EXIT_CODE})\033[0m" 59 | FAILURES+=("${PKG}; 'dart pub upgrade'") 60 | else 61 | for TASK in "$@"; do 62 | EXIT_CODE=0 63 | echo 64 | echo -e "\033[1mPKG: ${PKG}; TASK: ${TASK}\033[22m" 65 | case ${TASK} in 66 | analyze) 67 | echo 'dart analyze --fatal-infos .' 68 | dart analyze --fatal-infos . || EXIT_CODE=$? 69 | ;; 70 | format) 71 | echo 'dart format --output=none --set-exit-if-changed .' 72 | dart format --output=none --set-exit-if-changed . || EXIT_CODE=$? 73 | ;; 74 | test_0) 75 | echo 'dart test --test-randomize-ordering-seed=random' 76 | dart test --test-randomize-ordering-seed=random || EXIT_CODE=$? 77 | ;; 78 | test_1) 79 | echo 'dart test' 80 | dart test || EXIT_CODE=$? 81 | ;; 82 | *) 83 | echo -e "\033[31mUnknown TASK '${TASK}' - TERMINATING JOB\033[0m" 84 | exit 64 85 | ;; 86 | esac 87 | 88 | if [[ ${EXIT_CODE} -ne 0 ]]; then 89 | echo -e "\033[31mPKG: ${PKG}; TASK: ${TASK} - FAILED (${EXIT_CODE})\033[0m" 90 | FAILURES+=("${PKG}; TASK: ${TASK}") 91 | else 92 | echo -e "\033[32mPKG: ${PKG}; TASK: ${TASK} - SUCCEEDED\033[0m" 93 | SUCCESS_COUNT=$((SUCCESS_COUNT + 1)) 94 | fi 95 | 96 | done 97 | fi 98 | 99 | echo 100 | echo -e "\033[32mSUCCESS COUNT: ${SUCCESS_COUNT}\033[0m" 101 | 102 | if [ ${#FAILURES[@]} -ne 0 ]; then 103 | echo -e "\033[31mFAILURES: ${#FAILURES[@]}\033[0m" 104 | for i in "${FAILURES[@]}"; do 105 | echo -e "\033[31m $i\033[0m" 106 | done 107 | fi 108 | 109 | popd >/dev/null || exit 70 110 | echo 111 | done 112 | 113 | if [ ${#FAILURES[@]} -ne 0 ]; then 114 | exit 1 115 | fi 116 | --------------------------------------------------------------------------------