Skip to content
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

Ingest repo versions #17

Merged
merged 6 commits into from
Oct 17, 2020
Merged
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
4 changes: 2 additions & 2 deletions firestore.indexes.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"indexes": [
{
"collectionGroup": "repoVersions",
"collectionGroup": "editorVersions",
"queryScope": "COLLECTION",
"fields": [
{
Expand All @@ -19,7 +19,7 @@
]
},
{
"collectionGroup": "unityVersions",
"collectionGroup": "repoVersions",
"queryScope": "COLLECTION",
"fields": [
{
Expand Down
37 changes: 33 additions & 4 deletions functions/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion functions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@
"httpie": "^1.1.2",
"jsdom": "^16.4.0",
"lodash": "^4.17.20",
"node-fetch": "^2.6.1"
"node-fetch": "^2.6.1",
"semver": "^7.3.2"
},
"devDependencies": {
"@types/jsdom": "^16.2.4",
"@types/node": "^14.11.5",
"@types/node-fetch": "^2.5.7",
"@types/semver": "^7.3.4",
"@typescript-eslint/eslint-plugin": "^3.9.1",
"@typescript-eslint/parser": "^3.8.0",
"eslint": "^7.6.0",
Expand Down
2 changes: 1 addition & 1 deletion functions/src/api/repoVerions.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Request } from 'firebase-functions/lib/providers/https';
import { Response } from 'express-serve-static-core';
import { firebase, functions } from '../config/firebase';
import { RepoVersionInfo } from '../model/repoVersions';
import { RepoVersionInfo } from '../model/repoVersionInfo';

export const repoVersions = functions.https.onRequest(
async (request: Request, response: Response) => {
Expand Down
2 changes: 1 addition & 1 deletion functions/src/api/reportNewBuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { BuildInfo, CiBuilds, ImageType } from '../model/ciBuilds';
import { CiJobs } from '../model/ciJobs';
import { Discord } from '../config/discord';
import { EditorVersionInfo } from '../model/editorVersionInfo';
import { RepoVersionInfo } from '../model/repoVersions';
import { RepoVersionInfo } from '../model/repoVersionInfo';

export const reportNewBuild = functions.https.onRequest(async (req: Request, res: Response) => {
try {
Expand Down
2 changes: 2 additions & 0 deletions functions/src/cron/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { EventContext } from 'firebase-functions';
import { firebase, functions } from '../config/firebase';
import { Discord } from '../config/discord';
import { ingestUnityVersions } from '../logic/ingestUnityVersions';
import { ingestRepoVersions } from '../logic/ingestRepoVersions';

/**
* CPU-time for pubSub is not part of the free quota, so we'll keep it light weight.
Expand All @@ -24,5 +25,6 @@ export const trigger = functions.pubsub
});

const routineTasks = async () => {
await ingestRepoVersions();
await ingestUnityVersions();
};
21 changes: 21 additions & 0 deletions functions/src/logic/ingestRepoVersions/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { firebase } from '../../config/firebase';
import { Discord } from '../../config/discord';
import { scrapeVersions } from './scrapeVersions';
import { updateDatabase } from './updateDatabase';

export const ingestRepoVersions = async () => {
try {
const scrapedInfoList = await scrapeVersions();
firebase.logger.info('Found versions', scrapedInfoList);

await updateDatabase(scrapedInfoList);
} catch (err) {
const message = `
Something went wrong while importing repository versions for unity-ci/docker:
${err.message} (${err.status})\n${err.stackTrace}
`;

firebase.logger.error(message);
await Discord.sendAlert(message);
}
};
47 changes: 47 additions & 0 deletions functions/src/logic/ingestRepoVersions/scrapeVersions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import semver from 'semver';
import { RepoVersionInfo } from '../../model/repoVersionInfo';
import { GitHub } from '../../config/github';

export const scrapeVersions = async (): Promise<RepoVersionInfo[]> => {
const gitHub = await GitHub.init();

const releases = await gitHub.repos.listReleases({
owner: 'unity-ci',
repo: 'docker',
});

const versions = releases.data.map((release) => {
const {
id,
url,
name,
body: description,
tag_name: tagName,
author: { login: author },
target_commitish: commitIsh,
} = release;

const version = semver.valid(semver.coerce(tagName));
if (!version) {
throw new Error("Assumed versions to always be parsable, but they're not.");
}
const major = semver.major(version);
const minor = semver.major(version);
const patch = semver.major(version);

return {
version,
major,
minor,
patch,
id,
name,
description,
author,
commitIsh,
url,
};
});

return versions;
};
54 changes: 54 additions & 0 deletions functions/src/logic/ingestRepoVersions/updateDatabase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { isMatch } from 'lodash';
import { RepoVersionInfo } from '../../model/repoVersionInfo';
import { firebase } from '../../config/firebase';
import { Discord } from '../../config/discord';

const plural = (amount: number) => {
return amount === 1 ? 'version' : 'versions';
};

export const updateDatabase = async (ingestedInfoList: RepoVersionInfo[]): Promise<void> => {
const existingInfoList = await RepoVersionInfo.getAll();

const newVersions: RepoVersionInfo[] = [];
const updatedVersions: RepoVersionInfo[] = [];

ingestedInfoList.forEach((ingestedInfo: RepoVersionInfo) => {
const { version } = ingestedInfo;
const existingVersion = existingInfoList.find((info) => info.version === version);

if (!existingVersion) {
newVersions.push(ingestedInfo);
return;
}

if (!isMatch(existingVersion, ingestedInfo)) {
updatedVersions.push(ingestedInfo);
return;
}
});

let message = '';

if (newVersions.length >= 1) {
await RepoVersionInfo.createMany(newVersions);
message += `
${newVersions.length} new repository ${plural(newVersions.length)} detected.
(${newVersions.map((version) => version.version).join(', ')}`;
}

if (updatedVersions.length >= 1) {
await RepoVersionInfo.updateMany(updatedVersions);
message += `
${updatedVersions.length} updated repository ${plural(updatedVersions.length)} detected.
(${updatedVersions.map((version) => version.version).join(', ')})`;
}

message = message.trimEnd();
if (message.length >= 1) {
firebase.logger.info(message);
await Discord.sendMessageToMaintainers(message);
} else {
firebase.logger.info('Database is up-to-date. (no updated repo versions found)');
}
};
10 changes: 7 additions & 3 deletions functions/src/logic/ingestUnityVersions/updateDatabase.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { EditorVersionInfo } from '../../model/editorVersionInfo';
import { isMatch } from 'lodash';
import { firebase } from '../../config/firebase';
import { Discord } from '../../config/discord';
import { EditorVersionInfo } from '../../model/editorVersionInfo';

const plural = (amount: number) => {
return amount === 1 ? 'version' : 'versions';
Expand Down Expand Up @@ -32,12 +32,16 @@ export const updateDatabase = async (ingestedInfoList: EditorVersionInfo[]): Pro

if (newVersions.length >= 1) {
await EditorVersionInfo.createMany(newVersions);
message += `${newVersions.length} new ${plural(newVersions.length)} detected. `;
message += `
${newVersions.length} new Unity editor ${plural(newVersions.length)} detected.
(${newVersions.map((version) => version.version).join(', ')}`;
}

if (updatedVersions.length >= 1) {
await EditorVersionInfo.updateMany(updatedVersions);
message += `${updatedVersions.length} updated ${plural(updatedVersions.length)} detected. `;
message += `
${updatedVersions.length} updated Unity editor ${plural(updatedVersions.length)} detected.
(${updatedVersions.map((version) => version.version).join(', ')})`;
}

message = message.trimEnd();
Expand Down
2 changes: 1 addition & 1 deletion functions/src/model/ciJobs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { db, admin } from '../config/firebase';
import { EditorVersionInfo } from './editorVersionInfo';
import FieldValue = admin.firestore.FieldValue;
import Timestamp = admin.firestore.Timestamp;
import { RepoVersionInfo } from './repoVersions';
import { RepoVersionInfo } from './repoVersionInfo';
import { ImageType } from './ciBuilds';

const COLLECTION = 'ciJobs';
Expand Down
2 changes: 1 addition & 1 deletion functions/src/model/ciVersionInfo.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { db, admin, firebase } from '../config/firebase';
import Timestamp = admin.firestore.Timestamp;
import { EditorVersionInfo } from './editorVersionInfo';
import { RepoVersionInfo } from './repoVersions';
import { RepoVersionInfo } from './repoVersionInfo';

const COLLECTION = 'builtVersions';

Expand Down
10 changes: 5 additions & 5 deletions functions/src/model/editorVersionInfo.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { db, admin, firebase } from '../config/firebase';
import Timestamp = admin.firestore.Timestamp;

const COLLECTION = 'unityVersions';
const COLLECTION = 'editorVersions';

export interface EditorVersionInfo {
version: string;
Expand Down Expand Up @@ -42,11 +42,11 @@ export class EditorVersionInfo {
return snapshot.docs.map((doc) => doc.data()) as EditorVersionInfo[];
};

static createMany = async (versionInfoList: EditorVersionInfo[]) => {
static createMany = async (editorVersionList: EditorVersionInfo[]) => {
try {
const batch = db.batch();

versionInfoList.forEach((versionInfo) => {
editorVersionList.forEach((versionInfo) => {
const { version } = versionInfo;

const ref = db.collection(COLLECTION).doc(version);
Expand All @@ -56,7 +56,7 @@ export class EditorVersionInfo {

await batch.commit();
} catch (err) {
firebase.logger.error('Error occurred during batch commit of new version', err);
firebase.logger.error('Error occurred during batch commit of new editor versions', err);
}
};

Expand All @@ -74,7 +74,7 @@ export class EditorVersionInfo {

await batch.commit();
} catch (err) {
firebase.logger.error('Error occurred during batch commit of new version', err);
firebase.logger.error('Error occurred during batch commit of new editor versions', err);
}
};
}
Loading