diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..430a85e
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,11 @@
+# Set update schedule for GitHub Actions
+# See https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/keeping-your-actions-up-to-date-with-dependabot
+
+version: 2
+updates:
+
+- package-ecosystem: "github-actions"
+  directory: "/"
+  schedule:
+    # Check for updates to GitHub Actions every weekday
+    interval: "daily"
diff --git a/.github/workflows/test-package.yml b/.github/workflows/test-package.yml
index 07e2dbf..771cf1a 100644
--- a/.github/workflows/test-package.yml
+++ b/.github/workflows/test-package.yml
@@ -22,8 +22,8 @@
       matrix:
         sdk: [dev]
     steps:
-      - uses: actions/checkout@v2
-      - uses: dart-lang/setup-dart@v0.3
+      - uses: actions/checkout@v3
+      - uses: dart-lang/setup-dart@v1
         with:
           sdk: ${{ matrix.sdk }}
       - id: install
@@ -47,10 +47,10 @@
       matrix:
         # Add macos-latest and/or windows-latest if relevant for this package.
         os: [ubuntu-latest]
-        sdk: [dev]
+        sdk: [2.12.0, dev]
     steps:
-      - uses: actions/checkout@v2
-      - uses: dart-lang/setup-dart@v0.3
+      - uses: actions/checkout@v3
+      - uses: dart-lang/setup-dart@v1
         with:
           sdk: ${{ matrix.sdk }}
       - id: install
@@ -59,27 +59,3 @@
       - name: Run VM tests
         run: dart test --platform vm
         if: always() && steps.install.outcome == 'success'
-
-  # Run tests on a legacy SDK on a matrix consisting of two dimensions:
-  # 1. OS: ubuntu-latest, (macos-latest, windows-latest)
-  # 2. release: 2.1.0
-  test_legacy_sdk:
-    needs: analyze
-    runs-on: ${{ matrix.os }}
-    strategy:
-      fail-fast: false
-      matrix:
-        # Add macos-latest and/or windows-latest if relevant for this package.
-        os: [ubuntu-latest]
-        sdk: [2.1.0]
-    steps:
-      - uses: actions/checkout@v2
-      - uses: dart-lang/setup-dart@v0.3
-        with:
-          sdk: ${{ matrix.sdk }}
-      - id: install
-        name: Install dependencies
-        run: pub get
-      - name: Run VM tests
-        run: pub run test --platform vm
-        if: always() && steps.install.outcome == 'success'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 766efa6..2ee2a66 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,19 @@
+## 2.0.3-dev
+
+* Populate the pubspec `repository` field.
+
+## 2.0.2
+
+* Reverted `meta` constraint to `^1.3.0`.
+
+## 2.0.1
+
+* Update `meta` constraint to `>=1.3.0 <3.0.0`.
+
+## 2.0.0
+
+* Migrate to null safety.
+
 ## 1.0.6
 
 * Require Dart >=2.1
diff --git a/LICENSE b/LICENSE
index 389ce98..aa86769 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,5 @@
-Copyright 2017, the Dart project authors. All rights reserved.
+Copyright 2017, the Dart project authors.
+
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are
 met:
@@ -9,7 +10,7 @@
       copyright notice, this list of conditions and the following
       disclaimer in the documentation and/or other materials provided
       with the distribution.
-    * Neither the name of Google Inc. nor the names of its
+    * Neither the name of Google LLC nor the names of its
       contributors may be used to endorse or promote products derived
       from this software without specific prior written permission.
 
diff --git a/README.md b/README.md
index f0ff486..4ff6c90 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,7 @@
+[![Dart CI](https://github.com/dart-lang/test_process/actions/workflows/test-package.yml/badge.svg)](https://github.com/dart-lang/test_process/actions/workflows/test-package.yml)
+[![pub package](https://img.shields.io/pub/v/test_process.svg)](https://pub.dev/packages/test_process)
+[![package publisher](https://img.shields.io/pub/publisher/test_process.svg)](https://pub.dev/packages/test_process/publisher)
+
 A package for testing subprocesses.
 
 This exposes a [`TestProcess`][TestProcess] class that wraps `dart:io`'s
diff --git a/lib/test_process.dart b/lib/test_process.dart
index 301ce9d..be8efc7 100644
--- a/lib/test_process.dart
+++ b/lib/test_process.dart
@@ -28,15 +28,13 @@
 
   /// A [StreamQueue] that emits each line of stdout from the process.
   ///
-  /// A copy of the underlying stream can be retreived using [stdoutStream].
-  StreamQueue<String> get stdout => _stdout;
-  StreamQueue<String> _stdout;
+  /// A copy of the underlying stream can be retrieved using [stdoutStream].
+  late final StreamQueue<String> stdout = StreamQueue(stdoutStream());
 
   /// A [StreamQueue] that emits each line of stderr from the process.
   ///
-  /// A copy of the underlying stream can be retreived using [stderrStream].
-  StreamQueue<String> get stderr => _stderr;
-  StreamQueue<String> _stderr;
+  /// A copy of the underlying stream can be retrieved using [stderrStream].
+  late final StreamQueue<String> stderr = StreamQueue(stderrStream());
 
   /// A splitter that can emit new copies of [stdout].
   final StreamSplitter<String> _stdoutSplitter;
@@ -48,7 +46,7 @@
   IOSink get stdin => _process.stdin;
 
   /// A buffer of mixed stdout and stderr lines.
-  final _log = <String>[];
+  final List<String> _log = <String>[];
 
   /// Whether [_log] has been passed to [printOnFailure] yet.
   bool _loggedOutput = false;
@@ -62,8 +60,9 @@
 
   /// Completes to [_process]'s exit code if it's exited, otherwise completes to
   /// `null` immediately.
-  Future<int> get _exitCodeOrNull async =>
-      await exitCode.timeout(Duration.zero, onTimeout: () => null);
+  Future<int?> get _exitCodeOrNull async => await exitCode
+      .then<int?>((value) => value)
+      .timeout(Duration.zero, onTimeout: () => null);
 
   /// Starts a process.
   ///
@@ -79,12 +78,12 @@
   /// temporarily to help when debugging test failures.
   static Future<TestProcess> start(
       String executable, Iterable<String> arguments,
-      {String workingDirectory,
-      Map<String, String> environment,
+      {String? workingDirectory,
+      Map<String, String>? environment,
       bool includeParentEnvironment = true,
       bool runInShell = false,
-      String description,
-      Encoding encoding,
+      String? description,
+      Encoding encoding = utf8,
       bool forwardStdio = false}) async {
     var process = await Process.start(executable, arguments.toList(),
         workingDirectory: workingDirectory,
@@ -99,7 +98,6 @@
       description = "$humanExecutable ${arguments.join(" ")}";
     }
 
-    encoding ??= utf8;
     return TestProcess(process, description,
         encoding: encoding, forwardStdio: forwardStdio);
   }
@@ -112,7 +110,7 @@
   /// This is protected, which means it should only be called by subclasses.
   @protected
   TestProcess(Process process, this.description,
-      {Encoding encoding, bool forwardStdio = false})
+      {Encoding encoding = utf8, bool forwardStdio = false})
       : _process = process,
         _stdoutSplitter = StreamSplitter(process.stdout
             .transform(encoding.decoder)
@@ -124,9 +122,6 @@
     expect(_process.exitCode.then((_) => _logOutput()), completes,
         reason: 'Process `$description` never exited.');
 
-    _stdout = StreamQueue(stdoutStream());
-    _stderr = StreamQueue(stderrStream());
-
     // Listen eagerly so that the lines are interleaved properly between the two
     // streams.
     //
diff --git a/pubspec.yaml b/pubspec.yaml
index 19e80f7..b9519fd 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,18 +1,17 @@
 name: test_process
-version: 1.0.6-dev
-
+version: 2.0.3-dev
 description: A package for testing subprocesses.
-homepage: https://github.com/dart-lang/test_process
+repository: https://github.com/dart-lang/test_process
 
 environment:
-  sdk: '>=2.1.0 <3.0.0'
+  sdk: ">=2.12.0-0 <3.0.0"
 
 dependencies:
-  async: ^2.0.0
-  meta: ^1.0.0
-  path: ^1.0.0
-  test: ^1.0.0
+  async: ^2.5.0
+  meta: ^1.3.0
+  path: ^1.8.0
+  test: ^1.16.0
 
 dev_dependencies:
-  pedantic: ^1.0.0
-  test_descriptor: ^1.0.0
+  pedantic: ^1.10.0
+  test_descriptor: ^2.0.0