Skip to content

Commit fc3223c

Browse files
committed
Implement etag handling
Fixes #295
1 parent 5210b85 commit fc3223c

File tree

6 files changed

+241
-42
lines changed

6 files changed

+241
-42
lines changed

dist/index.mjs

Lines changed: 54 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
},
3535
"devDependencies": {
3636
"@eslint/js": "^9.28.0",
37+
"@octokit/types": "^14.1.0",
3738
"@opentf/std": "^0.13.0",
3839
"@total-typescript/ts-reset": "^0.6.1",
3940
"@types/node": "~20.19.0",

pnpm-lock.yaml

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/api.spec.ts

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
init,
2121
retryOrTimeout,
2222
} from "./api.ts";
23+
import { clearEtags } from "./etags.js";
2324
import { mockLoggingFunctions } from "./test-utils/logging.mock.ts";
2425
import { getBranchName } from "./utils.ts";
2526

@@ -29,6 +30,7 @@ vi.mock("@actions/github");
2930
interface MockResponse {
3031
data: any;
3132
status: number;
33+
headers: object;
3234
}
3335

3436
function* mockPageIterator<T, P>(
@@ -66,6 +68,10 @@ const mockOctokit = {
6668
},
6769
};
6870

71+
afterEach(() => {
72+
clearEtags();
73+
});
74+
6975
describe("API", () => {
7076
const {
7177
coreDebugLogMock,
@@ -119,6 +125,7 @@ describe("API", () => {
119125
Promise.resolve({
120126
data: undefined,
121127
status: 204,
128+
headers: {},
122129
}),
123130
);
124131

@@ -147,6 +154,7 @@ describe("API", () => {
147154
Promise.resolve({
148155
data: undefined,
149156
status: errorStatus,
157+
headers: {},
150158
}),
151159
);
152160

@@ -176,6 +184,7 @@ describe("API", () => {
176184
return Promise.resolve({
177185
data: undefined,
178186
status: 204,
187+
headers: {},
179188
});
180189
});
181190

@@ -219,6 +228,7 @@ describe("API", () => {
219228
Promise.resolve({
220229
data: mockData,
221230
status: 200,
231+
headers: {},
222232
}),
223233
);
224234

@@ -246,6 +256,7 @@ describe("API", () => {
246256
Promise.resolve({
247257
data: undefined,
248258
status: errorStatus,
259+
headers: {},
249260
}),
250261
);
251262

@@ -268,6 +279,7 @@ describe("API", () => {
268279
Promise.resolve({
269280
data: [],
270281
status: 200,
282+
headers: {},
271283
}),
272284
);
273285

@@ -303,6 +315,7 @@ describe("API", () => {
303315
Promise.resolve({
304316
data: mockData,
305317
status: 200,
318+
headers: {},
306319
}),
307320
);
308321

@@ -355,6 +368,7 @@ describe("API", () => {
355368
Promise.resolve({
356369
data: mockData,
357370
status: 200,
371+
headers: {},
358372
}),
359373
);
360374

@@ -387,6 +401,7 @@ describe("API", () => {
387401
Promise.resolve({
388402
data: undefined,
389403
status: errorStatus,
404+
headers: {},
390405
}),
391406
);
392407

@@ -417,6 +432,7 @@ describe("API", () => {
417432
Promise.resolve({
418433
data: mockData,
419434
status: 200,
435+
headers: {},
420436
}),
421437
);
422438

@@ -454,6 +470,7 @@ describe("API", () => {
454470
workflow_runs: [],
455471
},
456472
status: 200,
473+
headers: {},
457474
};
458475
return Promise.resolve(mockResponse);
459476
},
@@ -494,6 +511,7 @@ describe("API", () => {
494511
workflow_runs: [],
495512
},
496513
status: 200,
514+
headers: {},
497515
};
498516
return Promise.resolve(mockResponse);
499517
},
@@ -534,6 +552,7 @@ describe("API", () => {
534552
workflow_runs: [],
535553
},
536554
status: 200,
555+
headers: {},
537556
};
538557
return Promise.resolve(mockResponse);
539558
},
@@ -588,6 +607,7 @@ describe("API", () => {
588607
Promise.resolve({
589608
data: mockData,
590609
status: 200,
610+
headers: {},
591611
}),
592612
);
593613

@@ -620,6 +640,7 @@ describe("API", () => {
620640
Promise.resolve({
621641
data: undefined,
622642
status: errorStatus,
643+
headers: {},
623644
}),
624645
);
625646

@@ -653,6 +674,7 @@ describe("API", () => {
653674
Promise.resolve({
654675
data: mockData,
655676
status: 200,
677+
headers: {},
656678
}),
657679
);
658680

@@ -672,6 +694,64 @@ describe("API", () => {
672694
`,
673695
);
674696
});
697+
698+
it("should send the etag from the previous response in the If-None-Match header", async () => {
699+
const mockData = {
700+
total_count: 1,
701+
jobs: [
702+
{
703+
id: 0,
704+
steps: undefined,
705+
},
706+
],
707+
};
708+
const etag =
709+
"37c2311495bbea359329d0bb72561bdb2b2fffea1b7a54f696b5a287e7ccad1e";
710+
let submittedEtag = null;
711+
vi.spyOn(
712+
mockOctokit.rest.actions,
713+
"listJobsForWorkflowRun",
714+
).mockImplementation(({ headers }) => {
715+
if (headers["If-None-Match"]) {
716+
submittedEtag = headers["If-None-Match"];
717+
return Promise.resolve({
718+
data: null,
719+
status: 304,
720+
headers: {
721+
etag: `W/"${submittedEtag}"`,
722+
},
723+
});
724+
}
725+
return Promise.resolve({
726+
data: mockData,
727+
status: 200,
728+
headers: {
729+
etag: `W/"${etag}"`,
730+
},
731+
});
732+
});
733+
734+
// Behaviour
735+
// First API call will return 200 with an etag response header
736+
await fetchWorkflowRunJobSteps(0);
737+
expect(submittedEtag).eq(null);
738+
// Second API call will return 304 because of If-None-Match header
739+
await expect(fetchWorkflowRunJobSteps(0)).resolves.toStrictEqual([]);
740+
expect(submittedEtag).eq(etag);
741+
742+
// Logging
743+
assertOnlyCalled(coreDebugLogMock);
744+
expect(coreDebugLogMock).toHaveBeenCalledTimes(2);
745+
expect(coreDebugLogMock.mock.calls[0]?.[0]).toMatchInlineSnapshot(
746+
`
747+
"Fetched Workflow Run Job Steps:
748+
Repository: owner/repo
749+
Workflow Run ID: 0
750+
Jobs Fetched: [0]
751+
Steps Fetched: []"
752+
`,
753+
);
754+
});
675755
});
676756

677757
describe("fetchWorkflowRunUrl", () => {
@@ -683,6 +763,7 @@ describe("API", () => {
683763
Promise.resolve({
684764
data: mockData,
685765
status: 200,
766+
headers: {},
686767
}),
687768
);
688769

@@ -696,6 +777,7 @@ describe("API", () => {
696777
Promise.resolve({
697778
data: undefined,
698779
status: errorStatus,
780+
headers: {},
699781
}),
700782
);
701783

0 commit comments

Comments
 (0)