diff --git a/src/solidarity.test.ts b/src/solidarity.test.ts index 67f3229..b653d41 100644 --- a/src/solidarity.test.ts +++ b/src/solidarity.test.ts @@ -14,6 +14,8 @@ * limitations under the License. */ +import * as nock from "nock"; + import { Conclusion, OutputTitle, Solidarity, logger } from "./solidarity"; import { DEFAULT_CONFIGURATION } from "./config"; @@ -21,6 +23,8 @@ import fs from "fs"; import { parse } from "./parse"; import { version } from "../package.json"; +nock.disableNetConnect(); + const payload = JSON.parse(fs.readFileSync("./fixtures/payload.json", "utf8")); const failingDIff = parse( fs.readFileSync("./fixtures/pull.failing.diff", "utf8") @@ -110,3 +114,38 @@ test("solidarity should generate correct summary", async () => { s.config = DEFAULT_CONFIGURATION; expect(s.summary("foo", "1.0.0")).toMatchSnapshot(); }); + +test("update should chunk annotations", async () => { + const s = new Solidarity({ name: "foo", id: "bar", payload: payload } as any); + s.config = DEFAULT_CONFIGURATION; + const status = "completed"; + const conclusion = Conclusion.FAILURE; + + const update = jest.fn(); + s["context"].github = { + checks: { + update: update as any, + } as any, + } as any; + + const output = { + title: "title", + summary: "summary", + annotations: Array.from({ length: 101 }, () => { + return { + annotation_level: "warning" as const, + path: "path", + start_line: 0, + end_line: 1, + message: "message", + }; + }), + }; + + await s.update(status, conclusion, output); + + expect(update).toBeCalledTimes(3); + expect(update.mock.calls[0][0].output.annotations.length).toBe(50); + expect(update.mock.calls[1][0].output.annotations.length).toBe(50); + expect(update.mock.calls[2][0].output.annotations.length).toBe(1); +}); diff --git a/src/solidarity.ts b/src/solidarity.ts index 5035538..81a51ef 100644 --- a/src/solidarity.ts +++ b/src/solidarity.ts @@ -189,21 +189,33 @@ export class Solidarity { async update( status: "queued" | "in_progress" | "completed", conclusion?: Conclusion, - output?: ChecksUpdateParamsOutput, - details_url?: string + output?: ChecksUpdateParamsOutput ): Promise { try { - await this.context.github.checks.update({ + const request = { ...this.checkOptions, check_run_id: this.checkId as number, status, conclusion, ...(status === "completed" && { completed_at: new Date().toISOString(), + ...(output && { output }), }), - ...(output && { output }), - details_url, - }); + }; + + // There is a limit of 50 annotations per request + if (output && output.annotations && output.annotations.length > 50) { + await Promise.all( + chunk(output.annotations, 50).map((annotations) => { + return this.context.github.checks.update({ + ...request, + output: { ...output, annotations }, + }); + }) + ); + } else { + await this.context.github.checks.update(request); + } } catch (e) { this.logger.error({ err: e }, "Failed to update check"); } @@ -294,3 +306,13 @@ export class Solidarity { }); } } + +const chunk = (arr: Array, chunkSize: number): Array> => { + return arr.reduce( + (previous: any, _: any, index: number, array: Array) => + !(index % chunkSize) + ? previous.concat([array.slice(index, index + chunkSize)]) + : previous, + [] + ); +};