diff --git a/apps/backend/src/build/strategy/strategies/ci/query.e2e.test.ts b/apps/backend/src/build/strategy/strategies/ci/query.e2e.test.ts index aa3e27e6..ac6ea5dd 100644 --- a/apps/backend/src/build/strategy/strategies/ci/query.e2e.test.ts +++ b/apps/backend/src/build/strategy/strategies/ci/query.e2e.test.ts @@ -9,6 +9,7 @@ describe("#getBaseBucketForBuildAndCommit", () => { describe("when the build is triggered by a pull request", () => { let baseBucket: ScreenshotBucket; let build: Build; + let baseBucketBuild: Build; beforeEach(async () => { await setupDatabase(); @@ -29,10 +30,12 @@ describe("#getBaseBucketForBuildAndCommit", () => { { baseScreenshotBucketId: null, compareScreenshotBucketId: baseBucket.id, - jobStatus: "pending", + jobStatus: "complete", prHeadCommit: "766b744bc5fa27a330283dfd47ffafdaf905a941", name: "default", projectId: project.id, + type: "reference", + mode: "ci", }, { baseScreenshotBucketId: null, @@ -41,17 +44,75 @@ describe("#getBaseBucketForBuildAndCommit", () => { prHeadCommit: null, name: "default", projectId: project.id, + mode: "ci", }, ]); + baseBucketBuild = builds[0]!; build = builds[1]!; }); - it("returns the base bucket", async () => { - const result = await getBaseBucketForBuildAndCommit( - build, - "766b744bc5fa27a330283dfd47ffafdaf905a941", - ); - expect(result).toEqual(baseBucket); + describe("if the associated build is pending", () => { + beforeEach(async () => { + await baseBucketBuild.$query().patch({ jobStatus: "pending" }); + }); + + it("does not returns the bucket", async () => { + const result = await getBaseBucketForBuildAndCommit( + build, + "766b744bc5fa27a330283dfd47ffafdaf905a941", + ); + expect(result).toBeNull(); + }); + }); + + describe("if the associated build is a type check without any diff", () => { + beforeEach(async () => { + await baseBucketBuild.$query().patch({ type: "check" }); + }); + + it("does not returns the bucket", async () => { + const result = await getBaseBucketForBuildAndCommit( + build, + "766b744bc5fa27a330283dfd47ffafdaf905a941", + ); + expect(result).toBeNull(); + }); + }); + + describe("if the associated build is a type check with unapproved diff", () => { + beforeEach(async () => { + await baseBucketBuild.$query().patch({ type: "check" }); + await factory.ScreenshotDiff.create({ + buildId: baseBucketBuild.id, + validationStatus: "rejected", + }); + }); + + it("does not returns the bucket", async () => { + const result = await getBaseBucketForBuildAndCommit( + build, + "766b744bc5fa27a330283dfd47ffafdaf905a941", + ); + expect(result).toBeNull(); + }); + }); + + describe("if the associated build is a type check with approved diff", () => { + beforeEach(async () => { + await baseBucketBuild.$query().patch({ type: "check" }); + await factory.ScreenshotDiff.create({ + buildId: baseBucketBuild.id, + validationStatus: "accepted", + }); + }); + + it("returns the bucket", async () => { + const result = await getBaseBucketForBuildAndCommit( + build, + "766b744bc5fa27a330283dfd47ffafdaf905a941", + ); + expect(result).toEqual(baseBucket); + }); }); }); @@ -78,7 +139,8 @@ describe("#getBaseBucketForBuildAndCommit", () => { { baseScreenshotBucketId: null, compareScreenshotBucketId: baseBucket.id, - jobStatus: "pending", + jobStatus: "complete", + type: "reference", prHeadCommit: null, name: "default", projectId: project.id, diff --git a/apps/backend/src/build/strategy/strategies/ci/query.ts b/apps/backend/src/build/strategy/strategies/ci/query.ts index 2e04af25..07ed4492 100644 --- a/apps/backend/src/build/strategy/strategies/ci/query.ts +++ b/apps/backend/src/build/strategy/strategies/ci/query.ts @@ -1,4 +1,8 @@ -import { Build, ScreenshotBucket } from "@/database/models/index.js"; +import { + Build, + ScreenshotBucket, + ScreenshotDiff, +} from "@/database/models/index.js"; /** * Get the base bucket for a build and a commit. @@ -30,11 +34,32 @@ export async function getBaseBucketForBuildAndCommit( * Query the base bucket from a build. */ export function queryBaseBucket(build: Build) { - return ScreenshotBucket.query().where({ - projectId: build.projectId, - name: build.name, - complete: true, - valid: true, - mode: build.mode, - }); + const approvedBuilds = Build.query() + .select("compareScreenshotBucketId") + .where("projectId", build.projectId) + .where("name", build.name) + .where("mode", build.mode) + .where("jobStatus", "complete") + .whereNot("id", build.id) + .where((qb) => { + // Reference build or check build with accepted diffs + qb.where("type", "reference").orWhere((qb) => { + qb.where("type", "check").whereExists( + ScreenshotDiff.query() + .select(1) + .whereRaw('"buildId" = builds.id') + .where("validationStatus", "accepted"), + ); + }); + }); + + return ScreenshotBucket.query() + .where({ + projectId: build.projectId, + name: build.name, + complete: true, + valid: true, + mode: build.mode, + }) + .whereIn("id", approvedBuilds); }