private async getChecksStatus()

in functions/src/plugins/merge.ts [154:262]


  private async getChecksStatus(context: Context, pr: CachedPullRequest, config: MergeConfig, labels: Github.PullRequestsGetResponseLabelsItem[] = [], statuses?: GithubGQL.StatusContext[]): Promise<ChecksStatus> {
    const checksStatus: ChecksStatus = {
      pending: [],
      failure: []
    };
    const labelsNames = getLabelsNames(labels);

    // Check if there is any merge conflict
    if(config.checks.noConflict) {
      // If mergeable is null, we need to get the updated status
      if(pr.mergeable === null) {
        const {owner, repo} = context.repo();
        pr = await this.updateDbPR(context.github, owner, repo, pr.number, context.payload.repository.id);
      }
      // Check if there is a conflict with the base branch
      if(pr.mergeable === false) {
        checksStatus.failure.push(`conflicts with base branch "${pr.base.ref}"`);
      }
    }

    // Check if all required labels are present
    if(config.checks.requiredLabels) {
      const missingLabels: string[] = [];
      config.checks.requiredLabels.forEach(reqLabel => {
        if(!labelsNames.some(label => !!label.match(new RegExp(reqLabel)))) {
          missingLabels.push(reqLabel);
        }
      });

      if(missingLabels.length > 0) {
        checksStatus.pending.push(`missing required labels: ${missingLabels.join(', ')}`);
      }
    }

    // Check if all required labels when merge ready are present
    if(labelsNames.includes(config.mergeLabel) && config.checks.requiredLabelsWhenMergeReady) {
      const missingLabels: string[] = [];
      config.checks.requiredLabelsWhenMergeReady.forEach(reqLabel => {
        if(!labelsNames.some(label => !!label.match(new RegExp(reqLabel)))) {
          missingLabels.push(reqLabel);
        }
      });

      if(missingLabels.length > 0) {
        checksStatus.pending.push(`missing required labels: ${missingLabels.join(', ')}`);
      }
    }

    // Check if any forbidden label is present
    if(config.checks.forbiddenLabels) {
      const fbdLabels: string[] = [];
      config.checks.forbiddenLabels.forEach(fbdLabel => {
        if(labelsNames.some(label => !!label.match(new RegExp(fbdLabel)))) {
          fbdLabels.push(fbdLabel);
        }
      });

      if(fbdLabels.length > 0) {
        checksStatus.pending.push(`forbidden labels detected: ${fbdLabels.join(', ')}`);
      }
    }

    // Check if we have any failed/pending external status
    statuses = statuses || await this.getStatuses(context, pr.number, config);
    statuses.forEach(status => {
      switch(status.state) {
        case STATUS_STATE.Failure:
        case STATUS_STATE.Error:
        case GQL_STATUS_STATE.Failure:
        case GQL_STATUS_STATE.Error:
          checksStatus.failure.push(`status "${status.context}" is failing`);
          break;
        case STATUS_STATE.Pending:
        case GQL_STATUS_STATE.Pending:
          checksStatus.pending.push(`status "${status.context}" is pending`);
          break;
      }
    });

    // Check if all required statuses are present
    if(config.checks.requiredStatuses) {
      config.checks.requiredStatuses.forEach(reqCheck => {
        if(!statuses.some(status => !!status.context.match(new RegExp(reqCheck)))) {
          checksStatus.pending.push(`missing required status "${reqCheck}"`);
        }
      });
    }

    // Check if there is any review pending or that requested changes
    if(config.checks.requireReviews) {
      let nbPendingReviews = pr.pendingReviews;
      // Because we're adding cache for this value progressively, ensure that we have the data available
      // TODO(ocombe): remove this when all DB PRs have been updated
      if(typeof nbPendingReviews !== 'number') {
        nbPendingReviews = await this.getPendingReviews(context, pr);
        pr.pendingReviews = nbPendingReviews;
        const {owner, repo} = context.repo();
        await this.updateDbPR(context.github, owner, repo, pr.number, context.payload.repository.id, pr).catch(err => {
          throw err;
        });
      }

      if(nbPendingReviews > 0) {
        checksStatus.pending.push(`${nbPendingReviews} pending code review${nbPendingReviews > 1 ? 's' : ''}`);
      }
    }

    return checksStatus;
  }