Future post()

in app_dart/lib/src/request_handlers/reset_prod_task.dart [50:139]


  Future<Body> post() async {
    final DatastoreService datastore = datastoreProvider(config.db);
    final String encodedKey = requestData![taskKeyParam] as String? ?? '';
    final KeyHelper keyHelper = config.keyHelper;
    final String owner = requestData![ownerParam] as String? ?? 'flutter';
    final String repo = requestData![repoParam] as String? ?? 'flutter';
    String commitSha = requestData![commitShaParam] as String? ?? '';
    final Map<String, dynamic> properties =
        (requestData![propertiesParam] as Map<String, dynamic>?) ?? <String, dynamic>{};
    final TokenInfo token = await tokenInfo(request!);

    RepositorySlug slug;
    String? builder = requestData![builderParam] as String? ?? '';
    Task? task;
    Commit commit;

    if (encodedKey.isNotEmpty) {
      // Check params required for dashboard.
      checkRequiredParameters(<String>[taskKeyParam]);
    } else {
      // Checks params required when this API is called with curl.
      checkRequiredParameters(<String>[commitShaParam, builderParam, repoParam]);
    }

    if (encodedKey.isNotEmpty) {
      // Request coming from the dashboard.
      final Key<int> key = keyHelper.decode(encodedKey) as Key<int>;
      log.info('Rescheduling task with Key: ${key.id}');
      task = (await datastore.lookupByKey<Task>(<Key<int>>[key])).single;
      if (task!.status == 'Succeeded') {
        return Body.empty;
      }
      commit = await datastore.db.lookupValue<Commit>(task.commitKey!);
      slug = commit.slug;
      commitSha = commit.sha!;
      builder = task.builderName;
      if (builder == null) {
        final CiYaml ciYaml = await scheduler.getCiYaml(commit);
        final List<LuciBuilder> builders = await scheduler.getPostSubmitBuilders(ciYaml);
        builder = builders
            .where((LuciBuilder builder) => builder.taskName == task!.name)
            .map((LuciBuilder builder) => builder.name)
            .single;
      }
    } else {
      if (repo == 'flutter') {
        throw const BadRequestException(
            'Flutter repo does not support retries with curl, please use flutter-dashboard instead');
      }
      // Request not coming from dashboard means we need to create slug from parameters.
      slug = RepositorySlug(owner, repo);
      commit = Commit(repository: slug.fullName, sha: commitSha);
    }

    final Iterable<Build> currentBuilds = await luciBuildService.getProdBuilds(slug, commit.sha!, builder, repo);
    final List<Status> noReschedule = <Status>[Status.started, Status.scheduled, Status.success];
    final Build? build = currentBuilds.firstWhereOrNull(
      (Build element) {
        log.info('Found build status: ${element.status} inNoReschedule ${noReschedule.contains(element.status)}');
        return noReschedule.contains(element.status);
      },
    );
    log.info('Owner: $owner, Repo: $repo, Builder: $builder, CommitSha: ${commit.sha}, Build: $build');

    if (build != null) {
      throw const ConflictException();
    }
    final Map<String, List<String?>> tags = <String, List<String?>>{
      'triggered_by': <String?>[token.email],
      'trigger_type': <String>['manual'],
    };
    final Build buildResult = await luciBuildService.reschedulePostsubmitBuild(
      commitSha: commit.sha!,
      builderName: builder,
      repo: repo,
      properties: properties,
      tags: tags,
      bucket: task?.isFlaky ?? false ? 'staging' : 'prod',
    );
    if (task != null) {
      // Only try to update task when it really exists.
      task
        ..status = Task.statusNew
        ..startTimestamp = 0
        ..attempts = (task.attempts ?? 0) + 1;
      await datastore.insert(<Task>[task]);
    }
    final String buildUrl = 'https://ci.chromium.org/ui/b/${buildResult.id}';
    return Body.forString('Build url: $buildUrl');
  }