7 Commits
2.4.1 ... 2.5.0

Author SHA1 Message Date
Sven-Hendrik Haase
7319e4733e 2.5.0 2023-02-21 15:45:38 +01:00
Sven-Hendrik Haase
4e86b8565b Prepare release 2023-02-21 15:11:15 +01:00
Sven-Hendrik Haase
3a6baf0f12 Add CHANGELOG entry for retry feature 2023-02-21 15:08:59 +01:00
Sven-Hendrik Haase
e8c797e08e Merge pull request #96 from sonphantrung/retry-v2
Add retry to upload release (UPDATED VERSION)
2023-02-21 15:07:45 +01:00
Son Phan Trung
cf83be2c7f Merge branch 'master' into retry-v2 2023-02-21 20:08:09 +07:00
Son Phan Trung
cfdd9b50bd Merge branch 'retry' of https://github.com/messense/upload-release-action 2023-02-21 20:06:34 +07:00
messense
1819382cf9 Add retry to upload release 2022-07-03 11:23:10 +08:00
5 changed files with 655 additions and 5183 deletions

View File

@@ -1,5 +1,8 @@
# Changelog # Changelog
## [2.5.0] - 2023-02-21
- Add retry to upload release [#96](https://github.com/svenstaro/upload-release-action/pull/96) (thanks @sonphantrung)
## [2.4.1] - 2023-02-01 ## [2.4.1] - 2023-02-01
- Modernize octokit usage - Modernize octokit usage

175
dist/index.js vendored
View File

@@ -44,6 +44,7 @@ const core = __importStar(__nccwpck_require__(2186));
const github = __importStar(__nccwpck_require__(5438)); const github = __importStar(__nccwpck_require__(5438));
const path = __importStar(__nccwpck_require__(1017)); const path = __importStar(__nccwpck_require__(1017));
const glob = __importStar(__nccwpck_require__(1957)); const glob = __importStar(__nccwpck_require__(1957));
const attempt_1 = __nccwpck_require__(6494);
const releaseByTag = 'GET /repos/{owner}/{repo}/releases/tags/{tag}'; const releaseByTag = 'GET /repos/{owner}/{repo}/releases/tags/{tag}';
const createRelease = 'POST /repos/{owner}/{repo}/releases'; const createRelease = 'POST /repos/{owner}/{repo}/releases';
const repoAssets = 'GET /repos/{owner}/{repo}/releases/{release_id}/assets'; const repoAssets = 'GET /repos/{owner}/{repo}/releases/{release_id}/assets';
@@ -93,10 +94,14 @@ function upload_to_release(release, file, asset_name, tag, overwrite, octokit) {
core.debug(`No pre-existing asset called ${asset_name} found in release ${tag}. All good.`); core.debug(`No pre-existing asset called ${asset_name} found in release ${tag}. All good.`);
} }
core.debug(`Uploading ${file} to ${asset_name} in release ${tag}.`); core.debug(`Uploading ${file} to ${asset_name} in release ${tag}.`);
const uploaded_asset = yield octokit.request(uploadAssets, Object.assign(Object.assign({}, repo()), { release_id: release.data.id, url: release.data.upload_url, name: asset_name, data: file_bytes, headers: { const uploaded_asset = yield (0, attempt_1.retry)(() => __awaiter(this, void 0, void 0, function* () {
'content-type': 'binary/octet-stream', return octokit.request(uploadAssets, Object.assign(Object.assign({}, repo()), { release_id: release.data.id, url: release.data.upload_url, name: asset_name, data: file_bytes, headers: {
'content-length': file_size 'content-type': 'binary/octet-stream',
} })); 'content-length': file_size
} }));
}), {
maxAttempts: 3
});
return uploaded_asset.data.browser_download_url; return uploaded_asset.data.browser_download_url;
}); });
} }
@@ -2146,6 +2151,168 @@ function checkBypass(reqUrl) {
exports.checkBypass = checkBypass; exports.checkBypass = checkBypass;
//# sourceMappingURL=proxy.js.map //# sourceMappingURL=proxy.js.map
/***/ }),
/***/ 6494:
/***/ ((__unused_webpack_module, exports) => {
"use strict";
Object.defineProperty(exports, "__esModule", ({ value: true }));
function applyDefaults(options) {
if (!options) {
options = {};
}
return {
delay: (options.delay === undefined) ? 200 : options.delay,
initialDelay: (options.initialDelay === undefined) ? 0 : options.initialDelay,
minDelay: (options.minDelay === undefined) ? 0 : options.minDelay,
maxDelay: (options.maxDelay === undefined) ? 0 : options.maxDelay,
factor: (options.factor === undefined) ? 0 : options.factor,
maxAttempts: (options.maxAttempts === undefined) ? 3 : options.maxAttempts,
timeout: (options.timeout === undefined) ? 0 : options.timeout,
jitter: (options.jitter === true),
handleError: (options.handleError === undefined) ? null : options.handleError,
handleTimeout: (options.handleTimeout === undefined) ? null : options.handleTimeout,
beforeAttempt: (options.beforeAttempt === undefined) ? null : options.beforeAttempt,
calculateDelay: (options.calculateDelay === undefined) ? null : options.calculateDelay
};
}
async function sleep(delay) {
return new Promise((resolve, reject) => {
setTimeout(resolve, delay);
});
}
exports.sleep = sleep;
function defaultCalculateDelay(context, options) {
let delay = options.delay;
if (delay === 0) {
// no delay between attempts
return 0;
}
if (options.factor) {
delay *= Math.pow(options.factor, context.attemptNum - 1);
if (options.maxDelay !== 0) {
delay = Math.min(delay, options.maxDelay);
}
}
if (options.jitter) {
// Jitter will result in a random value between `minDelay` and
// calculated delay for a given attempt.
// See https://www.awsarchitectureblog.com/2015/03/backoff.html
// We're using the "full jitter" strategy.
const min = Math.ceil(options.minDelay);
const max = Math.floor(delay);
delay = Math.floor(Math.random() * (max - min + 1)) + min;
}
return Math.round(delay);
}
exports.defaultCalculateDelay = defaultCalculateDelay;
async function retry(attemptFunc, attemptOptions) {
const options = applyDefaults(attemptOptions);
for (const prop of [
'delay',
'initialDelay',
'minDelay',
'maxDelay',
'maxAttempts',
'timeout'
]) {
const value = options[prop];
if (!Number.isInteger(value) || (value < 0)) {
throw new Error(`Value for ${prop} must be an integer greater than or equal to 0`);
}
}
if ((options.factor.constructor !== Number) || (options.factor < 0)) {
throw new Error(`Value for factor must be a number greater than or equal to 0`);
}
if (options.delay < options.minDelay) {
throw new Error(`delay cannot be less than minDelay (delay: ${options.delay}, minDelay: ${options.minDelay}`);
}
const context = {
attemptNum: 0,
attemptsRemaining: options.maxAttempts ? options.maxAttempts : -1,
aborted: false,
abort() {
context.aborted = true;
}
};
const calculateDelay = options.calculateDelay || defaultCalculateDelay;
async function makeAttempt() {
if (options.beforeAttempt) {
options.beforeAttempt(context, options);
}
if (context.aborted) {
const err = new Error(`Attempt aborted`);
err.code = 'ATTEMPT_ABORTED';
throw err;
}
const onError = async (err) => {
if (options.handleError) {
await options.handleError(err, context, options);
}
if (context.aborted || (context.attemptsRemaining === 0)) {
throw err;
}
// We are about to try again so increment attempt number
context.attemptNum++;
const delay = calculateDelay(context, options);
if (delay) {
await sleep(delay);
}
return makeAttempt();
};
if (context.attemptsRemaining > 0) {
context.attemptsRemaining--;
}
if (options.timeout) {
return new Promise((resolve, reject) => {
const timer = setTimeout(() => {
if (options.handleTimeout) {
// If calling handleTimeout throws an error that is not wrapped in a promise
// we want to catch the error and reject.
try {
resolve(options.handleTimeout(context, options));
}
catch (e) {
reject(e);
}
}
else {
const err = new Error(`Retry timeout (attemptNum: ${context.attemptNum}, timeout: ${options.timeout})`);
err.code = 'ATTEMPT_TIMEOUT';
reject(err);
}
}, options.timeout);
attemptFunc(context, options).then((result) => {
clearTimeout(timer);
resolve(result);
}).catch((err) => {
clearTimeout(timer);
// Calling resolve with a Promise that rejects here will result
// in an unhandled rejection. Calling `reject` with errors
// does not result in an unhandled rejection
onError(err).then(resolve).catch(reject);
});
});
}
else {
// No timeout provided so wait indefinitely for the returned promise
// to be resolved.
return attemptFunc(context, options).catch(onError);
}
}
const initialDelay = options.calculateDelay
? options.calculateDelay(context, options)
: options.initialDelay;
if (initialDelay) {
await sleep(initialDelay);
}
return makeAttempt();
}
exports.retry = retry;
/***/ }), /***/ }),
/***/ 334: /***/ 334:

5629
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{ {
"name": "upload-release-action", "name": "upload-release-action",
"version": "2.4.1", "version": "2.5.0",
"private": true, "private": true,
"description": "Upload files to a GitHub release", "description": "Upload files to a GitHub release",
"main": "lib/main.js", "main": "lib/main.js",
@@ -29,6 +29,7 @@
"dependencies": { "dependencies": {
"@actions/core": "^1.10.0", "@actions/core": "^1.10.0",
"@actions/github": "^5", "@actions/github": "^5",
"@lifeomic/attempt": "^3.0.3",
"glob": "^7" "glob": "^7"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -5,6 +5,7 @@ import * as core from '@actions/core'
import * as github from '@actions/github' import * as github from '@actions/github'
import * as path from 'path' import * as path from 'path'
import * as glob from 'glob' import * as glob from 'glob'
import {retry} from '@lifeomic/attempt'
const releaseByTag = 'GET /repos/{owner}/{repo}/releases/tags/{tag}' as const const releaseByTag = 'GET /repos/{owner}/{repo}/releases/tags/{tag}' as const
const createRelease = 'POST /repos/{owner}/{repo}/releases' as const const createRelease = 'POST /repos/{owner}/{repo}/releases' as const
@@ -94,17 +95,24 @@ async function upload_to_release(
} }
core.debug(`Uploading ${file} to ${asset_name} in release ${tag}.`) core.debug(`Uploading ${file} to ${asset_name} in release ${tag}.`)
const uploaded_asset: UploadAssetResp = await octokit.request(uploadAssets, { const uploaded_asset: UploadAssetResp = await retry(
...repo(), async () => {
release_id: release.data.id, return octokit.request(uploadAssets, {
url: release.data.upload_url, ...repo(),
name: asset_name, release_id: release.data.id,
data: file_bytes, url: release.data.upload_url,
headers: { name: asset_name,
'content-type': 'binary/octet-stream', data: file_bytes,
'content-length': file_size headers: {
'content-type': 'binary/octet-stream',
'content-length': file_size
}
})
},
{
maxAttempts: 3
} }
}) )
return uploaded_asset.data.browser_download_url return uploaded_asset.data.browser_download_url
} }