diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 1d298f5..835033c 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -313,6 +313,114 @@ jobs: expected: failure actual: ${{ steps.wrong_shell.outcome }} + ci_multiline_tests: + name: Run Tests (Multiline) + if: startsWith(github.ref, 'refs/heads') + runs-on: ubuntu-18.04 + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Setup Node.js + uses: actions/setup-node@v1 + with: + node-version: 16 + - name: Install dependencies + run: npm ci + + - name: Multi-line 2 commands non existent first command + id: multi_line_2_commands_non_existent_first_command + uses: ./ + continue-on-error: true + with: + shell: bash + timeout_seconds: 1 + max_attempts: 2 + command: | + i-do-not-exist && \ + echo "i-exist" + - uses: nick-invision/assert-action@v1 + with: + expected: 2 + actual: ${{ steps.multi_line_2_commands_non_existent_first_command.outputs.total_attempts }} + - uses: nick-invision/assert-action@v1 + with: + expected: 'Final attempt failed' + actual: ${{ steps.multi_line_2_commands_non_existent_first_command.outputs.exit_error }} + comparison: contains + - uses: nick-invision/assert-action@v1 + with: + # The 127 error code indicates “command not found”. + expected: '127' + actual: ${{ steps.multi_line_2_commands_non_existent_first_command.outputs.exit_code }} + comparison: contains + - uses: nick-invision/assert-action@v1 + with: + expected: 'i-exist' + actual: ${{ steps.multi_line_2_commands_non_existent_first_command.outputs.exit_error }} + comparison: notContains + + - name: Multi-line 2 commands happy path test + id: multi_line_2_commands_happy_path + uses: ./ + with: + shell: bash + timeout_seconds: 1 + max_attempts: 2 + command: | + echo "foo" && \ + echo "bar" + - uses: nick-invision/assert-action@v1 + with: + expected: 1 + actual: ${{ steps.multi_line_2_commands_happy_path.outputs.total_attempts }} + + - name: Conventional multi-line non existent first command + id: conventional_multi_line_non_existent_first_command + uses: ./ + continue-on-error: true + with: + shell: bash + timeout_seconds: 1 + max_attempts: 2 + command: | + i-do-not-exist + echo "i-exist" + - uses: nick-invision/assert-action@v1 + with: + expected: 2 + actual: ${{ steps.conventional_multi_line_non_existent_first_command.outputs.total_attempts }} + - uses: nick-invision/assert-action@v1 + with: + expected: 'Final attempt failed' + actual: ${{ steps.conventional_multi_line_non_existent_first_command.outputs.exit_error }} + comparison: contains + - uses: nick-invision/assert-action@v1 + with: + # The 127 error code indicates “command not found”. + expected: '127' + actual: ${{ steps.conventional_multi_line_non_existent_first_command.outputs.exit_code }} + comparison: contains + - uses: nick-invision/assert-action@v1 + with: + expected: 'i-exist' + actual: ${{ steps.conventional_multi_line_non_existent_first_command.outputs.exit_error }} + comparison: notContains + + - name: Conventional multi-line happy path test + id: conventional_multi_line_happy_path + uses: ./ + with: + shell: bash + timeout_seconds: 1 + max_attempts: 2 + command: | + echo "foo" + echo "bar" + - uses: nick-invision/assert-action@v1 + with: + expected: 1 + actual: ${{ steps.conventional_multi_line_happy_path.outputs.total_attempts }} + ci_windows: name: Run Windows Tests if: startsWith(github.ref, 'refs/heads') diff --git a/dist/index.js b/dist/index.js index 656e63e..598b498 100644 --- a/dist/index.js +++ b/dist/index.js @@ -708,11 +708,15 @@ function getTimeout() { } function getExecutable() { if (!SHELL) { - return OS === 'win32' ? 'powershell' : 'bash'; + return OS === 'win32' ? 'powershell' : 'bash -e'; } var executable; switch (SHELL) { - case "bash": + case "bash": { + // -e to not ignore errors, but exit with non-zero code. + executable = "bash -e"; + break; + } case "python": case "pwsh": { executable = SHELL; @@ -776,7 +780,7 @@ function runCmd(attempt) { executable = getExecutable(); exit = 0; 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 = attempt > 1 && NEW_COMMAND_ON_RETRY ? child_process_1.exec(NEW_COMMAND_ON_RETRY, { 'shell': executable }) : child_process_1.exec(COMMAND, { 'shell': executable }); diff --git a/src/index.ts b/src/index.ts index b2fa2ff..2152f6a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -78,12 +78,16 @@ function getTimeout(): number { function getExecutable(): string { if (!SHELL) { - return OS === 'win32' ? 'powershell' : 'bash'; + return OS === 'win32' ? 'powershell' : 'bash -e'; } let executable: string; switch (SHELL) { - case "bash": + case "bash": { + // -e to not ignore errors, but exit with non-zero code. + executable = "bash -e"; + break; + } case "python": case "pwsh": { executable = SHELL; @@ -131,7 +135,7 @@ async function runCmd(attempt: number) { exit = 0; done = false; - debug(`Running command ${COMMAND} on ${OS} using shell ${executable}`) + debug(`Running command ${COMMAND} on ${OS} using shell "${executable}"`) var child = attempt > 1 && NEW_COMMAND_ON_RETRY ? exec(NEW_COMMAND_ON_RETRY, { 'shell': executable }) : exec(COMMAND, { 'shell': executable });