async checkSize()

in functions/src/plugins/size.ts [50:214]


  async checkSize(context: Context): Promise<void> {
    const appConfig = await this.getAppConfig(context);

    if(!appConfig.size || appConfig.size.disabled) {
      return;
    }

    const config: SizeConfig = {
      ...defaultAppConfig.size,
      ...appConfig.size,
      status: { ...defaultAppConfig.size.status, ...appConfig.size.status },
    };

    const statusEvent = context.payload;

    // only check on PRs the status has that artifacts
    if(statusEvent.context !== config.circleCiStatusName) {
      return;
    }

    if(statusEvent.state === STATUS_STATE.Pending) {
      await this.setStatus(
        STATUS_STATE.Pending,
        `Waiting for "${config.circleCiStatusName}"...`,
        config.status.context,
        context,
      );

      return;
    } else if(statusEvent.state === STATUS_STATE.Failure) {
      await this.setStatus(
        STATUS_STATE.Error,
        `Unable to calculate sizes. Failure: "${config.circleCiStatusName}"`,
        config.status.context,
        context,
      );

      return;
    }

    const {owner, repo} = context.repo();
    const buildNumber = this.getBuildNumberFromCircleCIUrl(statusEvent.target_url);

    let newArtifacts;
    try {
      newArtifacts = await this.getCircleCIArtifacts(owner, repo, buildNumber, config.exclude, config.include);
    } catch(e) {
      this.logError('CircleCI Artifact retrieval error: ' + e.message);
      await this.setStatus(
        STATUS_STATE.Error,
        `Unable to retrieve artifacts from "${config.circleCiStatusName}".`,
        config.status.context,
        context,
      );

      return;
    }

    const pr = await this.findPrBySha(statusEvent.sha, statusEvent.repository.id);
    if(!pr) {
      // this status doesn't have a PR therefore it's probably a commit to a branch
      // so we want to store any changes from that commit
      await this.upsertNewArtifacts(context, newArtifacts);

      await this.setStatus(
        STATUS_STATE.Success,
        `Baseline saved for ${statusEvent.sha}`,
        config.status.context,
        context,
      );

      return;
    }

    this.logDebug(`[size] Processing PR: ${pr.title}`);

    // set to pending since we are going to do a full run through
    await this.setStatus(
      STATUS_STATE.Pending,
      'Calculating artifact sizes...',
      config.status.context,
      context,
    );

    const targetBranchArtifacts = await this.getTargetBranchArtifacts(pr);

    if(targetBranchArtifacts.length === 0) {
      await this.setStatus(
        STATUS_STATE.Success,
        `No baseline available for ${pr.base.ref} / ${pr.base.sha}`,
        config.status.context,
        context,
      );

      return;
    }

    const comparisons = this.generateArtifactComparisons(targetBranchArtifacts, newArtifacts, config);
    const largestIncrease = comparisons.length > 0 ? comparisons[0] : null;
    const failure = largestIncrease && largestIncrease.failed;

    let description;
    if(!largestIncrease) {
      description = 'No matching artifacts to compare.';
    } else if(largestIncrease.delta === 0) {
      description = 'No size change against base branch.';
    } else {
      const direction = largestIncrease.delta > 0 ? 'increased' : 'decreased';
      const formattedBytes = formatBytes(Math.abs(largestIncrease.delta));
      description = `${largestIncrease.current.path} ${direction} by ${formattedBytes}.`;


      // Add comment if enabled
      if (config.comment) {
        let body = '|| Artifact | Baseline | Current | Change |\n|-|-|-|-|-|\n';

        for (const comparison of comparisons) {
          const emoji = comparison.delta <= 0 ? ':white_check_mark:' : ':grey_exclamation:';
          body += `| ${comparison.failed ? ':x:' : emoji}|${comparison.baseline.path}`;
          body += `|[${formatBytes(comparison.baseline.size)}](${comparison.baseline.url})`;
          body += `|[${formatBytes(comparison.current.size)}](${comparison.current.url})`;
          body += `|${comparison.delta > 0 ? '+' : ''}${formatBytes(comparison.delta)}|`;
        }

        try {
          const prDoc = await this.pullRequests.doc(pr.id.toString()).get();
          let commentId = prDoc.exists ? prDoc.data().sizeCheckComment : undefined;

          if (commentId !== undefined) {
            try {
              await context.github.issues.updateComment({
                owner,
                repo,
                comment_id: commentId,
                body, 
              });
            } catch {
              // Comment may have been deleted
              commentId = undefined;
            }
          }

          if (commentId === undefined) {
            const response = await context.github.issues.createComment({
              owner,
              repo,
              number: pr.number,
              body,
            });

            await prDoc.ref.update({ sizeCheckComment: response.data.id });
          }
        } catch (e) {
          this.logError(`Unable to add size comment [${e.message}]`);
        }
      }
    }

    return this.setStatus(
      failure ? STATUS_STATE.Failure : STATUS_STATE.Success,
      description,
      config.status.context,
      context,
    );
  }