Adds skia gold to engine release branches. (#3659)

issue: https://github.com/flutter/flutter/issues/146078

This starts running skia gold bot checks on release branches for the engine.  This works for the engine because our infrastructure forks all gold tests when a release branch is created.

See also:
 - https://github.com/flutter/engine/tree/main/testing/skia_gold_client#release-testing
diff --git a/app_dart/lib/src/request_handlers/push_gold_status_to_github.dart b/app_dart/lib/src/request_handlers/push_gold_status_to_github.dart
index 61edfc3..02270f0 100644
--- a/app_dart/lib/src/request_handlers/push_gold_status_to_github.dart
+++ b/app_dart/lib/src/request_handlers/push_gold_status_to_github.dart
@@ -78,9 +78,8 @@
         continue;
       }
 
-      final String defaultBranch = Config.defaultBranch(slug);
-      if (pr.base!.ref != defaultBranch) {
-        log.fine('This change is not staged to land on $defaultBranch, skipping.');
+      if (!Config.doesSkiaGoldRunOnBranch(slug, pr.base!.ref)) {
+        log.fine('This change\'s destination, ${pr.base!.ref}, does not run Skia Gold checks, skipping.');
         // This is potentially a release branch, or another change not landing
         // on master, we don't need a Gold check.
         continue;
diff --git a/app_dart/lib/src/service/config.dart b/app_dart/lib/src/service/config.dart
index fd0f7c2..fca2d34 100644
--- a/app_dart/lib/src/service/config.dart
+++ b/app_dart/lib/src/service/config.dart
@@ -67,6 +67,15 @@
     flutterSlug,
   };
 
+  static bool doesSkiaGoldRunOnBranch(gh.RepositorySlug slug, String? branch) {
+    if (slug == engineSlug) {
+      final RegExp releaseRegex = RegExp(r'flutter-\d?\.\d?-candidate\.\d?');
+      return defaultBranch(slug) == branch || (branch != null && releaseRegex.hasMatch(branch));
+    } else {
+      return defaultBranch(slug) == branch;
+    }
+  }
+
   /// The tip of tree branch for [slug].
   static String defaultBranch(gh.RepositorySlug slug) {
     final Map<gh.RepositorySlug, String> defaultBranches = <gh.RepositorySlug, String>{
diff --git a/app_dart/pubspec.yaml b/app_dart/pubspec.yaml
index 715954d..37b7286 100644
--- a/app_dart/pubspec.yaml
+++ b/app_dart/pubspec.yaml
@@ -23,7 +23,7 @@
   github: 9.24.0
   googleapis: 12.0.0
   googleapis_auth: 1.6.0
-  gql: 1.0.1-alpha+1696717343881
+  gql: 1.0.1-alpha+1709845491443
   graphql: 5.2.0-beta.7
   grpc: 3.2.4
   http: 1.2.1
diff --git a/app_dart/test/request_handlers/push_gold_status_to_github_test.dart b/app_dart/test/request_handlers/push_gold_status_to_github_test.dart
index d712a18..9f9e74a 100644
--- a/app_dart/test/request_handlers/push_gold_status_to_github_test.dart
+++ b/app_dart/test/request_handlers/push_gold_status_to_github_test.dart
@@ -546,6 +546,70 @@
           );
         });
 
+        test('runs on engine release branches', () async {
+          // New commit
+          final PullRequest pr = newPullRequest(123, 'abc', 'flutter-3.8-candidate.8');
+          enginePrsFromGitHub = <PullRequest>[pr];
+          final GithubGoldStatusUpdate status = newStatusUpdate(engineSlug, pr, '', '', '');
+          db.values[status.key] = status;
+          githubGoldStatusEngine = newGithubGoldStatus(engineSlug, pr, '', '', '');
+
+          // All checks completed
+          engineCheckRuns = <dynamic>[
+            <String, String>{'name': 'Linux linux_web_engine', 'status': 'completed', 'conclusion': 'success'},
+          ];
+
+          // Change detected by Gold
+          mockHttpClient = MockClient((http.Request request) async {
+            if (request.url.toString() ==
+                'https://flutter-engine-gold.skia.org/json/v1/changelist_summary/github/${pr.number}') {
+              return http.Response(tryjobDigests(pr), HttpStatus.ok);
+            }
+            throw const HttpException('Unexpected http request');
+          });
+          handler = PushGoldStatusToGithub(
+            config: config,
+            authenticationProvider: auth,
+            datastoreProvider: (DatastoreDB db) {
+              return DatastoreService(
+                config.db,
+                5,
+                retryOptions: retryOptions,
+              );
+            },
+            goldClient: mockHttpClient,
+            ingestionDelay: Duration.zero,
+          );
+
+          // Have not already commented for this commit.
+          when(issuesService.listCommentsByIssue(engineSlug, pr.number!)).thenAnswer(
+            (_) => Stream<IssueComment>.value(
+              IssueComment()..body = 'some other comment',
+            ),
+          );
+
+          final Body body = await tester.get<Body>(handler);
+          expect(body, same(Body.empty));
+
+          verify(
+            issuesService.addLabelsToIssue(
+              engineSlug,
+              pr.number!,
+              <String>[
+                kGoldenFileLabel,
+              ],
+            ),
+          ).called(1);
+
+          verify(
+            issuesService.createComment(
+              engineSlug,
+              pr.number!,
+              argThat(contains(config.flutterGoldCommentID(pr))),
+            ),
+          ).called(1);
+        });
+
         test('does nothing for branches not staged to land on main/master', () async {
           // New commit
           final PullRequest pr = newPullRequest(123, 'abc', 'release');