Skip to content

Commit

Permalink
feat: retry only on specific exit code (#58)
Browse files Browse the repository at this point in the history
* feat: retry only on specific exit code

* Run ci_cd on all push events

* dedupe step IDs

* add assertions for retry_on_exit_code tests

* minor: implemented suggested fix from @andersfischernielsen

* docs: update readme to reflect new retry_on_exit_code input

Co-authored-by: Anders Fischer-Nielsen <andersfischern@me.com>
  • Loading branch information
nick-fields and andersfischernielsen authored Apr 26, 2022
1 parent 7106228 commit f227091
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 14 deletions.
39 changes: 37 additions & 2 deletions .github/workflows/ci_cd.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
name: CI/CD
on:
push:
branches:
- '**'

jobs:
# runs on branch pushes only
ci:
Expand Down Expand Up @@ -79,6 +78,42 @@ jobs:
command: node -e "process.exit(1)"
on_retry_command: node -e "console.log('this is a retry command')"

- name: retry_on_exit_code (with expected error code)
id: retry_on_exit_code_expected
uses: ./
continue-on-error: true
with:
timeout_minutes: 1
retry_on_exit_code: 2
max_attempts: 3
command: node -e "process.exit(2)"
- uses: nick-invision/assert-action@v1
with:
expected: failure
actual: ${{ steps.retry_on_exit_code_expected.outcome }}
- uses: nick-invision/assert-action@v1
with:
expected: 3
actual: ${{ steps.retry_on_exit_code_expected.outputs.total_attempts }}

- name: retry_on_exit_code (with unexpected error code)
id: retry_on_exit_code_unexpected
uses: ./
continue-on-error: true
with:
timeout_minutes: 1
retry_on_exit_code: 2
max_attempts: 3
command: node -e "process.exit(1)"
- uses: nick-invision/assert-action@v1
with:
expected: failure
actual: ${{ steps.retry_on_exit_code_unexpected.outcome }}
- uses: nick-invision/assert-action@v1
with:
expected: 1
actual: ${{ steps.retry_on_exit_code_unexpected.outputs.total_attempts }}

- name: on-retry-cmd (on-retry fails)
id: on-retry-cmd-fails
uses: ./
Expand Down
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Retries an Action step on failure or timeout. This is currently intended to replace the `run` step for moody commands.

**NOTE:** Ownership of this project was transferred to my personal account `nick-fields` from my work account `nick-invision`. Details [here](#Ownership)
**NOTE:** Ownership of this project was transferred to my personal account `nick-fields` from my work account `nick-invision`. Details [here](#Ownership)

---

Expand Down Expand Up @@ -56,6 +56,10 @@ Retries an Action step on failure or timeout. This is currently intended to repl

**Optional** Exit successfully even if an error occurs. Same as native continue-on-error behavior, but for use in composite actions. Defaults to `false`

### `retry_on_exit_code`

**Optional** Specific exit code to retry on. This will only retry for the given error code and fail immediately other error codes.

## Outputs

### `total_attempts`
Expand Down Expand Up @@ -233,6 +237,6 @@ NodeJS is required for this action to run. This runs without issue on all GitHub

## **Ownership**

As of 2022/02/15 ownership of this project has been transferred to my personal account `nick-fields` from my work account `nick-invision` due to me leaving InVision. I am the author and have been the primary maintainer since day one and will continue to maintain this as needed.
As of 2022/02/15 ownership of this project has been transferred to my personal account `nick-fields` from my work account `nick-invision` due to me leaving InVision. I am the author and have been the primary maintainer since day one and will continue to maintain this as needed.

Existing workflow references to `nick-invision/retry@<whatever>` no longer work and must be updated to `nick-fields/retry@<whatever>`.
3 changes: 3 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ inputs:
new_command_on_retry:
description: Command to run if the first attempt fails. This command will be called on all subsequent attempts.
required: false
retry_on_exit_code:
description: Specific exit code to retry on. This will only retry for the given error code and fail immediately other error codes.
required: false
outputs:
total_attempts:
description: The final number of attempts made
Expand Down
24 changes: 14 additions & 10 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ var WARNING_ON_RETRY = core_1.getInput('warning_on_retry').toLowerCase() === 'tr
var ON_RETRY_COMMAND = core_1.getInput('on_retry_command');
var CONTINUE_ON_ERROR = getInputBoolean('continue_on_error');
var NEW_COMMAND_ON_RETRY = core_1.getInput('new_command_on_retry');
var RETRY_ON_EXIT_CODE = getInputNumber('retry_on_exit_code', false);
var OS = process.platform;
var OUTPUT_TOTAL_ATTEMPTS_KEY = 'total_attempts';
var OUTPUT_EXIT_CODE_KEY = 'exit_code';
Expand Down Expand Up @@ -479,17 +480,17 @@ function runAction() {
attempt = 1;
_a.label = 2;
case 2:
if (!(attempt <= MAX_ATTEMPTS)) return [3 /*break*/, 12];
if (!(attempt <= MAX_ATTEMPTS)) return [3 /*break*/, 13];
_a.label = 3;
case 3:
_a.trys.push([3, 5, , 11]);
_a.trys.push([3, 5, , 12]);
// just keep overwriting attempts output
core_1.setOutput(OUTPUT_TOTAL_ATTEMPTS_KEY, attempt);
return [4 /*yield*/, runCmd(attempt)];
case 4:
_a.sent();
core_1.info("Command completed after " + attempt + " attempt(s).");
return [3 /*break*/, 12];
return [3 /*break*/, 13];
case 5:
error_2 = _a.sent();
if (!(attempt === MAX_ATTEMPTS)) return [3 /*break*/, 6];
Expand All @@ -499,24 +500,27 @@ function runAction() {
// error: timeout
throw error_2;
case 7:
if (!(exit > 0 && RETRY_ON === 'timeout')) return [3 /*break*/, 8];
if (!(RETRY_ON_EXIT_CODE && RETRY_ON_EXIT_CODE !== exit)) return [3 /*break*/, 8];
throw error_2;
case 8:
if (!(exit > 0 && RETRY_ON === 'timeout')) return [3 /*break*/, 9];
// error: error
throw error_2;
case 8: return [4 /*yield*/, runRetryCmd()];
case 9:
case 9: return [4 /*yield*/, runRetryCmd()];
case 10:
_a.sent();
if (WARNING_ON_RETRY) {
core_1.warning("Attempt " + attempt + " failed. Reason: " + error_2.message);
}
else {
core_1.info("Attempt " + attempt + " failed. Reason: " + error_2.message);
}
_a.label = 10;
case 10: return [3 /*break*/, 11];
case 11:
_a.label = 11;
case 11: return [3 /*break*/, 12];
case 12:
attempt++;
return [3 /*break*/, 2];
case 12: return [2 /*return*/];
case 13: return [2 /*return*/];
}
});
});
Expand Down
3 changes: 3 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const WARNING_ON_RETRY = getInput('warning_on_retry').toLowerCase() === 'true';
const ON_RETRY_COMMAND = getInput('on_retry_command');
const CONTINUE_ON_ERROR = getInputBoolean('continue_on_error');
const NEW_COMMAND_ON_RETRY = getInput('new_command_on_retry');
const RETRY_ON_EXIT_CODE = getInputNumber('retry_on_exit_code', false);

const OS = process.platform;
const OUTPUT_TOTAL_ATTEMPTS_KEY = 'total_attempts';
Expand Down Expand Up @@ -187,6 +188,8 @@ async function runAction() {
} else if (!done && RETRY_ON === 'error') {
// error: timeout
throw error;
} else if (RETRY_ON_EXIT_CODE && RETRY_ON_EXIT_CODE !== exit){
throw error;
} else if (exit > 0 && RETRY_ON === 'timeout') {
// error: error
throw error;
Expand Down

0 comments on commit f227091

Please sign in to comment.