// 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 'dart:convert';
import 'dart:io';
import 'dart:math';

import 'package:cocoon_common/task_status.dart';
import 'package:cocoon_server/logging.dart';
import 'package:collection/collection.dart';
import 'package:github/github.dart';
import 'package:github/hooks.dart';
import 'package:googleapis/bigquery/v2.dart';
import 'package:googleapis/firestore/v1.dart' as g;
import 'package:meta/meta.dart';
import 'package:retry/retry.dart';

import '../foundation/utils.dart';
import '../model/ci_yaml/ci_yaml.dart';
import '../model/ci_yaml/target.dart';
import '../model/commit_ref.dart';
import '../model/firestore/ci_staging.dart';
import '../model/firestore/commit.dart' as fs;
import '../model/firestore/pr_check_runs.dart';
import '../model/firestore/task.dart' as fs;
import '../model/github/checks.dart' as cocoon_checks;
import '../model/github/checks.dart' show MergeGroup;
import '../model/github/workflow_job.dart';
import '../model/proto/internal/scheduler.pb.dart' as pb;
import 'big_query.dart';
import 'cache_service.dart';
import 'config.dart';
import 'content_aware_hash_service.dart';
import 'exceptions.dart';
import 'firestore.dart';
import 'get_files_changed.dart';
import 'github_checks_service.dart';
import 'luci_build_service.dart';
import 'luci_build_service/engine_artifacts.dart';
import 'luci_build_service/pending_task.dart';
import 'scheduler/ci_yaml_fetcher.dart';
import 'scheduler/files_changed_optimization.dart';
import 'scheduler/process_check_run_result.dart';

/// Scheduler service to validate all commits to supported Flutter repositories.
///
/// Scheduler responsibilties include:
///   1. Tracking commits in Cocoon
///   2. Ensuring commits are validated (via scheduling tasks against commits)
///   3. Retry mechanisms for tasks
class Scheduler {
  Scheduler({
    required CacheService cache,
    required Config config,
    required GithubChecksService githubChecksService,
    required LuciBuildService luciBuildService,
    required GetFilesChanged getFilesChanged,
    required CiYamlFetcher ciYamlFetcher,
    required ContentAwareHashService contentAwareHash,
    required FirestoreService firestore,
    required BigQueryService bigQuery,
  }) : _luciBuildService = luciBuildService,
       _githubChecksService = githubChecksService,
       _config = config,
       _getFilesChanged = getFilesChanged,
       _ciYamlFetcher = ciYamlFetcher,
       _contentAwareHash = contentAwareHash,
       _firestore = firestore,
       _bigQuery = bigQuery,
       _filesChangedOptimizer = FilesChangedOptimizer(
         getFilesChanged: getFilesChanged,
         ciYamlFetcher: ciYamlFetcher,
         config: config,
       );

  final GetFilesChanged _getFilesChanged;
  final Config _config;
  final GithubChecksService _githubChecksService;
  final CiYamlFetcher _ciYamlFetcher;
  final ContentAwareHashService _contentAwareHash;
  final LuciBuildService _luciBuildService;
  final FilesChangedOptimizer _filesChangedOptimizer;
  final FirestoreService _firestore;
  final BigQueryService _bigQuery;

  /// Name of the subcache to store scheduler related values in redis.
  static const String subcacheName = 'scheduler';

  /// List of check runs that do not need to be tracked or looked up in
  /// any staging logic.
  static const kCheckRunsToIgnore = [
    Config.kMergeQueueLockName,
    Config.kCiYamlCheckName,
  ];

  /// Briefly describes what the "Merge Queue Guard" check is for.
  ///
  /// Find more details about this check at [kMergeQueueLockName].
  ///
  /// This description appears next to the Github check run in the pull request
  /// and merge queue UI.
  static const String kMergeQueueLockDescription =
      'The merge queue guard is a GitHub check that prevents a PR from being '
      'merged or enqueued before it is ready. It becomes green automatically '
      'when all tests pass. No manual action is required. If you suspect that '
      'this check is not working correctly, contact #hackers-infra on Discord. '
      'If you need to merge your PR without tests (a rare situation, typically '
      'an emergency), then you can use the `emergency` label.';

  /// Ensure [commits] exist in Cocoon.
  ///
  /// If the commit already exists, it is ignored.
  ///
  /// Otherwise it is stored in Firestore, and scheduled, if appropriate.
  Future<void> addCommits(List<fs.Commit> commits) async {
    final newCommits = await _getMissingCommits(commits);
    log.debug('Found ${newCommits.length} new commits on GitHub');
    for (final commit in newCommits) {
      await _addCommit(commit);
    }
  }

  /// Schedule tasks against [PullRequest].
  ///
  /// If [PullRequest] was merged, schedule prod tasks against it.
  /// Otherwise if it is presubmit, schedule try tasks against it.
  Future<void> addPullRequest(PullRequest pr) async {
    // TODO(chillers): Support triggering on presubmit. https://github.com/flutter/flutter/issues/77858
    if (!pr.merged!) {
      log.warn(
        'Only pull requests that were closed and merged should have tasks scheduled',
      );
      return;
    }

    final sha = pr.mergeCommitSha!;
    if (await _commitExistsInFirestore(sha: sha)) {
      log.debug('$sha already exists in Firestore. Scheduling skipped.');
      return;
    }

    log.debug('Scheduling $sha via GitHub webhook');
    final mergedCommit = fs.Commit.fromGithubPullRequest(pr);
    await _addCommit(mergedCommit);
  }

  /// Processes postsubmit tasks.
  Future<void> _addCommit(fs.Commit commit) async {
    if (!_config.supportedRepos.contains(commit.slug)) {
      log.debug('Skipping ${commit.sha} as repo is not supported');
      return;
    }
    final contentHash = await _contentAwareHash.getHashByCommitSha(commit.sha);

    final _TaskCommitScheduling scheduling;
    if (Config.defaultBranch(commit.slug) == commit.branch) {
      scheduling = _TaskCommitScheduling.defaultUseTargetSchedulingPolicy;
    } else {
      scheduling = _TaskCommitScheduling.nonDefaultBranchSkipTestsByDefault;
    }

    final ciYaml = await _ciYamlFetcher.getCiYamlByCommit(
      commit.toRef(),
      postsubmit: true,
    );
    final targets = ciYaml.postsubmitTargets();
    final isFusion = commit.slug == Config.flutterSlug;
    if (isFusion) {
      final fusionPostTargets = ciYaml.postsubmitTargets(
        type: CiType.fusionEngine,
      );
      targets.addAll(fusionPostTargets);
      // Note on post submit targets: CiYaml filters out release_true for release branches and fusion trees
    }

    final tasks = [
      ...targets.map((t) => fs.Task.initialFromTarget(t, commit: commit)),
    ];
    final toBeScheduled = <PendingTask>[];
    for (var target in targets) {
      final task = tasks.singleWhere((task) => task.taskName == target.name);
      // For flutter/flutter builds (non-master branch), we mark all builds that
      // do not build the engine as "skipped" for later manual scheduling. Most
      // branches won't have any release builds at this stage, but experimental
      // branches *will*, which is why "!target.isReleaseBuild" is used.
      //
      // See https://github.com/flutter/flutter/issues/169088.
      if (scheduling.skipPostsubmitTasks && !target.isReleaseBuild) {
        task.setStatus(TaskStatus.skipped);
        continue;
      }
      final priority = await target.schedulerPolicy.triggerPriority(
        taskName: task.taskName,
        commitSha: commit.sha,
        recentTasks: await _firestore.queryRecentTasks(name: task.taskName),
      );
      if (priority != null) {
        // Mark task as in progress to ensure it isn't scheduled over
        task.setStatus(TaskStatus.inProgress);
        toBeScheduled.add(
          PendingTask(
            target: target,
            taskName: task.taskName,
            priority: priority,
            currentAttempt: 1,
          ),
        );
      }
    }

    log.info(
      'Initial targets created for $commit: '
      '${targets.map((t) => '"${t.name}"').join(', ')}',
    );
    await _addCommitFirestore(commit, tasks);

    log.info(
      'Immediately scheduled tasks for $commit: '
      '${toBeScheduled.map((t) => '"${t.taskName}"').join(', ')}',
    );
    await _batchScheduleBuilds(
      commit.toRef(),
      toBeScheduled,
      contentHash: contentHash,
    );
    await _uploadToBigQuery(commit);
  }

  Future<void> _addCommitFirestore(
    fs.Commit commit,
    List<fs.Task> tasks,
  ) async {
    await _firestore.writeViaTransaction(
      documentsToWrites([...tasks, commit], exists: false),
    );
  }

  /// Schedule all builds in batch requests instead of a single request.
  ///
  /// Each batch request contains [Config.batchSize] builds to be scheduled.
  Future<void> _batchScheduleBuilds(
    CommitRef commit,
    List<PendingTask> toBeScheduled, {
    String? contentHash,
  }) async {
    final batchLog = StringBuffer(
      'Scheduling ${toBeScheduled.length} tasks in batches for ${commit.sha} as follows:\n',
    );
    final futures = <Future<void>>[];
    for (var i = 0; i < toBeScheduled.length; i += _config.batchSize) {
      final batch = toBeScheduled.sublist(
        i,
        min(i + _config.batchSize, toBeScheduled.length),
      );
      batchLog.writeln('  - ${batch.map((t) => '"${t.taskName}"').join(', ')}');
      futures.add(
        _luciBuildService.schedulePostsubmitBuilds(
          commit: commit,
          toBeScheduled: batch,
          contentHash: contentHash,
        ),
      );
    }
    log.info('$batchLog');
    await Future.wait<void>(futures);
  }

  /// Return subset of [commits] not stored in Firestore.
  Future<List<fs.Commit>> _getMissingCommits(List<fs.Commit> commits) async {
    final newCommits = <fs.Commit>[];
    // Ensure commits are sorted from newest to oldest (descending order)
    commits.sort((a, b) => b.createTimestamp.compareTo(a.createTimestamp));
    for (final commit in commits) {
      // Cocoon may randomly drop commits, so check the entire list.
      if (!await _commitExistsInFirestore(sha: commit.sha)) {
        newCommits.add(commit);
      }
    }

    // Reverses commits to be in order of oldest to newest.
    return newCommits;
  }

  /// Whether [Commit] already exists in Firestore.
  ///
  /// Firestore is Cocoon's source of truth for what commits have been
  /// scheduled. Since webhooks or cron jobs can schedule commits, we must
  /// verify a commit has not already been scheduled.
  Future<bool> _commitExistsInFirestore({required String sha}) async {
    final commit = await fs.Commit.tryFromFirestoreBySha(_firestore, sha: sha);
    return commit != null;
  }

  /// Cancel all incomplete targets against a pull request.
  Future<void> cancelPreSubmitTargets({
    required PullRequest pullRequest,
    String reason = 'Newer commit available',
  }) async {
    log.info('Cancelling presubmit targets with buildbucket v2.');
    await _luciBuildService.cancelBuilds(
      pullRequest: pullRequest,
      reason: reason,
    );
  }

  /// Schedule presubmit targets against a pull request.
  ///
  /// Cancels all existing targets then schedules the targets.
  ///
  /// Schedules a [kCiYamlCheckName] to validate [CiYamlSet] is valid and all builds were able to be triggered.
  /// If [builderTriggerList] is specified, then trigger only those targets.
  Future<void> triggerPresubmitTargets({
    required PullRequest pullRequest,
    String reason = 'Newer commit available',
    List<String>? builderTriggerList,
  }) async {
    // Always cancel running builds so we don't ever schedule duplicates.
    log.info(
      'Attempting to cancel existing presubmit targets for ${pullRequest.number}',
    );
    await cancelPreSubmitTargets(pullRequest: pullRequest, reason: reason);

    final slug = pullRequest.base!.repo!.slug();

    // The MQ only waits for "required status checks" before deciding whether to
    // merge the PR into the target branch. This required check added to both
    // the PR and to the merge group, and so it must be completed in both cases.
    final lock = await lockMergeGroupChecks(slug, pullRequest.head!.sha!);

    // Track if we should unlock the merge group lock in case of non-fusion or
    // revert bots.
    var unlockMergeGroup = false;

    final ciValidationCheckRun = await _createCiYamlCheckRun(pullRequest, slug);

    log.info('Creating presubmit targets for ${pullRequest.number}');
    Object? exception;
    final isFusion = slug == Config.flutterSlug;
    do {
      try {
        final sha = pullRequest.head!.sha!;
        if (!isFusion) {
          unlockMergeGroup = true;
        }

        // Both the author and label should be checked to make sure that no one is
        // attempting to get a pull request without check through.
        if (pullRequest.user!.login == _config.autosubmitBot &&
            pullRequest.labels!.any(
              (element) => element.name == Config.revertOfLabel,
            )) {
          log.info(
            'Skipping generating the full set of checks for revert request.',
          );
          unlockMergeGroup = true;
          break;
        }
        // Feature request: skip engine builds and tests in monorepo if the PR only contains framework related
        // files.
        // NOTE: This creates an empty staging doc for the engine builds as staging is handled on check_run completion
        //       events from GitHub. Engine Tests are also skipped, and the base.sha is passed to LUCI to use prod
        //       binaries.
        if (await _filesChangedOptimizer.checkPullRequest(pullRequest)
            case final opt when opt.shouldUsePrebuiltEngine) {
          final logCrumb =
              'triggerPresubmitTargets($slug, $sha){frameworkOnly}';
          log.info('$logCrumb: FRAMEWORK_ONLY_TESTING_PR');

          await CiStaging.initializeDocument(
            firestoreService: _firestore,
            slug: slug,
            sha: sha,
            stage: CiStage.fusionEngineBuild,
            tasks: [],
            checkRunGuard: '',
          );

          await _runCiTestingStage(
            pullRequest: pullRequest,
            checkRunGuard: '$lock',
            logCrumb: logCrumb,

            // The if-branch already skips the engine build phase.
            testsToRun: switch (opt) {
              FilesChangedOptimization.skipPresubmitAllExceptFlutterAnalyze =>
                _FlutterRepoTestsToRun.frameworkFlutterAnalyzeOnly,
              FilesChangedOptimization.skipPresubmitEngine =>
                _FlutterRepoTestsToRun.frameworkTestsOnly,
              FilesChangedOptimization.none => throw StateError('Unreachable'),
            },
          );
          break;
        }
        final presubmitTargets = isFusion
            ? await _getTestsForStage(pullRequest, CiStage.fusionEngineBuild)
            : await getPresubmitTargets(pullRequest);
        final presubmitTriggerTargets = filterTargets(
          presubmitTargets,
          builderTriggerList,
        );

        // When running presubmits for a fusion PR; create a new staging document to track tasks needed
        // to complete before we can schedule more tests (i.e. build engine artifacts before testing against them).
        final EngineArtifacts engineArtifacts;
        if (isFusion) {
          await CiStaging.initializeDocument(
            firestoreService: _firestore,
            slug: slug,
            sha: sha,
            stage: CiStage.fusionEngineBuild,
            tasks: [...presubmitTriggerTargets.map((t) => t.name)],
            checkRunGuard: '$lock',
          );

          // Even though this appears to be an engine build, it could be a
          // release candidate build, where the engine artifacts are built
          // via the dart-internal builder.
          //
          // In either case, providing FLUTTER_PREBUILT_ENGINE_VERSION has no
          // consequences for engine builds, as it just won't be used (it is
          // only understood by the Flutter CLI).
          //
          // See https://github.com/flutter/flutter/issues/165810.
          engineArtifacts = EngineArtifacts.usingExistingEngine(commitSha: sha);
        } else {
          engineArtifacts = const EngineArtifacts.noFrameworkTests(
            reason: 'This is not the flutter/flutter repository',
          );
        }
        await _luciBuildService.scheduleTryBuilds(
          targets: presubmitTriggerTargets,
          pullRequest: pullRequest,
          engineArtifacts: engineArtifacts,
        );
      } on FormatException catch (e, s) {
        log.warn(
          'FormatException encountered when scheduling presubmit targets for '
          '${pullRequest.number}',
          e,
          s,
        );
        exception = e;
      } catch (e, s) {
        if (e is g.DetailedApiRequestError && e.status == HttpStatus.conflict) {
          rethrow;
        }
        log.warn(
          'Exception encountered when scheduling presubmit targets for '
          '${pullRequest.number}',
          e,
          s,
        );
        exception = e;
      }
    } while (false);

    // Update validate ci.yaml check
    await closeCiYamlCheckRun(
      'PR ${pullRequest.number}',
      exception,
      slug,
      ciValidationCheckRun,
    );

    // Normally the lock stays pending until the PR is ready to be enqueued, but
    // there are situations (see code above) when it needs to be unlocked
    // immediately.
    if (unlockMergeGroup) {
      await unlockMergeQueueGuard(slug, pullRequest.head!.sha!, lock);
    }
    log.info(
      'Finished triggering builds for: pr ${pullRequest.number}, commit ${pullRequest.base!.sha}, branch ${pullRequest.head!.ref} and slug $slug}',
    );
  }

  Future<void> closeCiYamlCheckRun(
    String description,
    Object? exception,
    RepositorySlug slug,
    CheckRun ciValidationCheckRun,
  ) async {
    log.info('Updating ci.yaml validation check for $description');
    if (exception == null) {
      // Success in validating ci.yaml
      log.info('ci.yaml validation check was successful for $description');
      await _githubChecksService.githubChecksUtil.updateCheckRun(
        _config,
        slug,
        ciValidationCheckRun,
        status: CheckRunStatus.completed,
        conclusion: CheckRunConclusion.success,
      );
    } else {
      log.warn('Marking $description ${Config.kCiYamlCheckName} as failed', e);
      // Failure when validating ci.yaml
      await _githubChecksService.githubChecksUtil.updateCheckRun(
        _config,
        slug,
        ciValidationCheckRun,
        status: CheckRunStatus.completed,
        conclusion: CheckRunConclusion.failure,
        output: CheckRunOutput(
          title: Config.kCiYamlCheckName,
          summary: '.ci.yaml has failures',
          text: exception.toString(),
        ),
      );
    }
  }

  Future<CheckRun> _createCiYamlCheckRun(
    PullRequest pullRequest,
    RepositorySlug slug,
  ) async {
    log.info('Creating ciYaml validation check run for ${pullRequest.number}');
    final ciValidationCheckRun = await _githubChecksService.githubChecksUtil
        .createCheckRun(
          _config,
          slug,
          pullRequest.head!.sha!,
          Config.kCiYamlCheckName,
          output: const CheckRunOutput(
            title: Config.kCiYamlCheckName,
            summary:
                'If this check is stuck pending, push an empty commit to retrigger the checks',
          ),
        );
    return ciValidationCheckRun;
  }

  static Duration debugCheckPretendDelay = const Duration(minutes: 1);

  Future<void> handleMergeGroupEvent({
    required cocoon_checks.MergeGroupEvent mergeGroupEvent,
  }) async {
    final MergeGroup(:headSha, :headRef, :baseRef) = mergeGroupEvent.mergeGroup;
    final slug = mergeGroupEvent.repository!.slug();
    final isFusion = slug == Config.flutterSlug;

    final logCrumb =
        'triggerTargetsForMergeGroup($slug, $headSha, ${isFusion ? 'real' : 'simulated'})';

    if (isFusion) {
      // Temporarily trigger content-aware-hash for merge groups.
      // We will not actually wait for the results yet.
      try {
        await _contentAwareHash.triggerWorkflow(headRef);
      } catch (e, s) {
        log.warn('contentAwareHash unexpectedly threw', e, s);
      }
      if (_config.flags.contentAwareHashing.waitOnContentHash) {
        log.info(
          '$logCrumb: content hashing requested; waiting on job to complete',
        );
        return;
      }
    }
    log.info('$logCrumb: scheduling merge group checks');
    return triggerTargetsForMergeGroup(
      baseRef: baseRef,
      headSha: headSha,
      headRef: headRef,
      slug: slug,
    );
  }

  Future<void> triggerTargetsForMergeGroup({
    required String headSha,
    required String headRef,
    required String baseRef,
    required RepositorySlug slug,
    String? contentHash,
  }) async {
    // Behave similar to addPullRequest, except we're not yet merged into master.
    //   - We are mirrored in to GoB
    //   - We want PROD builds
    //   - We want check_runs as well
    //   - We want updates on check_runs to the presubmit pubsub.
    // We do not want "Task" objects because these are for flutter-dashboard tracking (post submit)
    // final mergeGroup = mergeGroupEvent.mergeGroup;
    final isFusion = slug == Config.flutterSlug;

    final logCrumb =
        'triggerTargetsForMergeGroup($slug, $headSha, ${isFusion ? 'real' : 'simulated'}'
        '${contentHash != null ? ', contentHash: $contentHash' : ''})';
    log.info('$logCrumb: scheduling merge group checks');

    final lock = await lockMergeGroupChecks(slug, headSha);

    // If the repo is not fusion, it doesn't run anything in the MQ, so just
    // close the merge group guard.
    if (!isFusion) {
      await unlockMergeQueueGuard(slug, headSha, lock);
      return;
    }

    final mergeGroupTargets = {
      ...await getMergeGroupTargetsForStage(
        baseRef,
        slug,
        headSha,
        CiStage.fusionEngineBuild,
      ),
    };

    try {
      // Filter out targets missing builders - we cannot wait to complete the merge group if we will never complete.
      final availableBuilders = await _luciBuildService.getAvailableBuilderSet(
        project: 'flutter',
        bucket: 'prod',
      );
      final availableTargets = {
        ...mergeGroupTargets.where(
          (target) => availableBuilders.contains(target.name),
        ),
      };
      if (availableTargets.length != mergeGroupTargets.length) {
        log.warn(
          '$logCrumb: missing builders for targets: '
          '${mergeGroupTargets.difference(availableTargets)}',
        );
      }

      // Create the staging doc that will track our engine progress and allow us to unlock
      // the merge group lock later.
      await CiStaging.initializeDocument(
        firestoreService: _firestore,
        slug: slug,
        sha: headSha,
        stage: CiStage.fusionEngineBuild,
        tasks: [...availableTargets.map((t) => t.name)],
        checkRunGuard: '$lock',
      );

      // Create the minimal Commit needed to pass the next stage.
      // Note: headRef encodes refs/heads/... and what we want is the branch
      await _luciBuildService.scheduleMergeGroupBuilds(
        targets: [...availableTargets],
        commit: CommitRef(
          branch: headRef.substring('refs/heads/'.length),
          slug: slug,
          sha: headSha,
        ),
        contentHash: contentHash,
      );

      // Do not unlock the merge group guard in successful case - that will be done by staging checks.
      log.info('$logCrumb: successfully scheduled merge group checks');
    } catch (e, s) {
      log.warn(
        '$logCrumb: error encountered when scheduling merge group checks',
        e,
        s,
      );
      // If Cocoon/LUCI failed to schedule targets, the PR should be kicked out
      // of the queue. To do that, the merge queue guard must fail as it's the
      // only required GitHub check.
      await failGuardForMergeGroup(
        slug,
        headSha,
        'Failed to schedule checks for merge group',
        '''
$logCrumb

ERROR: $e
$s
''',
        lock,
      );
    }
  }

  // Work in progress - Content Aware hash retrieval.
  Future<void> processWorkflowJob(WorkflowJobEvent event) async {
    try {
      final artifactStatus = await _contentAwareHash.processWorkflowJob(event);
      log.info(
        'scheduler.processWorkflowJob(): artifacts status: $artifactStatus '
        'for ${event.workflowJob?.checkRunUrl}',
      );

      // TODO: MergeQueueHashStatus
      //   - .build: trigger targets!
      //   - .wait: something is building.
      //   - .completed: hash already built, complete!
      //   - .*: do nothing
      // FOR NOW: trigger builds for build/wait/completed because they are also
      //          building for SHA.
      switch (artifactStatus.status) {
        case MergeQueueHashStatus.build ||
                MergeQueueHashStatus.wait ||
                MergeQueueHashStatus.complete
            when _config.flags.contentAwareHashing.waitOnContentHash &&
                artifactStatus.contentHash.isNotEmpty:
          // Note from codefu: We do not have the merge queue lock yet.
          // It was short-circuited if the waitOnContentHash is set. The
          // CAH document _has_ been created. In the future, "wait" will need
          // to create the lock - and auto complete it - to let the merge
          // group complete.
          final job = event.workflowJob!;
          log.info(
            'triggering merge group targets for $artifactStatus / ${job.headSha}',
          );
          await triggerTargetsForMergeGroup(
            headSha: job.headSha!,
            headRef: 'refs/heads/${job.headBranch!}',
            baseRef:
                'refs/heads/${tryParseGitHubMergeQueueBranch(job.headBranch!).branch}',
            slug: event.repository!.slug(),
            contentHash: artifactStatus.status == MergeQueueHashStatus.build
                ? artifactStatus.contentHash
                : null,
          );

        default:
          break;
      }
    } catch (e, s) {
      log.debug(
        'scheduler.processWorkflowJob(${event.workflowJob?.checkRunUrl}) failed (no-op)',
        e,
        s,
      );
    }
  }

  Future<List<Target>> getMergeGroupTargetsForStage(
    String baseRef,
    RepositorySlug slug,
    String headSha,
    CiStage stage,
  ) async {
    final mergeGroupTargets =
        [
          ...await getMergeGroupTargets(baseRef, slug, headSha),
          ...await getMergeGroupTargets(
            baseRef,
            slug,
            headSha,
            type: CiType.fusionEngine,
          ),
        ].where(
          (Target target) => switch (stage) {
            CiStage.fusionEngineBuild => target.isReleaseBuild,
            CiStage.fusionTests => !target.isReleaseBuild,
          },
        );

    return [...mergeGroupTargets];
  }

  Future<List<Target>> getMergeGroupTargets(
    String baseRef,
    RepositorySlug slug,
    String headSha, {
    CiType type = CiType.any,
  }) async {
    log.info(
      'Attempting to read merge group targets from ci.yaml for $headSha',
    );

    final branch = baseRef.substring('refs/heads/'.length);
    final ciYaml = await _ciYamlFetcher.getCiYamlByCommit(
      CommitRef(sha: headSha, branch: branch, slug: slug),
    );
    log.info(
      'ci.yaml loaded successfully; collecting merge group targets for $headSha',
    );

    final inner = ciYaml.ciYamlFor(type);

    // Filter out targets with schedulers different than luci or cocoon.
    bool filter(Target target) =>
        target.scheduler == pb.SchedulerSystem.luci ||
        target.scheduler == pb.SchedulerSystem.cocoon;
    return [...inner.presubmitTargets.where(filter)];
  }

  /// Cancels builds for a destroyed merge group.
  Future<void> cancelDestroyedMergeGroupTargets({
    required String headSha,
  }) async {
    log.info('Cancelling merge group targets for $headSha');
    await _luciBuildService.cancelBuildsBySha(
      sha: headSha,
      reason: 'Merge group was destroyed',
    );
    // Mark content hash as invalid (if it exists)
    await _completeArtifacts(headSha, false);
  }

  /// Pushes the required "Merge Queue Guard" check to the merge queue, which
  /// serves as a "lock".
  ///
  /// While this check is still in progress, the merge queue will not merge the
  /// respective PR onto the target branch (e.g. main or master), because this
  /// check is "required".
  Future<CheckRun> lockMergeGroupChecks(
    RepositorySlug slug,
    String headSha,
  ) async {
    return _githubChecksService.githubChecksUtil.createCheckRun(
      _config,
      slug,
      headSha,
      Config.kMergeQueueLockName,
      output: const CheckRunOutput(
        title: Config.kMergeQueueLockName,
        summary: kMergeQueueLockDescription,
      ),
    );
  }

  /// Completes the "Merge Queue Guard" check run.
  ///
  /// If the guard is guarding a merge group, this immediately makes the merge
  /// group eligible for landing onto the target branch (e.g. master), depending
  /// on the success of the merge groups queued in front of this one.
  ///
  /// If the guard is guarding a pull request, this immediately makes the pull
  /// request eligible for enqueuing into the merge queue.
  Future<void> unlockMergeQueueGuard(
    RepositorySlug slug,
    String headSha,
    CheckRun lock,
  ) async {
    log.info('Unlocking Merge Queue Guard for $slug/$headSha');
    await _githubChecksService.githubChecksUtil.updateCheckRun(
      _config,
      slug,
      lock,
      status: CheckRunStatus.completed,
      conclusion: CheckRunConclusion.success,
    );
  }

  /// Fails the "Merge Queue Guard" check for a merge group.
  ///
  /// This removes the merge group from the merge queue without landing it. The
  /// corresponding pull request will have to be fixed and re-enqueued again.
  Future<void> failGuardForMergeGroup(
    RepositorySlug slug,
    String headSha,
    String summary,
    String details,
    CheckRun lock,
  ) async {
    log.info('Failing merge group guard for merge group $headSha in $slug');
    await _githubChecksService.githubChecksUtil.updateCheckRun(
      _config,
      slug,
      lock,
      status: CheckRunStatus.completed,
      conclusion: CheckRunConclusion.failure,
      output: CheckRunOutput(
        title: Config.kCiYamlCheckName,
        summary: summary,
        text: details,
      ),
    );
  }

  /// If [builderTriggerList] is specificed, return only builders that are contained in [presubmitTarget].
  /// Otherwise, return [presubmitTarget].
  List<Target> filterTargets(
    List<Target> presubmitTarget,
    List<String>? builderTriggerList,
  ) {
    if (builderTriggerList != null && builderTriggerList.isNotEmpty) {
      return presubmitTarget
          .where((Target target) => builderTriggerList.contains(target.name))
          .toList();
    }
    return presubmitTarget;
  }

  /// Get LUCI presubmit builders from .ci.yaml.
  ///
  /// Filters targets with runIf, matching them to the diff of [pullRequest].
  ///
  /// In the case there is an issue getting the diff from GitHub, all targets are returned.
  @visibleForTesting
  Future<List<Target>> getPresubmitTargets(
    PullRequest pullRequest, {
    CiType type = CiType.any,
  }) async {
    log.info(
      'Attempting to read presubmit targets from ci.yaml for ${pullRequest.number}',
    );

    final branch = pullRequest.base!.ref!;
    final slug = pullRequest.base!.repo!.slug();
    final ciYaml = await _ciYamlFetcher.getCiYamlByCommit(
      CommitRef(slug: slug, branch: branch, sha: pullRequest.head!.sha!),
    );

    log.info('ci.yaml loaded successfully.');
    log.info('Collecting presubmit targets for ${pullRequest.number}');

    final inner = ciYaml.ciYamlFor(type);

    // Filter out schedulers targets with schedulers different than luci or cocoon.
    final presubmitTargets = inner.presubmitTargets
        .where(
          (Target target) =>
              target.scheduler == pb.SchedulerSystem.luci ||
              target.scheduler == pb.SchedulerSystem.cocoon,
        )
        .toList();

    log.info('Collected ${presubmitTargets.length} presubmit targets.');
    // Release branches should run every test.
    if (pullRequest.base!.ref !=
        Config.defaultBranch(pullRequest.base!.repo!.slug())) {
      log.info(
        'Release branch found, scheduling all targets for ${pullRequest.number}',
      );
      return presubmitTargets;
    }

    // Filter builders based on the PR diff
    final filesChanged = await _getFilesChanged.get(
      pullRequest.base!.repo!.slug(),
      pullRequest.number!,
    );
    return getTargetsToRun(presubmitTargets, filesChanged);
  }

  /// Process a completed GitHub `check_run`.
  ///
  /// Handles both fusion engine build and test stages, and both pull requests
  /// and merge groups.
  Future<bool> processCheckRunCompleted(
    cocoon_checks.CheckRun checkRun,
    RepositorySlug? slug,
  ) async {
    final name = checkRun.name;
    final sha = checkRun.headSha;
    final conclusion = TaskConclusion.fromName(checkRun.conclusion);

    if (name == null ||
        sha == null ||
        slug == null ||
        conclusion == TaskConclusion.unknown ||
        kCheckRunsToIgnore.contains(name)) {
      return true;
    }

    final logCrumb = 'checkCompleted($name, $slug, $sha, $conclusion)';

    final isFusion = slug == Config.flutterSlug;
    if (!isFusion) {
      return true;
    }

    final isMergeGroup = detectMergeGroup(checkRun);

    // Check runs are fired at every stage. However, at this point it is unknown
    // if this check run belongs in the engine build stage or in the test stage.
    // So first look for it in the engine stage, and if it's missing, look for
    // it in the test stage.
    var stage = CiStage.fusionEngineBuild;
    var stagingConclusion = await _recordCurrentCiStage(
      slug: slug,
      sha: sha,
      stage: stage,
      name: name,
      conclusion: conclusion,
    );

    if (stagingConclusion.result == StagingConclusionResult.missing) {
      // Check run not found in the engine stage. Look for it in the test stage.
      stage = CiStage.fusionTests;
      stagingConclusion = await _recordCurrentCiStage(
        slug: slug,
        sha: sha,
        stage: stage,
        name: name,
        conclusion: conclusion,
      );
    }

    // First; check if we even recorded anything. This can occur if we've already passed the check_run and
    // have moved on to running more tests (which wouldn't be present in our document).
    if (!stagingConclusion.isOk) {
      return false;
    }

    // If an internal error happened in Cocoon, we need human assistance to
    // figure out next steps.
    if (stagingConclusion.result == StagingConclusionResult.internalError) {
      // If an internal error happened in the merge group, there may be no further
      // signals from GitHub that would cause the merge group to either land or
      // fail. The safest thing to do is to kick the pull request out of the queue
      // and let humans sort it out. If the group is left hanging in the queue, it
      // will hold up all other PRs that are trying to land.
      if (isMergeGroup) {
        await _completeArtifacts(sha, false);
        final guard = checkRunFromString(stagingConclusion.checkRunGuard!);
        await failGuardForMergeGroup(
          slug,
          sha,
          stagingConclusion.summary,
          stagingConclusion.details,
          guard,
        );
      }
      return false;
    }

    // Are there tests remaining? Keep waiting.
    if (stagingConclusion.isPending) {
      log.info(
        '$logCrumb: not progressing, remaining work count: ${stagingConclusion.remaining}',
      );
      return false;
    }

    if (stagingConclusion.isFailed) {
      // Something failed in the current CI stage:
      //
      // * If this is a pull request: keep the merge guard open and do not proceed
      //   to the next stage. Let the author sort out what's up.
      // * If this is a merge group: kick the pull request out of the queue, and
      //   let the author sort it out.
      if (isMergeGroup) {
        await _completeArtifacts(sha, false);
        final guard = checkRunFromString(stagingConclusion.checkRunGuard!);
        await failGuardForMergeGroup(
          slug,
          sha,
          stagingConclusion.summary,
          stagingConclusion.details,
          guard,
        );
      }
      return true;
    }

    // The logic for finishing a stage is different between build and test stages:
    //
    // * If this is a build stage, then:
    //    * If this is a pull request presubmit, then start the test stage.
    //    * If this is a merge group (in MQ), then close the MQ guard, letting
    //      GitHub land it.
    // * If this is a test stage, then close the MQ guard (allowing the PR to
    //   enter the MQ).
    switch (stage) {
      case CiStage.fusionEngineBuild:
        if (isMergeGroup) {
          await _completeArtifacts(sha, true);
        }
        await _closeSuccessfulEngineBuildStage(
          checkRun: checkRun,
          mergeQueueGuard: stagingConclusion.checkRunGuard!,
          slug: slug,
          sha: sha,
          logCrumb: logCrumb,
        );
      case CiStage.fusionTests:
        await _closeSuccessfulTestStage(
          mergeQueueGuard: stagingConclusion.checkRunGuard!,
          slug: slug,
          sha: sha,
          logCrumb: logCrumb,
        );
    }
    return true;
  }

  Future<void> _completeArtifacts(String commitSha, bool successful) async {
    try {
      await _contentAwareHash.completeArtifacts(
        commitSha: commitSha,
        successful: successful,
      );
    } catch (e, s) {
      log.warn(
        'failed to simulate completing artifacts with successful:$successful',
        e,
        s,
      );
    }
  }

  /// Whether the [checkRunEvent] is for a merge group (rather than a pull request).
  bool detectMergeGroup(cocoon_checks.CheckRun checkRun) {
    final headBranch = checkRun.checkSuite?.headBranch;
    if (headBranch == null) {
      return false;
    }
    return tryParseGitHubMergeQueueBranch(headBranch).parsed;
  }

  Future<void> _closeSuccessfulEngineBuildStage({
    required cocoon_checks.CheckRun checkRun,
    required String mergeQueueGuard,
    required RepositorySlug slug,
    required String sha,
    required String logCrumb,
  }) async {
    // We know that we're in a fusion repo; now we need to figure out if we are
    //   1) in a presubmit test or
    //   2) in the merge queue
    if (detectMergeGroup(checkRun)) {
      await _closeMergeQueue(
        mergeQueueGuard: mergeQueueGuard,
        slug: slug,
        sha: sha,
        stage: CiStage.fusionEngineBuild,
        logCrumb: logCrumb,
      );
      return;
    }

    log.info(
      '$logCrumb: Stage completed successfully: ${CiStage.fusionEngineBuild}',
    );

    await proceedToCiTestingStage(
      checkRun: checkRun,
      mergeQueueGuard: mergeQueueGuard,
      slug: slug,
      sha: sha,
      logCrumb: logCrumb,
    );
  }

  Future<void> _closeSuccessfulTestStage({
    required String mergeQueueGuard,
    required RepositorySlug slug,
    required String sha,
    required String logCrumb,
  }) async {
    log.info('$logCrumb: Stage completed: ${CiStage.fusionTests}');
    await unlockMergeQueueGuard(slug, sha, checkRunFromString(mergeQueueGuard));
  }

  /// Returns the presubmit targets for the fusion repo [pullRequest] that should run for the given [stage].
  Future<List<Target>> _getTestsForStage(
    PullRequest pullRequest,
    CiStage stage, {
    bool skipEngine = false,
  }) async {
    final presubmitTargets =
        [
          ...await getPresubmitTargets(pullRequest),
          if (!skipEngine)
            ...await getPresubmitTargets(
              pullRequest,
              type: CiType.fusionEngine,
            ),
        ].where(
          (Target target) => switch (stage) {
            CiStage.fusionEngineBuild => target.isReleaseBuild,
            CiStage.fusionTests => !target.isReleaseBuild,
          },
        );
    return [...presubmitTargets];
  }

  Future<void> _closeMergeQueue({
    required String mergeQueueGuard,
    required RepositorySlug slug,
    required String sha,
    required CiStage stage,
    required String logCrumb,
  }) async {
    log.info('$logCrumb: Merge Queue finished successfully');

    // Unlock the guarding check_run.
    final checkRunGuard = checkRunFromString(mergeQueueGuard);
    await unlockMergeQueueGuard(slug, sha, checkRunGuard);
  }

  /// Schedules post-engine build tests (i.e. engine tests, and framework tests).
  Future<void> _runCiTestingStage({
    required PullRequest pullRequest,
    required String checkRunGuard,
    required String logCrumb,
    required _FlutterRepoTestsToRun testsToRun,
  }) async {
    try {
      // Both the author and label should be checked to make sure that no one is
      // attempting to get a pull request without check through.
      if (pullRequest.user!.login == _config.autosubmitBot &&
          pullRequest.labels!.any(
            (element) => element.name == Config.revertOfLabel,
          )) {
        log.info(
          '$logCrumb: skipping generating the full set of checks for revert request.',
        );
      } else {
        // Schedule the tests that would have run in a call to triggerPresubmitTargets - but for both the
        // engine and the framework.
        var presubmitTargets = await _getTestsForStage(
          pullRequest,
          CiStage.fusionTests,
          skipEngine:
              testsToRun != _FlutterRepoTestsToRun.engineTestsAndFrameworkTests,
        );

        // Create the document for tracking test check runs.
        final List<String> tasks;
        if (testsToRun == _FlutterRepoTestsToRun.frameworkFlutterAnalyzeOnly) {
          const linuxAnalyze = 'Linux analyze';
          final singleTarget = presubmitTargets.firstWhereOrNull(
            (t) => t.name == linuxAnalyze,
          );
          if (singleTarget == null) {
            log.warn('No target found named "$linuxAnalyze"');
            tasks = [];
            presubmitTargets = [];
          } else {
            log.info('Only running target "$linuxAnalyze"');
            tasks = [linuxAnalyze];
            presubmitTargets = [singleTarget];
          }
        } else {
          tasks = [...presubmitTargets.map((t) => t.name)];
        }

        await CiStaging.initializeDocument(
          firestoreService: _firestore,
          slug: pullRequest.base!.repo!.slug(),
          sha: pullRequest.head!.sha!,
          stage: CiStage.fusionTests,
          tasks: tasks,
          checkRunGuard: checkRunGuard,
        );

        // Here is where it gets fun: how do framework tests* know what engine
        // artifacts to fetch and use on CI? For presubmits on flutter/flutter;
        // see https://github.com/flutter/flutter/issues/164031.
        //
        // *In theory, also engine tests, but engine tests build from the engine
        // from source and rely on remote-build execution (RBE) for builds to
        // fast and cached.
        final EngineArtifacts engineArtifacts;
        if (testsToRun != _FlutterRepoTestsToRun.engineTestsAndFrameworkTests) {
          // Use the engine that this PR was branched off of.
          engineArtifacts = EngineArtifacts.usingExistingEngine(
            commitSha: pullRequest.base!.sha!,
          );
        } else {
          // Use the engine that was built from source *for* this PR.
          engineArtifacts = EngineArtifacts.builtFromSource(
            commitSha: pullRequest.head!.sha!,
          );
        }

        await _luciBuildService.scheduleTryBuilds(
          targets: presubmitTargets,
          pullRequest: pullRequest,
          engineArtifacts: engineArtifacts,
        );
      }
    } on FormatException catch (e, s) {
      log.warn(
        '$logCrumb: FormatException encountered when scheduling presubmit '
        'targets for ${pullRequest.number}',
        e,
        s,
      );
      rethrow;
    } catch (e, s) {
      log.warn(
        '$logCrumb: Exception encountered when scheduling presubmit targets '
        'for ${pullRequest.number}',
        e,
        s,
      );
      rethrow;
    }
  }

  @visibleForTesting
  Future<void> proceedToCiTestingStage({
    required cocoon_checks.CheckRun checkRun,
    required RepositorySlug slug,
    required String sha,
    required String mergeQueueGuard,
    required String logCrumb,
  }) async {
    final checkRunGuard = checkRunFromString(mergeQueueGuard);

    // Look up the PR in our cache first. This reduces github quota and requires less calls.
    PullRequest? pullRequest;
    final id = checkRun.id!;
    final name = checkRun.name!;
    try {
      pullRequest = await PrCheckRuns.findPullRequestFor(_firestore, id, name);
    } catch (e, s) {
      log.warn('$logCrumb: unable to find PR in PrCheckRuns', e, s);
    }

    // We've failed to find the pull request; try a reverse look it from the check suite.
    if (pullRequest == null) {
      final checkSuiteId = checkRun.checkSuite!.id!;
      pullRequest = await _githubChecksService.findMatchingPullRequest(
        slug,
        sha,
        checkSuiteId,
      );
    }

    // We cannot make any forward progress. Abandon all hope, Check runs who enter here.
    if (pullRequest == null) {
      throw 'No PR found matching this check_run($id, $name)';
    }

    try {
      await _runCiTestingStage(
        pullRequest: pullRequest,
        checkRunGuard: '$checkRunGuard',
        logCrumb: logCrumb,
        testsToRun: _FlutterRepoTestsToRun.engineTestsAndFrameworkTests,
      );
    } catch (error, stacktrace) {
      final githubService = await _config.createDefaultGitHubService();
      await githubService.createComment(
        slug,
        issueNumber: pullRequest.number!,
        body:
            '''
CI had a failure that stopped further tests from running.  We need to investigate to determine the root cause.

SHA at time of execution: $sha.

Possible causes:
* **Configuration Changes:** The `.ci.yaml` file might have been modified between the creation of this pull request and the start of this test run. This can lead to ci yaml validation errors.
* **Infrastructure Issues:** Problems with the CI environment itself (e.g., quota) could have caused the failure.

A blank commit, or merging to head, will be required to resume running CI for this PR.

**Error Details:**

```
$error
```

Stack trace:

```
$stacktrace
```
''',
      );
    }
  }

  Future<StagingConclusion> _recordCurrentCiStage({
    required RepositorySlug slug,
    required String sha,
    required CiStage stage,
    required String name,
    required TaskConclusion conclusion,
  }) async {
    final logCrumb = 'checkCompleted($name, $slug, $sha, $conclusion)';
    final documentName = CiStaging.documentNameFor(
      slug: slug,
      sha: sha,
      stage: stage,
    );
    log.info('$logCrumb: $documentName');

    // We're doing a transactional update, which could fail if multiple tasks are running at the same time; so retry
    // a sane amount of times before giving up.
    const r = RetryOptions(maxAttempts: 3, delayFactor: Duration(seconds: 2));

    return r.retry(() {
      return CiStaging.markConclusion(
        firestoreService: _firestore,
        slug: slug,
        sha: sha,
        stage: stage,
        checkRun: name,
        conclusion: conclusion,
      );
    });
  }

  /// Reschedules a failed build using a [CheckRunEvent]. The CheckRunEvent is
  /// generated when someone clicks the re-run button from a failed build from
  /// the Github UI.
  ///
  /// If the rerequested check is for [Config.kCiYamlCheckName], all presubmit jobs are retried.
  /// Otherwise, the specific check will be retried.
  ///
  /// Relevant APIs:
  ///   https://developer.github.com/v3/checks/runs/#check-runs-and-requested-actions
  @useResult
  Future<ProcessCheckRunResult> processCheckRun(
    cocoon_checks.CheckRunEvent checkRunEvent,
  ) async {
    switch (checkRunEvent.action) {
      case 'completed':
        if (!_config.flags.closeMqGuardAfterPresubmit) {
          await processCheckRunCompleted(
            checkRunEvent.checkRun!,
            checkRunEvent.repository?.slug(),
          );
        }
        return const ProcessCheckRunResult.success();
      case 'rerequested':
        log.debug(
          'Rerun requested by GitHub user: ${checkRunEvent.sender?.login}',
        );
        final name = checkRunEvent.checkRun!.name;
        var success = false;
        if (name == Config.kMergeQueueLockName) {
          final slug = checkRunEvent.repository!.slug();
          final checkSuiteId = checkRunEvent.checkRun!.checkSuite!.id!;
          log.debug(
            'Requested re-run of "${Config.kMergeQueueLockName}" for '
            '$slug / $checkSuiteId - ignoring',
          );
          success = true;
        } else if (name == Config.kCiYamlCheckName) {
          // The CheckRunEvent.checkRun.pullRequests array is empty for this
          // event, so we need to find the matching pull request.
          final slug = checkRunEvent.repository!.slug();
          final headSha = checkRunEvent.checkRun!.headSha!;
          final checkSuiteId = checkRunEvent.checkRun!.checkSuite!.id!;
          final pullRequest = await _githubChecksService
              .findMatchingPullRequest(slug, headSha, checkSuiteId);
          if (pullRequest != null) {
            log.debug(
              'Matched PR: ${pullRequest.number} Repo: ${slug.fullName}',
            );
            await triggerPresubmitTargets(pullRequest: pullRequest);
            success = true;
          } else {
            log.warn('No matching PR found for head_sha in check run event.');
          }
        } else {
          try {
            final slug = checkRunEvent.repository!.slug();
            final sha = checkRunEvent.checkRun!.headSha!;

            // Only merged commits are added to the Database.
            // If a commit is found, this must be a postsubmit checkrun.
            final fsCommit = await fs.Commit.tryFromFirestoreBySha(
              _firestore,
              sha: sha,
            );

            // TODO(matanlurey): Refactor into its own branch.
            // https://github.com/flutter/flutter/issues/167211.
            final isPresubmit = fsCommit == null;
            if (isPresubmit) {
              log.debug(
                'Rescheduling presubmit build for ${checkRunEvent.checkRun?.name}',
              );
              final pullRequest = await PrCheckRuns.findPullRequestForSha(
                _firestore,
                checkRunEvent.checkRun!.headSha!,
              );
              if (pullRequest == null) {
                return ProcessCheckRunResult.userError(
                  'Asked to reschedule presubmits for unknown sha/PR: ${checkRunEvent.checkRun!.headSha!}',
                );
              }

              final isFusion = slug == Config.flutterSlug;
              final List<Target> presubmitTargets;
              final EngineArtifacts engineArtifacts;
              if (isFusion) {
                // Fusion repos have presubmits split across two .ci.yaml files.
                // /ci.yaml
                // /engine/src/flutter/.ci.yaml
                presubmitTargets = [
                  ...await getPresubmitTargets(pullRequest),
                  ...await getPresubmitTargets(
                    pullRequest,
                    type: CiType.fusionEngine,
                  ),
                ];
                final opt = await _filesChangedOptimizer.checkPullRequest(
                  pullRequest,
                );
                if (opt.shouldUsePrebuiltEngine) {
                  engineArtifacts = EngineArtifacts.usingExistingEngine(
                    commitSha: pullRequest.base!.sha!,
                  );
                } else {
                  engineArtifacts = EngineArtifacts.builtFromSource(
                    commitSha: pullRequest.head!.sha!,
                  );
                }
              } else {
                presubmitTargets = await getPresubmitTargets(pullRequest);
                engineArtifacts = const EngineArtifacts.noFrameworkTests(
                  reason: 'Not flutter/flutter',
                );
              }

              final target = presubmitTargets.firstWhereOrNull(
                (target) => checkRunEvent.checkRun!.name == target.name,
              );
              if (target == null) {
                return ProcessCheckRunResult.missingEntity(
                  'Could not reschedule checkRun "${checkRunEvent.checkRun!.name}", '
                  'not found in list of presubmit targets: ${presubmitTargets.map((t) => t.name).toList()}',
                );
              }
              await _luciBuildService.scheduleTryBuilds(
                targets: [target],
                pullRequest: pullRequest,
                engineArtifacts: engineArtifacts,
              );
            } else {
              log.debug('Rescheduling postsubmit build.');

              final checkName = checkRunEvent.checkRun!.name!;
              final fs.Task fsTask;
              {
                // Query the lastest run of the `checkName` againt commit `sha`.
                final fsTasks = await _firestore.queryRecentTasks(
                  limit: 1,
                  commitSha: fsCommit.sha,
                  name: checkName,
                );
                if (fsTasks.isEmpty) {
                  throw StateError('Expected 1+ tasks for $checkName');
                }
                fsTask = fsTasks.first;
              }
              log.debug('Latest firestore task is $fsTask');
              final ciYaml = await _ciYamlFetcher.getCiYamlByCommit(
                fsCommit.toRef(),
                postsubmit: true,
              );
              final target = ciYaml.postsubmitTargets().singleWhere(
                (target) => target.name == fsTask.taskName,
              );
              await _luciBuildService
                  .reschedulePostsubmitBuildUsingCheckRunEvent(
                    checkRunEvent,
                    commit: fsCommit.toRef(),
                    task: fsTask,
                    target: target,
                  );
            }

            success = true;
          } on NoBuildFoundException {
            log.warn('No build found to reschedule.');
          } on FormatException catch (e) {
            // See https://github.com/flutter/flutter/issues/165018.
            log.info('CheckName: $name failed due to user error: $e');
            return ProcessCheckRunResult.userError('$e');
          }
        }

        log.debug('CheckName: $name State: $success');

        // TODO(matanlurey): It would be better to early return above where it is not a success.
        if (!success) {
          return const ProcessCheckRunResult.unexpectedError(
            'Not successful. See previous log messages',
          );
        }
    }

    return const ProcessCheckRunResult.success();
  }

  /// Push [Commit] to BigQuery as part of the infra metrics dashboards.
  Future<void> _uploadToBigQuery(fs.Commit commit) async {
    const projectId = 'flutter-dashboard';
    const dataset = 'cocoon';
    const table = 'Checklist';

    log.info('Uploading commit ${commit.sha} info to bigquery.');

    final tabledataResource = _bigQuery.tabledata;
    final tableDataInsertAllRequestRows = <Map<String, Object>>[];

    /// Consolidate [commits] together
    ///
    /// Prepare for bigquery [insertAll]
    tableDataInsertAllRequestRows.add(<String, Object>{
      'json': <String, Object?>{
        'CreateTimestamp': commit.createTimestamp,
        'FlutterRepositoryPath': commit.repositoryPath,
        'CommitSha': commit.sha,
        'CommitAuthorLogin': commit.author,
        'CommitAuthorAvatarURL': commit.avatar,
        'CommitMessage': commit.message,
        'Branch': commit.branch,
      },
    });

    /// Final [rows] to be inserted to [BigQuery]
    final rows = TableDataInsertAllRequest.fromJson(<String, Object>{
      'rows': tableDataInsertAllRequestRows,
    });

    /// Insert [commits] to [BigQuery]
    try {
      if (rows.rows == null) {
        log.warn('Rows to be inserted is null');
      } else {
        log.info(
          'Inserting ${rows.rows!.length} into big query for ${commit.sha}',
        );
      }
      await tabledataResource.insertAll(rows, projectId, dataset, table);
    } on ApiRequestError catch (e) {
      log.warn('Failed to add commits to BigQuery', e);
    }
  }

  /// Parses CheckRun from a previously json string encode
  CheckRun checkRunFromString(String input) {
    final checkRunJson = json.decode(input) as Map<String, dynamic>;
    // Workaround for https://github.com/SpinlockLabs/github.dart/issues/412
    if (checkRunJson['conclusion'] == 'null') {
      checkRunJson.remove('conclusion');
    }
    return CheckRun.fromJson(checkRunJson);
  }
}

/// Describes in `flutter/flutter` which tests to schedule.
enum _FlutterRepoTestsToRun {
  /// Run tests _of_ the engine, and tests in the framework (that use an engine).
  engineTestsAndFrameworkTests,

  /// Run only tests in the framework (that use an engine), skpping engine tests.
  frameworkTestsOnly,

  /// No tests.
  frameworkFlutterAnalyzeOnly,
}

enum _TaskCommitScheduling {
  /// Schedule according to how [Target.schedulerPolicy] is computed.
  defaultUseTargetSchedulingPolicy,

  /// Non-default branches skip tests by default for later (manual) scheduling.
  nonDefaultBranchSkipTestsByDefault;

  /// Whether postsubmit tasks should be initially skipped.
  bool get skipPostsubmitTasks {
    return this == nonDefaultBranchSkipTestsByDefault;
  }
}
