mirror of
https://github.com/nick-fields/retry.git
synced 2026-02-10 07:05:29 +00:00
Compare commits
9 Commits
v2.8.2
...
nrf/add-te
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
634988cced | ||
|
|
14672906e6 | ||
|
|
1139f998ef | ||
|
|
1d41e5db1a | ||
|
|
1859f94181 | ||
|
|
cc15f2ffff | ||
|
|
db9d6ef914 | ||
|
|
943e742917 | ||
|
|
0711ba3d78 |
2
.github/ISSUE_TEMPLATE/bug-report.md
vendored
2
.github/ISSUE_TEMPLATE/bug-report.md
vendored
@@ -16,4 +16,4 @@ A clear and concise description of what you expected to happen.
|
|||||||
If applicable, add screenshots to help explain your problem.
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
**Logs**
|
**Logs**
|
||||||
Enable [debug logging](https://docs.github.com/en/free-pro-team@latest/actions/managing-workflow-runs/enabling-debug-logging#enabling-step-debug-logging) then attach the [raw logs](https://docs.github.com/en/free-pro-team@latest/actions/managing-workflow-runs/using-workflow-run-logs#downloading-logs) (specifically the raw output of this action).
|
Enable [debug logging](https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/enabling-debug-logging#enabling-step-debug-logging) then attach the [raw logs](https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/using-workflow-run-logs#downloading-logs) (specifically the raw output of this action).
|
||||||
|
|||||||
24
.github/workflows/ci_cd.yml
vendored
24
.github/workflows/ci_cd.yml
vendored
@@ -1,12 +1,16 @@
|
|||||||
name: CI/CD
|
name: CI/CD
|
||||||
on:
|
on:
|
||||||
|
# only on PRs into and merge to default branch
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
push:
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# runs on branch pushes only
|
|
||||||
ci_unit:
|
ci_unit:
|
||||||
name: Run Unit Tests
|
name: Run Unit Tests
|
||||||
if: startsWith(github.ref, 'refs/heads')
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -26,7 +30,6 @@ jobs:
|
|||||||
|
|
||||||
ci_integration:
|
ci_integration:
|
||||||
name: Run Integration Tests
|
name: Run Integration Tests
|
||||||
if: startsWith(github.ref, 'refs/heads')
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -137,7 +140,6 @@ jobs:
|
|||||||
|
|
||||||
ci_integration_envvar:
|
ci_integration_envvar:
|
||||||
name: Run Integration Env Var Tests
|
name: Run Integration Env Var Tests
|
||||||
if: startsWith(github.ref, 'refs/heads')
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -159,7 +161,6 @@ jobs:
|
|||||||
|
|
||||||
ci_integration_large_output:
|
ci_integration_large_output:
|
||||||
name: Run Integration Large Output Tests
|
name: Run Integration Large Output Tests
|
||||||
if: startsWith(github.ref, 'refs/heads')
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -191,7 +192,6 @@ jobs:
|
|||||||
|
|
||||||
ci_integration_retry_on_exit_code:
|
ci_integration_retry_on_exit_code:
|
||||||
name: Run Integration retry_on_exit_code Tests
|
name: Run Integration retry_on_exit_code Tests
|
||||||
if: startsWith(github.ref, 'refs/heads')
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -240,7 +240,6 @@ jobs:
|
|||||||
|
|
||||||
ci_integration_continue_on_error:
|
ci_integration_continue_on_error:
|
||||||
name: Run Integration continue_on_error Tests
|
name: Run Integration continue_on_error Tests
|
||||||
if: startsWith(github.ref, 'refs/heads')
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -288,7 +287,6 @@ jobs:
|
|||||||
|
|
||||||
ci_integration_retry_wait_seconds:
|
ci_integration_retry_wait_seconds:
|
||||||
name: Run Integration Tests (retry_wait_seconds)
|
name: Run Integration Tests (retry_wait_seconds)
|
||||||
if: startsWith(github.ref, 'refs/heads')
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -325,7 +323,6 @@ jobs:
|
|||||||
|
|
||||||
ci_integration_on_retry_cmd:
|
ci_integration_on_retry_cmd:
|
||||||
name: Run Integration Tests (on_retry_command)
|
name: Run Integration Tests (on_retry_command)
|
||||||
if: startsWith(github.ref, 'refs/heads')
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -369,7 +366,6 @@ jobs:
|
|||||||
# timeout tests take longer to run so run in parallel
|
# timeout tests take longer to run so run in parallel
|
||||||
ci_integration_timeout_seconds:
|
ci_integration_timeout_seconds:
|
||||||
name: Run Integration Timeout Tests (seconds)
|
name: Run Integration Timeout Tests (seconds)
|
||||||
if: startsWith(github.ref, 'refs/heads')
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -400,7 +396,6 @@ jobs:
|
|||||||
|
|
||||||
ci_integration_timeout_retry_on_timeout:
|
ci_integration_timeout_retry_on_timeout:
|
||||||
name: Run Integration Timeout Tests (retry_on timeout)
|
name: Run Integration Timeout Tests (retry_on timeout)
|
||||||
if: startsWith(github.ref, 'refs/heads')
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -432,7 +427,6 @@ jobs:
|
|||||||
|
|
||||||
ci_integration_timeout_retry_on_error:
|
ci_integration_timeout_retry_on_error:
|
||||||
name: Run Integration Timeout Tests (retry_on error)
|
name: Run Integration Timeout Tests (retry_on error)
|
||||||
if: startsWith(github.ref, 'refs/heads')
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -468,7 +462,6 @@ jobs:
|
|||||||
|
|
||||||
ci_integration_timeout_minutes:
|
ci_integration_timeout_minutes:
|
||||||
name: Run Integration Timeout Tests (minutes)
|
name: Run Integration Timeout Tests (minutes)
|
||||||
if: startsWith(github.ref, 'refs/heads')
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -499,7 +492,6 @@ jobs:
|
|||||||
|
|
||||||
ci_windows:
|
ci_windows:
|
||||||
name: Run Windows Tests
|
name: Run Windows Tests
|
||||||
if: startsWith(github.ref, 'refs/heads')
|
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -571,7 +563,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- run: echo "If this is hit, all tests successfully passed"
|
- run: echo "If this is hit, all tests successfully passed"
|
||||||
|
|
||||||
# runs on push to master only
|
# runs on merge to default only
|
||||||
cd:
|
cd:
|
||||||
name: Publish Action
|
name: Publish Action
|
||||||
needs: [ci_all_tests_passed]
|
needs: [ci_all_tests_passed]
|
||||||
@@ -588,7 +580,7 @@ jobs:
|
|||||||
run: npm ci
|
run: npm ci
|
||||||
- name: Release
|
- name: Release
|
||||||
id: semantic
|
id: semantic
|
||||||
uses: cycjimmy/semantic-release-action@v2
|
uses: cycjimmy/semantic-release-action@v4
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Tag
|
- name: Tag
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ Retries an Action step on failure or timeout. This is currently intended to repl
|
|||||||
|
|
||||||
### `shell`
|
### `shell`
|
||||||
|
|
||||||
**Optional** Shell to use to execute `command`. Defaults to `powershell` on Windows, `bash` otherwise. Supports bash, python, pwsh, sh, cmd, and powershell per [docs](https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions#using-a-specific-shell)
|
**Optional** Shell to use to execute `command`. Defaults to `powershell` on Windows, `bash` otherwise. Supports bash, python, pwsh, sh, cmd, and powershell per [docs](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsshell)
|
||||||
|
|
||||||
### `polling_interval_seconds`
|
### `polling_interval_seconds`
|
||||||
|
|
||||||
@@ -156,7 +156,7 @@ with:
|
|||||||
```yaml
|
```yaml
|
||||||
- uses: nick-fields/retry@v2
|
- uses: nick-fields/retry@v2
|
||||||
id: retry
|
id: retry
|
||||||
# see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions#jobsjob_idcontinue-on-error
|
# see https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idcontinue-on-error
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
timeout_seconds: 15
|
timeout_seconds: 15
|
||||||
|
|||||||
65
dist/index.js
vendored
65
dist/index.js
vendored
@@ -891,6 +891,21 @@ exports.retryWait = retryWait;
|
|||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
var __extends = (this && this.__extends) || (function () {
|
||||||
|
var extendStatics = function (d, b) {
|
||||||
|
extendStatics = Object.setPrototypeOf ||
|
||||||
|
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
||||||
|
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
||||||
|
return extendStatics(d, b);
|
||||||
|
};
|
||||||
|
return function (d, b) {
|
||||||
|
if (typeof b !== "function" && b !== null)
|
||||||
|
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
||||||
|
extendStatics(d, b);
|
||||||
|
function __() { this.constructor = d; }
|
||||||
|
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||||
|
};
|
||||||
|
})();
|
||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||||
return new (P || (P = Promise))(function (resolve, reject) {
|
return new (P || (P = Promise))(function (resolve, reject) {
|
||||||
@@ -941,14 +956,26 @@ var OS = process.platform;
|
|||||||
var OUTPUT_TOTAL_ATTEMPTS_KEY = 'total_attempts';
|
var OUTPUT_TOTAL_ATTEMPTS_KEY = 'total_attempts';
|
||||||
var OUTPUT_EXIT_CODE_KEY = 'exit_code';
|
var OUTPUT_EXIT_CODE_KEY = 'exit_code';
|
||||||
var OUTPUT_EXIT_ERROR_KEY = 'exit_error';
|
var OUTPUT_EXIT_ERROR_KEY = 'exit_error';
|
||||||
var exit;
|
|
||||||
var done;
|
var done;
|
||||||
|
var ErrorWithCode = /** @class */ (function (_super) {
|
||||||
|
__extends(ErrorWithCode, _super);
|
||||||
|
function ErrorWithCode(message, code) {
|
||||||
|
var _this = _super.call(this) || this;
|
||||||
|
_this.message = message;
|
||||||
|
_this.code = code;
|
||||||
|
_this.code = code;
|
||||||
|
_this.message = message;
|
||||||
|
return _this;
|
||||||
|
}
|
||||||
|
return ErrorWithCode;
|
||||||
|
}(Error));
|
||||||
function getExecutable(inputs) {
|
function getExecutable(inputs) {
|
||||||
if (!inputs.shell) {
|
if (!inputs.shell) {
|
||||||
return OS === 'win32' ? 'powershell' : 'bash';
|
return OS === 'win32' ? 'powershell' : 'bash';
|
||||||
}
|
}
|
||||||
var executable;
|
var executable;
|
||||||
switch (inputs.shell) {
|
var shellName = inputs.shell.split(' ')[0];
|
||||||
|
switch (shellName) {
|
||||||
case 'bash':
|
case 'bash':
|
||||||
case 'python':
|
case 'python':
|
||||||
case 'pwsh': {
|
case 'pwsh': {
|
||||||
@@ -957,7 +984,7 @@ function getExecutable(inputs) {
|
|||||||
}
|
}
|
||||||
case 'sh': {
|
case 'sh': {
|
||||||
if (OS === 'win32') {
|
if (OS === 'win32') {
|
||||||
throw new Error("Shell ".concat(inputs.shell, " not allowed on OS ").concat(OS));
|
throw new Error("Shell ".concat(shellName, " not allowed on OS ").concat(OS));
|
||||||
}
|
}
|
||||||
executable = inputs.shell;
|
executable = inputs.shell;
|
||||||
break;
|
break;
|
||||||
@@ -965,13 +992,13 @@ function getExecutable(inputs) {
|
|||||||
case 'cmd':
|
case 'cmd':
|
||||||
case 'powershell': {
|
case 'powershell': {
|
||||||
if (OS !== 'win32') {
|
if (OS !== 'win32') {
|
||||||
throw new Error("Shell ".concat(inputs.shell, " not allowed on OS ").concat(OS));
|
throw new Error("Shell ".concat(shellName, " not allowed on OS ").concat(OS));
|
||||||
}
|
}
|
||||||
executable = inputs.shell + '.exe';
|
executable = shellName + '.exe' + inputs.shell.replace(shellName, '');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
throw new Error("Shell ".concat(inputs.shell, " not supported. See https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions#using-a-specific-shell for supported shells"));
|
throw new Error("Shell ".concat(shellName, " not supported. See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsshell for supported shells"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return executable;
|
return executable;
|
||||||
@@ -1005,7 +1032,7 @@ function runRetryCmd(inputs) {
|
|||||||
function runCmd(attempt, inputs) {
|
function runCmd(attempt, inputs) {
|
||||||
var _a, _b;
|
var _a, _b;
|
||||||
return __awaiter(this, void 0, void 0, function () {
|
return __awaiter(this, void 0, void 0, function () {
|
||||||
var end_time, executable, child;
|
var end_time, executable, exit, timeout, child;
|
||||||
return __generator(this, function (_c) {
|
return __generator(this, function (_c) {
|
||||||
switch (_c.label) {
|
switch (_c.label) {
|
||||||
case 0:
|
case 0:
|
||||||
@@ -1013,6 +1040,7 @@ function runCmd(attempt, inputs) {
|
|||||||
executable = getExecutable(inputs);
|
executable = getExecutable(inputs);
|
||||||
exit = 0;
|
exit = 0;
|
||||||
done = false;
|
done = false;
|
||||||
|
timeout = false;
|
||||||
(0, core_1.debug)("Running command ".concat(inputs.command, " on ").concat(OS, " using shell ").concat(executable));
|
(0, core_1.debug)("Running command ".concat(inputs.command, " on ").concat(OS, " using shell ").concat(executable));
|
||||||
child = attempt > 1 && inputs.new_command_on_retry
|
child = attempt > 1 && inputs.new_command_on_retry
|
||||||
? (0, child_process_1.spawn)(inputs.new_command_on_retry, { shell: executable })
|
? (0, child_process_1.spawn)(inputs.new_command_on_retry, { shell: executable })
|
||||||
@@ -1026,13 +1054,17 @@ function runCmd(attempt, inputs) {
|
|||||||
child.on('exit', function (code, signal) {
|
child.on('exit', function (code, signal) {
|
||||||
(0, core_1.debug)("Code: ".concat(code));
|
(0, core_1.debug)("Code: ".concat(code));
|
||||||
(0, core_1.debug)("Signal: ".concat(signal));
|
(0, core_1.debug)("Signal: ".concat(signal));
|
||||||
if (code && code > 0) {
|
|
||||||
exit = code;
|
|
||||||
}
|
|
||||||
// timeouts are killed manually
|
// timeouts are killed manually
|
||||||
if (signal === 'SIGTERM') {
|
if (signal === 'SIGTERM') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// On Windows signal is null.
|
||||||
|
if (timeout) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (code && code > 0) {
|
||||||
|
exit = code;
|
||||||
|
}
|
||||||
done = true;
|
done = true;
|
||||||
});
|
});
|
||||||
_c.label = 1;
|
_c.label = 1;
|
||||||
@@ -1045,17 +1077,18 @@ function runCmd(attempt, inputs) {
|
|||||||
_c.label = 4;
|
_c.label = 4;
|
||||||
case 4:
|
case 4:
|
||||||
if (!(!done && child.pid)) return [3 /*break*/, 6];
|
if (!(!done && child.pid)) return [3 /*break*/, 6];
|
||||||
|
timeout = true;
|
||||||
(0, tree_kill_1.default)(child.pid);
|
(0, tree_kill_1.default)(child.pid);
|
||||||
return [4 /*yield*/, (0, util_1.retryWait)(milliseconds_1.default.seconds(inputs.retry_wait_seconds))];
|
return [4 /*yield*/, (0, util_1.retryWait)(milliseconds_1.default.seconds(inputs.retry_wait_seconds))];
|
||||||
case 5:
|
case 5:
|
||||||
_c.sent();
|
_c.sent();
|
||||||
throw new Error("Timeout of ".concat((0, inputs_1.getTimeout)(inputs), "ms hit"));
|
throw new ErrorWithCode("Timeout of ".concat((0, inputs_1.getTimeout)(inputs), "ms hit"), exit);
|
||||||
case 6:
|
case 6:
|
||||||
if (!(exit > 0)) return [3 /*break*/, 8];
|
if (!(exit > 0)) return [3 /*break*/, 8];
|
||||||
return [4 /*yield*/, (0, util_1.retryWait)(milliseconds_1.default.seconds(inputs.retry_wait_seconds))];
|
return [4 /*yield*/, (0, util_1.retryWait)(milliseconds_1.default.seconds(inputs.retry_wait_seconds))];
|
||||||
case 7:
|
case 7:
|
||||||
_c.sent();
|
_c.sent();
|
||||||
throw new Error("Child_process exited with error code ".concat(exit));
|
throw new ErrorWithCode("Child_process exited with error code ".concat(exit), exit);
|
||||||
case 8: return [2 /*return*/];
|
case 8: return [2 /*return*/];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1063,7 +1096,7 @@ function runCmd(attempt, inputs) {
|
|||||||
}
|
}
|
||||||
function runAction(inputs) {
|
function runAction(inputs) {
|
||||||
return __awaiter(this, void 0, void 0, function () {
|
return __awaiter(this, void 0, void 0, function () {
|
||||||
var attempt, error_2;
|
var attempt, error_2, exit;
|
||||||
return __generator(this, function (_a) {
|
return __generator(this, function (_a) {
|
||||||
switch (_a.label) {
|
switch (_a.label) {
|
||||||
case 0: return [4 /*yield*/, (0, inputs_1.validateInputs)(inputs)];
|
case 0: return [4 /*yield*/, (0, inputs_1.validateInputs)(inputs)];
|
||||||
@@ -1085,8 +1118,9 @@ function runAction(inputs) {
|
|||||||
return [3 /*break*/, 13];
|
return [3 /*break*/, 13];
|
||||||
case 5:
|
case 5:
|
||||||
error_2 = _a.sent();
|
error_2 = _a.sent();
|
||||||
|
exit = error_2 instanceof ErrorWithCode ? error_2.code : 1;
|
||||||
if (!(attempt === inputs.max_attempts)) return [3 /*break*/, 6];
|
if (!(attempt === inputs.max_attempts)) return [3 /*break*/, 6];
|
||||||
throw new Error("Final attempt failed. ".concat(error_2.message));
|
throw new ErrorWithCode("Final attempt failed. ".concat(error_2.message), exit);
|
||||||
case 6:
|
case 6:
|
||||||
if (!(!done && inputs.retry_on === 'error')) return [3 /*break*/, 7];
|
if (!(!done && inputs.retry_on === 'error')) return [3 /*break*/, 7];
|
||||||
// error: timeout
|
// error: timeout
|
||||||
@@ -1124,8 +1158,7 @@ runAction(inputs)
|
|||||||
process.exit(0); // success
|
process.exit(0); // success
|
||||||
})
|
})
|
||||||
.catch(function (err) {
|
.catch(function (err) {
|
||||||
// exact error code if available, otherwise just 1
|
var exitCode = err instanceof ErrorWithCode ? err.code : 1;
|
||||||
var exitCode = exit > 0 ? exit : 1;
|
|
||||||
if (inputs.continue_on_error) {
|
if (inputs.continue_on_error) {
|
||||||
(0, core_1.warning)(err.message);
|
(0, core_1.warning)(err.message);
|
||||||
}
|
}
|
||||||
|
|||||||
49
src/index.ts
49
src/index.ts
@@ -11,16 +11,25 @@ const OUTPUT_TOTAL_ATTEMPTS_KEY = 'total_attempts';
|
|||||||
const OUTPUT_EXIT_CODE_KEY = 'exit_code';
|
const OUTPUT_EXIT_CODE_KEY = 'exit_code';
|
||||||
const OUTPUT_EXIT_ERROR_KEY = 'exit_error';
|
const OUTPUT_EXIT_ERROR_KEY = 'exit_error';
|
||||||
|
|
||||||
let exit: number;
|
|
||||||
let done: boolean;
|
let done: boolean;
|
||||||
|
|
||||||
|
class ErrorWithCode extends Error {
|
||||||
|
constructor(readonly message: string, readonly code: number) {
|
||||||
|
super();
|
||||||
|
this.code = code;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getExecutable(inputs: Inputs): string {
|
function getExecutable(inputs: Inputs): string {
|
||||||
if (!inputs.shell) {
|
if (!inputs.shell) {
|
||||||
return OS === 'win32' ? 'powershell' : 'bash';
|
return OS === 'win32' ? 'powershell' : 'bash';
|
||||||
}
|
}
|
||||||
|
|
||||||
let executable: string;
|
let executable: string;
|
||||||
switch (inputs.shell) {
|
const shellName = inputs.shell.split(' ')[0];
|
||||||
|
|
||||||
|
switch (shellName) {
|
||||||
case 'bash':
|
case 'bash':
|
||||||
case 'python':
|
case 'python':
|
||||||
case 'pwsh': {
|
case 'pwsh': {
|
||||||
@@ -29,7 +38,7 @@ function getExecutable(inputs: Inputs): string {
|
|||||||
}
|
}
|
||||||
case 'sh': {
|
case 'sh': {
|
||||||
if (OS === 'win32') {
|
if (OS === 'win32') {
|
||||||
throw new Error(`Shell ${inputs.shell} not allowed on OS ${OS}`);
|
throw new Error(`Shell ${shellName} not allowed on OS ${OS}`);
|
||||||
}
|
}
|
||||||
executable = inputs.shell;
|
executable = inputs.shell;
|
||||||
break;
|
break;
|
||||||
@@ -37,14 +46,14 @@ function getExecutable(inputs: Inputs): string {
|
|||||||
case 'cmd':
|
case 'cmd':
|
||||||
case 'powershell': {
|
case 'powershell': {
|
||||||
if (OS !== 'win32') {
|
if (OS !== 'win32') {
|
||||||
throw new Error(`Shell ${inputs.shell} not allowed on OS ${OS}`);
|
throw new Error(`Shell ${shellName} not allowed on OS ${OS}`);
|
||||||
}
|
}
|
||||||
executable = inputs.shell + '.exe';
|
executable = shellName + '.exe' + inputs.shell.replace(shellName, '');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Shell ${inputs.shell} not supported. See https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions#using-a-specific-shell for supported shells`
|
`Shell ${shellName} not supported. See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsshell for supported shells`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -69,8 +78,9 @@ async function runCmd(attempt: number, inputs: Inputs) {
|
|||||||
const end_time = Date.now() + getTimeout(inputs);
|
const end_time = Date.now() + getTimeout(inputs);
|
||||||
const executable = getExecutable(inputs);
|
const executable = getExecutable(inputs);
|
||||||
|
|
||||||
exit = 0;
|
let exit = 0;
|
||||||
done = false;
|
done = false;
|
||||||
|
let timeout = false;
|
||||||
|
|
||||||
debug(`Running command ${inputs.command} on ${OS} using shell ${executable}`);
|
debug(`Running command ${inputs.command} on ${OS} using shell ${executable}`);
|
||||||
const child =
|
const child =
|
||||||
@@ -88,13 +98,21 @@ async function runCmd(attempt: number, inputs: Inputs) {
|
|||||||
child.on('exit', (code, signal) => {
|
child.on('exit', (code, signal) => {
|
||||||
debug(`Code: ${code}`);
|
debug(`Code: ${code}`);
|
||||||
debug(`Signal: ${signal}`);
|
debug(`Signal: ${signal}`);
|
||||||
if (code && code > 0) {
|
|
||||||
exit = code;
|
|
||||||
}
|
|
||||||
// timeouts are killed manually
|
// timeouts are killed manually
|
||||||
if (signal === 'SIGTERM') {
|
if (signal === 'SIGTERM') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// On Windows signal is null.
|
||||||
|
if (timeout) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (code && code > 0) {
|
||||||
|
exit = code;
|
||||||
|
}
|
||||||
|
|
||||||
done = true;
|
done = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -103,12 +121,13 @@ async function runCmd(attempt: number, inputs: Inputs) {
|
|||||||
} while (Date.now() < end_time && !done);
|
} while (Date.now() < end_time && !done);
|
||||||
|
|
||||||
if (!done && child.pid) {
|
if (!done && child.pid) {
|
||||||
|
timeout = true;
|
||||||
kill(child.pid);
|
kill(child.pid);
|
||||||
await retryWait(ms.seconds(inputs.retry_wait_seconds));
|
await retryWait(ms.seconds(inputs.retry_wait_seconds));
|
||||||
throw new Error(`Timeout of ${getTimeout(inputs)}ms hit`);
|
throw new ErrorWithCode(`Timeout of ${getTimeout(inputs)}ms hit`, exit);
|
||||||
} else if (exit > 0) {
|
} else if (exit > 0) {
|
||||||
await retryWait(ms.seconds(inputs.retry_wait_seconds));
|
await retryWait(ms.seconds(inputs.retry_wait_seconds));
|
||||||
throw new Error(`Child_process exited with error code ${exit}`);
|
throw new ErrorWithCode(`Child_process exited with error code ${exit}`, exit);
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -126,8 +145,9 @@ async function runAction(inputs: Inputs) {
|
|||||||
break;
|
break;
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
|
const exit = error instanceof ErrorWithCode ? error.code : 1;
|
||||||
if (attempt === inputs.max_attempts) {
|
if (attempt === inputs.max_attempts) {
|
||||||
throw new Error(`Final attempt failed. ${error.message}`);
|
throw new ErrorWithCode(`Final attempt failed. ${error.message}`, exit);
|
||||||
} else if (!done && inputs.retry_on === 'error') {
|
} else if (!done && inputs.retry_on === 'error') {
|
||||||
// error: timeout
|
// error: timeout
|
||||||
throw error;
|
throw error;
|
||||||
@@ -156,8 +176,7 @@ runAction(inputs)
|
|||||||
process.exit(0); // success
|
process.exit(0); // success
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
// exact error code if available, otherwise just 1
|
const exitCode = err instanceof ErrorWithCode ? err.code : 1;
|
||||||
const exitCode = exit > 0 ? exit : 1;
|
|
||||||
|
|
||||||
if (inputs.continue_on_error) {
|
if (inputs.continue_on_error) {
|
||||||
warning(err.message);
|
warning(err.message);
|
||||||
|
|||||||
Reference in New Issue
Block a user