[app_dart] Add CreateBranch handler (#2332)

diff --git a/app_dart/bin/server.dart b/app_dart/bin/server.dart
index 168a21b..0d10fec 100644
--- a/app_dart/bin/server.dart
+++ b/app_dart/bin/server.dart
@@ -56,6 +56,11 @@
         config: config,
         authenticationProvider: authProvider,
       ),
+      '/api/create-branch': CreateBranch(
+        branchService: branchService,
+        config: config,
+        authenticationProvider: authProvider,
+      ),
       '/api/file_flaky_issue_and_pr': FileFlakyIssueAndPR(
         config: config,
         authenticationProvider: authProvider,
diff --git a/app_dart/lib/cocoon_service.dart b/app_dart/lib/cocoon_service.dart
index e6c5770..9dabcb3 100644
--- a/app_dart/lib/cocoon_service.dart
+++ b/app_dart/lib/cocoon_service.dart
@@ -5,6 +5,7 @@
 export 'src/foundation/utils.dart';
 export 'src/model/appengine/service_account_info.dart';
 export 'src/request_handlers/check_flaky_builders.dart';
+export 'src/request_handlers/create_branch.dart';
 export 'src/request_handlers/file_flaky_issue_and_pr.dart';
 export 'src/request_handlers/flush_cache.dart';
 export 'src/request_handlers/get_authentication_status.dart';
diff --git a/app_dart/lib/src/request_handlers/create_branch.dart b/app_dart/lib/src/request_handlers/create_branch.dart
new file mode 100644
index 0000000..3379216
--- /dev/null
+++ b/app_dart/lib/src/request_handlers/create_branch.dart
@@ -0,0 +1,34 @@
+// Copyright 2020 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'dart:async';
+
+import '../request_handling/api_request_handler.dart';
+import '../request_handling/body.dart';
+import '../service/branch_service.dart';
+
+/// Creates the flutter/recipes branch to match a flutter/flutter branch.
+///
+/// This is intended for oncall use as a fallback when creating recipe branches.
+class CreateBranch extends ApiRequestHandler<Body> {
+  const CreateBranch({
+    required this.branchService,
+    required super.config,
+    required super.authenticationProvider,
+  });
+
+  final BranchService branchService;
+
+  static const String branchParam = 'branch';
+
+  @override
+  Future<Body> get() async {
+    checkRequiredQueryParameters(<String>[branchParam]);
+    final String branch = request!.uri.queryParameters[branchParam]!;
+
+    await branchService.branchFlutterRecipes(branch);
+
+    return Body.empty;
+  }
+}
diff --git a/app_dart/test/request_handlers/create_branch_test.dart b/app_dart/test/request_handlers/create_branch_test.dart
new file mode 100644
index 0000000..742d551
--- /dev/null
+++ b/app_dart/test/request_handlers/create_branch_test.dart
@@ -0,0 +1,36 @@
+// Copyright 2021 The Flutter Authors. 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:cocoon_service/src/request_handlers/create_branch.dart';
+import 'package:cocoon_service/src/request_handling/request_handler.dart';
+import 'package:cocoon_service/src/service/branch_service.dart';
+import 'package:mockito/mockito.dart';
+import 'package:test/test.dart';
+
+import '../src/datastore/fake_config.dart';
+import '../src/request_handling/fake_authentication.dart';
+import '../src/request_handling/fake_http.dart';
+import '../src/request_handling/request_handler_tester.dart';
+import '../src/utilities/mocks.dart';
+
+void main() {
+  group(CreateBranch, () {
+    test('runs', () async {
+      final RequestHandlerTester tester = RequestHandlerTester();
+      tester.request = FakeHttpRequest(
+        queryParametersValue: <String, String>{
+          CreateBranch.branchParam: 'flutter-3.7-candidate.1',
+        },
+      );
+      final BranchService branchService = MockBranchService();
+      final RequestHandler handler = CreateBranch(
+        branchService: branchService,
+        config: FakeConfig(),
+        authenticationProvider: FakeAuthenticationProvider(),
+      );
+      await tester.get(handler);
+      verify(branchService.branchFlutterRecipes('flutter-3.7-candidate.1'));
+    });
+  });
+}