async checkMatchesTemplate()

in functions/src/issues.ts [624:719]


  async checkMatchesTemplate(
    org: string,
    name: string,
    issue: types.internal.Issue
  ): Promise<CheckMatchesTemplateResult> {
    const result = new CheckMatchesTemplateResult();
    const templateOpts = this.parseIssueOptions(org, name, issue);

    const templatePath = templateOpts.path;
    result.templatePath = templatePath;

    log.debug("Template options: ", templateOpts);
    if (!templateOpts.validate) {
      log.debug(`Template optons specify no verification.`);
      result.skipped = true;
      return result;
    }

    const validationConfig = this.config.getRepoTemplateValidationConfig(
      org,
      name,
      templatePath
    );
    log.debug("Validation config: ", validationConfig);

    // Try to get the issue template, but skip validation if we can't.
    let data = undefined;
    try {
      data = await this.gh_client.getIssueTemplate(
        org,
        name,
        templateOpts.path
      );
    } catch (e) {
      const err = `failed to get issue template for ${org}/${name} at ${templateOpts.path};`;
      log.warn(`checkMatchesTemplate: ${err}: ${JSON.stringify(e)}`);

      result.failure = {
        otherError: err
      };
      return result;
    }

    const checker = new template.TemplateChecker("###", "[REQUIRED]", data);
    const issueBody = issue.body;

    const missingSections = checker.matchesTemplateSections(issueBody);
    if (missingSections.invalid.length > 0) {
      log.debug(
        `checkMatchesTemplate: missing ${missingSections.invalid.length} sections from the template.`
      );
      result.matches = false;
      result.message = MSG_FOLLOW_TEMPLATE;
      result.failure = {
        missingSections: missingSections.invalid
      };
      return result;
    }

    const emptySections = checker.getRequiredSectionsEmpty(issueBody);

    let maxEmptySections = 0;
    if (validationConfig && validationConfig.required_section_validation) {
      switch (validationConfig.required_section_validation) {
        case "strict":
          // Any empty required section is a violation
          maxEmptySections = 0;
          break;
        case "relaxed":
          // As long as you fill out one required section, it's ok
          maxEmptySections = emptySections.all.length - 1;
          break;
        case "none":
          maxEmptySections = emptySections.all.length;
          break;
      }
    }

    const numEmptySections = emptySections.invalid.length;
    if (numEmptySections > maxEmptySections) {
      log.debug(
        `checkMatchesTemplate: ${numEmptySections} required sections are empty, which is greater than ${maxEmptySections}.`
      );
      result.matches = false;
      result.message = MSG_MISSING_INFO;
      result.failure = {
        emptySections: emptySections.invalid
      };
    } else if (numEmptySections > 0) {
      log.debug(
        `checkMatchesTemplate: ${numEmptySections} required sections are empty but max was ${maxEmptySections}.`
      );
    }

    return result;
  }