Skip to content

Commit

Permalink
Merge pull request #625 from mj-hd/feat-shortdesc-gitlab
Browse files Browse the repository at this point in the history
feat(reg-notify-gitlab-plugin): support short description
  • Loading branch information
Quramy authored Nov 30, 2023
2 parents 2ebddcf + 213f7f1 commit 7c0eaa4
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 24 deletions.
7 changes: 7 additions & 0 deletions packages/reg-notify-gitlab-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,20 @@ reg-suit prepare -p notify-gitlab
privateToken: string;
gitlabUrl?: string;
commentTo?: "note" | "description" | "discussion";
shortDescription?: boolean;
}
```

- `projectId` - _Required_ - Your GitLab project id. You can get this id via `https://gitlab.com/<your-name>/<your-project-name/edit>` page.
- `privateToken` - _Required_ - Your GitLab API token. If you want more detail, see [Personal access tokens doc](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html).
- `gitlabUrl` - _Optional_ - Set if you host your GitLab instance. Default: `https://gitlab.com`
- `commentTo` - _Optional_ - How this plugin comments to MR. If `"note"`, it posts or puts the comment as a MR's note. if `"description"`, your MR's description gets updated. If `"discussion"`, it posts or puts the comment as a MR's _resolvable_ note. Default: `"note"`.
- `shortDescription` - _Optional_ Returns a small table with the item counts.
Example:

| 🔴 Changed | ⚪️ New | 🔵 Passing |
| ---------- | ------- | ---------- |
| 3 | 4 | 120 |

### Auto complete on GitLab CI

Expand Down
74 changes: 60 additions & 14 deletions packages/reg-notify-gitlab-plugin/src/create-comment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,59 @@ export interface CommentSeed {
newItemsCount: number;
deletedItemsCount: number;
passedItemsCount: number;
shortDescription?: boolean;
}

function tableItem(itemCount: number, header: string): [number, string] | null {
return itemCount == 0 ? null : [itemCount, header];
}

/**
* Returns a small table with the item counts.
*
* @example
* | 🔴 Changed | ⚪️ New | 🔵 Passing |
* | --- | --- | --- |
* | 3 | 4 | 120 |
*/
function shortDescription({ failedItemsCount, newItemsCount, deletedItemsCount, passedItemsCount }: CommentSeed) {
const descriptions = [
tableItem(failedItemsCount, ":red_circle: Changed"),
tableItem(newItemsCount, ":white_circle: New"),
tableItem(deletedItemsCount, ":black_circle: Deleted"),
tableItem(passedItemsCount, ":large_blue_circle: Passing"),
];

const filteredDescriptions = descriptions.filter((item): item is [number, string] => item != null);

const headerColumns = filteredDescriptions.map(([_, header]) => header);
const headerDelimiter = filteredDescriptions.map(() => " --- ");
const itemCount = filteredDescriptions.map(([itemCount]) => itemCount);

return [
`| ${headerColumns.join(" | ")} |`,
`| ${headerDelimiter.join(" | ")} |`,
`| ${itemCount.join(" | ")} |`,
].join("\n");
}

function longDescription(eventBody: CommentSeed) {
const lines = [];
lines.push(new Array(eventBody.failedItemsCount + 1).join(":red_circle: "));
lines.push(new Array(eventBody.newItemsCount + 1).join(":white_circle: "));
lines.push(new Array(eventBody.deletedItemsCount + 1).join(":black_circle: "));
lines.push(new Array(eventBody.passedItemsCount + 1).join(":large_blue_circle: "));
lines.push("");
lines.push(`<details>
<summary>What do the circles mean?</summary>
The number of circles represent the number of changed images. <br />
:red_circle: : Changed items,
:white_circle: : New items,
:black_circle: : Deleted items, and
:large_blue_circle: : Passed items
<br />
</details><br />`);
return lines.join("\n");
}

// NOTE: The following function is copied from /packages/reg-gh-app/src/pr-comment-fns.ts
Expand All @@ -23,20 +76,13 @@ export function createCommentBody(eventBody: CommentSeed) {
lines.push(`Check [this report](${eventBody.reportUrl}), and review them.`);
lines.push("");
}
lines.push(new Array(eventBody.failedItemsCount + 1).join(":red_circle: "));
lines.push(new Array(eventBody.newItemsCount + 1).join(":white_circle: "));
lines.push(new Array(eventBody.deletedItemsCount + 1).join(":black_circle: "));
lines.push(new Array(eventBody.passedItemsCount + 1).join(":large_blue_circle: "));
lines.push("");
lines.push(`<details>
<summary>What balls mean?</summary>
The number of balls represents the number of images change detected. <br />
:red_circle: : Changed items,
:white_circle: : New items,
:black_circle: : Deleted items, and
:large_blue_circle: Passed items
<br />
</details><br />`);

if (eventBody.shortDescription === true) {
lines.push(shortDescription(eventBody));
} else {
lines.push(longDescription(eventBody));
}

// lines.push(`<details>
// <summary>How can I change the check status?</summary>
// If reviewers accepts this differences, the reg context status will be green automatically.
Expand Down
25 changes: 25 additions & 0 deletions packages/reg-notify-gitlab-plugin/src/gitlab-api-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ export class DefaultGitLabApiClient implements GitLabApiClient {
"Private-Token": this._token,
},
});
if (400 <= res.status) {
throw new Error(`HTTP ${res.status}: Failed to request.`);
}

return res.json() as any as Promise<MergeRequestResource[]>;
}
Expand All @@ -92,9 +95,13 @@ export class DefaultGitLabApiClient implements GitLabApiClient {
method: "PUT",
headers: {
"Private-Token": this._token,
"Content-Type": "application/json",
},
body: JSON.stringify(params),
});
if (400 <= res.status) {
throw new Error(`HTTP ${res.status}: Failed to request.`);
}

return res.json() as any as Promise<MergeRequestResource>;
}
Expand All @@ -108,6 +115,9 @@ export class DefaultGitLabApiClient implements GitLabApiClient {
},
},
);
if (400 <= res.status) {
throw new Error(`HTTP ${res.status}: Failed to request.`);
}
return res.json() as any as Promise<CommitResource[]>;
}

Expand All @@ -120,6 +130,9 @@ export class DefaultGitLabApiClient implements GitLabApiClient {
},
},
);
if (400 <= res.status) {
throw new Error(`HTTP ${res.status}: Failed to request.`);
}

return res.json() as any as Promise<NoteResouce[]>;
}
Expand All @@ -131,12 +144,16 @@ export class DefaultGitLabApiClient implements GitLabApiClient {
method: "POST",
headers: {
"Private-Token": this._token,
"Content-Type": "application/json",
},
body: JSON.stringify({
body: params.body,
}),
},
);
if (400 <= res.status) {
throw new Error(`HTTP ${res.status}: Failed to request.`);
}

return res.json() as any as Promise<NoteResouce>;
}
Expand All @@ -148,12 +165,16 @@ export class DefaultGitLabApiClient implements GitLabApiClient {
method: "PUT",
headers: {
"Private-Token": this._token,
"Content-Type": "application/json",
},
body: JSON.stringify({
body: params.body,
}),
},
);
if (400 <= res.status) {
throw new Error(`HTTP ${res.status}: Failed to request.`);
}

return res.json() as any as Promise<NoteResouce>;
}
Expand All @@ -165,12 +186,16 @@ export class DefaultGitLabApiClient implements GitLabApiClient {
method: "POST",
headers: {
"Private-Token": this._token,
"Content-Type": "application/json",
},
body: JSON.stringify({
body: params.body,
}),
},
);
if (400 <= res.status) {
throw new Error(`HTTP ${res.status}: Failed to request.`);
}

return res.json() as any as Promise<DiscussionResource>;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export interface GitLabPluginOption {
projectId?: string;
privateToken: string;
commentTo?: "note" | "description" | "discussion";
shortDescription?: boolean;
}

export class GitLabNotifierPlugin implements NotifierPlugin<GitLabPluginOption> {
Expand All @@ -19,12 +20,14 @@ export class GitLabNotifierPlugin implements NotifierPlugin<GitLabPluginOption>
private _projectId!: string | undefined;
private _token!: string | undefined;
private _commentTo: "note" | "description" | "discussion" = "note";
private _shortDescription?: boolean;

init(config: PluginCreateOptions<GitLabPluginOption>) {
this._noEmit = config.noEmit;
this._logger = config.logger;
this._token = config.options.privateToken;
this._commentTo = config.options.commentTo || "note";
this._shortDescription = config.options.shortDescription;

const ciProjectUrl = process.env["CI_PROJECT_URL"];
if (ciProjectUrl && !config.options.gitlabUrl) {
Expand Down Expand Up @@ -62,6 +65,7 @@ export class GitLabNotifierPlugin implements NotifierPlugin<GitLabPluginOption>
client,
notifyParams: params,
projectId: this._projectId,
shortDescription: this._shortDescription,
});
} else if (this._commentTo === "discussion") {
await addDiscussionToMergeRequests({
Expand All @@ -70,6 +74,7 @@ export class GitLabNotifierPlugin implements NotifierPlugin<GitLabPluginOption>
client,
notifyParams: params,
projectId: this._projectId,
shortDescription: this._shortDescription,
});
} else {
await commentToMergeRequests({
Expand All @@ -78,6 +83,7 @@ export class GitLabNotifierPlugin implements NotifierPlugin<GitLabPluginOption>
client,
notifyParams: params,
projectId: this._projectId,
shortDescription: this._shortDescription,
});
}
}
Expand Down
45 changes: 35 additions & 10 deletions packages/reg-notify-gitlab-plugin/src/use-cases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ export type Context = {
logger: PluginLogger;
notifyParams: NotifyParams;
projectId: string;
shortDescription?: boolean;
};

export const COMMENT_MARK = "<!-- reg-notify-gitlab-plugin posted -->";
export const DESC_BODY_START_MARK = COMMENT_MARK;
export const DESC_BODY_END_MARK = "<!-- reg-notify-gitlab-plugin posted end -->";

function createNoteBody(params: NotifyParams) {
function createNoteBody(params: NotifyParams, shortDescription?: boolean) {
return (
COMMENT_MARK +
"\n" +
Expand All @@ -24,11 +25,12 @@ function createNoteBody(params: NotifyParams) {
deletedItemsCount: params.comparisonResult.deletedItems.length,
passedItemsCount: params.comparisonResult.passedItems.length,
reportUrl: params.reportUrl,
shortDescription,
})
);
}

function modifyDescription(description: string, params: NotifyParams) {
function modifyDescription(description: string, params: NotifyParams, shortDescription?: boolean) {
if (description.indexOf(DESC_BODY_START_MARK) === -1) {
return (
description +
Expand All @@ -41,6 +43,7 @@ function modifyDescription(description: string, params: NotifyParams) {
deletedItemsCount: params.comparisonResult.deletedItems.length,
passedItemsCount: params.comparisonResult.passedItems.length,
reportUrl: params.reportUrl,
shortDescription,
}) +
"\n" +
DESC_BODY_END_MARK
Expand All @@ -59,6 +62,7 @@ function modifyDescription(description: string, params: NotifyParams) {
deletedItemsCount: params.comparisonResult.deletedItems.length,
passedItemsCount: params.comparisonResult.passedItems.length,
reportUrl: params.reportUrl,
shortDescription,
}) +
"\n" +
DESC_BODY_END_MARK +
Expand All @@ -67,7 +71,14 @@ function modifyDescription(description: string, params: NotifyParams) {
);
}

export async function commentToMergeRequests({ noEmit, logger, client, notifyParams, projectId }: Context) {
export async function commentToMergeRequests({
noEmit,
logger,
client,
notifyParams,
projectId,
shortDescription,
}: Context) {
try {
const mrList = await client.getMergeRequests({ project_id: +projectId });
if (!mrList.length) {
Expand Down Expand Up @@ -104,7 +115,7 @@ export async function commentToMergeRequests({ noEmit, logger, client, notifyPar
await client.postMergeRequestNote({
project_id: +projectId,
merge_request_iid: mr.iid,
body: createNoteBody(notifyParams),
body: createNoteBody(notifyParams, shortDescription),
});
}
} else {
Expand All @@ -113,7 +124,7 @@ export async function commentToMergeRequests({ noEmit, logger, client, notifyPar
project_id: +projectId,
merge_request_iid: mr.iid,
note_id: commentedNote.id,
body: createNoteBody(notifyParams),
body: createNoteBody(notifyParams, shortDescription),
});
}
}
Expand All @@ -129,7 +140,14 @@ export async function commentToMergeRequests({ noEmit, logger, client, notifyPar
}
}

export async function addDiscussionToMergeRequests({ noEmit, logger, client, notifyParams, projectId }: Context) {
export async function addDiscussionToMergeRequests({
noEmit,
logger,
client,
notifyParams,
projectId,
shortDescription,
}: Context) {
try {
const mrList = await client.getMergeRequests({ project_id: +projectId });
if (!mrList.length) {
Expand Down Expand Up @@ -166,7 +184,7 @@ export async function addDiscussionToMergeRequests({ noEmit, logger, client, not
await client.postMergeRequestDiscussion({
project_id: +projectId,
merge_request_iid: mr.iid,
body: createNoteBody(notifyParams),
body: createNoteBody(notifyParams, shortDescription),
});
}
} else {
Expand All @@ -175,7 +193,7 @@ export async function addDiscussionToMergeRequests({ noEmit, logger, client, not
project_id: +projectId,
merge_request_iid: mr.iid,
note_id: commentedNote.id,
body: createNoteBody(notifyParams),
body: createNoteBody(notifyParams, shortDescription),
});
}
}
Expand All @@ -191,7 +209,14 @@ export async function addDiscussionToMergeRequests({ noEmit, logger, client, not
}
}

export async function appendOrUpdateMergerequestsBody({ noEmit, logger, client, notifyParams, projectId }: Context) {
export async function appendOrUpdateMergerequestsBody({
noEmit,
logger,
client,
notifyParams,
projectId,
shortDescription,
}: Context) {
try {
const mrList = await client.getMergeRequests({ project_id: +projectId });
if (!mrList.length) {
Expand All @@ -218,7 +243,7 @@ export async function appendOrUpdateMergerequestsBody({ noEmit, logger, client,

await Promise.all(
targetMrs.map(async ({ mr }) => {
const newDescription = modifyDescription(mr.description, notifyParams);
const newDescription = modifyDescription(mr.description, notifyParams, shortDescription);
const spinner = logger.getSpinner("commenting merge request" + logger.colors.magenta(mr.web_url));
spinner.start();
try {
Expand Down

0 comments on commit 7c0eaa4

Please sign in to comment.