Skip to content

Commit

Permalink
Fix Build Reporting (#52)
Browse files Browse the repository at this point in the history
* Make discord a global instance to reduce the amount of connects called

* Fix formatting
  • Loading branch information
AndrewKahr authored Jun 6, 2024
1 parent 31e7fd4 commit e3d917f
Show file tree
Hide file tree
Showing 18 changed files with 131 additions and 155 deletions.
7 changes: 3 additions & 4 deletions functions/src/api/reportBuildFailure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ const internalToken = defineSecret('INTERNAL_TOKEN');
export const reportBuildFailure = onRequest(
{ secrets: [discordToken, internalToken] },
async (req: Request, res: Response) => {
const discordClient = new Discord();
await discordClient.init(discordToken.value());
await Discord.init(discordToken.value());

try {
if (!Token.isValid(req.header('authorization'), internalToken.value())) {
Expand All @@ -41,7 +40,7 @@ export const reportBuildFailure = onRequest(
`;
logger.error(message, err);

await discordClient.sendAlert(message);
await Discord.sendAlert(message);

if (req.body?.jobId?.toString().startsWith('dryRun')) {
await CiBuilds.removeDryRunBuild(req.body.buildId);
Expand All @@ -51,6 +50,6 @@ export const reportBuildFailure = onRequest(
res.status(500).send('Something went wrong');
}

await discordClient.disconnect();
Discord.disconnect();
},
);
7 changes: 4 additions & 3 deletions functions/src/api/reportNewBuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ const internalToken = defineSecret('INTERNAL_TOKEN');
export const reportNewBuild = onRequest(
{ secrets: [discordToken, internalToken] },
async (req: Request, res: Response) => {
const discordClient = new Discord();
await discordClient.init(discordToken.value());
await Discord.init(discordToken.value());

try {
if (!Token.isValid(req.header('authorization'), internalToken.value())) {
Expand Down Expand Up @@ -53,14 +52,16 @@ export const reportNewBuild = onRequest(
${err.message}
`;
logger.error(message, err);
await discordClient.sendAlert(message);
await Discord.sendAlert(message);

if (req.body?.jobId?.toString().startsWith('dryRun')) {
await CiBuilds.removeDryRunBuild(req.body.buildId);
await CiJobs.removeDryRunJob(req.body.jobId);
}

res.status(500).send('Something went wrong');

Discord.disconnect();
}
},
);
Expand Down
9 changes: 4 additions & 5 deletions functions/src/api/reportPublication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ const internalToken = defineSecret('INTERNAL_TOKEN');
export const reportPublication = onRequest(
{ secrets: [discordToken, internalToken] },
async (req: Request, res: Response) => {
const discordClient = new Discord();
await discordClient.init(discordToken.value());
await Discord.init(discordToken.value());

try {
if (!Token.isValid(req.header('authorization'), internalToken.value())) {
Expand Down Expand Up @@ -50,7 +49,7 @@ export const reportPublication = onRequest(
}
logger.info(message);
if (!isDryRun) {
await discordClient.sendNews(message);
await Discord.sendNews(message);
}
}

Expand All @@ -67,7 +66,7 @@ export const reportPublication = onRequest(
${err.message}
`;
logger.error(message, err);
await discordClient.sendAlert(message);
await Discord.sendAlert(message);

if (req.body?.jobId?.toString().startsWith('dryRun')) {
await CiBuilds.removeDryRunBuild(req.body.buildId);
Expand All @@ -77,6 +76,6 @@ export const reportPublication = onRequest(
res.status(500).send('Something went wrong');
}

await discordClient.disconnect();
await Discord.disconnect();
},
);
13 changes: 4 additions & 9 deletions functions/src/api/retryBuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ const githubClientSecret = defineSecret('GITHUB_CLIENT_SECRET');
export const retryBuild = onRequest(
{ secrets: [discordToken, githubClientSecret, githubPrivateKey] },
async (request: Request, response: Response) => {
const discordClient = new Discord();
await discordClient.init(discordToken.value());
await Discord.init(discordToken.value());

try {
response.set('Content-Type', 'application/json');
Expand Down Expand Up @@ -82,13 +81,7 @@ export const retryBuild = onRequest(
const gitHubClient = await GitHub.init(githubPrivateKey.value(), githubClientSecret.value());
const repoVersionInfo = await RepoVersionInfo.getLatest();
const scheduler = new Ingeminator(1, gitHubClient, repoVersionInfo);
const scheduledSuccessfully = await scheduler.rescheduleBuild(
jobId,
job,
buildId,
build,
discordClient,
);
const scheduledSuccessfully = await scheduler.rescheduleBuild(jobId, job, buildId, build);

// Report result
if (scheduledSuccessfully) {
Expand All @@ -108,5 +101,7 @@ export const retryBuild = onRequest(
console.log('error', JSON.stringify(error, Object.getOwnPropertyNames(error)));
response.status(401).send({ message: 'Unauthorized' });
}

Discord.disconnect();
},
);
5 changes: 2 additions & 3 deletions functions/src/api/testFunction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,11 @@ export const testFunction = onRequest(
},
async (request: Request, response: Response) => {
// Run all non-sensitive functions to verify that the deployment is working.
const discordClient = new Discord();
let info = 'Ok';
let code = 200;

try {
await discordClient.init(discordToken.value());
await Discord.init(discordToken.value());

const versions = await scrapeVersions(
githubPrivateKeyConfigSecret.value(),
Expand All @@ -53,7 +52,7 @@ export const testFunction = onRequest(
info = error.message;
code = 500;
} finally {
await discordClient.disconnect();
await Discord.disconnect();
}

response.status(code).send(info);
Expand Down
28 changes: 11 additions & 17 deletions functions/src/cron/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,10 @@ export const trigger = onSchedule(
secrets: [discordToken, githubPrivateKeyConfigSecret, githubClientSecretConfigSecret],
},
async () => {
const discordClient = new Discord();
await discordClient.init(discordToken.value());
await Discord.init(discordToken.value());

try {
await routineTasks(
discordClient,
githubPrivateKeyConfigSecret.value(),
githubClientSecretConfigSecret.value(),
);
Expand All @@ -43,29 +41,25 @@ export const trigger = onSchedule(
const routineTasksFailedMessage = `Something went wrong while running routine tasks.\n${fullError}`;

logger.error(routineTasksFailedMessage);
await discordClient.sendAlert(routineTasksFailedMessage);
await Discord.sendAlert(routineTasksFailedMessage);
}

await discordClient.disconnect();
Discord.disconnect();
},
);

const routineTasks = async (
discordClient: Discord,
githubPrivateKey: string,
githubClientSecret: string,
) => {
const routineTasks = async (githubPrivateKey: string, githubClientSecret: string) => {
try {
await discordClient.sendDebugLine('begin');
await Discord.sendDebugLine('begin');
await dataMigrations();
await ingestRepoVersions(discordClient, githubPrivateKey, githubClientSecret);
await ingestUnityVersions(discordClient);
await cleanUpBuilds(discordClient);
await scheduleBuildsFromTheQueue(discordClient, githubPrivateKey, githubClientSecret);
await ingestRepoVersions(githubPrivateKey, githubClientSecret);
await ingestUnityVersions();
await cleanUpBuilds();
await scheduleBuildsFromTheQueue(githubPrivateKey, githubClientSecret);
} catch (error: any) {
logger.error(error);
await discordClient.sendAlert(error);
await Discord.sendAlert(error);
} finally {
await discordClient.sendDebugLine('end');
await Discord.sendDebugLine('end');
}
};
5 changes: 2 additions & 3 deletions functions/src/logic/buildQueue/cleanUpBuilds.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Discord } from '../../service/discord';
import { Cleaner } from './cleaner';

export const cleanUpBuilds = async (discordClient: Discord) => {
await Cleaner.cleanUp(discordClient);
export const cleanUpBuilds = async () => {
await Cleaner.cleanUp();
};
14 changes: 7 additions & 7 deletions functions/src/logic/buildQueue/cleaner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ export class Cleaner {

static buildsProcessed: number;

public static async cleanUp(discordClient: Discord) {
public static async cleanUp() {
this.buildsProcessed = 0;
await this.cleanUpBuildsThatDidntReportBack(discordClient);
await this.cleanUpBuildsThatDidntReportBack();
}

private static async cleanUpBuildsThatDidntReportBack(discordClient: Discord) {
private static async cleanUpBuildsThatDidntReportBack() {
const startedBuilds = await CiBuilds.getStartedBuilds();

for (const startedBuild of startedBuilds) {
Expand All @@ -27,7 +27,7 @@ export class Cleaner {

if (publishedDate) {
const buildWasPublishedAlreadyMessage = `[Cleaner] Build "${tag}" has a publication date, but it's status is "started". Was a rebuild requested for this build?`;
await discordClient.sendDebug(buildWasPublishedAlreadyMessage);
await Discord.sendDebug(buildWasPublishedAlreadyMessage);

// Maybe set status to published. However, that will increase complexity.
// Deleting a tag from dockerhub and rebuilding will yield this error currently.
Expand All @@ -38,7 +38,7 @@ export class Cleaner {

if (!lastBuildStart) {
// In theory this should never happen.
await discordClient.sendAlert(
await Discord.sendAlert(
`[Cleaner] Build "${tag}" with status "started" does not have a "lastBuildStart" date.`,
);
continue;
Expand All @@ -59,7 +59,7 @@ export class Cleaner {
// Image does not exist
if (!response) {
const markAsFailedMessage = `[Cleaner] Build for "${tag}" with status "started" never reported back in. Marking it as failed. It will retry automatically.`;
await discordClient.sendAlert(markAsFailedMessage);
await Discord.sendAlert(markAsFailedMessage);
await CiBuilds.markBuildAsFailed(buildId, {
reason: markAsFailedMessage,
});
Expand All @@ -69,7 +69,7 @@ export class Cleaner {

// Image exists
const markAsSuccessfulMessage = `[Cleaner] Build for "${tag}" got stuck. But the image was successfully uploaded. Marking it as published.`;
await discordClient.sendDebug(markAsSuccessfulMessage);
await Discord.sendDebug(markAsSuccessfulMessage);
await CiBuilds.markBuildAsPublished(buildId, jobId, {
digest: '', // missing from dockerhub v1 api payload
specificTag: `${baseOs}-${repoVersion}`,
Expand Down
32 changes: 12 additions & 20 deletions functions/src/logic/buildQueue/ingeminator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class Ingeminator {
this.repoVersionInfo = repoVersionInfo;
}

async rescheduleFailedJobs(jobs: CiJobQueue, discordClient: Discord) {
async rescheduleFailedJobs(jobs: CiJobQueue) {
if (jobs.length <= 0) {
throw new Error(
'[Ingeminator] Expected ingeminator to be called with jobs to retry, none were given.',
Expand All @@ -37,15 +37,15 @@ export class Ingeminator {
);
}

await this.rescheduleFailedBuildsForJob(job, discordClient);
await this.rescheduleFailedBuildsForJob(job);
}
}

private async rescheduleFailedBuildsForJob(job: CiJobQueueItem, discordClient: Discord) {
private async rescheduleFailedBuildsForJob(job: CiJobQueueItem) {
const { id: jobId, data: jobData } = job;
const builds = await CiBuilds.getFailedBuildsQueue(jobId);
if (builds.length <= 0) {
await discordClient.sendDebug(
await Discord.sendDebug(
`[Ingeminator] Looks like all failed builds for job \`${jobId}\` are already scheduled.`,
);
return;
Expand All @@ -56,7 +56,7 @@ export class Ingeminator {

// Space for more?
if (this.numberToSchedule <= 0) {
await discordClient.sendDebug(
await Discord.sendDebug(
`[Ingeminator] waiting for more spots to become available for builds of ${jobId}.`,
);
return;
Expand All @@ -78,9 +78,9 @@ export class Ingeminator {
const alertingPeriodMilliseconds = alertingPeriodMinutes * 60 * 1000;
if (lastFailure.toMillis() + alertingPeriodMilliseconds >= Timestamp.now().toMillis()) {
logger.error(maxRetriesReachedMessage);
await discordClient.sendAlert(maxRetriesReachedMessage);
await Discord.sendAlert(maxRetriesReachedMessage);
} else {
await discordClient.sendDebug(maxRetriesReachedMessage);
await Discord.sendDebug(maxRetriesReachedMessage);
}

return;
Expand All @@ -90,32 +90,24 @@ export class Ingeminator {
const backoffMinutes = failureCount * 15;
const backoffMilliseconds = backoffMinutes * 60 * 1000;
if (lastFailure.toMillis() + backoffMilliseconds >= Timestamp.now().toMillis()) {
await discordClient.sendDebug(
await Discord.sendDebug(
`[Ingeminator] Backoff period of ${backoffMinutes} minutes has not expired for ${buildId}.`,
);
continue;
}

// Schedule a build
this.numberToSchedule -= 1;
if (!(await this.rescheduleBuild(jobId, jobData, buildId, BuildData, discordClient))) {
if (!(await this.rescheduleBuild(jobId, jobData, buildId, BuildData))) {
return;
}
}

await CiJobs.markJobAsScheduled(jobId);
await discordClient.sendDebug(
`[Ingeminator] rescheduled any failing editor images for ${jobId}.`,
);
await Discord.sendDebug(`[Ingeminator] rescheduled any failing editor images for ${jobId}.`);
}

public async rescheduleBuild(
jobId: string,
jobData: CiJob,
buildId: string,
buildData: CiBuild,
discordClient: Discord,
) {
public async rescheduleBuild(jobId: string, jobData: CiJob, buildId: string, buildData: CiBuild) {
// Info from job
const { editorVersionInfo } = jobData;
const { version: editorVersion, changeSet } = editorVersionInfo as EditorVersionInfo;
Expand Down Expand Up @@ -151,7 +143,7 @@ export class Ingeminator {
[Ingeminator] failed to ingeminate job ${jobId},
status: ${response.status}, response: ${response.data}.`;
logger.error(failureMessage);
await discordClient.sendAlert(failureMessage);
await Discord.sendAlert(failureMessage);
return false;
}

Expand Down
Loading

0 comments on commit e3d917f

Please sign in to comment.