diff --git a/index.ts b/index.ts index 95a7300..ac66d09 100644 --- a/index.ts +++ b/index.ts @@ -1,9 +1,9 @@ /* eslint-disable no-void */ import { dirname } from 'path'; import { mkdir, writeFile } from 'fs/promises'; -import * as core from '@actions/core'; -import * as github from '@actions/github'; - +import core from '@actions/core'; +import github from '@actions/github'; +import retry from 'async-retry'; import type { Context } from '@actions/github/lib/context'; import type { HeadersInit } from 'node-fetch'; import fetch from 'node-fetch'; @@ -66,13 +66,10 @@ interface FetchAssetFileOptions { readonly token: string; } -const MAX_RETRY = 5; -const RETRY_INTERVAL = 1000; - -const fetchAssetFile = async ( +const baseFetchAssetFile = async ( octokit: ReturnType, { id, outputPath, owner, repo, token }: FetchAssetFileOptions -): Promise => { +) => { const { body, headers: { accept, 'user-agent': userAgent }, @@ -96,28 +93,27 @@ const fetchAssetFile = async ( if (typeof userAgent !== 'undefined') headers = { ...headers, 'user-agent': userAgent }; - let i = 0; - while (true) { - const response = await fetch(url, { body, headers, method }); - if (!response.ok) { - if (i < MAX_RETRY) { - i++; - await new Promise((resolve) => setTimeout(resolve, RETRY_INTERVAL)); - continue; - } else { - const text = await response.text(); - core.warning(text); - throw new Error('Invalid response'); - } - } - const blob = await response.blob(); - const arrayBuffer = await blob.arrayBuffer(); - await mkdir(dirname(outputPath), { recursive: true }); - await writeFile(outputPath, new Uint8Array(arrayBuffer)); - return; + const response = await fetch(url, { body, headers, method }); + if (!response.ok) { + const text = await response.text(); + core.warning(text); + throw new Error('Invalid response'); } + const blob = await response.blob(); + const arrayBuffer = await blob.arrayBuffer(); + await mkdir(dirname(outputPath), { recursive: true }); + void (await writeFile(outputPath, new Uint8Array(arrayBuffer))); }; +const fetchAssetFile = ( + octokit: ReturnType, + options: FetchAssetFileOptions +) => + retry(() => baseFetchAssetFile(octokit, options), { + retries: 5, + minTimeout: 1000, + }); + const printOutput = (release: GetReleaseResult): void => { core.setOutput('version', release.data.tag_name); core.setOutput('name', release.data.name); diff --git a/package.json b/package.json index 751e815..743cebd 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ }, "homepage": "https://github.com/dsaltares/fetch-gh-release-asset#readme", "devDependencies": { + "@types/async-retry": "^1.4.4", "@types/node": "^17.0.22", "@typescript-eslint/eslint-plugin": "^5.16.0", "@typescript-eslint/parser": "^5.16.0", @@ -35,6 +36,7 @@ "dependencies": { "@actions/core": "^1.6.0", "@actions/github": "^5.0.1", + "async-retry": "^1.3.3", "node-fetch": "^3.2.3" } } diff --git a/yarn.lock b/yarn.lock index a03d521..326c695 100644 --- a/yarn.lock +++ b/yarn.lock @@ -183,6 +183,13 @@ dependencies: "@octokit/openapi-types" "^11.2.0" +"@types/async-retry@^1.4.4": + version "1.4.4" + resolved "https://registry.yarnpkg.com/@types/async-retry/-/async-retry-1.4.4.tgz#3304ce1e64f8757723f166518fc4c4b68df4fe66" + integrity sha512-IGT+yESLPYje0MV8MfOpT5V5oH9lAKLwlosQRyq75tYJmntkkWcfEThHLxsgYjGmYXJEY7ZZkYPb4xuW+NA6GA== + dependencies: + "@types/retry" "*" + "@types/json-schema@^7.0.9": version "7.0.11" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" @@ -198,6 +205,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.31.tgz#a5bb84ecfa27eec5e1c802c6bbf8139bdb163a5d" integrity sha512-AR0x5HbXGqkEx9CadRH3EBYx/VkiUgZIhP4wvPn/+5KIsgpNoyFaRlVe0Zlx9gRtg8fA06a9tskE2MSN7TcG4Q== +"@types/retry@*": + version "0.12.2" + resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.2.tgz#ed279a64fa438bb69f2480eda44937912bb7480a" + integrity sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow== + "@typescript-eslint/eslint-plugin@^5.16.0": version "5.22.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.22.0.tgz#7b52a0de2e664044f28b36419210aea4ab619e2a" @@ -370,6 +382,13 @@ astral-regex@^2.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== +async-retry@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.3.3.tgz#0e7f36c04d8478e7a58bdbed80cedf977785f280" + integrity sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw== + dependencies: + retry "0.13.1" + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -1580,6 +1599,11 @@ resolve@^1.10.1, resolve@^1.20.0, resolve@^1.22.0: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +retry@0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" + integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== + reusify@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"