Compare commits

...

3 Commits

Author SHA1 Message Date
Nick Fields
7f8f3d9f0f Merge pull request #50 from asnewman/new-command-on-retry-feature
Add new_command_on_retry
2021-12-09 20:05:34 -05:00
Nick Fields
bf1736e338 minor: regenerate dist 2021-12-09 20:02:53 -05:00
asnewman
f7cf641580 Add new_command_on_retry 2021-12-08 20:15:21 -08:00
5 changed files with 39 additions and 6 deletions

View File

@@ -60,6 +60,15 @@ jobs:
actual: ${{ steps.sad_path_wait_sec.outputs.exit_error }} actual: ${{ steps.sad_path_wait_sec.outputs.exit_error }}
comparison: contains comparison: contains
- name: new-command-on-retry
id: new-command-on-retry
uses: ./
with:
timeout_minutes: 1
max_attempts: 3
command: node -e "process.exit(1)"
new_command_on_retry: node -e "console.log('this is the new command on retry')"
- name: on-retry-cmd - name: on-retry-cmd
id: on-retry-cmd id: on-retry-cmd
uses: ./ uses: ./

View File

@@ -44,6 +44,10 @@ Retries an Action step on failure or timeout. This is currently intended to repl
**Optional** Command to run before a retry (such as a cleanup script). Any error thrown from retry command is caught and surfaced as a warning. **Optional** Command to run before a retry (such as a cleanup script). Any error thrown from retry command is caught and surfaced as a warning.
### `new_command_on_retry`
**Optional** Command to run if the first attempt fails. This command will be called on all subsequent attempts.
### `continue_on_error` ### `continue_on_error`
**Optional** Exit successfully even if an error occurs. Same as native continue-on-error behavior, but for use in composite actions. Defaults to `false` **Optional** Exit successfully even if an error occurs. Same as native continue-on-error behavior, but for use in composite actions. Defaults to `false`
@@ -179,6 +183,17 @@ with:
on_retry_command: npm run cleanup-flaky-script-output on_retry_command: npm run cleanup-flaky-script-output
``` ```
### Run different command after first failure
```yaml
uses: nick-invision/retry@v2
with:
timeout_seconds: 15
max_attempts: 3
command: npx jest
new_command_on_retry: npx jest --onlyFailures
```
### Run multi-line, multi-command script ### Run multi-line, multi-command script
```yaml ```yaml

View File

@@ -36,6 +36,9 @@ inputs:
continue_on_error: continue_on_error:
description: Exits successfully even if an error occurs. Same as native continue-on-error behavior, but for use in composite actions. Default is false description: Exits successfully even if an error occurs. Same as native continue-on-error behavior, but for use in composite actions. Default is false
default: false default: false
new_command_on_retry:
description: Command to run if the first attempt fails. This command will be called on all subsequent attempts.
required: false
outputs: outputs:
total_attempts: total_attempts:
description: The final number of attempts made description: The final number of attempts made

9
dist/index.js vendored
View File

@@ -288,6 +288,7 @@ var RETRY_ON = core_1.getInput('retry_on') || 'any';
var WARNING_ON_RETRY = core_1.getInput('warning_on_retry').toLowerCase() === 'true'; var WARNING_ON_RETRY = core_1.getInput('warning_on_retry').toLowerCase() === 'true';
var ON_RETRY_COMMAND = core_1.getInput('on_retry_command'); var ON_RETRY_COMMAND = core_1.getInput('on_retry_command');
var CONTINUE_ON_ERROR = getInputBoolean('continue_on_error'); var CONTINUE_ON_ERROR = getInputBoolean('continue_on_error');
var NEW_COMMAND_ON_RETRY = core_1.getInput('new_command_on_retry');
var OS = process.platform; 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';
@@ -408,7 +409,7 @@ function runRetryCmd() {
}); });
}); });
} }
function runCmd() { function runCmd(attempt) {
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, child;
@@ -420,7 +421,9 @@ function runCmd() {
exit = 0; exit = 0;
done = false; done = false;
core_1.debug("Running command " + COMMAND + " on " + OS + " using shell " + executable); core_1.debug("Running command " + COMMAND + " on " + OS + " using shell " + executable);
child = child_process_1.exec(COMMAND, { 'shell': executable }); child = attempt > 1 && NEW_COMMAND_ON_RETRY
? child_process_1.exec(NEW_COMMAND_ON_RETRY, { 'shell': executable })
: child_process_1.exec(COMMAND, { 'shell': executable });
(_a = child.stdout) === null || _a === void 0 ? void 0 : _a.on('data', function (data) { (_a = child.stdout) === null || _a === void 0 ? void 0 : _a.on('data', function (data) {
process.stdout.write(data); process.stdout.write(data);
}); });
@@ -482,7 +485,7 @@ function runAction() {
_a.trys.push([3, 5, , 11]); _a.trys.push([3, 5, , 11]);
// just keep overwriting attempts output // just keep overwriting attempts output
core_1.setOutput(OUTPUT_TOTAL_ATTEMPTS_KEY, attempt); core_1.setOutput(OUTPUT_TOTAL_ATTEMPTS_KEY, attempt);
return [4 /*yield*/, runCmd()]; return [4 /*yield*/, runCmd(attempt)];
case 4: case 4:
_a.sent(); _a.sent();
core_1.info("Command completed after " + attempt + " attempt(s)."); core_1.info("Command completed after " + attempt + " attempt(s).");

View File

@@ -17,6 +17,7 @@ const RETRY_ON = getInput('retry_on') || 'any';
const WARNING_ON_RETRY = getInput('warning_on_retry').toLowerCase() === 'true'; const WARNING_ON_RETRY = getInput('warning_on_retry').toLowerCase() === 'true';
const ON_RETRY_COMMAND = getInput('on_retry_command'); const ON_RETRY_COMMAND = getInput('on_retry_command');
const CONTINUE_ON_ERROR = getInputBoolean('continue_on_error'); const CONTINUE_ON_ERROR = getInputBoolean('continue_on_error');
const NEW_COMMAND_ON_RETRY = getInput('new_command_on_retry');
const OS = process.platform; const OS = process.platform;
const OUTPUT_TOTAL_ATTEMPTS_KEY = 'total_attempts'; const OUTPUT_TOTAL_ATTEMPTS_KEY = 'total_attempts';
@@ -122,7 +123,7 @@ async function runRetryCmd(): Promise<void> {
} }
} }
async function runCmd() { async function runCmd(attempt: number) {
const end_time = Date.now() + getTimeout(); const end_time = Date.now() + getTimeout();
const executable = getExecutable(); const executable = getExecutable();
@@ -130,7 +131,9 @@ async function runCmd() {
done = false; done = false;
debug(`Running command ${COMMAND} on ${OS} using shell ${executable}`) debug(`Running command ${COMMAND} on ${OS} using shell ${executable}`)
var child = exec(COMMAND, { 'shell': executable }); var child = attempt > 1 && NEW_COMMAND_ON_RETRY
? exec(NEW_COMMAND_ON_RETRY, { 'shell': executable })
: exec(COMMAND, { 'shell': executable });
child.stdout?.on('data', (data) => { child.stdout?.on('data', (data) => {
process.stdout.write(data); process.stdout.write(data);
@@ -175,7 +178,7 @@ async function runAction() {
try { try {
// just keep overwriting attempts output // just keep overwriting attempts output
setOutput(OUTPUT_TOTAL_ATTEMPTS_KEY, attempt); setOutput(OUTPUT_TOTAL_ATTEMPTS_KEY, attempt);
await runCmd(); await runCmd(attempt);
info(`Command completed after ${attempt} attempt(s).`); info(`Command completed after ${attempt} attempt(s).`);
break; break;
} catch (error) { } catch (error) {