sclorg / testing-farm-as-github-action

GitHub Action to execute tests by Testing Farm and update Pull Request status
MIT License
13 stars 11 forks source link

Add possibility to create comment with results #81

Closed zmiklank closed 1 week ago

zmiklank commented 1 year ago

We can use, e.g., https://github.com/marocchino/sticky-pull-request-comment

Only nice to have.

jamacku commented 1 year ago

Here is an example of implementation I use in our GA. It's based on probot/metadata javascript library, which works only for GitHub Apps (Bots).

Example of implementation from redhat-plumbers-in-action/devel-freezer:

Store comment ID in a PR comment

source: https://github.com/redhat-plumbers-in-action/devel-freezer/blob/main/src/metadata.ts#L84-L142

/**
 * Based on probot-metadata - https://github.com/probot/metadata
 */
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class MetadataController {
  static readonly regex = /\n\n<!-- devel-freezer = (.*) -->/;

  static async getMetadata(issueNumber: number, key: string, context: Context) {
    const body =
      (
        await context.octokit.issues.get(
          context.issue({ issue_number: issueNumber })
        )
      ).data.body || '';

    const match = body.match(MetadataController.regex);

    if (match) {
      const data = JSON.parse(match[1]);
      return key ? data && data[key] : data;
    }
  }

  static async setMetadata(
    key: string,
    value: string,
    context: Context,
    issueNumber?: number
  ) {
    let body =
      (
        await context.octokit.issues.get(
          context.issue(issueNumber ? { issue_number: issueNumber } : {})
        )
      ).data.body || '';

    let data = {};

    body = body.replace(MetadataController.regex, (_, json) => {
      data = JSON.parse(json);
      return '';
    });

    if (!data) data = {};

    if (typeof key === 'object') {
      Object.assign(data, key);
    } else {
      (data as { [key: string]: string })[key] = value;
    }

    return context.octokit.issues.update(
      context.issue({
        body: `${body}\n\n<!-- devel-freezer = ${JSON.stringify(data)} -->`,
        ...(issueNumber ? { issue_number: issueNumber } : {}),
      })
    );
  }
}

Use Metadata to create/update comment

source: https://github.com/redhat-plumbers-in-action/devel-freezer/blob/main/src/pull-request.ts#L57-L110

  private async publishComment(
    content: string,
    context: {
      [K in keyof typeof events]: Context<(typeof events)[K][number]>;
    }[keyof typeof events]
  ) {
    if (this.metadata.commentID) {
      this.updateComment(content, context);
      return;
    }

    const commentPayload = (await this.createComment(content, context))?.data;

    if (!commentPayload) {
      warning(`Failed to create comment.`);
      return;
    }

    return commentPayload.id;
  }

  private createComment(
    body: string,
    context: {
      [K in keyof typeof events]: Context<(typeof events)[K][number]>;
    }[keyof typeof events]
  ) {
    if (!body || body === '') return;

    return context.octokit.issues.createComment(
      // !FIXME: This is wrong, don't use `as`
      (context as Context<(typeof events.pull_request)[number]>).issue({
        issue_number: this.id,
        body,
      })
    );
  }

  private async updateComment(
    body: string,
    context: {
      [K in keyof typeof events]: Context<(typeof events)[K][number]>;
    }[keyof typeof events]
  ) {
    if (!this.metadata.commentID) return;

    return context.octokit.issues.updateComment(
      // !FIXME: This is wrong, don't use `as`
      (context as Context<(typeof events.pull_request)[number]>).issue({
        comment_id: +this.metadata.commentID,
        body,
      })
    );
  }