Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create GitHub comment summary report from Testing Farm results #211

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,16 @@ async function action(pr: PullRequest): Promise<void> {
);
}

// Create comment summary with Testing Farm request/result to Pull Request
if (getBooleanInput('comment_summary')) {
await pr.publishStatusComment(
getInput('pull_request_status_name'),
getInput('compose'),
finalState,
${tfArtifactUrl}
);
}

// Create Github Summary
if (getBooleanInput('create_github_summary')) {
await summary
Expand Down
92 changes: 92 additions & 0 deletions src/metadata.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import { getInput } from '@actions/core';
import { context } from '@actions/github';
import MetadataController from 'issue-metadata';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have to add issue-metadata to the list of dependencies - yarn add issue-metadata

import { z } from 'zod';

let summary_info: { "pull_request_status_name": string, "compose": string, "results": string, "logs": string }


type MetadataObject = {
TFCommentID: string | undefined;
TFDatetime: string | undefined
TFSummaryInfo: unknown[];
};



export class Metadata {
private _TFcommentID: MetadataObject['TFCommentID'];

constructor(
readonly issueNumber: number,
readonly controller: MetadataController,
metadata: MetadataObject
) {
this._TFcommentID = metadata?.TFCommentID ?? undefined;
this._TFDatetime = metadata?.TFDatetime ?? undefined;
this._TFSummaryInfo = metadata?._TFSummaryInfo ?? [];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are missing the declarations for _TFDatetime and _TFSummaryInfo.

}

get commentID() {
return this._TFcommentID;
}

get summaryInfo() {
return this._TFSummaryInfo;
}

get dateTimeInfo() {
return this._TFDatetime;
}

set commentID(value: MetadataObject['TFCommentID']) {
if (this._TFcommentID === undefined) {
this._TFcommentID = value;
}
}

set dateTimeInfo(value: MetadataObject['TFDatetime']) {
this._TFDatetime = value;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would personally avoid using setters and getters. They make code unreadable.


set updateSummaryInfo(value: MetadataObject['TFSummaryInfo']) {
this._TFSummaryInfo = value;
}

static readonly metadataCommentID = 'tf-comment-id';

async setMetadata(): Promise<void> {
if (this.TestingFarmCommentID !== undefined) {
await this.controller.setMetadata(
this.issueNumber,
Metadata.metadataCommentID,
this.commentID ?? ''
);
}

// TODO: clear tag when un-freezed
await this.controller.setMetadata(
this.issueNumber,
);
}

static async getMetadata(issueNumber: number): Promise<Metadata> {
const controller = new MetadataController('tf-comment-id', {
...context.repo,
headers: {
authorization: `Bearer ${getInput('token', { required: true })}`,
},
});

const parsedCommentID = z
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move the validation scheme into schema/ dir.

.string()
.safeParse(
await controller.getMetadata(issueNumber, Metadata.metadataCommentID)
);

return new Metadata(issueNumber, controller, {
commentID: parsedCommentID.success ? parsedCommentID.data : undefined,
});
}

}
79 changes: 78 additions & 1 deletion src/pull-request.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { debug, getBooleanInput, getInput } from '@actions/core';
import { context } from '@actions/github';
import { Endpoints } from '@octokit/types';
import { Metadata } from './metadata';

import { CustomOctokit } from './octokit';

Expand All @@ -14,12 +15,33 @@ export class PullRequest {
* @param sha - The head sha of the Pull Request
* @param octokit - The Octokit instance to use for interacting with the GitHub API
*/
private _metadata: Metadata | undefined;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move metadata property into constructor and make it readonly instead of private

private constructor(
readonly number: number,
readonly sha: string,
readonly octokit: CustomOctokit
readonly octokit: CustomOctokit,
) {}

set metadata(metadata: Metadata) {
this._metadata = metadata;
}

get metadata() {
if (!this._metadata) {
raise('Metadata is not set.');
}

return this._metadata;
}

isCommented(): boolean {
return !!this.metadata.commentID;
}

async setMetadata() {
this.metadata = await Metadata.getMetadata(this.id);
}

/**
* Set the Pull Request status using the GitHub API.
* @param state - The state of the status, can be one of error, failure, pending or success
Expand Down Expand Up @@ -95,4 +117,59 @@ export class PullRequest {

return new this(data.number, data.head.sha, octokit);
}

async publishStatusComment(pull_request_status_name: string, compose: string, final_state: string): Promise<number | undefined> {
const table_row = '|${pull_request_status_name}|${compose}|$[final_state}|<a href="${tfArtifactUrl}">test</a>|'
if (this.metadata.commentID) {
this.updateStatusComment(table_row);
return;
}
const createTable = '### Testing Farm as a GitHub Action summary\n\n
| Compose | Version | Test result | link to logs |\n
|--------|--------|--------|--------|'
const commentPayload = await this.createStatusComment(createTable);

if (!commentPayload) {
warning(`Failed to create comment.`);
return;
}
this.metadata.commentID = id === undefined ? id : commentPayload.id.toString();
await this.metadata.setMetadata();
}

async createStatusComment(body: string) {
if (!body || body === '') return;

debug(`Creating comment for PR: #${this.id}`);

const { data } = await this.octokit.request(
'POST /repos/{owner}/{repo}/issues/{issue_number}/comments',
{
...context.repo,
issue_number: this.id,
body,
}
);

return data;
}

private async updateStatusComment(body: string) {
if (!this.metadata.commentID) return;

debug(`Updating comment with ID: ${this.metadata.commentID}`);
const createTable = '### Testing Farm as a GitHub Action summary\n\n
| Compose | Version | Test result | link to logs |\n
|--------|--------|--------|--------|'
const { data } = await this.octokit.request(
'PATCH /repos/{owner}/{repo}/issues/comments/{comment_id}',
{
...context.repo,
comment_id: +this.metadata.commentID,
body,
}
);

return data;
}
}