Skip to content
This repository was archived by the owner on Mar 13, 2025. It is now read-only.

Commit b8f97cc

Browse files
committed
Updates for dashboard
1 parent 8d36255 commit b8f97cc

File tree

4 files changed

+118
-23
lines changed

4 files changed

+118
-23
lines changed

models/Issue.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,24 @@ const schema = new mongoose.Schema({
1818
prizes: [{type: Number, required: true}], // extracted from title
1919
provider: {type: String, required: true}, // github or gitlab
2020
repositoryId: {type: Number, required: true},
21-
21+
labels: [{type: String, required: true}],
22+
assignee: {type: String, required: false},
23+
updatedAt: {
24+
type: Date,
25+
default: Date.now
26+
},
2227
// From topcoder api
23-
challengeId: {type: Number, required: true, unique: true}
28+
challengeId: {type: Number, required: true, unique: true},
29+
projectId: {type: mongoose.Schema.Types.ObjectId, ref: 'Project'}
2430
});
2531

2632
// Issue number, provider, repositoryId must be unique
2733
schema.index({number: 1, provider: 1, repositoryId: 1}, {unique: true});
34+
schema.index({labels: 1});
35+
schema.index({projectId: 1});
2836

29-
37+
schema.pre('save', function preSave(next) {
38+
this.updatedAt = Date.now(); // eslint-disable-line
39+
return next();
40+
});
3041
module.exports = schema;

services/IssueService.js

Lines changed: 100 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ function parsePrizes(issue) {
5050
}
5151

5252
issue.prizes = _.map(matches, (match) => parseInt(match.replace('$', ''), 10));
53-
issue.title = issue.title.replace(/^(\[.*\])/, '');
53+
issue.title = issue.title.replace(/^(\[.*\])/, '').trim();
5454
}
5555

5656
/**
@@ -107,15 +107,25 @@ async function handleEventGracefully(event, issue, err) {
107107
* @returns {Object} the found db issue if exists
108108
* @private
109109
*/
110-
async function ensureChallengeExists(issue) {
111-
const dbIssue = await Issue.findOne({
110+
async function ensureChallengeExists(event, issue) {
111+
let dbIssue = await Issue.findOne({
112112
number: issue.number,
113113
provider: issue.provider,
114114
repositoryId: issue.repositoryId
115115
});
116-
117116
if (!dbIssue) {
118-
throw errors.internalDependencyError(`there is no challenge for the updated issue ${issue.number}`);
117+
// create if only in next retry of event
118+
// else there can be conflict when issue being created
119+
if (event.retryCount && _.toInteger(event.retryCount) > 1) {
120+
await handleIssueCreate(event, issue);
121+
dbIssue = await Issue.findOne({
122+
number: issue.number,
123+
provider: issue.provider,
124+
repositoryId: issue.repositoryId
125+
});
126+
} else {
127+
throw errors.internalDependencyError(`there is no challenge for the updated issue ${issue.number}`);
128+
}
119129
}
120130
return dbIssue;
121131
}
@@ -255,13 +265,17 @@ async function handleIssueAssignment(event, issue) {
255265
if (userMapping && userMapping.topcoderUsername) {
256266
let dbIssue;
257267
try {
258-
dbIssue = await ensureChallengeExists(issue);
268+
dbIssue = await ensureChallengeExists(event, issue);
259269

260270
logger.debug(`Getting the topcoder member ID for member name: ${userMapping.topcoderUsername}`);
261271
const topcoderUserId = await topcoderApiHelper.getTopcoderMemberId(userMapping.topcoderUsername);
262272
// Update the challenge
263273
logger.debug(`Assigning user to challenge: ${userMapping.topcoderUsername}`);
264274
assignUserAsRegistrant(topcoderUserId, dbIssue.challengeId);
275+
dbIssue.set({
276+
assignee: issue.assignee
277+
});
278+
await dbIssue.save();
265279
} catch (err) {
266280
handleEventGracefully(event, issue, err);
267281
return;
@@ -323,7 +337,7 @@ async function handleIssueComment(event, issue) {
323337
async function handleIssueUpdate(event, issue) {
324338
let dbIssue;
325339
try {
326-
dbIssue = await ensureChallengeExists(issue);
340+
dbIssue = await ensureChallengeExists(event, issue);
327341

328342
if (_.isMatch(dbIssue, issue)) {
329343
// Title, body, prizes doesn't change, just ignore
@@ -337,17 +351,19 @@ async function handleIssueUpdate(event, issue) {
337351
detailedRequirements: issue.body,
338352
prizes: issue.prizes
339353
});
354+
// Save
355+
dbIssue.set({
356+
title: issue.title,
357+
body: issue.body,
358+
prizes: issue.prizes,
359+
labels: issue.labels,
360+
assignee: issue.assignee
361+
});
362+
await dbIssue.save();
340363
} catch (e) {
341364
await handleEventGracefully(event, issue, e);
342365
return;
343366
}
344-
// Save
345-
dbIssue.set({
346-
title: issue.title,
347-
body: issue.body,
348-
prizes: issue.prizes
349-
});
350-
await dbIssue.save();
351367
// comment on the git ticket for the user to self-sign up with the Topcoder x Self-Service tool
352368
const contestUrl = getUrlForChallengeId(dbIssue.challengeId);
353369
const comment = `Contest ${contestUrl} has been updated - the new changes has been updated for this ticket.`;
@@ -370,7 +386,7 @@ async function handleIssueUpdate(event, issue) {
370386
async function handleIssueClose(event, issue) {
371387
let dbIssue;
372388
try {
373-
dbIssue = await ensureChallengeExists(issue);
389+
dbIssue = await ensureChallengeExists(event, issue);
374390
if (!event.paymentSuccessful) {
375391
// if issue is closed without assignee then do nothing
376392
if (!event.data.assignee.id) {
@@ -519,6 +535,45 @@ async function handleIssueCreate(event, issue) {
519535
logger.debug(`new challenge created with id ${issue.challengeId} for issue ${issue.number}`);
520536
}
521537

538+
/**
539+
* handles the issue label updated event
540+
* @param {Object} event the event
541+
* @param {Object} issue the issue
542+
* @private
543+
*/
544+
async function handleIssueLabelUpdated(event, issue) {
545+
let dbIssue;
546+
try {
547+
dbIssue = await ensureChallengeExists(event, issue);
548+
} catch (e) {
549+
await handleEventGracefully(event, issue, e);
550+
return;
551+
}
552+
dbIssue.set({
553+
labels: issue.labels
554+
});
555+
await dbIssue.save();
556+
}
557+
558+
/**
559+
* handles the issue un assignment event
560+
* @param {Object} event the event
561+
* @param {Object} issue the issue
562+
* @private
563+
*/
564+
async function handleIssueUnAssignment(event, issue) {
565+
let dbIssue;
566+
try {
567+
dbIssue = await ensureChallengeExists(event, issue);
568+
} catch (e) {
569+
await handleEventGracefully(event, issue, e);
570+
return;
571+
}
572+
dbIssue.set({
573+
assignee: null
574+
});
575+
await dbIssue.save();
576+
}
522577

523578
/**
524579
* Process issue event.
@@ -532,8 +587,21 @@ async function process(event) {
532587
title: event.data.issue.title,
533588
body: event.data.issue.body,
534589
provider: event.provider,
535-
repositoryId: event.data.repository.id
590+
repositoryId: event.data.repository.id,
591+
labels: event.data.issue.labels
536592
};
593+
let fullRepoUrl;
594+
if (event.provider === 'github') {
595+
fullRepoUrl = `https://github.com/${event.data.repository.full_name}`;
596+
} else if (event.provider === 'gitlab') {
597+
fullRepoUrl = `${config.GITLAB_API_BASE_URL}/${event.data.repository.full_name}`;
598+
}
599+
600+
const project = await models.Project.findOne({
601+
repoUrl: fullRepoUrl
602+
});
603+
604+
issue.projectId = project.id;
537605

538606
// Parse prize from title
539607
parsePrizes(issue);
@@ -543,6 +611,14 @@ async function process(event) {
543611
// Markdown the body
544612
issue.body = md.render(_.get(issue, 'body', ''));
545613

614+
if (event.data.issue.assignees && event.data.issue.assignees.length > 0 && event.data.issue.assignees[0].id) {
615+
if (event.provider === 'github') {
616+
issue.assignee = await gitHubService.getUsernameById(copilot, event.data.issue.assignees[0].id);
617+
} else if (event.provider === 'gitlab') {
618+
issue.assignee = await gitlabService.getUsernameById(copilot, event.data.issue.assignees[0].id);
619+
}
620+
}
621+
console.warn(JSON.stringify(issue));
546622
if (event.event === 'issue.created') {
547623
await handleIssueCreate(event, issue);
548624
} else if (event.event === 'issue.updated') {
@@ -553,11 +629,16 @@ async function process(event) {
553629
await handleIssueComment(event, issue);
554630
} else if (event.event === 'issue.assigned') {
555631
await handleIssueAssignment(event, issue);
632+
} else if (event.event === 'issue.labelUpdated') {
633+
await handleIssueLabelUpdated(event, issue);
634+
} else if (event.event === 'issue.unassigned') {
635+
await handleIssueUnAssignment(event, issue);
556636
}
557637
}
558638

559639
process.schema = Joi.object().keys({
560-
event: Joi.string().valid('issue.created', 'issue.updated', 'issue.closed', 'comment.created', 'comment.updated', 'issue.assigned').required(),
640+
event: Joi.string().valid('issue.created', 'issue.updated', 'issue.closed', 'comment.created', 'comment.updated', 'issue.assigned',
641+
'issue.labelUpdated', 'issue.unassigned').required(),
561642
provider: Joi.string().valid('github', 'gitlab').required(),
562643
data: Joi.object().keys({
563644
issue: Joi.object().keys({
@@ -586,7 +667,8 @@ process.schema = Joi.object().keys({
586667
}),
587668
assignee: Joi.object().keys({
588669
id: Joi.number().required().allow(null)
589-
})
670+
}),
671+
labels: Joi.array().items(Joi.string())
590672
}).required(),
591673
retryCount: Joi.number().integer().default(0).optional(),
592674
paymentSuccessful: Joi.boolean().default(false).optional()

utils/kafka.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ class Kafka {
4343
return;
4444
}
4545

46-
if (event && _.includes(['issue.created', 'issue.updated', 'issue.closed', 'comment.created', 'comment.updated', 'issue.assigned'], event.event)) {
46+
if (event && _.includes(['issue.created', 'issue.updated', 'issue.closed',
47+
'comment.created', 'comment.updated', 'issue.assigned', 'issue.labelUpdated', 'issue.unassigned']
48+
, event.event)) {
4749
IssueService
4850
.process(event)
4951
.catch(logger.error);

utils/topcoder-api-helper.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ async function getProjectBillingAccountId(id) {
248248
});
249249
const billingAccountId = _.get(response, 'data.result.content.billingAccountIds[0]');
250250
if (!billingAccountId) {
251-
_.set(response, 'data.result.content', `There is no billing account id associated with project ${id}`)
251+
_.set(response, 'data.result.content', `There is no billing account id associated with project ${id}`);
252252
throw new Error(response);
253253
}
254254
return billingAccountId;

0 commit comments

Comments
 (0)