Skip to content

DOP-3604: post comment to github PR on successful build completion #828

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

Draft
wants to merge 20 commits into
base: main
Choose a base branch
from
Draft
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
1 change: 1 addition & 0 deletions .github/workflows/deploy-stg-ecs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ on:
branches:
- "master"
- "integration"
- "DOP-3604"
concurrency:
group: environment-stg-${{ github.ref }}
cancel-in-progress: true
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.legacy
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Debian Bookworm removes Python 2, and Bullseye exits its support period in 2024.
# The solution is probably to switch to Ubuntu 22.04 at that point, which is supported until 2027.
FROM node:14-bullseye-slim
FROM node:18-bullseye-slim

ARG MUT_VERSION=0.10.3

Expand Down
1 change: 1 addition & 0 deletions api/controllers/v1/github.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ async function prepGithubPushPayload(githubEvent: any, branchRepository: BranchR
url: githubEvent.repository.clone_url,
newHead: githubEvent.after,
urlSlug: urlSlug,
organization: githubEvent.repository.organization,
prefix: prefix,
project: project,
},
Expand Down
87 changes: 67 additions & 20 deletions api/controllers/v1/jobs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { RepoEntitlementsRepository } from '../../../src/repositories/repoEntitl
import { BranchRepository } from '../../../src/repositories/branchRepository';
import { ConsoleLogger } from '../../../src/services/logger';
import { SlackConnector } from '../../../src/services/slack';
import { GithubConnector } from '../../../src/services/github';
import { JobRepository } from '../../../src/repositories/jobRepository';
import { JobQueueMessage } from '../../../src/entities/queueMessage';
import { Job, JobStatus } from '../../../src/entities/job';
Expand Down Expand Up @@ -134,36 +135,63 @@ async function stopECSTask(taskId: string, consoleLogger: ConsoleLogger) {
await ecs.stopZombieECSTask(taskId);
}

async function retry(message: JobQueueMessage, consoleLogger: ConsoleLogger, url: string): Promise<any> {
try {
const tries = message.tries;
// TODO: c.get('maxRetries') is of type 'Unknown', needs validation
if (tries < c.get('maxRetries')) {
const sqs = new SQSConnector(consoleLogger, c);
message['tries'] += 1;
let retryDelay = 10;
if (c.get('retryDelay')) {
retryDelay = c.get('retryDelay');
}
await sqs.sendMessage(message, url, retryDelay * tries);
}
} catch (err) {
consoleLogger.error(message['jobId'], err);
}
}
// async function retry(message: JobQueueMessage, consoleLogger: ConsoleLogger, url: string): Promise<any> {
// try {
// const tries = message.tries;
// // TODO: c.get('maxRetries') is of type 'Unknown', needs validation
// // ARM: I don't think we even do retries anymore
// if (tries < c.get('maxRetries')) {
// const sqs = new SQSConnector(consoleLogger, c);
// message['tries'] += 1;
// let retryDelay = 10;
// if (c.get('retryDelay')) {
// retryDelay = c.get('retryDelay');
// }
// await sqs.sendMessage(message, url, retryDelay * tries);
// }
// } catch (err) {
// consoleLogger.error(message['jobId'], err);
// }
// }
async function NotifyBuildSummary(jobId: string): Promise<any> {
const consoleLogger = new ConsoleLogger();
const client = new mongodb.MongoClient(c.get('dbUrl'));
await client.connect();
const db = client.db(c.get('dbName'));
const env = c.get<string>('env');
const githubToken = c.get<string>('githubSecret');

const jobRepository = new JobRepository(db, c, consoleLogger);
// TODO: Make fullDocument be of type Job, validate existence

const fullDocument = await jobRepository.getJobById(jobId);
if (!fullDocument) {
consoleLogger.error('Cannot find job entry in db', '');
return;
}
const repoName = fullDocument.payload.repoName;
const username = fullDocument.user;
const githubConnector = new GithubConnector(consoleLogger, c, githubToken);
const slackConnector = new SlackConnector(consoleLogger, c);

// Github comment
await githubConnector.getParentPRs(fullDocument.payload).then(function (results) {
for (const pr of results) {
githubConnector.getPullRequestCommentId(fullDocument.payload, pr).then(function (id) {
console.log(`The comment ID is: ${id}`);
if (id != undefined) {
prepGithubComment(fullDocument, c.get<string>('dashboardUrl'), true).then(function (ghmessage) {
githubConnector.updateComment(fullDocument.payload, id, ghmessage);
});
} else {
prepGithubComment(fullDocument, c.get<string>('dashboardUrl'), false).then(function (ghmessage) {
githubConnector.postComment(fullDocument.payload, pr, ghmessage);
});
}
});
}
});

// Slack notification
const repoEntitlementRepository = new RepoEntitlementsRepository(db, c, consoleLogger);
const entitlement = await repoEntitlementRepository.getSlackUserIdByGithubUsername(username);
if (!entitlement?.['slack_user_id']) {
Expand Down Expand Up @@ -192,6 +220,18 @@ export const extractUrlFromMessage = (fullDocument): string[] => {
return urls.map((url) => url.replace(/([^:]\/)\/+/g, '$1'));
};

async function prepGithubComment(fullDocument: Job, jobUrl: string, isUpdate = false): Promise<string> {
if (isUpdate) {
return `\n* job log: [${fullDocument.payload.newHead}|${jobUrl}]`;
}
const urls = extractUrlFromMessage(fullDocument);
let stagingUrl = '';
if (urls.length > 0) {
stagingUrl = urls[urls.length - 1];
}
return `✨ Staging URL: [${stagingUrl}|${stagingUrl}]\n\n#### 🪵 Logs\n\n* job log: [${fullDocument.payload.newHead}|${jobUrl}]`;
}

async function prepSummaryMessage(
env: string,
fullDocument: Job,
Expand All @@ -201,12 +241,11 @@ async function prepSummaryMessage(
failed = false
): Promise<string> {
const urls = extractUrlFromMessage(fullDocument);
let mms_urls = [null, null];
let mms_urls = ['', ''];
// mms-docs needs special handling as it builds two sites (cloudmanager & ops manager)
// so we need to extract both URLs
if (repoName === 'mms-docs') {
if (urls.length >= 2) {
// TODO: Type 'string[]' is not assignable to type 'null[]'.
mms_urls = urls.slice(-2);
}
}
Expand Down Expand Up @@ -266,6 +305,10 @@ async function NotifyBuildProgress(jobId: string): Promise<any> {
const jobRepository = new JobRepository(db, c, consoleLogger);
// TODO: Make fullDocument be of type Job, validate existence
const fullDocument = await jobRepository.getJobById(jobId);
if (!fullDocument) {
consoleLogger.error('Cannot find job in db.', '');
return;
}
const jobTitle = fullDocument.title;
const username = fullDocument.user;
const repoEntitlementRepository = new RepoEntitlementsRepository(db, c, consoleLogger);
Expand Down Expand Up @@ -317,6 +360,10 @@ async function SubmitArchiveJob(jobId: string) {
branches: new BranchRepository(db, c, consoleLogger),
};
const job = await models.jobs.getJobById(jobId);
if (!job) {
consoleLogger.error('Cannot find job in db', JSON.stringify({ jobId }));
return;
}
const repo = await models.branches.getRepo(job.payload.repoName);

/* NOTE
Expand Down
Loading