Skip to content

Commit 90d0082

Browse files
committed
Use discussions instad of notes
1 parent 126dd9f commit 90d0082

File tree

2 files changed

+180
-18
lines changed

2 files changed

+180
-18
lines changed

src/githubHelper.ts

Lines changed: 158 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import * as utils from './utils';
44
import { Octokit as GitHubApi, RestEndpointMethodTypes } from '@octokit/rest';
55
import { Endpoints } from '@octokit/types';
66
import {
7+
GitLabDiscussion,
8+
GitLabDiscussionNote,
79
GitlabHelper,
810
GitLabIssue,
911
GitLabMergeRequest,
@@ -555,6 +557,85 @@ export class GithubHelper {
555557
);
556558
return comments;
557559
}
560+
561+
/**
562+
*
563+
* @param discussions
564+
* @returns Comments ready for requestImportIssue()
565+
*/
566+
async processDiscussionsIntoComments(
567+
discussions: GitLabDiscussion[]
568+
): Promise<CommentImport[]> {
569+
if (!discussions || !discussions.length) {
570+
console.log(`\t...no comments available, nothing to migrate.`);
571+
return [];
572+
}
573+
574+
let comments: CommentImport[] = [];
575+
576+
// sort notes in ascending order of when they were created (by id)
577+
discussions = discussions.sort((a, b) => Number.parseInt(a.id) - Number.parseInt(b.id));
578+
579+
let nrOfMigratedNotes = 0;
580+
let nrOfSkippedNotes = 0;
581+
for (let discussion of discussions) {
582+
let discussionComments = [];
583+
584+
for (let note of discussion.notes) {
585+
if (this.checkIfNoteCanBeSkipped(note.body)) {
586+
nrOfSkippedNotes++;
587+
continue;
588+
}
589+
590+
let username = note.author.username as string;
591+
this.users.add(username);
592+
let userIsPoster =
593+
(settings.usermap &&
594+
settings.usermap[username] ===
595+
settings.github.token_owner) ||
596+
username === settings.github.token_owner;
597+
598+
// only add line ref for first note of discussion
599+
const add_line_ref = discussion.notes.indexOf(note) === 0;
600+
601+
discussionComments.push({
602+
created_at: note.created_at,
603+
body: await this.convertIssuesAndComments(
604+
note.body,
605+
note,
606+
!userIsPoster || !note.body,
607+
add_line_ref,
608+
),
609+
});
610+
611+
nrOfMigratedNotes++;
612+
}
613+
614+
// Combine notes for discussion into one comment
615+
if (discussionComments.length == 1) {
616+
comments.push(discussionComments[0]);
617+
}
618+
else if (discussionComments.length > 1) {
619+
let combinedBody = '**Discussion in GitLab:**\n\n';
620+
let first_created_at = discussionComments[0].created_at;
621+
622+
combinedBody += discussionComments.map(comment => comment.body).join('\n\n');
623+
624+
comments.push({
625+
created_at: first_created_at,
626+
body: combinedBody,
627+
});
628+
}
629+
}
630+
631+
console.log(
632+
`\t...Done creating discussion comments (migrated ${nrOfMigratedNotes} comments, skipped ${
633+
nrOfSkippedNotes
634+
} comments)`
635+
);
636+
return comments;
637+
}
638+
558639
/**
559640
* Calls the preview API for issue importing
560641
*
@@ -685,7 +766,7 @@ export class GithubHelper {
685766
* Return false when it got skipped, otherwise true.
686767
*/
687768
async processNote(
688-
note: GitLabNote,
769+
note: GitLabNote | GitLabDiscussionNote,
689770
githubIssue: Pick<GitHubIssue | GitHubPullRequest, 'number'>
690771
) {
691772
if (this.checkIfNoteCanBeSkipped(note.body)) return false;
@@ -960,10 +1041,10 @@ export class GithubHelper {
9601041
'\t...this is a placeholder for a deleted GitLab merge request, no comments are created.'
9611042
);
9621043
} else {
963-
let notes = await this.gitlabHelper.getAllMergeRequestNotes(
1044+
let discussions = await this.gitlabHelper.getAllMergeRequestDiscussions(
9641045
mergeRequest.iid
9651046
);
966-
comments = await this.processNotesIntoComments(notes);
1047+
comments = await this.processDiscussionsIntoComments(discussions);
9671048
}
9681049

9691050
return this.requestImportIssue(props, comments);
@@ -1004,30 +1085,72 @@ export class GithubHelper {
10041085
return Promise.resolve();
10051086
}
10061087

1007-
let notes = await this.gitlabHelper.getAllMergeRequestNotes(
1088+
let discussions = await this.gitlabHelper.getAllMergeRequestDiscussions(
10081089
mergeRequest.iid
10091090
);
10101091

10111092
// if there are no notes, then there is nothing to do!
1012-
if (notes.length === 0) {
1093+
if (discussions.length === 0) {
10131094
console.log(
10141095
`\t...no pull request comments available, nothing to migrate.`
10151096
);
10161097
return;
10171098
}
10181099

10191100
// Sort notes in ascending order of when they were created (by id)
1020-
notes = notes.sort((a, b) => a.id - b.id);
1101+
discussions = discussions.sort((a, b) => a.notes[0].id - b.notes[0].id);
10211102

10221103
let nrOfMigratedNotes = 0;
1023-
for (let note of notes) {
1024-
const gotMigrated = await this.processNote(note, pullRequest);
1025-
if (gotMigrated) nrOfMigratedNotes++;
1104+
let nrOfSkippedNotes = 0;
1105+
for (let discussion of discussions) {
1106+
if (discussion.individual_note) {
1107+
const gotMigrated = await this.processNote(discussion.notes[0], pullRequest);
1108+
if (gotMigrated) {
1109+
nrOfMigratedNotes++;
1110+
}
1111+
else {
1112+
nrOfSkippedNotes++;
1113+
}
1114+
}
1115+
else {
1116+
// console.log('Processing discussion:');
1117+
let discussionBody = '**Discussion in GitLab:**\n\n';
1118+
1119+
for (let note of discussion.notes) {
1120+
if (this.checkIfNoteCanBeSkipped(note.body)) {
1121+
nrOfSkippedNotes++;
1122+
continue;
1123+
}
1124+
1125+
const add_line_ref = discussion.notes.indexOf(note) === 0;
1126+
let bodyConverted = await this.convertIssuesAndComments(note.body, note, true, add_line_ref);
1127+
discussionBody += bodyConverted;
1128+
discussionBody += '\n\n';
1129+
nrOfMigratedNotes++;
1130+
}
1131+
1132+
await utils.sleep(this.delayInMs);
1133+
1134+
if (!settings.dryRun) {
1135+
await this.githubApi.issues
1136+
.createComment({
1137+
owner: this.githubOwner,
1138+
repo: this.githubRepo,
1139+
issue_number: pullRequest.number,
1140+
body: discussionBody,
1141+
})
1142+
.catch(x => {
1143+
console.error('could not create GitHub issue comment!');
1144+
console.error(x);
1145+
process.exit(1);
1146+
});
1147+
}
1148+
}
10261149
}
10271150

10281151
console.log(
10291152
`\t...Done creating pull request comments (migrated ${nrOfMigratedNotes} pull request comments, skipped ${
1030-
notes.length - nrOfMigratedNotes
1153+
nrOfSkippedNotes
10311154
} pull request comments)`
10321155
);
10331156
}
@@ -1153,8 +1276,9 @@ export class GithubHelper {
11531276
*/
11541277
async convertIssuesAndComments(
11551278
str: string,
1156-
item: GitLabIssue | GitLabMergeRequest | GitLabNote | MilestoneImport,
1157-
add_line: boolean = true
1279+
item: GitLabIssue | GitLabMergeRequest | GitLabNote | MilestoneImport | GitLabDiscussionNote,
1280+
add_line: boolean = true,
1281+
add_line_ref: boolean = true,
11581282
): Promise<string> {
11591283
// A note on implementation:
11601284
// We don't convert project names once at the beginning because otherwise
@@ -1170,7 +1294,7 @@ export class GithubHelper {
11701294
settings.projectmap !== null &&
11711295
Object.keys(settings.projectmap).length > 0;
11721296

1173-
if (add_line) str = GithubHelper.addMigrationLine(str, item, repoLink);
1297+
if (add_line) str = GithubHelper.addMigrationLine(str, item, repoLink, add_line_ref);
11741298
let reString = '';
11751299

11761300
// Store usernames found in the text
@@ -1342,7 +1466,7 @@ export class GithubHelper {
13421466
* Adds a line of text at the beginning of a comment that indicates who, when
13431467
* and from GitLab.
13441468
*/
1345-
static addMigrationLine(str: string, item: any, repoLink: string): string {
1469+
static addMigrationLine(str: string, item: any, repoLink: string, add_line_ref: boolean = true): string {
13461470
if (!item || !item.author || !item.author.username || !item.created_at) {
13471471
return str;
13481472
}
@@ -1362,11 +1486,12 @@ export class GithubHelper {
13621486
dateformatOptions
13631487
);
13641488

1365-
const attribution = `In GitLab by @${item.author.username} on ${formattedDate}`;
1489+
const attribution = `***In GitLab by @${item.author.username} on ${formattedDate}:***`;
13661490
const lineRef =
1367-
item && item.position
1491+
item && item.position && add_line_ref
13681492
? GithubHelper.createLineRef(item.position, repoLink)
13691493
: '';
1494+
13701495
const summary = attribution + (lineRef ? `\n\n${lineRef}` : '');
13711496

13721497
return `${summary}\n\n${str}`;
@@ -1386,7 +1511,7 @@ export class GithubHelper {
13861511
return '';
13871512
}
13881513
const base_sha = position.base_sha;
1389-
const head_sha = position.head_sha;
1514+
let head_sha = position.head_sha;
13901515
var path = '';
13911516
var line = '';
13921517
var slug = '';
@@ -1410,7 +1535,22 @@ export class GithubHelper {
14101535
}
14111536
// Mention the file and line number. If we can't get this for some reason then use the commit id instead.
14121537
const ref = path && line ? `${path} line ${line}` : `${head_sha}`;
1413-
return `Commented on [${ref}](${repoLink}/compare/${base_sha}..${head_sha}${slug})\n\n`;
1538+
let lineRef = `Commented on [${ref}](${repoLink}/compare/${base_sha}..${head_sha}${slug})\n\n`;
1539+
1540+
if (position.line_range.start.type === 'new') {
1541+
const startLine = position.line_range.start.new_line;
1542+
const endLine = position.line_range.end.new_line;
1543+
const lineRange = (startLine !== endLine) ? `L${startLine}-L${endLine}` : `L${startLine}`;
1544+
lineRef += `${repoLink}/blob/${head_sha}/${path}#${lineRange}\n\n`;
1545+
}
1546+
else {
1547+
const startLine = position.line_range.start.old_line;
1548+
const endLine = position.line_range.end.old_line;
1549+
const lineRange = (startLine !== endLine) ? `L${startLine}-L${endLine}` : `L${startLine}`;
1550+
lineRef += `${repoLink}/blob/${head_sha}/${path}#${lineRange}\n\n`;
1551+
}
1552+
1553+
return lineRef;
14141554
}
14151555

14161556
/**

src/gitlabHelper.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { Gitlab } from '@gitbeaker/node';
22
import {
3+
DiscussionNote,
4+
DiscussionSchema,
35
IssueSchema,
46
MergeRequestSchema,
57
MilestoneSchema,
@@ -9,6 +11,8 @@ import {
911
import { GitlabSettings } from './settings';
1012
import axios from 'axios';
1113

14+
export type GitLabDiscussion = DiscussionSchema;
15+
export type GitLabDiscussionNote = DiscussionNote;
1216
export type GitLabIssue = IssueSchema;
1317
export type GitLabNote = NoteSchema;
1418
export type GitLabUser = Omit<UserSchema, 'created_at'>;
@@ -163,4 +167,22 @@ export class GitlabHelper {
163167
return [];
164168
}
165169
}
170+
171+
/**
172+
* Gets all notes for a given merge request.
173+
*/
174+
async getAllMergeRequestDiscussions(pullRequestIid: number): Promise<GitLabDiscussion[]> {
175+
try {
176+
return this.gitlabApi.MergeRequestDiscussions.all(
177+
this.gitlabProjectId,
178+
pullRequestIid,
179+
{}
180+
);
181+
} catch (err) {
182+
console.error(
183+
`Could not fetch notes for GitLab merge request #${pullRequestIid}.`
184+
);
185+
return [];
186+
}
187+
}
166188
}

0 commit comments

Comments
 (0)