public async validatePullRequestTarget()

in tools/@aws-cdk/prlint/lint.ts [195:328]


  public async validatePullRequestTarget(): Promise<LinterActions> {
    let ret: LinterActions = {};

    const number = this.props.number;
    const sha = (await this.pr()).head.sha;

    console.log(`⌛  Fetching PR number ${number}`);
    const pr = await this.pr();
    console.log(`PR base ref is: ${pr.base.ref}`)

    console.log(`⌛  Fetching files for PR number ${number}`);
    const files = await this.client.paginate(this.client.pulls.listFiles, this.prParams);

    console.log('⌛  Validating...');

    const validationCollector = new ValidationCollector(pr, files);

    validationCollector.validateRuleSet({
      exemption: shouldExemptReadme,
      exemptionMessage: `Not validating README changes since the PR is labeled with '${Exemption.README}'`,
      testRuleSet: [{ test: featureContainsReadme }],
    });

    validationCollector.validateRuleSet({
      exemption: shouldExemptTest,
      exemptionMessage: `Not validating test changes since the PR is labeled with '${Exemption.TEST}'`,
      testRuleSet: [{ test: featureContainsTest }, { test: fixContainsTest }],
    });

    validationCollector.validateRuleSet({
      exemption: shouldExemptIntegTest,
      exemptionMessage: `Not validating integration test changes since the PR is labeled with '${Exemption.INTEG_TEST}'`,
      testRuleSet: [{ test: featureContainsIntegTest }, { test: fixContainsIntegTest }],
    });

    validationCollector.validateRuleSet({
      exemption: shouldExemptBreakingChange,
      exemptionMessage: `Not validating breaking changes since the PR is labeled with '${Exemption.BREAKING_CHANGE}'`,
      testRuleSet: [{ test: assertStability }],
    });

    validationCollector.validateRuleSet({
      exemption: shouldExemptCliIntegTested,
      testRuleSet: [{ test: noCliChanges }],
    });

    validationCollector.validateRuleSet({
      exemption: shouldExemptAnalyticsMetadataChange,
      testRuleSet: [
        { test: noMetadataChanges },
        { test: noAnalyticsClassesChanges },
        { test: noAnalyticsEnumsChanges },
        { test: noAnalyticsEnumAutomationChanges },
        { test: noAnalyticsEnumLikeAutomationChanges },
      ],
    });

    validationCollector.validateRuleSet({
      testRuleSet: [
        { test: validateBreakingChangeFormat },
        { test: validateTitlePrefix },
        { test: validateTitleScope },
        { test: validateTitleLowercase },
        { test: validateBranch },
      ],
    });

    validationCollector.validateRuleSet({
      exemption: shouldExemptSizeCheck,
      testRuleSet: [
        { test: prIsSmall },
      ],
    })

    if (pr.base.ref === 'main') {
      // Only check CodeCov for PRs targeting 'main'
      const runs = await this.checkRuns(sha);
      const codeCovRuns = CODECOV_CHECKS.map(c => runs[c] as CheckRun | undefined);

      validationCollector.validateRuleSet({
        exemption: () => hasLabel(pr, Exemption.CODECOV),
        testRuleSet: [{
          test: () => {
            const summary = summarizeRunConclusions(codeCovRuns.map(r => r?.conclusion));
            console.log('CodeCov Summary:', summary);

            switch (summary) {
              case 'failure': return TestResult.failure('CodeCov is indicating a drop in code coverage');
              // If we don't know the result of the CodeCov results yet, we pretend that there isn't a problem.
              //
              // It would be safer to ask for changes until we're confident that CodeCov has passed, but if we do
              // that the following sequence of events happens:
              //
              // 1. PR is ready to be merged (approved, everything passes)
              // 2. Mergify enqueues it and merges from main
              // 3. CodeCov needs to run again
              // 4. PR linter requests changes because CodeCov result is uncertain
              // 5. Mergify dequeues the PR because PR linter requests changes
              //
              // This looks very confusing and noisy, and also will never fix itself, so the PR ends up unmerged.
              //
              // The better solution would probably be not to do a "Request Changes" review, but leave a comment
              // and create a GitHub "status" on the PR to say 'success/pending/failure', and make it required.
              // (https://github.com/aws/aws-cdk/issues/33136)
              //
              // For now, not doing anything with a 'waiting' status is a smaller delta, and the race condition posed by it is
              // unlikely to happen given that there are much slower jobs that the merge is blocked on anyway.
              case 'waiting': return TestResult.success();
              case 'success': return TestResult.success();
            }
          },
        }],
      });
    }

    // We always delete all comments; in the future we will just communicate via reviews.
    ret.deleteComments = await this.findExistingPRLinterComments();

    ret = mergeLinterActions(ret, await this.validationToActions(validationCollector));

    // also assess whether the PR needs review or not
    try {
      const state = await this.codeBuildJobSucceeded(sha);
      console.log(`PR code build job ${state ? "SUCCESSFUL" : "not yet successful"}`);
      if (state) {
        console.log('Assessing if the PR needs a review now');
        ret = mergeLinterActions(ret, await this.assessNeedsReview());
      }
    } catch (e) {
      console.log(`assessing review failed for sha ${sha}: `, e);
    }

    return ret;
  }