Skip to content

Commit e46338a

Browse files
authored
Verify that build status reporters indeed work (#19)
* fix typo * Log more info about incoming requests * Finetune logging * Make dryRun functionality slightly more robust * Pipe dockerInfo straight into model * Fix typo * Upgrade firebase-admin for inequality operator * Fix type, unintended overwrite * Guard against overwrite * Guard against overwrites in jobs too * Type safety for CiJobs * Improve messages * Remove dryRun builds * Also remove job * remove try blocks from model * Improve clarity of intention for dryRuns
1 parent 26c2722 commit e46338a

File tree

10 files changed

+594
-626
lines changed

10 files changed

+594
-626
lines changed

functions/package-lock.json

Lines changed: 464 additions & 554 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

functions/package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@
1616
},
1717
"main": "lib/index.js",
1818
"dependencies": {
19-
"@octokit/auth-app": "^2.6.0",
19+
"@octokit/auth-app": "^2.7.0",
2020
"@octokit/rest": "^18.0.6",
2121
"eris": "^0.13.3",
22-
"firebase-admin": "^8.10.0",
23-
"firebase-functions": "^3.6.1",
22+
"firebase-admin": "^9.2.0",
23+
"firebase-functions": "^3.11.0",
2424
"httpie": "^1.1.2",
2525
"jsdom": "^16.4.0",
2626
"lodash": "^4.17.20",
@@ -29,12 +29,12 @@
2929
},
3030
"devDependencies": {
3131
"@types/jsdom": "^16.2.4",
32-
"@types/node": "^14.11.5",
32+
"@types/node": "^14.11.10",
3333
"@types/node-fetch": "^2.5.7",
3434
"@types/semver": "^7.3.4",
3535
"@typescript-eslint/eslint-plugin": "^3.9.1",
3636
"@typescript-eslint/parser": "^3.8.0",
37-
"eslint": "^7.6.0",
37+
"eslint": "^7.11.0",
3838
"eslint-plugin-import": "^2.22.0",
3939
"firebase-functions-test": "^0.2.0",
4040
"typescript": "^3.8.0"

functions/src/api/reportBuildFailure.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ export const reportBuildFailure = functions.https.onRequest(async (req: Request,
1515
}
1616

1717
const { body } = req;
18+
firebase.logger.debug('Build failure report incoming.', body);
19+
1820
const { jobId, buildId, reason } = body;
1921
const failure: BuildFailure = { reason };
2022

@@ -26,10 +28,16 @@ export const reportBuildFailure = functions.https.onRequest(async (req: Request,
2628
} catch (err) {
2729
const message = `
2830
Something went wrong while wrong while reporting a build failure
29-
${err.message} (${err.status})\n${err.stackTrace}
31+
${err.message}
3032
`;
31-
firebase.logger.error(message);
33+
firebase.logger.error(message, err);
3234
await Discord.sendAlert(message);
35+
36+
if (req.body?.jobId?.toString().startsWith('dryRun')) {
37+
await CiBuilds.removeDryRunBuild(req.body.buildId);
38+
await CiJobs.removeDryRunJob(req.body.jobId);
39+
}
40+
3341
res.status(500).send('Something went wrong');
3442
}
3543
});

functions/src/api/reportNewBuild.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ export const reportNewBuild = functions.https.onRequest(async (req: Request, res
1717
}
1818

1919
const { body } = req;
20+
firebase.logger.debug('new incoming build report', body);
21+
2022
const { buildId, jobId, imageType, baseOs, repoVersion, editorVersion, targetPlatform } = body;
2123
const buildInfo: BuildInfo = {
2224
baseOs,
@@ -25,8 +27,8 @@ export const reportNewBuild = functions.https.onRequest(async (req: Request, res
2527
targetPlatform,
2628
};
2729

28-
if (jobId === 'dryRun') {
29-
await createDryRunJob(imageType, editorVersion);
30+
if (jobId.toString().startsWith('dryRun')) {
31+
await createDryRunJob(jobId, imageType, editorVersion);
3032
}
3133

3234
await CiJobs.markJobAsInProgress(jobId);
@@ -37,21 +39,28 @@ export const reportNewBuild = functions.https.onRequest(async (req: Request, res
3739
} catch (err) {
3840
const message = `
3941
Something went wrong while wrong while reporting a new build.
40-
${err.message} (${err.status})\n${err.stackTrace}
42+
${err.message}
4143
`;
42-
firebase.logger.error(message);
44+
firebase.logger.error(message, err);
4345
await Discord.sendAlert(message);
46+
47+
if (req.body?.jobId?.toString().startsWith('dryRun')) {
48+
await CiBuilds.removeDryRunBuild(req.body.buildId);
49+
await CiJobs.removeDryRunJob(req.body.jobId);
50+
}
51+
4452
res.status(500).send('Something went wrong');
4553
}
4654
});
4755

48-
const createDryRunJob = async (imageType: ImageType, editorVersion: string) => {
56+
const createDryRunJob = async (jobId: string, imageType: ImageType, editorVersion: string) => {
57+
firebase.logger.debug('running dryrun for image', imageType, editorVersion);
4958
const repoVersionInfo = await RepoVersionInfo.getLatest();
5059

5160
if (imageType === 'editor') {
5261
const editorVersionInfo = await EditorVersionInfo.get(editorVersion);
53-
await CiJobs.create(imageType, repoVersionInfo, editorVersionInfo);
62+
await CiJobs.create(jobId, imageType, repoVersionInfo, editorVersionInfo);
5463
} else {
55-
await CiJobs.create(imageType, repoVersionInfo);
64+
await CiJobs.create(jobId, imageType, repoVersionInfo);
5665
}
5766
};

functions/src/api/reportPublication.ts

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { firebase, functions } from '../config/firebase';
22
import { Request } from 'firebase-functions/lib/providers/https';
33
import { Response } from 'express-serve-static-core';
44
import { Token } from '../config/token';
5-
import { CiBuilds, DockerInfo } from '../model/ciBuilds';
5+
import { CiBuilds } from '../model/ciBuilds';
66
import { CiJobs } from '../model/ciJobs';
77
import { Discord } from '../config/discord';
88

@@ -15,28 +15,42 @@ export const reportPublication = functions.https.onRequest(async (req: Request,
1515
}
1616

1717
const { body } = req;
18-
const { jobId, buildId, imageRepo, imageName, friendlyTag, specificTag, digest } = body;
19-
const dockerInfo: DockerInfo = { imageRepo, imageName, friendlyTag, specificTag, digest };
18+
firebase.logger.debug('Publication report incoming.', body);
19+
const isDryRun = req.body.jobId?.toString().startsWith('dryRun');
2020

21+
const { jobId, buildId, dockerInfo } = body;
2122
await CiBuilds.markBuildAsPublished(buildId, dockerInfo);
2223
const jobHasCompleted = await CiBuilds.haveAllBuildsForJobBeenPublished(jobId);
23-
firebase.logger.info('Publication reported.', body);
2424

2525
if (jobHasCompleted) {
2626
await CiJobs.markJobAsCompleted(jobId);
27-
const message = `Job completed for ${jobId}.`;
27+
const message = `New images published for ${jobId}.`;
2828
firebase.logger.info(message);
29-
await Discord.sendMessageToMaintainers(message);
29+
if (!isDryRun) {
30+
await Discord.sendMessageToMaintainers(message);
31+
}
32+
}
33+
34+
firebase.logger.info('Publication reported.', body);
35+
if (isDryRun) {
36+
await CiBuilds.removeDryRunBuild(req.body.buildId);
37+
await CiJobs.removeDryRunJob(req.body.jobId);
3038
}
3139

3240
res.status(200).send('OK');
3341
} catch (err) {
3442
const message = `
3543
Something went wrong while wrong while reporting a new publication
36-
${err.message} (${err.status})\n${err.stackTrace}
44+
${err.message}
3745
`;
38-
firebase.logger.error(message);
46+
firebase.logger.error(message, err);
3947
await Discord.sendAlert(message);
48+
49+
if (req.body?.jobId?.toString().startsWith('dryRun')) {
50+
await CiBuilds.removeDryRunBuild(req.body.buildId);
51+
await CiJobs.removeDryRunJob(req.body.jobId);
52+
}
53+
4054
res.status(500).send('Something went wrong');
4155
}
4256
});

functions/src/logic/ingestRepoVersions/index.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ import { updateDatabase } from './updateDatabase';
66
export const ingestRepoVersions = async () => {
77
try {
88
const scrapedInfoList = await scrapeVersions();
9-
firebase.logger.info('Found versions', scrapedInfoList);
10-
119
await updateDatabase(scrapedInfoList);
1210
} catch (err) {
1311
const message = `

functions/src/logic/ingestUnityVersions/updateDatabase.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,6 @@ export const updateDatabase = async (ingestedInfoList: EditorVersionInfo[]): Pro
4949
firebase.logger.info(message);
5050
await Discord.sendMessageToMaintainers(message);
5151
} else {
52-
firebase.logger.info('Database is up-to-date. (no updated info found)');
52+
firebase.logger.info('Database is up-to-date. (no updated Unity versions found)');
5353
}
5454
};

functions/src/model/ciBuilds.ts

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -73,31 +73,48 @@ export class CiBuilds {
7373
imageType: ImageType,
7474
buildInfo: BuildInfo,
7575
) => {
76-
try {
77-
const data: CiBuild = {
78-
status: BuildStatus.started,
79-
buildId,
80-
relatedJobId,
81-
imageType,
82-
buildInfo,
83-
failure: null,
84-
dockerInfo: null,
85-
meta: {
86-
lastBuildStart: Timestamp.now(),
87-
failureCount: 0,
88-
lastBuildFailure: null,
89-
publishedDate: null,
90-
},
91-
addedDate: Timestamp.now(),
92-
modifiedDate: Timestamp.now(),
93-
};
94-
95-
await db.collection(COLLECTION).doc(buildId).set({ data });
96-
} catch (err) {
97-
firebase.logger.error('Error occurred while trying to enqueue a new build', err);
76+
const data: CiBuild = {
77+
status: BuildStatus.started,
78+
buildId,
79+
relatedJobId,
80+
imageType,
81+
buildInfo,
82+
failure: null,
83+
dockerInfo: null,
84+
meta: {
85+
lastBuildStart: Timestamp.now(),
86+
failureCount: 0,
87+
lastBuildFailure: null,
88+
publishedDate: null,
89+
},
90+
addedDate: Timestamp.now(),
91+
modifiedDate: Timestamp.now(),
92+
};
93+
94+
const ref = await db.collection(COLLECTION).doc(buildId);
95+
const snapshot = await ref.get();
96+
97+
if (snapshot.exists) {
98+
// noinspection ExceptionCaughtLocallyJS
99+
throw new Error('A build with this identifier already exists');
98100
}
101+
102+
const result = await ref.create(data);
103+
firebase.logger.debug('Build created', result);
99104
};
100105

106+
static async removeDryRunBuild(buildId: string) {
107+
if (!buildId.startsWith('dryRun')) {
108+
throw new Error('Unexpected behaviour, expected only dryRun builds to be deleted');
109+
}
110+
111+
const ref = await db.collection(COLLECTION).doc(buildId);
112+
const doc = await ref.get();
113+
firebase.logger.info('dryRun produced this build endResult', doc.data());
114+
115+
await ref.delete();
116+
}
117+
101118
static markBuildAsFailed = async (buildId: string, failure: BuildFailure) => {
102119
const build = await db.collection(COLLECTION).doc(buildId);
103120

@@ -125,7 +142,6 @@ export class CiBuilds {
125142
const snapshot = await db
126143
.collection(COLLECTION)
127144
.where('jobId', '==', jobId)
128-
// @ts-ignore
129145
.where('status', '!=', BuildStatus.published)
130146
.limit(1)
131147
.get();

functions/src/model/ciJobs.ts

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { db, admin } from '../config/firebase';
1+
import { db, admin, firebase } from '../config/firebase';
22
import { EditorVersionInfo } from './editorVersionInfo';
33
import FieldValue = admin.firestore.FieldValue;
44
import Timestamp = admin.firestore.Timestamp;
@@ -42,42 +42,47 @@ export class CiJobs {
4242
};
4343

4444
static create = async (
45+
jobId: string,
4546
imageType: ImageType,
4647
repoVersionInfo: RepoVersionInfo,
4748
editorVersionInfo: EditorVersionInfo | null = null,
4849
) => {
49-
const jobId = await CiJobs.generateJobId(imageType, repoVersionInfo, editorVersionInfo);
50-
await db
51-
.collection(COLLECTION)
52-
.doc(jobId)
53-
.set({
54-
status: JobStatus.created,
55-
imageType,
56-
repoVersionInfo,
57-
editorVersionInfo,
58-
meta: {
59-
lastBuildStart: null,
60-
failureCount: 0,
61-
lastBuildFailure: null,
62-
},
63-
addedDate: Timestamp.now(),
64-
modifiedDate: Timestamp.now(),
65-
});
50+
const job: CiJob = {
51+
status: JobStatus.created,
52+
imageType,
53+
repoVersionInfo,
54+
editorVersionInfo,
55+
meta: {
56+
lastBuildStart: null,
57+
failureCount: 0,
58+
lastBuildFailure: null,
59+
},
60+
addedDate: Timestamp.now(),
61+
modifiedDate: Timestamp.now(),
62+
};
63+
64+
const result = await db.collection(COLLECTION).doc(jobId).create(job);
65+
firebase.logger.debug('Job created', result);
6666
};
6767

6868
static markJobAsInProgress = async (jobId: string) => {
69-
const job = await db.collection(COLLECTION).doc(jobId);
70-
const snapshot = await job.get();
69+
const ref = await db.collection(COLLECTION).doc(jobId);
70+
const snapshot = await ref.get();
71+
72+
if (!snapshot.exists) {
73+
throw new Error(`Trying to mark job '${jobId}' as in progress. But it does not exist.`);
74+
}
75+
7176
const currentBuild = snapshot.data() as CiJob;
77+
firebase.logger.warn(currentBuild);
7278

73-
// TODO - move this logic out of the model
7479
// Do not override failure or completed
7580
let { status } = currentBuild;
7681
if ([JobStatus.created, JobStatus.scheduled].includes(status)) {
7782
status = JobStatus.inProgress;
7883
}
7984

80-
await job.update({
85+
await ref.update({
8186
status,
8287
'meta.lastBuildStart': Timestamp.now(),
8388
modifiedDate: Timestamp.now(),
@@ -89,7 +94,7 @@ export class CiJobs {
8994

9095
await job.update({
9196
status: JobStatus.failure,
92-
'meta.failures': FieldValue.increment(1),
97+
'meta.failureCount': FieldValue.increment(1),
9398
'meta.lastBuildFailure': Timestamp.now(),
9499
modifiedDate: Timestamp.now(),
95100
});
@@ -104,6 +109,14 @@ export class CiJobs {
104109
});
105110
};
106111

112+
static async removeDryRunJob(jobId: string) {
113+
if (!jobId.startsWith('dryRun')) {
114+
throw new Error('Expect only dryRun jobs to be deleted.');
115+
}
116+
117+
await db.collection(COLLECTION).doc(jobId).delete();
118+
}
119+
107120
static generateJobId(
108121
imageType: string,
109122
repoVersionInfo: RepoVersionInfo,

functions/src/model/repoVersionInfo.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export class RepoVersionInfo {
2828
.limit(1)
2929
.get();
3030

31-
if (snapshot.docs.length <= 1) {
31+
if (snapshot.docs.length <= 0) {
3232
throw new Error('No repository versions have been ingested yet');
3333
}
3434

0 commit comments

Comments
 (0)