Skip to content

Commit be35e05

Browse files
committed
test: fetch-retry for github actions
1 parent 152decc commit be35e05

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

.github/workflows/run-tests.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ jobs:
124124
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
125125
NEXT_VERSION: ${{ matrix.version }}
126126
NEXT_RESOLVED_VERSION: ${{ steps.resolve-next-version.outputs.version }}
127+
NODE_OPTIONS: --import ${{ github.workspace }}/tools/fetch-retry.mjs
127128
- name: Upload blob report to GitHub Actions Artifacts
128129
uses: actions/upload-artifact@v4
129130
if: always()
@@ -220,13 +221,15 @@ jobs:
220221
env:
221222
NEXT_VERSION: ${{ matrix.version }}
222223
NEXT_RESOLVED_VERSION: ${{ steps.resolve-next-version.outputs.version }}
224+
NODE_OPTIONS: --import ${{ github.workspace }}/tools/fetch-retry.mjs
223225
- name: 'Unit and integration tests'
224226
run: npm run test:ci:unit-and-integration -- --shard=${{ matrix.shard }}/8
225227
env:
226228
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
227229
NEXT_VERSION: ${{ matrix.version }}
228230
NEXT_RESOLVED_VERSION: ${{ steps.resolve-next-version.outputs.version }}
229231
TEMP: ${{ github.workspace }}/..
232+
NODE_OPTIONS: --import ${{ github.workspace }}/tools/fetch-retry.mjs
230233

231234
smoke:
232235
if: always()
@@ -289,6 +292,7 @@ jobs:
289292
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
290293
NEXT_VERSION: ${{ matrix.version }}
291294
NEXT_RESOLVED_VERSION: ${{ steps.resolve-next-version.outputs.version }}
295+
NODE_OPTIONS: --import ${{ github.workspace }}/tools/fetch-retry.mjs
292296

293297
merge-reports:
294298
if: always()

tools/fetch-retry.mjs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// We are seeing quite a bit of 'fetch failed' cases in Github Actions that don't really reproduce
2+
// locally. We are likely hitting some limits there when attempting to parallelize. They are not consistent
3+
// so instead of reducing parallelism, we add a retry with backoff here.
4+
5+
const originalFetch = globalThis.fetch
6+
7+
const NUM_RETRIES = 5
8+
9+
globalThis.fetch = async (...args) => {
10+
let backoff = 100
11+
for (let attempt = 1; attempt <= NUM_RETRIES; attempt++) {
12+
try {
13+
return await originalFetch.apply(globalThis, args)
14+
} catch (error) {
15+
let shouldRetry = false
16+
// not ideal, but there is no error code for that
17+
if (error.message === 'fetch failed' && attempt < NUM_RETRIES) {
18+
// on this error we try again
19+
shouldRetry = true
20+
}
21+
22+
if (shouldRetry) {
23+
// leave some trace in logs what's happening
24+
console.error('[fetch-retry] fetch thrown, retrying...', {
25+
args,
26+
attempt,
27+
errorMsg: error.message,
28+
})
29+
30+
const currentBackoff = backoff
31+
await new Promise((resolve) => {
32+
setTimeout(resolve, currentBackoff)
33+
})
34+
backoff *= 2
35+
continue
36+
}
37+
38+
throw error
39+
}
40+
}
41+
}

0 commit comments

Comments
 (0)