diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 7ad33701..aaf0d46b 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 + uses: actions/cache@69d9d449aced6a2ede0bc19182fadc3a0a42d2b0 with: path: "~/.pub-cache/hosted" key: "os:ubuntu-latest;pub-cache-hosted;sdk:stable" @@ -28,37 +28,37 @@ jobs: os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - name: Setup Dart SDK - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: stable - id: checkout name: Checkout repository - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - name: mono_repo self validate run: dart pub global activate mono_repo 6.5.7 - name: mono_repo self validate run: dart pub global run mono_repo generate --validate job_002: - name: "analyze_and_format; Dart 2.19.0; PKGS: pkgs/corpus, pkgs/dart_flutter_team_lints, pkgs/firehose, pkgs/repo_manage; `dart analyze --fatal-infos .`" + name: "analyze_and_format; Dart 2.19.0; PKGS: pkgs/corpus, pkgs/dart_flutter_team_lints, pkgs/repo_manage; `dart analyze --fatal-infos .`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 + uses: actions/cache@69d9d449aced6a2ede0bc19182fadc3a0a42d2b0 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;sdk:2.19.0;packages:pkgs/corpus-pkgs/dart_flutter_team_lints-pkgs/firehose-pkgs/repo_manage;commands:analyze" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:2.19.0;packages:pkgs/corpus-pkgs/dart_flutter_team_lints-pkgs/repo_manage;commands:analyze" restore-keys: | - os:ubuntu-latest;pub-cache-hosted;sdk:2.19.0;packages:pkgs/corpus-pkgs/dart_flutter_team_lints-pkgs/firehose-pkgs/repo_manage + os:ubuntu-latest;pub-cache-hosted;sdk:2.19.0;packages:pkgs/corpus-pkgs/dart_flutter_team_lints-pkgs/repo_manage os:ubuntu-latest;pub-cache-hosted;sdk:2.19.0 os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - name: Setup Dart SDK - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: "2.19.0" - id: checkout name: Checkout repository - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - id: pkgs_corpus_pub_upgrade name: pkgs/corpus; dart pub upgrade run: dart pub upgrade @@ -77,15 +77,6 @@ jobs: run: dart analyze --fatal-infos . if: "always() && steps.pkgs_dart_flutter_team_lints_pub_upgrade.conclusion == 'success'" working-directory: pkgs/dart_flutter_team_lints - - id: pkgs_firehose_pub_upgrade - name: pkgs/firehose; dart pub upgrade - run: dart pub upgrade - if: "always() && steps.checkout.conclusion == 'success'" - working-directory: pkgs/firehose - - name: "pkgs/firehose; dart analyze --fatal-infos ." - run: dart analyze --fatal-infos . - if: "always() && steps.pkgs_firehose_pub_upgrade.conclusion == 'success'" - working-directory: pkgs/firehose - id: pkgs_repo_manage_pub_upgrade name: pkgs/repo_manage; dart pub upgrade run: dart pub upgrade @@ -98,11 +89,43 @@ jobs: needs: - job_001 job_003: + name: "analyze_and_format; Dart 3.0.0; PKG: pkgs/firehose; `dart analyze --fatal-infos .`" + runs-on: ubuntu-latest + steps: + - name: Cache Pub hosted dependencies + uses: actions/cache@69d9d449aced6a2ede0bc19182fadc3a0a42d2b0 + with: + path: "~/.pub-cache/hosted" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0;packages:pkgs/firehose;commands:analyze" + restore-keys: | + os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0;packages:pkgs/firehose + os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0 + os:ubuntu-latest;pub-cache-hosted + os:ubuntu-latest + - name: Setup Dart SDK + uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + with: + sdk: "3.0.0" + - id: checkout + name: Checkout repository + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - id: pkgs_firehose_pub_upgrade + name: pkgs/firehose; dart pub upgrade + run: dart pub upgrade + if: "always() && steps.checkout.conclusion == 'success'" + working-directory: pkgs/firehose + - name: "pkgs/firehose; dart analyze --fatal-infos ." + run: dart analyze --fatal-infos . + if: "always() && steps.pkgs_firehose_pub_upgrade.conclusion == 'success'" + working-directory: pkgs/firehose + needs: + - job_001 + job_004: name: "analyze_and_format; Dart dev; PKGS: pkgs/corpus, pkgs/dart_flutter_team_lints, pkgs/firehose, pkgs/repo_manage; `dart analyze --fatal-infos .`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 + uses: actions/cache@69d9d449aced6a2ede0bc19182fadc3a0a42d2b0 with: path: "~/.pub-cache/hosted" key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:pkgs/corpus-pkgs/dart_flutter_team_lints-pkgs/firehose-pkgs/repo_manage;commands:analyze" @@ -112,12 +135,12 @@ jobs: os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - name: Setup Dart SDK - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: dev - id: checkout name: Checkout repository - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - id: pkgs_corpus_pub_upgrade name: pkgs/corpus; dart pub upgrade run: dart pub upgrade @@ -156,12 +179,12 @@ jobs: working-directory: pkgs/repo_manage needs: - job_001 - job_004: + job_005: name: "analyze_and_format; Dart dev; PKGS: pkgs/corpus, pkgs/dart_flutter_team_lints, pkgs/firehose, pkgs/repo_manage; `dart format --output=none --set-exit-if-changed .`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 + uses: actions/cache@69d9d449aced6a2ede0bc19182fadc3a0a42d2b0 with: path: "~/.pub-cache/hosted" key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:pkgs/corpus-pkgs/dart_flutter_team_lints-pkgs/firehose-pkgs/repo_manage;commands:format" @@ -171,12 +194,12 @@ jobs: os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - name: Setup Dart SDK - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: dev - id: checkout name: Checkout repository - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - id: pkgs_corpus_pub_upgrade name: pkgs/corpus; dart pub upgrade run: dart pub upgrade @@ -215,12 +238,12 @@ jobs: working-directory: pkgs/repo_manage needs: - job_001 - job_005: + job_006: name: "unit_test; Dart 2.19.0; PKG: pkgs/corpus; `dart test`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 + uses: actions/cache@69d9d449aced6a2ede0bc19182fadc3a0a42d2b0 with: path: "~/.pub-cache/hosted" key: "os:ubuntu-latest;pub-cache-hosted;sdk:2.19.0;packages:pkgs/corpus;commands:test_1" @@ -230,12 +253,12 @@ jobs: os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - name: Setup Dart SDK - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: "2.19.0" - id: checkout name: Checkout repository - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - id: pkgs_corpus_pub_upgrade name: pkgs/corpus; dart pub upgrade run: dart pub upgrade @@ -250,12 +273,13 @@ jobs: - job_002 - job_003 - job_004 - job_006: + - job_005 + job_007: name: "unit_test; Dart 2.19.0; PKG: pkgs/dart_flutter_team_lints; `dart test`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 + uses: actions/cache@69d9d449aced6a2ede0bc19182fadc3a0a42d2b0 with: path: "~/.pub-cache/hosted" key: "os:ubuntu-latest;pub-cache-hosted;sdk:2.19.0;packages:pkgs/dart_flutter_team_lints;commands:test_1" @@ -265,12 +289,12 @@ jobs: os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - name: Setup Dart SDK - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: "2.19.0" - id: checkout name: Checkout repository - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - id: pkgs_dart_flutter_team_lints_pub_upgrade name: pkgs/dart_flutter_team_lints; dart pub upgrade run: dart pub upgrade @@ -285,27 +309,28 @@ jobs: - job_002 - job_003 - job_004 - job_007: - name: "unit_test; Dart 2.19.0; PKG: pkgs/firehose; `dart test`" + - job_005 + job_008: + name: "unit_test; Dart 3.0.0; PKG: pkgs/firehose; `dart test`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 + uses: actions/cache@69d9d449aced6a2ede0bc19182fadc3a0a42d2b0 with: path: "~/.pub-cache/hosted" - key: "os:ubuntu-latest;pub-cache-hosted;sdk:2.19.0;packages:pkgs/firehose;commands:test_1" + key: "os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0;packages:pkgs/firehose;commands:test_1" restore-keys: | - os:ubuntu-latest;pub-cache-hosted;sdk:2.19.0;packages:pkgs/firehose - os:ubuntu-latest;pub-cache-hosted;sdk:2.19.0 + os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0;packages:pkgs/firehose + os:ubuntu-latest;pub-cache-hosted;sdk:3.0.0 os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - name: Setup Dart SDK - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: - sdk: "2.19.0" + sdk: "3.0.0" - id: checkout name: Checkout repository - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - id: pkgs_firehose_pub_upgrade name: pkgs/firehose; dart pub upgrade run: dart pub upgrade @@ -320,12 +345,13 @@ jobs: - job_002 - job_003 - job_004 - job_008: + - job_005 + job_009: name: "unit_test; Dart dev; PKG: pkgs/corpus; `dart test`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 + uses: actions/cache@69d9d449aced6a2ede0bc19182fadc3a0a42d2b0 with: path: "~/.pub-cache/hosted" key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:pkgs/corpus;commands:test_1" @@ -335,12 +361,12 @@ jobs: os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - name: Setup Dart SDK - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: dev - id: checkout name: Checkout repository - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - id: pkgs_corpus_pub_upgrade name: pkgs/corpus; dart pub upgrade run: dart pub upgrade @@ -355,12 +381,13 @@ jobs: - job_002 - job_003 - job_004 - job_009: + - job_005 + job_010: name: "unit_test; Dart dev; PKG: pkgs/dart_flutter_team_lints; `dart test`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 + uses: actions/cache@69d9d449aced6a2ede0bc19182fadc3a0a42d2b0 with: path: "~/.pub-cache/hosted" key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:pkgs/dart_flutter_team_lints;commands:test_1" @@ -370,12 +397,12 @@ jobs: os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - name: Setup Dart SDK - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: dev - id: checkout name: Checkout repository - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - id: pkgs_dart_flutter_team_lints_pub_upgrade name: pkgs/dart_flutter_team_lints; dart pub upgrade run: dart pub upgrade @@ -390,12 +417,13 @@ jobs: - job_002 - job_003 - job_004 - job_010: + - job_005 + job_011: name: "unit_test; Dart dev; PKG: pkgs/firehose; `dart test`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 + uses: actions/cache@69d9d449aced6a2ede0bc19182fadc3a0a42d2b0 with: path: "~/.pub-cache/hosted" key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:pkgs/firehose;commands:test_1" @@ -405,12 +433,12 @@ jobs: os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - name: Setup Dart SDK - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: dev - id: checkout name: Checkout repository - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - id: pkgs_firehose_pub_upgrade name: pkgs/firehose; dart pub upgrade run: dart pub upgrade @@ -425,12 +453,13 @@ jobs: - job_002 - job_003 - job_004 - job_011: + - job_005 + job_012: name: "analyze_format; Dart dev; PKG: pkgs/blast_repo; `dart format --output=none --set-exit-if-changed .`, `dart analyze --fatal-infos .`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 + uses: actions/cache@69d9d449aced6a2ede0bc19182fadc3a0a42d2b0 with: path: "~/.pub-cache/hosted" key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:pkgs/blast_repo;commands:format-analyze" @@ -440,12 +469,12 @@ jobs: os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - name: Setup Dart SDK - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: dev - id: checkout name: Checkout repository - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - id: pkgs_blast_repo_pub_upgrade name: pkgs/blast_repo; dart pub upgrade run: dart pub upgrade @@ -470,12 +499,13 @@ jobs: - job_008 - job_009 - job_010 - job_012: + - job_011 + job_013: name: "test; Dart dev; PKG: pkgs/blast_repo; `dart test --test-randomize-ordering-seed=random`" runs-on: ubuntu-latest steps: - name: Cache Pub hosted dependencies - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 + uses: actions/cache@69d9d449aced6a2ede0bc19182fadc3a0a42d2b0 with: path: "~/.pub-cache/hosted" key: "os:ubuntu-latest;pub-cache-hosted;sdk:dev;packages:pkgs/blast_repo;commands:test_0" @@ -485,12 +515,12 @@ jobs: os:ubuntu-latest;pub-cache-hosted os:ubuntu-latest - name: Setup Dart SDK - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: dev - id: checkout name: Checkout repository - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - id: pkgs_blast_repo_pub_upgrade name: pkgs/blast_repo; dart pub upgrade run: dart pub upgrade @@ -512,3 +542,4 @@ jobs: - job_009 - job_010 - job_011 + - job_012 diff --git a/.github/workflows/health.yaml b/.github/workflows/health.yaml new file mode 100644 index 00000000..49f964d7 --- /dev/null +++ b/.github/workflows/health.yaml @@ -0,0 +1,71 @@ +# A CI configuration to check PR health. + +name: Health + +# Callers of this workflow should use it as follows: +# +# name: Health +# on: +# pull_request: +# branches: [ main ] +# types: [opened, synchronize, reopened, labeled, unlabeled] +# jobs: +# health: +# uses: dart-lang/ecosystem/.github/workflows/health.yaml@main + +# Callers may optionally specify the version of the SDK to use when running the +# health check. This can be useful if your package has a very recent minimum SDK +# constraint. This is done via the `sdk` input parameter. Note that this +# parameter is not required; it defaults to `stable` - using the most recent +# stable release of the Dart SDK. +# +# The checks can also be restricted to any subset of version, changelog, and license, +# if needed. +# +# jobs: +# health: +# uses: dart-lang/ecosystem/.github/workflows/health.yaml@main +# with: +# sdk: beta +# checks: "version,changelog,license" + +on: + workflow_call: + inputs: + sdk: + description: >- + The channel, or a specific version from a channel, to install + ('2.19.0','stable', 'beta', 'dev'). Using one of the three channels + will give you the latest version published to that channel. + default: "stable" + required: false + type: string + checks: + description: What to check for in the PR health check - any subset of "version,changelog,license" + default: "version,changelog,license" + type: string + required: false + +jobs: + health: + # These permissions are required for us to create comments on PRs. + permissions: + pull-requests: write + + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + with: + sdk: ${{ inputs.sdk }} + + - name: Install firehose + run: dart pub global activate --source git https://github.com/dart-lang/ecosystem.git --git-path pkgs/firehose/ --git-ref=unifiedWorkflow #TODO remove, just for testing + + - name: Validate packages + if: ${{ github.event_name == 'pull_request' }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + ISSUE_NUMBER: ${{ github.event.number }} + PR_LABELS: "${{ join(github.event.pull_request.labels.*.name) }}" + run: dart pub global run firehose --health ${{ inputs.checks }} diff --git a/.github/workflows/health_internal.yaml b/.github/workflows/health_internal.yaml new file mode 100644 index 00000000..81616c55 --- /dev/null +++ b/.github/workflows/health_internal.yaml @@ -0,0 +1,12 @@ +# A CI configuration to check PR health. + +name: Health +on: + pull_request: + branches: [ main ] + types: [opened, synchronize, reopened, labeled, unlabeled] +jobs: + health: + uses: ./.github/workflows/health.yaml + with: + checks: "changelog,license" \ No newline at end of file diff --git a/pkgs/firehose/CHANGELOG.md b/pkgs/firehose/CHANGELOG.md index 44c2b1c3..2fca5073 100644 --- a/pkgs/firehose/CHANGELOG.md +++ b/pkgs/firehose/CHANGELOG.md @@ -1,3 +1,6 @@ +## 0.3.18-wip +- Add Github workflow for PR health. + ## 0.3.17 - Correctly parse pre-release versions from the CHANGELOG. diff --git a/pkgs/firehose/README.md b/pkgs/firehose/README.md index e923f9f6..18134bf7 100644 --- a/pkgs/firehose/README.md +++ b/pkgs/firehose/README.md @@ -1,11 +1,12 @@ [![pub package](https://img.shields.io/pub/v/firehose.svg)](https://pub.dev/packages/firehose) [![package publisher](https://img.shields.io/pub/publisher/firehose.svg)](https://pub.dev/packages/firehose/publisher) -## What's this? +## firehose +### What's this? This is a tool to automate publishing of pub packages from GitHub actions. -## Conventions and setup +### Conventions and setup When run from a PR, this tool will validate the package pubspecs and changelogs and indicate whether the criteria for publishing has been met. @@ -15,18 +16,18 @@ version, and the changelog version and pubspec version should agree. When run in response to a git tag event (a tag with a pattern like `v1.2.3` or `name_v1.2.3` for monorepos), this tool will publish the indicated package. -## Pre-release versions +### Pre-release versions Pre-release versions (aka, `'1.2.3-dev'`) are handled specially; this tool will validate the package but will not auto-publish it. This can be used to accumulate several changes and later publish them as a group. -## Disabling auto-publishing +### Disabling auto-publishing In order to disable package validation and auto-publishing, add the `publish_to: none` key to your pubspec. -## PR branch actions +### PR branch actions For PRs, this tool: @@ -34,7 +35,7 @@ For PRs, this tool: - validates that the changelog version equals the pubspec version - performs a `dart pub publish --dry-run` -## Git tag actions +### Git tag actions In response to a git tag event, this tool: @@ -42,7 +43,7 @@ In response to a git tag event, this tool: - determines the indicated package - attempts to publish that package (`dart pub publish --force`) -## Mono-repos +### Mono-repos This tool can work with either single package repos or with mono-repos (repos containing several packages). It will scan for and detect packages in a mono @@ -52,7 +53,7 @@ repo; to omit packages from validation and auto-publishing, add a For single package repos, the tag pattern should be `v1.2.3`. For mono-repos, the tag pattern must be prefixed with the package name, e.g. `foo-v1.2.3`. -## Integrating this tool into a repo +### Integrating this tool into a repo - copy the yaml below into a `.github/workflows/publish.yaml` file in your repo - update the target branch below if necessary (currently, `main`) @@ -78,7 +79,7 @@ jobs: uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main ``` -## Publishing from a specific version of the SDK +### Publishing from a specific version of the SDK Callers may optionally specify the version of the SDK to use when publishing a package. This can be useful if your package has a very recent minimum SDK @@ -94,7 +95,49 @@ jobs: sdk: beta ``` -## Workflow docs +### Workflow docs The description of the common workflow for repos using this tool can be found at https://github.com/dart-lang/ecosystem/wiki/Publishing-automation. + +
+ +## health + +### What's this? + +This is a Github workflow to check PR health. + +### Conventions and setup + +When run from a PR, this tool will check a configurable subset of the following + +* If the package versioning is correct and consistent, see `firehose` description above. +* If a changelog entry has been added. +* If all `.dart` files have a license header. + +This tool can work with either single package repos or with mono-repos (repos +containing several packages). + +### Integrating this tool into a repo + +- copy the yaml below into a `.github/workflows/health.yaml` file in your repo +- update the target branch below if necessary (currently, `main`) + +```yaml +name: Health +on: + pull_request: + branches: [ main ] + types: [opened, synchronize, reopened, labeled, unlabeled] +jobs: + health: + uses: dart-lang/ecosystem/.github/workflows/health.yaml@main +# with: +# checks: "version,changelog,license" +``` + +### Workflow docs + +The description of the common workflow for repos using this tool can be found at +https://github.com/dart-lang/ecosystem/wiki/Pull-Request-Health. \ No newline at end of file diff --git a/pkgs/firehose/bin/firehose.dart b/pkgs/firehose/bin/firehose.dart index e561bd98..5e01d275 100644 --- a/pkgs/firehose/bin/firehose.dart +++ b/pkgs/firehose/bin/firehose.dart @@ -20,10 +20,11 @@ void main(List arguments) async { var validate = argResults['validate'] == true; var publish = argResults['publish'] == true; + var health = argResults['health'] != null; - if (!validate && !publish) { - _usage(argParser, - error: 'Error: one of --validate or --publish must be specified.'); + if (!validate && !publish && !health) { + _usage(argParser, error: ''' +Error: one of --validate, --publish, or --health must be specified.'''); exit(1); } @@ -41,6 +42,8 @@ void main(List arguments) async { await firehose.validate(); } else if (publish) { await firehose.publish(); + } else if (health) { + await firehose.healthCheck(argResults['health'] as List); } } on ArgParserException catch (e) { _usage(argParser, error: e.message); @@ -73,6 +76,11 @@ ArgParser _createArgs() { help: 'Validate packages and indicate whether --publish would publish ' 'anything.', ) + ..addMultiOption( + 'health', + defaultsTo: ['version', 'license', 'changelog'], + help: 'Check PR health.', + ) ..addFlag( 'publish', negatable: false, diff --git a/pkgs/firehose/lib/firehose.dart b/pkgs/firehose/lib/firehose.dart index 73c27408..56a51d42 100644 --- a/pkgs/firehose/lib/firehose.dart +++ b/pkgs/firehose/lib/firehose.dart @@ -2,9 +2,13 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. +// ignore_for_file: always_declare_return_types + import 'dart:io'; +import 'dart:math'; import 'package:firehose/src/repo.dart'; +import 'package:path/path.dart' as path; import 'src/github.dart'; import 'src/pub.dart'; @@ -15,6 +19,13 @@ const String _botSuffix = '[bot]'; const String _githubActionsUser = 'github-actions[bot]'; const String _publishBotTag = '## Package publishing'; +const String _publishBotTag2 = '### Package publish validation'; + +const String _licenseBotTag = '### License Headers'; + +const String _changelogBotTag = '### Changelog entry'; + +const String _prHealthTag = '## PR Health'; const String _ignoreWarningsLabel = 'publish-ignore-warnings'; @@ -23,6 +34,178 @@ class Firehose { Firehose(this.directory); + Future healthCheck(List argResult) async { + print('Start health check for the checks $argResult'); + var checks = [ + if (argResult.contains('version')) validateCheck, + if (argResult.contains('license')) licenseCheck, + if (argResult.contains('changelog')) changelogCheck, + ]; + await _healthCheck(checks); + } + + Future _healthCheck( + List Function(Github)> checks) async { + var github = Github(); + + // Do basic validation of our expected env var. + if (!_expectEnv(github.githubAuthToken, 'GITHUB_TOKEN')) return; + if (!_expectEnv(github.repoSlug, 'GITHUB_REPOSITORY')) return; + if (!_expectEnv(github.issueNumber, 'ISSUE_NUMBER')) return; + if (!_expectEnv(github.sha, 'GITHUB_SHA')) return; + + if ((github.actor ?? '').endsWith(_botSuffix)) { + print('Skipping package validation for ${github.actor} PRs.'); + return; + } + + var checked = + await Future.wait(checks.map((check) => check(github)).toList()); + await writeInComment(github, checked); + + github.close(); + } + + Future validateCheck(Github github) async { + var results = await _validate(github); + + var markdownTable = ''' +| Package | Version | Status | Publish tag (post-merge) | +| :--- | ---: | :--- | ---: | +${results.describeAsMarkdown} + + '''; + + return HealthCheckResult( + _publishBotTag2, + results.severity, + markdownTable, + ); + } + + Future licenseCheck(Github github) async { + final license = ''' +// Copyright (c) ${DateTime.now().year}, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file.'''; + + var filePaths = await _getFilesWithoutLicenses(github); + + var markdownResult = ''' +Some `.dart` files were found to not have license headers. Please add the following header to all listed files: +``` +$license +``` + +| Files | +| :--- | +${filePaths.map((e) => '|$e|').join('\n')} + +Either manually or by running the following in your repository directory + +``` +dart pub global activate --source git https://github.com/mosuem/file_licenser +dart pub global run file_licenser . +``` + +'''; //TODO: replace by pub.dev version + + return HealthCheckResult( + _licenseBotTag, + filePaths.isNotEmpty ? Severity.error : Severity.success, + markdownResult, + ); + } + + Future changelogCheck(Github github) async { + var filePaths = await _packagesWithoutChangelog(github); + + final markdownResult = ''' +Changes to these files need to be accounted for in their respective changelogs: + +| Package | Files | +| :--- | :--- | +${filePaths.entries.map((e) => '| package:${e.key.name} | ${e.value.map((e) => path.relative(e, from: Directory.current.path)).join('
')} |').join('\n')} +'''; + + return HealthCheckResult( + _changelogBotTag, + filePaths.isNotEmpty ? Severity.error : Severity.success, + markdownResult, + ); + } + + Future>> _packagesWithoutChangelog( + Github github) async { + final repo = Repository(); + final packages = repo.locatePackages(); + + final files = await github.listFilesForPR(); + print('Collecting packages without changed changelogs:'); + final packagesWithoutChangedChangelog = packages.where((package) { + var changelogPath = package.changelog.file.path; + var changelog = + path.relative(changelogPath, from: Directory.current.path); + return !files.contains(changelog); + }).toList(); + print('Done, found ${packagesWithoutChangedChangelog.length} packages.'); + + print('Collecting files without license headers in those packages:'); + var packagesWithChanges = >{}; + for (final file in files) { + for (final package in packagesWithoutChangedChangelog) { + if (fileNeedsEntryInChangelog(package, file)) { + print(file); + packagesWithChanges.update( + package, + (changedFiles) => [...changedFiles, file], + ifAbsent: () => [file], + ); + } + } + } + print(''' +Done, found ${packagesWithChanges.length} packages with a need for a changelog.'''); + return packagesWithChanges; + } + + bool fileNeedsEntryInChangelog(Package package, String file) { + final directoryPath = package.directory.path; + final directory = + path.relative(directoryPath, from: Directory.current.path); + final isInPackage = path.isWithin(directory, file); + final isInLib = path.isWithin(path.join(directory, 'lib'), file); + final isInBin = path.isWithin(path.join(directory, 'bin'), file); + final isPubspec = file.endsWith('pubspec.yaml'); + final isReadme = file.endsWith('README.md'); + return isInPackage && (isInLib || isInBin || isPubspec || isReadme); + } + + Future> _getFilesWithoutLicenses(Github github) async { + var dir = Directory.current; + var dartFiles = await dir + .list(recursive: true) + .where((f) => f.path.endsWith('.dart')) + .toList(); + print('Collecting files without license headers:'); + var filesWithoutLicenses = dartFiles + .map((file) { + var fileContents = File(file.path).readAsStringSync(); + var fileContainsCopyright = fileContents.contains('// Copyright (c)'); + if (!fileContainsCopyright) { + var relativePath = + path.relative(file.path, from: Directory.current.path); + print(relativePath); + return relativePath; + } + }) + .whereType() + .toList(); + print(''' +Done, found ${filesWithoutLicenses.length} files without license headers'''); + return filesWithoutLicenses; + } + /// Validate the packages in the repository. /// /// This method is intended to run in the context of a PR. It will: @@ -53,8 +236,6 @@ ${results.describeAsMarkdown} Documentation at https://github.com/dart-lang/ecosystem/wiki/Publishing-automation. '''; - - // Write the publish info status to the job summary. github.appendStepSummary(markdownTable); var existingCommentId = await allowFailure( @@ -99,6 +280,59 @@ Documentation at https://github.com/dart-lang/ecosystem/wiki/Publishing-automati github.close(); } + Future writeInComment( + Github github, + List results, + ) async { + var commentText = results.map((e) { + var markdown = e.markdown; + var s = ''' + + +Details + + +$markdown + + +'''; + return '${e.tag} ${e.severity.emoji}\n\n$s'; + }).join('\n'); + + var summary = '$_prHealthTag\n\n$commentText'; + github.appendStepSummary(summary); + + var repoSlug = github.repoSlug!; + var issueNumber = github.issueNumber!; + + var existingCommentId = await allowFailure( + github.findCommentId( + repoSlug, + issueNumber, + user: _githubActionsUser, + searchTerm: _prHealthTag, + ), + logError: print, + ); + + if (existingCommentId == null) { + await allowFailure( + github.createComment(repoSlug, issueNumber, summary), + logError: print, + ); + } else { + await allowFailure( + github.updateComment(repoSlug, existingCommentId, summary), + logError: print, + ); + } + + if (results.any((result) => result.severity == Severity.error) && + exitCode == 0) { + exitCode = 1; + } + } + Future _validate(Github github) async { var repo = Repository(); var packages = repo.locatePackages(); @@ -289,6 +523,9 @@ class VerificationResults { void addResult(Result result) => results.add(result); + Severity get severity => + Severity.values[results.map((e) => e.severity.index).reduce(max)]; + bool get hasSuccess => results.any((r) => r.severity == Severity.success); bool get hasError => results.any((r) => r.severity == Severity.error); @@ -310,6 +547,14 @@ class VerificationResults { } } +class HealthCheckResult { + final String tag; + final Severity severity; + final String markdown; + + HealthCheckResult(this.tag, this.severity, this.markdown); +} + class Result { final Severity severity; final Package package; @@ -343,4 +588,10 @@ enum Severity { success, info, error; + + String get emoji => switch (this) { + Severity.info => ':heavy_check_mark:', + Severity.error => ':exclamation:', + success => ':heavy_check_mark:', + }; } diff --git a/pkgs/firehose/lib/src/github.dart b/pkgs/firehose/lib/src/github.dart index 822d5e20..76a57a44 100644 --- a/pkgs/firehose/lib/src/github.dart +++ b/pkgs/firehose/lib/src/github.dart @@ -192,6 +192,19 @@ class Github { 'https://api.github.com/repos/$repoSlug/issues/comments/$commentId')); } + Future> listFilesForPR() async { + var result = await callRestApiGet( + Uri.parse( + 'https://api.github.com/repos/$repoSlug/pulls/$issueNumber/files'), + ); + var json = jsonDecode(result) as List; + var filenames = json + .map((e) => e as Map) + .map((e) => e['filename'] as String) + .toList(); + return filenames; + } + void close() { _httpClient?.close(); } diff --git a/pkgs/firehose/pubspec.yaml b/pkgs/firehose/pubspec.yaml index 9cf472a9..205f46e5 100644 --- a/pkgs/firehose/pubspec.yaml +++ b/pkgs/firehose/pubspec.yaml @@ -1,10 +1,10 @@ name: firehose description: A tool to automate publishing of Pub packages from GitHub actions. -version: 0.3.17 +version: 0.3.18-wip repository: https://github.com/dart-lang/ecosystem/tree/main/pkgs/firehose environment: - sdk: '>=2.19.0 <3.0.0' + sdk: ^3.0.0 executables: firehose: firehose