Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new_command_on_retry #50

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/workflows/ci_cd.yml
Expand Up @@ -60,6 +60,15 @@ jobs:
actual: ${{ steps.sad_path_wait_sec.outputs.exit_error }}
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
id: on-retry-cmd
uses: ./
Expand Down
15 changes: 15 additions & 0 deletions README.md
Expand Up @@ -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.

### `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`

**Optional** Exit successfully even if an error occurs. Same as native continue-on-error behavior, but for use in composite actions. Defaults to `false`
Expand Down Expand Up @@ -179,6 +183,17 @@ with:
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

```yaml
Expand Down
3 changes: 3 additions & 0 deletions action.yml
Expand Up @@ -36,6 +36,9 @@ inputs:
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
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:
total_attempts:
description: The final number of attempts made
Expand Down
9 changes: 6 additions & 3 deletions dist/index.js
Expand Up @@ -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 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 OS = process.platform;
var OUTPUT_TOTAL_ATTEMPTS_KEY = 'total_attempts';
var OUTPUT_EXIT_CODE_KEY = 'exit_code';
Expand Down Expand Up @@ -408,7 +409,7 @@ function runRetryCmd() {
});
});
}
function runCmd() {
function runCmd(attempt) {
var _a, _b;
return __awaiter(this, void 0, void 0, function () {
var end_time, executable, child;
Expand All @@ -420,7 +421,9 @@ function runCmd() {
exit = 0;
done = false;
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) {
process.stdout.write(data);
});
Expand Down Expand Up @@ -482,7 +485,7 @@ function runAction() {
_a.trys.push([3, 5, , 11]);
// just keep overwriting attempts output
core_1.setOutput(OUTPUT_TOTAL_ATTEMPTS_KEY, attempt);
return [4 /*yield*/, runCmd()];
return [4 /*yield*/, runCmd(attempt)];
case 4:
_a.sent();
core_1.info("Command completed after " + attempt + " attempt(s).");
Expand Down
9 changes: 6 additions & 3 deletions src/index.ts
Expand Up @@ -17,6 +17,7 @@ const RETRY_ON = getInput('retry_on') || 'any';
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 OS = process.platform;
const OUTPUT_TOTAL_ATTEMPTS_KEY = 'total_attempts';
Expand Down Expand Up @@ -122,15 +123,17 @@ async function runRetryCmd(): Promise<void> {
}
}

async function runCmd() {
async function runCmd(attempt: number) {
const end_time = Date.now() + getTimeout();
const executable = getExecutable();

exit = 0;
done = false;

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) => {
process.stdout.write(data);
Expand Down Expand Up @@ -175,7 +178,7 @@ async function runAction() {
try {
// just keep overwriting attempts output
setOutput(OUTPUT_TOTAL_ATTEMPTS_KEY, attempt);
await runCmd();
await runCmd(attempt);
info(`Command completed after ${attempt} attempt(s).`);
break;
} catch (error) {
Expand Down