Resurrect Github actions (#470)

This reverts all but the intended line of the last commit of #458 .
This should resurrect github actions.
diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml
new file mode 100644
index 0000000..cdd2b59
--- /dev/null
+++ b/.github/workflows/dart.yml
@@ -0,0 +1,577 @@
+# Created with package:mono_repo v3.4.6
+name: Dart CI
+on:
+  push:
+    branches:
+      - master
+      - null_safety
+      - migrate_github_actions
+  pull_request:
+    branches:
+      - master
+      - null_safety
+  schedule:
+    - cron: "0 0 * * 0"
+defaults:
+  run:
+    shell: bash
+env:
+  PUB_ENVIRONMENT: bot.github
+
+jobs:
+  job_001:
+    name: "format; linux; Dart dev; PKG: protobuf; `dartfmt -n --set-exit-if-changed .`"
+    runs-on: ubuntu-latest
+    steps:
+      - name: Cache Pub hosted dependencies
+        uses: actions/cache@v2
+        with:
+          path: "~/.pub-cache/hosted"
+          key: "os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:protobuf;commands:dartfmt"
+          restore-keys: |
+            os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:protobuf
+            os:ubuntu-latest;pub-cache-hosted;dart:dev
+            os:ubuntu-latest;pub-cache-hosted
+            os:ubuntu-latest
+      - uses: dart-lang/setup-dart@v0.3
+        with:
+          sdk: dev
+      - id: checkout
+        uses: actions/checkout@v2
+      - id: protobuf_pub_upgrade
+        name: "protobuf; pub upgrade --no-precompile"
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: protobuf
+        run: pub upgrade --no-precompile
+      - name: "protobuf; dartfmt -n --set-exit-if-changed ."
+        if: "always() && steps.protobuf_pub_upgrade.conclusion == 'success'"
+        working-directory: protobuf
+        run: dartfmt -n --set-exit-if-changed .
+  job_002:
+    name: "format; linux; Dart dev; PKG: protoc_plugin; `./../tool/setup.sh`, `make protos`, `dartfmt -n --set-exit-if-changed .`"
+    runs-on: ubuntu-latest
+    steps:
+      - name: Cache Pub hosted dependencies
+        uses: actions/cache@v2
+        with:
+          path: "~/.pub-cache/hosted"
+          key: "os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:protoc_plugin;commands:command_0-command_2-dartfmt"
+          restore-keys: |
+            os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:protoc_plugin
+            os:ubuntu-latest;pub-cache-hosted;dart:dev
+            os:ubuntu-latest;pub-cache-hosted
+            os:ubuntu-latest
+      - uses: dart-lang/setup-dart@v0.3
+        with:
+          sdk: dev
+      - id: checkout
+        uses: actions/checkout@v2
+      - id: protoc_plugin_pub_upgrade
+        name: "protoc_plugin; pub upgrade --no-precompile"
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: protoc_plugin
+        run: pub upgrade --no-precompile
+      - name: protoc_plugin; ./../tool/setup.sh
+        if: "always() && steps.protoc_plugin_pub_upgrade.conclusion == 'success'"
+        working-directory: protoc_plugin
+        run: ./../tool/setup.sh
+      - name: protoc_plugin; make protos
+        if: "always() && steps.protoc_plugin_pub_upgrade.conclusion == 'success'"
+        working-directory: protoc_plugin
+        run: make protos
+      - name: "protoc_plugin; dartfmt -n --set-exit-if-changed ."
+        if: "always() && steps.protoc_plugin_pub_upgrade.conclusion == 'success'"
+        working-directory: protoc_plugin
+        run: dartfmt -n --set-exit-if-changed .
+  job_003:
+    name: "analyze; linux; Dart dev; PKG: protobuf; `dartanalyzer --fatal-infos --fatal-warnings lib test`"
+    runs-on: ubuntu-latest
+    steps:
+      - name: Cache Pub hosted dependencies
+        uses: actions/cache@v2
+        with:
+          path: "~/.pub-cache/hosted"
+          key: "os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:protobuf;commands:dartanalyzer_1"
+          restore-keys: |
+            os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:protobuf
+            os:ubuntu-latest;pub-cache-hosted;dart:dev
+            os:ubuntu-latest;pub-cache-hosted
+            os:ubuntu-latest
+      - uses: dart-lang/setup-dart@v0.3
+        with:
+          sdk: dev
+      - id: checkout
+        uses: actions/checkout@v2
+      - id: protobuf_pub_upgrade
+        name: "protobuf; pub upgrade --no-precompile"
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: protobuf
+        run: pub upgrade --no-precompile
+      - name: "protobuf; dartanalyzer --fatal-infos --fatal-warnings lib test"
+        if: "always() && steps.protobuf_pub_upgrade.conclusion == 'success'"
+        working-directory: protobuf
+        run: dartanalyzer --fatal-infos --fatal-warnings lib test
+    needs:
+      - job_001
+      - job_002
+  job_004:
+    name: "analyze; linux; Dart 2.7.0; PKG: protobuf; `dartanalyzer --fatal-warnings .`"
+    runs-on: ubuntu-latest
+    steps:
+      - name: Cache Pub hosted dependencies
+        uses: actions/cache@v2
+        with:
+          path: "~/.pub-cache/hosted"
+          key: "os:ubuntu-latest;pub-cache-hosted;dart:2.7.0;packages:protobuf;commands:dartanalyzer_0"
+          restore-keys: |
+            os:ubuntu-latest;pub-cache-hosted;dart:2.7.0;packages:protobuf
+            os:ubuntu-latest;pub-cache-hosted;dart:2.7.0
+            os:ubuntu-latest;pub-cache-hosted
+            os:ubuntu-latest
+      - uses: dart-lang/setup-dart@v0.3
+        with:
+          sdk: "2.7.0"
+      - id: checkout
+        uses: actions/checkout@v2
+      - id: protobuf_pub_upgrade
+        name: "protobuf; pub upgrade --no-precompile"
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: protobuf
+        run: pub upgrade --no-precompile
+      - name: "protobuf; dartanalyzer --fatal-warnings ."
+        if: "always() && steps.protobuf_pub_upgrade.conclusion == 'success'"
+        working-directory: protobuf
+        run: dartanalyzer --fatal-warnings .
+    needs:
+      - job_001
+      - job_002
+  job_005:
+    name: "analyze; linux; Dart dev; PKG: protoc_plugin; `./../tool/setup.sh`, `make protos`, `dartanalyzer --fatal-infos --fatal-warnings .`"
+    runs-on: ubuntu-latest
+    steps:
+      - name: Cache Pub hosted dependencies
+        uses: actions/cache@v2
+        with:
+          path: "~/.pub-cache/hosted"
+          key: "os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:protoc_plugin;commands:command_0-command_2-dartanalyzer_2"
+          restore-keys: |
+            os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:protoc_plugin
+            os:ubuntu-latest;pub-cache-hosted;dart:dev
+            os:ubuntu-latest;pub-cache-hosted
+            os:ubuntu-latest
+      - uses: dart-lang/setup-dart@v0.3
+        with:
+          sdk: dev
+      - id: checkout
+        uses: actions/checkout@v2
+      - id: protoc_plugin_pub_upgrade
+        name: "protoc_plugin; pub upgrade --no-precompile"
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: protoc_plugin
+        run: pub upgrade --no-precompile
+      - name: protoc_plugin; ./../tool/setup.sh
+        if: "always() && steps.protoc_plugin_pub_upgrade.conclusion == 'success'"
+        working-directory: protoc_plugin
+        run: ./../tool/setup.sh
+      - name: protoc_plugin; make protos
+        if: "always() && steps.protoc_plugin_pub_upgrade.conclusion == 'success'"
+        working-directory: protoc_plugin
+        run: make protos
+      - name: "protoc_plugin; dartanalyzer --fatal-infos --fatal-warnings ."
+        if: "always() && steps.protoc_plugin_pub_upgrade.conclusion == 'success'"
+        working-directory: protoc_plugin
+        run: dartanalyzer --fatal-infos --fatal-warnings .
+    needs:
+      - job_001
+      - job_002
+  job_006:
+    name: "analyze; linux; Dart 2.7.0; PKG: protoc_plugin; `./../tool/setup.sh`, `make protos`, `dartanalyzer --fatal-warnings .`"
+    runs-on: ubuntu-latest
+    steps:
+      - name: Cache Pub hosted dependencies
+        uses: actions/cache@v2
+        with:
+          path: "~/.pub-cache/hosted"
+          key: "os:ubuntu-latest;pub-cache-hosted;dart:2.7.0;packages:protoc_plugin;commands:command_0-command_2-dartanalyzer_0"
+          restore-keys: |
+            os:ubuntu-latest;pub-cache-hosted;dart:2.7.0;packages:protoc_plugin
+            os:ubuntu-latest;pub-cache-hosted;dart:2.7.0
+            os:ubuntu-latest;pub-cache-hosted
+            os:ubuntu-latest
+      - uses: dart-lang/setup-dart@v0.3
+        with:
+          sdk: "2.7.0"
+      - id: checkout
+        uses: actions/checkout@v2
+      - id: protoc_plugin_pub_upgrade
+        name: "protoc_plugin; pub upgrade --no-precompile"
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: protoc_plugin
+        run: pub upgrade --no-precompile
+      - name: protoc_plugin; ./../tool/setup.sh
+        if: "always() && steps.protoc_plugin_pub_upgrade.conclusion == 'success'"
+        working-directory: protoc_plugin
+        run: ./../tool/setup.sh
+      - name: protoc_plugin; make protos
+        if: "always() && steps.protoc_plugin_pub_upgrade.conclusion == 'success'"
+        working-directory: protoc_plugin
+        run: make protos
+      - name: "protoc_plugin; dartanalyzer --fatal-warnings ."
+        if: "always() && steps.protoc_plugin_pub_upgrade.conclusion == 'success'"
+        working-directory: protoc_plugin
+        run: dartanalyzer --fatal-warnings .
+    needs:
+      - job_001
+      - job_002
+  job_007:
+    name: "run_tests; linux; Dart 2.7.0; PKG: protobuf; `pub run test`"
+    runs-on: ubuntu-latest
+    steps:
+      - name: Cache Pub hosted dependencies
+        uses: actions/cache@v2
+        with:
+          path: "~/.pub-cache/hosted"
+          key: "os:ubuntu-latest;pub-cache-hosted;dart:2.7.0;packages:protobuf;commands:test"
+          restore-keys: |
+            os:ubuntu-latest;pub-cache-hosted;dart:2.7.0;packages:protobuf
+            os:ubuntu-latest;pub-cache-hosted;dart:2.7.0
+            os:ubuntu-latest;pub-cache-hosted
+            os:ubuntu-latest
+      - uses: dart-lang/setup-dart@v0.3
+        with:
+          sdk: "2.7.0"
+      - id: checkout
+        uses: actions/checkout@v2
+      - id: protobuf_pub_upgrade
+        name: "protobuf; pub upgrade --no-precompile"
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: protobuf
+        run: pub upgrade --no-precompile
+      - name: protobuf; pub run test
+        if: "always() && steps.protobuf_pub_upgrade.conclusion == 'success'"
+        working-directory: protobuf
+        run: pub run test
+    needs:
+      - job_001
+      - job_002
+      - job_003
+      - job_004
+      - job_005
+      - job_006
+  job_008:
+    name: "run_tests; osx; Dart 2.7.0; PKG: protobuf; `pub run test`"
+    runs-on: macos-latest
+    steps:
+      - name: Cache Pub hosted dependencies
+        uses: actions/cache@v2
+        with:
+          path: "~/.pub-cache/hosted"
+          key: "os:macos-latest;pub-cache-hosted;dart:2.7.0;packages:protobuf;commands:test"
+          restore-keys: |
+            os:macos-latest;pub-cache-hosted;dart:2.7.0;packages:protobuf
+            os:macos-latest;pub-cache-hosted;dart:2.7.0
+            os:macos-latest;pub-cache-hosted
+            os:macos-latest
+      - uses: dart-lang/setup-dart@v0.3
+        with:
+          sdk: "2.7.0"
+      - id: checkout
+        uses: actions/checkout@v2
+      - id: protobuf_pub_upgrade
+        name: "protobuf; pub upgrade --no-precompile"
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: protobuf
+        run: pub upgrade --no-precompile
+      - name: protobuf; pub run test
+        if: "always() && steps.protobuf_pub_upgrade.conclusion == 'success'"
+        working-directory: protobuf
+        run: pub run test
+    needs:
+      - job_001
+      - job_002
+      - job_003
+      - job_004
+      - job_005
+      - job_006
+  job_009:
+    name: "run_tests; windows; Dart 2.7.0; PKG: protobuf; `pub run test`"
+    runs-on: windows-latest
+    steps:
+      - uses: dart-lang/setup-dart@v0.3
+        with:
+          sdk: "2.7.0"
+      - id: checkout
+        uses: actions/checkout@v2
+      - id: protobuf_pub_upgrade
+        name: "protobuf; pub.bat upgrade --no-precompile"
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: protobuf
+        run: pub.bat upgrade --no-precompile
+      - name: protobuf; pub run test
+        if: "always() && steps.protobuf_pub_upgrade.conclusion == 'success'"
+        working-directory: protobuf
+        run: pub.bat run test
+    needs:
+      - job_001
+      - job_002
+      - job_003
+      - job_004
+      - job_005
+      - job_006
+  job_010:
+    name: "run_tests; linux; Dart dev; PKG: protobuf; `pub run test`"
+    runs-on: ubuntu-latest
+    steps:
+      - name: Cache Pub hosted dependencies
+        uses: actions/cache@v2
+        with:
+          path: "~/.pub-cache/hosted"
+          key: "os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:protobuf;commands:test"
+          restore-keys: |
+            os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:protobuf
+            os:ubuntu-latest;pub-cache-hosted;dart:dev
+            os:ubuntu-latest;pub-cache-hosted
+            os:ubuntu-latest
+      - uses: dart-lang/setup-dart@v0.3
+        with:
+          sdk: dev
+      - id: checkout
+        uses: actions/checkout@v2
+      - id: protobuf_pub_upgrade
+        name: "protobuf; pub upgrade --no-precompile"
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: protobuf
+        run: pub upgrade --no-precompile
+      - name: protobuf; pub run test
+        if: "always() && steps.protobuf_pub_upgrade.conclusion == 'success'"
+        working-directory: protobuf
+        run: pub run test
+    needs:
+      - job_001
+      - job_002
+      - job_003
+      - job_004
+      - job_005
+      - job_006
+  job_011:
+    name: "run_tests; osx; Dart dev; PKG: protobuf; `pub run test`"
+    runs-on: macos-latest
+    steps:
+      - name: Cache Pub hosted dependencies
+        uses: actions/cache@v2
+        with:
+          path: "~/.pub-cache/hosted"
+          key: "os:macos-latest;pub-cache-hosted;dart:dev;packages:protobuf;commands:test"
+          restore-keys: |
+            os:macos-latest;pub-cache-hosted;dart:dev;packages:protobuf
+            os:macos-latest;pub-cache-hosted;dart:dev
+            os:macos-latest;pub-cache-hosted
+            os:macos-latest
+      - uses: dart-lang/setup-dart@v0.3
+        with:
+          sdk: dev
+      - id: checkout
+        uses: actions/checkout@v2
+      - id: protobuf_pub_upgrade
+        name: "protobuf; pub upgrade --no-precompile"
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: protobuf
+        run: pub upgrade --no-precompile
+      - name: protobuf; pub run test
+        if: "always() && steps.protobuf_pub_upgrade.conclusion == 'success'"
+        working-directory: protobuf
+        run: pub run test
+    needs:
+      - job_001
+      - job_002
+      - job_003
+      - job_004
+      - job_005
+      - job_006
+  job_012:
+    name: "run_tests; windows; Dart dev; PKG: protobuf; `pub run test`"
+    runs-on: windows-latest
+    steps:
+      - uses: dart-lang/setup-dart@v0.3
+        with:
+          sdk: dev
+      - id: checkout
+        uses: actions/checkout@v2
+      - id: protobuf_pub_upgrade
+        name: "protobuf; pub.bat upgrade --no-precompile"
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: protobuf
+        run: pub.bat upgrade --no-precompile
+      - name: protobuf; pub run test
+        if: "always() && steps.protobuf_pub_upgrade.conclusion == 'success'"
+        working-directory: protobuf
+        run: pub.bat run test
+    needs:
+      - job_001
+      - job_002
+      - job_003
+      - job_004
+      - job_005
+      - job_006
+  job_013:
+    name: "run_tests; linux; Dart 2.7.0; PKG: protoc_plugin; `./../tool/setup.sh`, `make protos`, `pub run test`"
+    runs-on: ubuntu-latest
+    steps:
+      - name: Cache Pub hosted dependencies
+        uses: actions/cache@v2
+        with:
+          path: "~/.pub-cache/hosted"
+          key: "os:ubuntu-latest;pub-cache-hosted;dart:2.7.0;packages:protoc_plugin;commands:command_0-command_2-test"
+          restore-keys: |
+            os:ubuntu-latest;pub-cache-hosted;dart:2.7.0;packages:protoc_plugin
+            os:ubuntu-latest;pub-cache-hosted;dart:2.7.0
+            os:ubuntu-latest;pub-cache-hosted
+            os:ubuntu-latest
+      - uses: dart-lang/setup-dart@v0.3
+        with:
+          sdk: "2.7.0"
+      - id: checkout
+        uses: actions/checkout@v2
+      - id: protoc_plugin_pub_upgrade
+        name: "protoc_plugin; pub upgrade --no-precompile"
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: protoc_plugin
+        run: pub upgrade --no-precompile
+      - name: protoc_plugin; ./../tool/setup.sh
+        if: "always() && steps.protoc_plugin_pub_upgrade.conclusion == 'success'"
+        working-directory: protoc_plugin
+        run: ./../tool/setup.sh
+      - name: protoc_plugin; make protos
+        if: "always() && steps.protoc_plugin_pub_upgrade.conclusion == 'success'"
+        working-directory: protoc_plugin
+        run: make protos
+      - name: protoc_plugin; pub run test
+        if: "always() && steps.protoc_plugin_pub_upgrade.conclusion == 'success'"
+        working-directory: protoc_plugin
+        run: pub run test
+    needs:
+      - job_001
+      - job_002
+      - job_003
+      - job_004
+      - job_005
+      - job_006
+  job_014:
+    name: "run_tests; linux; Dart dev; PKG: protoc_plugin; `./../tool/setup.sh`, `make protos`, `pub run test`"
+    runs-on: ubuntu-latest
+    steps:
+      - name: Cache Pub hosted dependencies
+        uses: actions/cache@v2
+        with:
+          path: "~/.pub-cache/hosted"
+          key: "os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:protoc_plugin;commands:command_0-command_2-test"
+          restore-keys: |
+            os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:protoc_plugin
+            os:ubuntu-latest;pub-cache-hosted;dart:dev
+            os:ubuntu-latest;pub-cache-hosted
+            os:ubuntu-latest
+      - uses: dart-lang/setup-dart@v0.3
+        with:
+          sdk: dev
+      - id: checkout
+        uses: actions/checkout@v2
+      - id: protoc_plugin_pub_upgrade
+        name: "protoc_plugin; pub upgrade --no-precompile"
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: protoc_plugin
+        run: pub upgrade --no-precompile
+      - name: protoc_plugin; ./../tool/setup.sh
+        if: "always() && steps.protoc_plugin_pub_upgrade.conclusion == 'success'"
+        working-directory: protoc_plugin
+        run: ./../tool/setup.sh
+      - name: protoc_plugin; make protos
+        if: "always() && steps.protoc_plugin_pub_upgrade.conclusion == 'success'"
+        working-directory: protoc_plugin
+        run: make protos
+      - name: protoc_plugin; pub run test
+        if: "always() && steps.protoc_plugin_pub_upgrade.conclusion == 'success'"
+        working-directory: protoc_plugin
+        run: pub run test
+    needs:
+      - job_001
+      - job_002
+      - job_003
+      - job_004
+      - job_005
+      - job_006
+  job_015:
+    name: "format_analyze; linux; Dart dev; PKGS: api_benchmark, query_benchmark; `./../tool/setup.sh`, `./compile_protos.sh`, `dartfmt -n --set-exit-if-changed .`, `dartanalyzer --fatal-warnings .`"
+    runs-on: ubuntu-latest
+    steps:
+      - name: Cache Pub hosted dependencies
+        uses: actions/cache@v2
+        with:
+          path: "~/.pub-cache/hosted"
+          key: "os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:api_benchmark-query_benchmark;commands:command_0-command_1-dartfmt-dartanalyzer_0"
+          restore-keys: |
+            os:ubuntu-latest;pub-cache-hosted;dart:dev;packages:api_benchmark-query_benchmark
+            os:ubuntu-latest;pub-cache-hosted;dart:dev
+            os:ubuntu-latest;pub-cache-hosted
+            os:ubuntu-latest
+      - uses: dart-lang/setup-dart@v0.3
+        with:
+          sdk: dev
+      - id: checkout
+        uses: actions/checkout@v2
+      - id: api_benchmark_pub_upgrade
+        name: "api_benchmark; pub upgrade --no-precompile"
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: api_benchmark
+        run: pub upgrade --no-precompile
+      - name: api_benchmark; ./../tool/setup.sh
+        if: "always() && steps.api_benchmark_pub_upgrade.conclusion == 'success'"
+        working-directory: api_benchmark
+        run: ./../tool/setup.sh
+      - name: api_benchmark; ./compile_protos.sh
+        if: "always() && steps.api_benchmark_pub_upgrade.conclusion == 'success'"
+        working-directory: api_benchmark
+        run: ./compile_protos.sh
+      - name: "api_benchmark; dartfmt -n --set-exit-if-changed ."
+        if: "always() && steps.api_benchmark_pub_upgrade.conclusion == 'success'"
+        working-directory: api_benchmark
+        run: dartfmt -n --set-exit-if-changed .
+      - name: "api_benchmark; dartanalyzer --fatal-warnings ."
+        if: "always() && steps.api_benchmark_pub_upgrade.conclusion == 'success'"
+        working-directory: api_benchmark
+        run: dartanalyzer --fatal-warnings .
+      - id: query_benchmark_pub_upgrade
+        name: "query_benchmark; pub upgrade --no-precompile"
+        if: "always() && steps.checkout.conclusion == 'success'"
+        working-directory: query_benchmark
+        run: pub upgrade --no-precompile
+      - name: query_benchmark; ./../tool/setup.sh
+        if: "always() && steps.query_benchmark_pub_upgrade.conclusion == 'success'"
+        working-directory: query_benchmark
+        run: ./../tool/setup.sh
+      - name: query_benchmark; ./compile_protos.sh
+        if: "always() && steps.query_benchmark_pub_upgrade.conclusion == 'success'"
+        working-directory: query_benchmark
+        run: ./compile_protos.sh
+      - name: "query_benchmark; dartfmt -n --set-exit-if-changed ."
+        if: "always() && steps.query_benchmark_pub_upgrade.conclusion == 'success'"
+        working-directory: query_benchmark
+        run: dartfmt -n --set-exit-if-changed .
+      - name: "query_benchmark; dartanalyzer --fatal-warnings ."
+        if: "always() && steps.query_benchmark_pub_upgrade.conclusion == 'success'"
+        working-directory: query_benchmark
+        run: dartanalyzer --fatal-warnings .
+    needs:
+      - job_001
+      - job_002
+      - job_003
+      - job_004
+      - job_005
+      - job_006
+      - job_007
+      - job_008
+      - job_009
+      - job_010
+      - job_011
+      - job_012
+      - job_013
+      - job_014
diff --git a/api_benchmark/mono_pkg.yaml b/api_benchmark/mono_pkg.yaml
index 27f061e..67f40c1 100644
--- a/api_benchmark/mono_pkg.yaml
+++ b/api_benchmark/mono_pkg.yaml
@@ -1,7 +1,9 @@
 # See https://github.com/dart-lang/mono_repo for details
+
 stages:
-  - format_analyzer_tests:
+  - format_analyze:
     - group:
+      - command: ./../tool/setup.sh
       - command: ./compile_protos.sh
       - dartfmt
       - dartanalyzer: --fatal-warnings .
diff --git a/mono_repo.yaml b/mono_repo.yaml
index 8aa5093..af64ff6 100644
--- a/mono_repo.yaml
+++ b/mono_repo.yaml
@@ -1,18 +1,15 @@
-travis:
-  before_install:
-# Install our custom protoc, as the version we get with apt-get is too old.
-    - wget -O protoc.zip https://github.com/protocolbuffers/protobuf/releases/download/v3.14.0/protoc-3.14.0-linux-x86_64.zip
-    - unzip -d protoc protoc.zip
-    - export PATH=$PWD/protoc/bin:$PATH
-    - echo $PATH
-# Run the protoc_plugin tests with the protobuf from the repo, not from pub.
-# This could be avoided with a fix of: https://github.com/dart-lang/mono_repo/issues/117.
-    - "echo \"dependency_overrides: {protobuf: {path: ../protobuf}}\" >> protoc_plugin/pubspec.yaml"
-
-  os:
-    - linux
-    - osx
-    - windows
+github:
+  on:
+    # Run CI on pushes to the master branch, and on PRs against master.
+    push:
+      branches: [master, null_safety]
+    pull_request:
+      branches: [master, null_safety]
+    schedule:
+      - cron: "0 0 * * 0"
 
 merge_stages:
-- format_analyzer_tests
+- format_analyze
+- format
+- analyze
+- run_tests
diff --git a/protobuf/mono_pkg.yaml b/protobuf/mono_pkg.yaml
index 03eeda5..5548006 100644
--- a/protobuf/mono_pkg.yaml
+++ b/protobuf/mono_pkg.yaml
@@ -1,13 +1,21 @@
 # See https://github.com/dart-lang/mono_repo for details
+
+# - format stage runs only on Linux and only using dev SDK
+# - analyze stage runs only on Linux with different flags for 2.7.0 and dev SDKs
+# - test stage runs for all oses and all sdks
+
 stages:
-  - format_analyzer_tests:
+  - format:
+    - group: [dartfmt]
+      dart: [dev]
+  - analyze:
     - group:
       - dartanalyzer: --fatal-infos --fatal-warnings lib test
-      - dartfmt
       dart: [dev]
     - group:
       - dartanalyzer: --fatal-warnings .
       dart: [2.7.0]
-    - group:
-      - test
+  - run_tests:
+    - group: [test]
       dart: [2.7.0, dev]
+      os: [linux, osx, windows]
diff --git a/protoc_plugin/CHANGELOG.md b/protoc_plugin/CHANGELOG.md
index 0405d5f..1e41a67 100644
--- a/protoc_plugin/CHANGELOG.md
+++ b/protoc_plugin/CHANGELOG.md
@@ -1,7 +1,13 @@
+## 19.3.1
+
+* Emit binary coded descriptors, which can be used to reflect over the options
+  given to the descriptor.
+
 ## 19.3.0
 
 * Generate constructors with optional named arguments for prefilling fields.
 * Output language version 2.7 in generated files to support extension methods.
+
 ## 19.2.1
 
 * Support optional proto3 fields.
diff --git a/protoc_plugin/Makefile b/protoc_plugin/Makefile
index 1aaec06..df2b114 100644
--- a/protoc_plugin/Makefile
+++ b/protoc_plugin/Makefile
@@ -25,6 +25,7 @@
 	google/protobuf/unittest_well_known_types \
 	google/protobuf/unittest \
 	google/protobuf/wrappers \
+	custom_option \
 	dart_name \
         default_value_escape \
 	enum_extension \
diff --git a/protoc_plugin/lib/code_generator.dart b/protoc_plugin/lib/code_generator.dart
index 753d3ac..2ae410c 100644
--- a/protoc_plugin/lib/code_generator.dart
+++ b/protoc_plugin/lib/code_generator.dart
@@ -28,6 +28,9 @@
 
   String get fileImportPrefix => _getFileImportPrefix();
 
+  String get binaryDescriptorName =>
+      '${lowerCaseFirstLetter(classname)}Descriptor';
+
   String _getFileImportPrefix() {
     var path = fileGen.protoFileUri.toString();
     if (importPrefixes.containsKey(path)) {
@@ -43,6 +46,21 @@
   ///
   /// (Represents the .pb.dart file that we need to import in order to use it.)
   FileGenerator get fileGen;
+
+  // The generator containing this entity.
+  ProtobufContainer get _parent;
+
+  /// The top-level parent of this entity. If this entity is a top-level entity,
+  /// returns this.
+  ProtobufContainer get toplevelParent {
+    if (_parent == null) {
+      return null;
+    }
+    if (_parent is FileGenerator) {
+      return this;
+    }
+    return _parent.toplevelParent;
+  }
 }
 
 class CodeGenerator extends ProtobufContainer {
@@ -112,5 +130,7 @@
   @override
   FileGenerator get fileGen => null;
   @override
+  ProtobufContainer get _parent => null;
+  @override
   List<int> get fieldPath => [];
 }
diff --git a/protoc_plugin/lib/enum_generator.dart b/protoc_plugin/lib/enum_generator.dart
index c27541a..e02ac7f 100644
--- a/protoc_plugin/lib/enum_generator.dart
+++ b/protoc_plugin/lib/enum_generator.dart
@@ -11,6 +11,7 @@
 }
 
 class EnumGenerator extends ProtobufContainer {
+  @override
   final ProtobufContainer _parent;
   @override
   final String classname;
@@ -170,6 +171,8 @@
     var name = getJsonConstant(fileGen);
     var json = _descriptor.writeToJsonMap();
 
+    out.println('@$_coreImportPrefix.Deprecated'
+        '(\'Use ${toplevelParent.binaryDescriptorName} instead\')');
     out.print("const $name = ");
     writeJsonConst(out, json);
     out.println(";");
diff --git a/protoc_plugin/lib/file_generator.dart b/protoc_plugin/lib/file_generator.dart
index c905529..5a619f6 100644
--- a/protoc_plugin/lib/file_generator.dart
+++ b/protoc_plugin/lib/file_generator.dart
@@ -9,13 +9,18 @@
 const String _protobufImportPrefix = r'$pb';
 const String _asyncImportPrefix = r'$async';
 const String _coreImportPrefix = r'$core';
+const String _convertImportPrefix = r'$convert';
 const String _fixnumImportPrefix = r'$fixnum';
 const String _grpcImportPrefix = r'$grpc';
 const String _mixinImportPrefix = r'$mixin';
+const String _typedDataImportPrefix = r'$typed_data';
 const String _protobufImport =
     "import 'package:protobuf/protobuf.dart' as $_protobufImportPrefix;";
 const String _asyncImport = "import 'dart:async' as $_asyncImportPrefix;";
 const String _coreImport = "import 'dart:core' as $_coreImportPrefix;";
+const String _typedDataImport =
+    "import 'dart:typed_data' as $_typedDataImportPrefix;";
+const String _convertImport = "import 'dart:convert' as $_convertImportPrefix;";
 const String _grpcImport =
     "import 'package:grpc/service_api.dart' as $_grpcImportPrefix;";
 
@@ -209,6 +214,8 @@
   @override
   FileGenerator get fileGen => this;
   @override
+  ProtobufContainer get _parent => null;
+  @override
   List<int> get fieldPath => [];
 
   /// Generates all the Dart files for this .proto file.
@@ -439,7 +446,8 @@
       [OutputConfiguration config = const DefaultOutputConfiguration()]) {
     if (!_linked) throw StateError("not linked");
     var out = makeWriter();
-    _writeHeading(out);
+    _writeHeading(out,
+        extraIgnores: {'deprecated_member_use_from_same_package'});
 
     if (serviceGenerators.isNotEmpty) {
       out.println(_asyncImport);
@@ -510,13 +518,27 @@
     return _formatter.format(out.toString());
   }
 
+  void writeBinaryDescriptor(IndentingWriter out, String identifierName,
+      String name, GeneratedMessage descriptor) {
+    var descriptorText = base64Encode(descriptor.writeToBuffer());
+    out.println('/// Descriptor for `$name`. Decode as a '
+        '`${descriptor.info_.qualifiedMessageName}`.');
+    out.println('final $_typedDataImportPrefix.Uint8List '
+        '$identifierName = '
+        '$_convertImportPrefix.base64Decode(\'$descriptorText\');');
+  }
+
   /// Returns the contents of the .pbjson.dart file for this .proto file.
   String generateJsonFile(
       [OutputConfiguration config = const DefaultOutputConfiguration()]) {
     if (!_linked) throw StateError("not linked");
     var out = makeWriter();
-    _writeHeading(out);
+    _writeHeading(out,
+        extraIgnores: {'deprecated_member_use_from_same_package'});
 
+    out.println(_coreImport);
+    out.println(_convertImport);
+    out.println(_typedDataImport);
     // Import the .pbjson.dart files we depend on.
     var imports = _findJsonProtosToImport();
     for (var target in imports) {
@@ -526,12 +548,18 @@
 
     for (var e in enumGenerators) {
       e.generateConstants(out);
+      writeBinaryDescriptor(
+          out, e.binaryDescriptorName, e._descriptor.name, e._descriptor);
     }
     for (var m in messageGenerators) {
       m.generateConstants(out);
+      writeBinaryDescriptor(
+          out, m.binaryDescriptorName, m._descriptor.name, m._descriptor);
     }
     for (var s in serviceGenerators) {
       s.generateConstants(out);
+      writeBinaryDescriptor(
+          out, s.binaryDescriptorName, s._descriptor.name, s._descriptor);
     }
 
     return out.toString();
@@ -555,14 +583,17 @@
   }
 
   /// Writes the header at the top of the dart file.
-  void _writeHeading(IndentingWriter out) {
+  void _writeHeading(IndentingWriter out,
+      {Set<String> extraIgnores = const <String>{}}) {
+    var extraIgnoresString =
+        extraIgnores.isEmpty ? '' : ',${extraIgnores.join(',')}';
     out.println('''
 ///
 //  Generated code. Do not modify.
 //  source: ${descriptor.name}
 //
 // @dart = 2.7
-// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
+// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields$extraIgnoresString
 ''');
   }
 
diff --git a/protoc_plugin/lib/grpc_generator.dart b/protoc_plugin/lib/grpc_generator.dart
index aa70a17..56db999 100644
--- a/protoc_plugin/lib/grpc_generator.dart
+++ b/protoc_plugin/lib/grpc_generator.dart
@@ -181,8 +181,7 @@
   factory _GrpcMethod(GrpcServiceGenerator service, GenerationContext ctx,
       MethodDescriptorProto method) {
     final grpcName = method.name;
-    final dartName =
-        grpcName.substring(0, 1).toLowerCase() + grpcName.substring(1);
+    final dartName = lowerCaseFirstLetter(grpcName);
 
     final clientStreaming = method.clientStreaming;
     final serverStreaming = method.serverStreaming;
diff --git a/protoc_plugin/lib/message_generator.dart b/protoc_plugin/lib/message_generator.dart
index ae089ec..3809434 100644
--- a/protoc_plugin/lib/message_generator.dart
+++ b/protoc_plugin/lib/message_generator.dart
@@ -51,6 +51,7 @@
 
   PbMixin mixin;
 
+  @override
   final ProtobufContainer _parent;
   final DescriptorProto _descriptor;
   final List<EnumGenerator> _enumGenerators = <EnumGenerator>[];
@@ -683,6 +684,8 @@
     var nestedEnumNames =
         _enumGenerators.map((e) => e.getJsonConstant(fileGen)).toList();
 
+    out.println('@$_coreImportPrefix.Deprecated'
+        '(\'Use ${toplevelParent.binaryDescriptorName} instead\')');
     out.addBlock("const $name = const {", "};", () {
       for (var key in json.keys) {
         out.print("'$key': ");
diff --git a/protoc_plugin/lib/names.dart b/protoc_plugin/lib/names.dart
index 01a2e79..463ccc7 100644
--- a/protoc_plugin/lib/names.dart
+++ b/protoc_plugin/lib/names.dart
@@ -431,9 +431,8 @@
 
 /// The name to use by default for the Dart getter and setter.
 /// (A suffix will be added if there is a conflict.)
-String _defaultFieldName(String fieldMethodSuffix) {
-  return '${fieldMethodSuffix[0].toLowerCase()}${fieldMethodSuffix.substring(1)}';
-}
+String _defaultFieldName(String fieldMethodSuffix) =>
+    lowerCaseFirstLetter(fieldMethodSuffix);
 
 String _defaultHasMethodName(String fieldMethodSuffix) =>
     'has$fieldMethodSuffix';
@@ -584,3 +583,6 @@
   // The number of entries is one higher than the highest seen index.
   return highestIndexSeen + 1;
 }
+
+String lowerCaseFirstLetter(String input) =>
+    input[0].toLowerCase() + input.substring(1);
diff --git a/protoc_plugin/lib/protoc.dart b/protoc_plugin/lib/protoc.dart
index f836d94..8757465 100644
--- a/protoc_plugin/lib/protoc.dart
+++ b/protoc_plugin/lib/protoc.dart
@@ -1,5 +1,6 @@
 library protoc;
 
+import 'dart:convert';
 import 'dart:io';
 
 import 'package:dart_style/dart_style.dart';
diff --git a/protoc_plugin/lib/service_generator.dart b/protoc_plugin/lib/service_generator.dart
index 7157b1a..be349e0 100644
--- a/protoc_plugin/lib/service_generator.dart
+++ b/protoc_plugin/lib/service_generator.dart
@@ -132,8 +132,7 @@
 
   List<MethodDescriptorProto> get _methodDescriptors => _descriptor.method;
 
-  String _methodName(String name) =>
-      name.substring(0, 1).toLowerCase() + name.substring(1);
+  String _methodName(String name) => lowerCaseFirstLetter(name);
 
   String get _parentClass => _generatedService;
 
@@ -226,6 +225,9 @@
     for (var key in _transitiveDeps.keys) {
       typeConstants[key] = _transitiveDeps[key].getJsonConstant(fileGen);
     }
+
+    out.println('@$_coreImportPrefix.Deprecated'
+        '(\'Use ${binaryDescriptorName} instead\')');
     out.addBlock("const $messageJsonConstant = const {", "};", () {
       for (var key in typeConstants.keys) {
         var typeConst = typeConstants[key];
@@ -243,6 +245,14 @@
     }
   }
 
+  String get binaryDescriptorName {
+    var prefix = lowerCaseFirstLetter(classname);
+    if (prefix.endsWith('Base')) {
+      prefix = prefix.substring(0, prefix.length - 4);
+    }
+    return '${prefix}Descriptor';
+  }
+
   static final String _future = '$_asyncImportPrefix.Future';
   static final String _generatedMessage =
       '$_protobufImportPrefix.GeneratedMessage';
diff --git a/protoc_plugin/mono_pkg.yaml b/protoc_plugin/mono_pkg.yaml
index ce7959f..089b27b 100644
--- a/protoc_plugin/mono_pkg.yaml
+++ b/protoc_plugin/mono_pkg.yaml
@@ -1,16 +1,25 @@
 # See https://github.com/dart-lang/mono_repo for details
 stages:
-  - format_analyzer_tests:
+  - format:
     - group:
+      - command: ./../tool/setup.sh
       - command: make protos
       - dartfmt
+      dart: [dev]
+  - analyze:
+    - group:
+      - command: ./../tool/setup.sh
+      - command: make protos
       - dartanalyzer: --fatal-infos --fatal-warnings .
       dart: [dev]
     - group:
+      - command: ./../tool/setup.sh
       - command: make protos
       - dartanalyzer: --fatal-warnings .
       dart: [2.7.0]
+  - run_tests:
     - group:
+      - command: ./../tool/setup.sh
       - command: make protos
       - test
       dart: [2.7.0, dev]
diff --git a/protoc_plugin/pubspec.yaml b/protoc_plugin/pubspec.yaml
index 49562ba..b3e5cb9 100644
--- a/protoc_plugin/pubspec.yaml
+++ b/protoc_plugin/pubspec.yaml
@@ -1,5 +1,5 @@
 name: protoc_plugin
-version: 19.3.0
+version: 19.3.1
 description: Protoc compiler plugin to generate Dart code
 homepage: https://github.com/dart-lang/protobuf
 
diff --git a/protoc_plugin/test/all_tests.dart b/protoc_plugin/test/all_tests.dart
index fb96be2..fc3408f 100755
--- a/protoc_plugin/test/all_tests.dart
+++ b/protoc_plugin/test/all_tests.dart
@@ -10,6 +10,7 @@
 import 'client_generator_test.dart' as client_generator;
 import 'const_generator_test.dart' as const_generator;
 import 'default_value_escape_test.dart' as default_value_escape;
+import 'descriptor_test.dart' as descriptor_test;
 import 'enum_generator_test.dart' as enum_generator;
 import 'extension_generator_test.dart' as extension_generator_test;
 import 'extension_test.dart' as extension_test;
@@ -50,6 +51,7 @@
   client_generator.main();
   const_generator.main();
   default_value_escape.main();
+  descriptor_test.main();
   enum_generator.main();
   extension_generator_test.main();
   extension_test.main();
diff --git a/protoc_plugin/test/descriptor_test.dart b/protoc_plugin/test/descriptor_test.dart
new file mode 100644
index 0000000..b58353a
--- /dev/null
+++ b/protoc_plugin/test/descriptor_test.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2020, 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.
+
+import 'package:protoc_plugin/src/descriptor.pb.dart';
+import 'package:protobuf/protobuf.dart';
+import '../out/protos/google/protobuf/unittest.pbjson.dart';
+import '../out/protos/custom_option.pb.dart';
+import '../out/protos/custom_option.pbjson.dart';
+import 'package:test/test.dart';
+
+void main() {
+  test('Can decode message descriptor', () {
+    final descriptor = DescriptorProto.fromBuffer(testAllTypesDescriptor);
+    expect(descriptor.name, 'TestAllTypes');
+    final nestedEnumDescriptor = descriptor.enumType.first;
+    expect(nestedEnumDescriptor.name, 'NestedEnum');
+  });
+  test('Can decode enum descriptor', () {
+    final descriptor = EnumDescriptorProto.fromBuffer(foreignEnumDescriptor);
+    expect(descriptor.name, 'ForeignEnum');
+    expect(descriptor.value.map((v) => v.name),
+        ['FOREIGN_FOO', 'FOREIGN_BAR', 'FOREIGN_BAZ']);
+  });
+  test('Can decode service descriptor', () {
+    final descriptor = ServiceDescriptorProto.fromBuffer(testServiceDescriptor);
+    expect(descriptor.name, 'TestService');
+    expect(descriptor.method.map((m) => m.name), ['Foo', 'Bar']);
+  });
+  test('Can read custom options', () {
+    final registry = ExtensionRegistry()..add(Custom_option.myOption);
+    final descriptor =
+        DescriptorProto.fromBuffer(myMessageDescriptor, registry);
+    final option = descriptor.options.getExtension(Custom_option.myOption);
+    expect(option, 'Hello world!');
+  });
+}
diff --git a/protoc_plugin/test/goldens/oneMessage.pbjson b/protoc_plugin/test/goldens/oneMessage.pbjson
index 0cac887..b26d869 100644
--- a/protoc_plugin/test/goldens/oneMessage.pbjson
+++ b/protoc_plugin/test/goldens/oneMessage.pbjson
@@ -3,8 +3,12 @@
 //  source: test
 //
 // @dart = 2.7
-// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
+// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package
 
+import 'dart:core' as $core;
+import 'dart:convert' as $convert;
+import 'dart:typed_data' as $typed_data;
+@$core.Deprecated('Use phoneNumberDescriptor instead')
 const PhoneNumber$json = const {
   '1': 'PhoneNumber',
   '2': const [
@@ -14,3 +18,5 @@
   ],
 };
 
+/// Descriptor for `PhoneNumber`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List phoneNumberDescriptor = $convert.base64Decode('CgtQaG9uZU51bWJlchIWCgZudW1iZXIYASACKAlSBm51bWJlchIUCgR0eXBlGAIgASgFMgBSBHR5cGUSFQoEbmFtZRgDIAEoCToBJFIEbmFtZQ==');
diff --git a/protoc_plugin/test/goldens/service.pbserver b/protoc_plugin/test/goldens/service.pbserver
index a6ad4e6..34515c8 100644
--- a/protoc_plugin/test/goldens/service.pbserver
+++ b/protoc_plugin/test/goldens/service.pbserver
@@ -3,7 +3,7 @@
 //  source: test
 //
 // @dart = 2.7
-// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
+// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package
 
 import 'dart:async' as $async;
 
diff --git a/protoc_plugin/test/goldens/serviceGenerator.pb.json b/protoc_plugin/test/goldens/serviceGenerator.pb.json
index 7a33efe..30784bf 100644
--- a/protoc_plugin/test/goldens/serviceGenerator.pb.json
+++ b/protoc_plugin/test/goldens/serviceGenerator.pb.json
@@ -3,18 +3,27 @@
 //  source: testpkg.proto
 //
 // @dart = 2.7
-// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
+// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package
 
+import 'dart:core' as $core;
+import 'dart:convert' as $convert;
+import 'dart:typed_data' as $typed_data;
 import 'foobar.pbjson.dart' as $1;
 
+@$core.Deprecated('Use someRequestDescriptor instead')
 const SomeRequest$json = const {
   '1': 'SomeRequest',
 };
 
+/// Descriptor for `SomeRequest`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List someRequestDescriptor = $convert.base64Decode('CgtTb21lUmVxdWVzdA==');
+@$core.Deprecated('Use someReplyDescriptor instead')
 const SomeReply$json = const {
   '1': 'SomeReply',
 };
 
+/// Descriptor for `SomeReply`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List someReplyDescriptor = $convert.base64Decode('CglTb21lUmVwbHk=');
 const TestServiceBase$json = const {
   '1': 'Test',
   '2': const [
@@ -23,6 +32,7 @@
   ],
 };
 
+@$core.Deprecated('Use testServiceDescriptor instead')
 const TestServiceBase$messageJson = const {
   '.testpkg.SomeRequest': SomeRequest$json,
   '.testpkg.SomeReply': SomeReply$json,
@@ -30,3 +40,5 @@
   '.foo.bar.AnotherReply': $1.AnotherReply$json,
 };
 
+/// Descriptor for `Test`. Decode as a `google.protobuf.ServiceDescriptorProto`.
+final $typed_data.Uint8List testServiceDescriptor = $convert.base64Decode('CgRUZXN0EjMKB0FNZXRob2QSFC50ZXN0cGtnLlNvbWVSZXF1ZXN0GhIudGVzdHBrZy5Tb21lUmVwbHkSPQoNQW5vdGhlck1ldGhvZBIVLmZvby5iYXIuRW1wdHlNZXNzYWdlGhUuZm9vLmJhci5Bbm90aGVyUmVwbHk=');
diff --git a/protoc_plugin/test/goldens/topLevelEnum.pbjson b/protoc_plugin/test/goldens/topLevelEnum.pbjson
index 6a549fb..03bbcd9 100644
--- a/protoc_plugin/test/goldens/topLevelEnum.pbjson
+++ b/protoc_plugin/test/goldens/topLevelEnum.pbjson
@@ -3,8 +3,12 @@
 //  source: test
 //
 // @dart = 2.7
-// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
+// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package
 
+import 'dart:core' as $core;
+import 'dart:convert' as $convert;
+import 'dart:typed_data' as $typed_data;
+@$core.Deprecated('Use phoneTypeDescriptor instead')
 const PhoneType$json = const {
   '1': 'PhoneType',
   '2': const [
@@ -15,3 +19,5 @@
   ],
 };
 
+/// Descriptor for `PhoneType`. Decode as a `google.protobuf.EnumDescriptorProto`.
+final $typed_data.Uint8List phoneTypeDescriptor = $convert.base64Decode('CglQaG9uZVR5cGUSCgoGTU9CSUxFEAASCAoESE9NRRABEggKBFdPUksQAhIMCghCVVNJTkVTUxAC');
diff --git a/protoc_plugin/test/message_test.dart b/protoc_plugin/test/message_test.dart
index d575e14..a8d4a5d 100755
--- a/protoc_plugin/test/message_test.dart
+++ b/protoc_plugin/test/message_test.dart
@@ -3,6 +3,8 @@
 // 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: deprecated_member_use_from_same_package
+
 library message_test;
 
 import 'package:protoc_plugin/src/descriptor.pb.dart' show DescriptorProto;
diff --git a/protoc_plugin/test/protos/custom_option.proto b/protoc_plugin/test/protos/custom_option.proto
new file mode 100644
index 0000000..05d39bd
--- /dev/null
+++ b/protoc_plugin/test/protos/custom_option.proto
@@ -0,0 +1,15 @@
+// Copyright (c) 2020, 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.
+
+syntax = "proto2";
+
+import "descriptor.proto";
+
+extend google.protobuf.MessageOptions {
+  optional string my_option = 51234;
+}
+
+message MyMessage {
+  option (my_option) = "Hello world!";
+}
diff --git a/query_benchmark/mono_pkg.yaml b/query_benchmark/mono_pkg.yaml
index 27f061e..67f40c1 100644
--- a/query_benchmark/mono_pkg.yaml
+++ b/query_benchmark/mono_pkg.yaml
@@ -1,7 +1,9 @@
 # See https://github.com/dart-lang/mono_repo for details
+
 stages:
-  - format_analyzer_tests:
+  - format_analyze:
     - group:
+      - command: ./../tool/setup.sh
       - command: ./compile_protos.sh
       - dartfmt
       - dartanalyzer: --fatal-warnings .
diff --git a/tool/ci.sh b/tool/ci.sh
new file mode 100755
index 0000000..594f4e0
--- /dev/null
+++ b/tool/ci.sh
@@ -0,0 +1,126 @@
+#!/bin/bash
+# Created with package:mono_repo v3.4.6
+
+# Support built in commands on windows out of the box.
+function pub() {
+  if [[ $TRAVIS_OS_NAME == "windows" ]]; then
+    command pub.bat "$@"
+  else
+    command pub "$@"
+  fi
+}
+function dartfmt() {
+  if [[ $TRAVIS_OS_NAME == "windows" ]]; then
+    command dartfmt.bat "$@"
+  else
+    command dartfmt "$@"
+  fi
+}
+function dartanalyzer() {
+  if [[ $TRAVIS_OS_NAME == "windows" ]]; then
+    command dartanalyzer.bat "$@"
+  else
+    command dartanalyzer "$@"
+  fi
+}
+
+if [[ -z ${PKGS} ]]; then
+  echo -e '\033[31mPKGS environment variable must be set! - TERMINATING JOB\033[0m'
+  exit 64
+fi
+
+if [[ "$#" == "0" ]]; then
+  echo -e '\033[31mAt least one task argument must be provided! - TERMINATING JOB\033[0m'
+  exit 64
+fi
+
+SUCCESS_COUNT=0
+declare -a FAILURES
+
+for PKG in ${PKGS}; do
+  echo -e "\033[1mPKG: ${PKG}\033[22m"
+  EXIT_CODE=0
+  pushd "${PKG}" >/dev/null || EXIT_CODE=$?
+
+  if [[ ${EXIT_CODE} -ne 0 ]]; then
+    echo -e "\033[31mPKG: '${PKG}' does not exist - TERMINATING JOB\033[0m"
+    exit 64
+  fi
+
+  pub upgrade --no-precompile || EXIT_CODE=$?
+
+  if [[ ${EXIT_CODE} -ne 0 ]]; then
+    echo -e "\033[31mPKG: ${PKG}; 'pub upgrade' - FAILED  (${EXIT_CODE})\033[0m"
+    FAILURES+=("${PKG}; 'pub upgrade'")
+  else
+    for TASK in "$@"; do
+      EXIT_CODE=0
+      echo
+      echo -e "\033[1mPKG: ${PKG}; TASK: ${TASK}\033[22m"
+      case ${TASK} in
+      command_0)
+        echo './../tool/setup.sh'
+        ./../tool/setup.sh || EXIT_CODE=$?
+        ;;
+      command_1)
+        echo './compile_protos.sh'
+        ./compile_protos.sh || EXIT_CODE=$?
+        ;;
+      command_2)
+        echo 'make protos'
+        make protos || EXIT_CODE=$?
+        ;;
+      dartanalyzer_0)
+        echo 'dartanalyzer --fatal-warnings .'
+        dartanalyzer --fatal-warnings . || EXIT_CODE=$?
+        ;;
+      dartanalyzer_1)
+        echo 'dartanalyzer --fatal-infos --fatal-warnings lib test'
+        dartanalyzer --fatal-infos --fatal-warnings lib test || EXIT_CODE=$?
+        ;;
+      dartanalyzer_2)
+        echo 'dartanalyzer --fatal-infos --fatal-warnings .'
+        dartanalyzer --fatal-infos --fatal-warnings . || EXIT_CODE=$?
+        ;;
+      dartfmt)
+        echo 'dartfmt -n --set-exit-if-changed .'
+        dartfmt -n --set-exit-if-changed . || EXIT_CODE=$?
+        ;;
+      test)
+        echo 'pub run test'
+        pub run test || EXIT_CODE=$?
+        ;;
+      *)
+        echo -e "\033[31mUnknown TASK '${TASK}' - TERMINATING JOB\033[0m"
+        exit 64
+        ;;
+      esac
+
+      if [[ ${EXIT_CODE} -ne 0 ]]; then
+        echo -e "\033[31mPKG: ${PKG}; TASK: ${TASK} - FAILED (${EXIT_CODE})\033[0m"
+        FAILURES+=("${PKG}; TASK: ${TASK}")
+      else
+        echo -e "\033[32mPKG: ${PKG}; TASK: ${TASK} - SUCCEEDED\033[0m"
+        SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
+      fi
+
+    done
+  fi
+
+  echo
+  echo -e "\033[32mSUCCESS COUNT: ${SUCCESS_COUNT}\033[0m"
+
+  if [ ${#FAILURES[@]} -ne 0 ]; then
+    echo -e "\033[31mFAILURES: ${#FAILURES[@]}\033[0m"
+    for i in "${FAILURES[@]}"; do
+      echo -e "\033[31m  $i\033[0m"
+    done
+  fi
+
+  popd >/dev/null || exit 70
+  echo
+done
+
+if [ ${#FAILURES[@]} -ne 0 ]; then
+  exit 1
+fi
diff --git a/tool/setup.sh b/tool/setup.sh
new file mode 100755
index 0000000..07f0d56
--- /dev/null
+++ b/tool/setup.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+wget -O protoc.zip https://github.com/protocolbuffers/protobuf/releases/download/v3.14.0/protoc-3.14.0-linux-x86_64.zip
+unzip -d protoc protoc.zip
+if [[ -z "${GITHUB_ENV}" ]]; then
+  # Local mono_repo presubmit run
+  export PATH=$PWD/protoc/bin:$PATH
+else
+  # GitHub Actions
+  echo "PATH=$PWD/protoc/bin:$PATH" >> $GITHUB_ENV
+fi