-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1501 from argos-ci/build-reviews
feat: store build reviews in a dedicated table
- Loading branch information
Showing
10 changed files
with
283 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/** | ||
* @param {import('knex').Knex} knex | ||
*/ | ||
export const up = async (knex) => { | ||
await knex.schema.createTable("build_reviews", (table) => { | ||
table.bigIncrements("id").primary(); | ||
table.dateTime("createdAt").notNullable(); | ||
table.dateTime("updatedAt").notNullable(); | ||
table.bigInteger("userId").index(); | ||
table.foreign("userId").references("users.id"); | ||
table.bigInteger("buildId").index().notNullable(); | ||
table.foreign("buildId").references("builds.id"); | ||
table.enum("state", ["pending", "approved", "rejected"]).notNullable(); | ||
}); | ||
}; | ||
|
||
/** | ||
* @param {import('knex').Knex} knex | ||
*/ | ||
export const down = async (knex) => { | ||
await knex.schema.dropTable("build_reviews"); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
#!/usr/bin/env node | ||
import { callbackify } from "node:util"; | ||
|
||
import { Build } from "@/database/models/index.js"; | ||
import logger from "@/logger/index.js"; | ||
|
||
import { buildReviewJob } from "../build-review-job.js"; | ||
|
||
const main = callbackify(async () => { | ||
const batch = 2000; | ||
const totalCount = await Build.query() | ||
.where("conclusion", "changes-detected") | ||
.resultSize(); | ||
|
||
let total = 0; | ||
for (let offset = 0; offset < totalCount; offset += batch) { | ||
const nodes = await Build.query() | ||
.select("id") | ||
.where("conclusion", "changes-detected") | ||
.limit(batch) | ||
.offset(offset) | ||
.orderBy("id", "desc"); | ||
|
||
const ids = nodes.map((node) => node.id); | ||
const percentage = Math.round((total / totalCount) * 100); | ||
logger.info( | ||
`Processing ${total}/${totalCount} (${percentage}%) - Pushing ${ids.length} builds in queue`, | ||
); | ||
await buildReviewJob.push(...ids); | ||
total += nodes.length; | ||
} | ||
|
||
logger.info(`${total} builds pushed in queue (100% complete)`); | ||
}); | ||
|
||
main((err) => { | ||
if (err) { | ||
throw err; | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import { assertNever } from "@argos/util/assertNever"; | ||
import { invariant } from "@argos/util/invariant"; | ||
|
||
import { Build } from "@/database/models/Build.js"; | ||
import { BuildReview } from "@/database/models/BuildReview.js"; | ||
import { createJob } from "@/job-core/index.js"; | ||
import logger from "@/logger/index.js"; | ||
|
||
export const buildReviewJob = createJob("build-reviews", { | ||
complete: () => {}, | ||
error: (value, error) => { | ||
console.error("Error while processing build", value, error); | ||
}, | ||
perform: async (buildId: string) => { | ||
logger.info(`[${buildId}] Processing for review`); | ||
const build = await Build.query().findById(buildId).throwIfNotFound(); | ||
const [[status], review] = await Promise.all([ | ||
Build.getReviewStatuses([build]), | ||
BuildReview.query().select("id").where("buildId", build.id).first(), | ||
]); | ||
if (review) { | ||
logger.info(`[${buildId}] Review already exists`); | ||
return; | ||
} | ||
invariant(status !== undefined, "Status should be defined"); | ||
if (status) { | ||
logger.info(`[${buildId}] Review created`); | ||
const state = (() => { | ||
switch (status) { | ||
case "accepted": | ||
return "approved" as const; | ||
case "rejected": | ||
return "rejected" as const; | ||
default: | ||
assertNever(status); | ||
} | ||
})(); | ||
|
||
// Simulate 10 minutes after build creation | ||
const date = new Date( | ||
new Date(build.createdAt).getTime() + 10 * 60 * 1000, | ||
).toISOString(); | ||
|
||
await BuildReview.query().insert({ | ||
buildId: build.id, | ||
createdAt: date, | ||
updatedAt: date, | ||
state, | ||
}); | ||
logger.info(`[${buildId}] Review created ${state}`); | ||
} else { | ||
logger.info(`[${buildId}] No review needed`); | ||
} | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import type { RelationMappings } from "objection"; | ||
|
||
import { Model } from "../util/model.js"; | ||
import { mergeSchemas, timestampsSchema } from "../util/schemas.js"; | ||
import { Build } from "./Build.js"; | ||
import { User } from "./User.js"; | ||
|
||
export class BuildReview extends Model { | ||
static override tableName = "build_reviews"; | ||
|
||
static override jsonSchema = mergeSchemas(timestampsSchema, { | ||
required: ["buildId", "state"], | ||
properties: { | ||
buildId: { type: "string" }, | ||
userId: { type: ["string", "null"] }, | ||
state: { type: "string", enum: ["pending", "approved", "rejected"] }, | ||
}, | ||
}); | ||
|
||
buildId!: string; | ||
userId!: string; | ||
state!: "pending" | "approved" | "rejected"; | ||
|
||
static override get relationMappings(): RelationMappings { | ||
return { | ||
build: { | ||
relation: Model.BelongsToOneRelation, | ||
modelClass: Build, | ||
join: { | ||
from: "build_reviews.buildId", | ||
to: "builds.id", | ||
}, | ||
}, | ||
user: { | ||
relation: Model.BelongsToOneRelation, | ||
modelClass: User, | ||
join: { | ||
from: "build_reviews.userId", | ||
to: "users.id", | ||
}, | ||
}, | ||
}; | ||
} | ||
|
||
build?: Build; | ||
user?: User; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import "../setup.js"; | ||
|
||
import { buildReviewJob } from "@/build/build-review-job.js"; | ||
import { createJobWorker } from "@/job-core/index.js"; | ||
|
||
createJobWorker(buildReviewJob); |