From 9194d9aa4359b54b51d63a6a4c4e6c0e24ed910f Mon Sep 17 00:00:00 2001 From: Thomas Dax Date: Sat, 31 Aug 2024 12:54:26 +0200 Subject: [PATCH] `BuildsService`: Start all jobs that match the scope exactly (v6) (#2487) Backport of https://github.com/vivid-planet/comet/pull/2486 --- .changeset/tiny-books-bathe.md | 7 +++++++ .../api/cms-api/src/builds/builds.service.spec.ts | 14 ++++++++++++++ packages/api/cms-api/src/builds/builds.service.ts | 11 ++++++----- 3 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 .changeset/tiny-books-bathe.md diff --git a/.changeset/tiny-books-bathe.md b/.changeset/tiny-books-bathe.md new file mode 100644 index 0000000000..24da55e718 --- /dev/null +++ b/.changeset/tiny-books-bathe.md @@ -0,0 +1,7 @@ +--- +"@comet/cms-api": patch +--- + +`BuildsService`: Start all jobs that match the scope exactly + +Previously, the first job that matched the scope exactly would be started, and the rest would be ignored. This has been fixed so that all jobs that match the scope exactly are started. diff --git a/packages/api/cms-api/src/builds/builds.service.spec.ts b/packages/api/cms-api/src/builds/builds.service.spec.ts index 1854424d8a..6fe83e7cdc 100644 --- a/packages/api/cms-api/src/builds/builds.service.spec.ts +++ b/packages/api/cms-api/src/builds/builds.service.spec.ts @@ -27,6 +27,15 @@ const jobMainEnglish = { }, }; +const jobMainEnglish2 = { + metadata: { + name: "main-en-2", + annotations: { + [CONTENT_SCOPE_ANNOTATION]: '{"domain":"main","language":"en"}', + }, + }, +}; + const jobMainGerman = { metadata: { name: "main-de", @@ -62,6 +71,11 @@ describe("BuildsService", () => { await expect(service.getBuilderCronJobsToStart([{ domain: "main", language: "en" }])).resolves.toEqual([jobMainEnglish]); }); + it("should return two jobs if two jobs have the exact same scope", async () => { + mockedBuildTemplatesService.getAllBuilderCronJobs.mockResolvedValueOnce([jobMainEnglish, jobMainEnglish2]); + await expect(service.getBuilderCronJobsToStart([{ domain: "main", language: "en" }])).resolves.toEqual([jobMainEnglish, jobMainEnglish2]); + }); + it("should return multiple jobs for multiple exact matches", async () => { await expect( service.getBuilderCronJobsToStart([ diff --git a/packages/api/cms-api/src/builds/builds.service.ts b/packages/api/cms-api/src/builds/builds.service.ts index 46b1cc4e69..e3ffaefc36 100644 --- a/packages/api/cms-api/src/builds/builds.service.ts +++ b/packages/api/cms-api/src/builds/builds.service.ts @@ -157,7 +157,8 @@ export class BuildsService { const builderCronJobs = await this.buildTemplatesService.getAllBuilderCronJobs(); const getMatchingBuilderCronJobs = (scope: ContentScope) => { - const matchingCronJobs: V1CronJob[] = []; + const partiallyMatchingCronJobs: V1CronJob[] = []; + const exactlyMatchingCronJobs: V1CronJob[] = []; for (const cronJob of builderCronJobs) { const cronJobScope = this.kubernetesService.getContentScope(cronJob); @@ -169,22 +170,22 @@ export class BuildsService { // Exact match between job's scope and the scope with changes. if (Object.entries(cronJobScope).every(([key, value]) => (scope as Record)[key] === value)) { - return [cronJob]; + exactlyMatchingCronJobs.push(cronJob); } // Check if scopes match partially. For instance, a job's scope may be { "domain": "main" }, but the change was in // { "domain": "main", "language": "en" }. Or the job's scope may be { "domain": "main", "language": "en" }, but the change // was in { "domain": "main" }. In both cases, the job should still be started. if (Object.entries(cronJobScope).some(([key, value]) => (scope as Record)[key] === value)) { - matchingCronJobs.push(cronJob); + partiallyMatchingCronJobs.push(cronJob); } } - if (matchingCronJobs.length === 0) { + if (exactlyMatchingCronJobs.length === 0 && partiallyMatchingCronJobs.length === 0) { throw new Error(`Found changes in scope ${JSON.stringify(scope)} but no matching builder cron job!`); } - return matchingCronJobs; + return exactlyMatchingCronJobs.length > 0 ? exactlyMatchingCronJobs : partiallyMatchingCronJobs; }; const uniqueMatchingCronJobs = new Set();