entrypoint.sh: closing EOF delimiter never written to $GITHUB_OUTPUT when capture_stdout=true and remote command fails

Open Beginner friendly
#416 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
82/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
github-actions, shell
Domain
ci-cd, devops

Research direction

Start in entrypoint.sh, focusing on the capture_stdout branch and its TARGET | tee pipeline under set -euo pipefail. Reproduce the failure with the isolated shell snippet, then verify that a failed remote command still writes the closing EOF delimiter to GITHUB_OUTPUT while preserving the command's non-zero status.

Written by the indexing model from the issue text.

Description

Summary

When capture_stdout: true and the remote command exits non-zero, entrypoint.sh dies (via set -e +
pipefail) before writing the closing EOF delimiter to $GITHUB_OUTPUT. The GitHub Actions
runner then fails the step with a confusing secondary error that masks the real remote command failure:

Error: Unable to process file command 'output' successfully.
Invalid value. Matching delimiter not found 'EOF'

Root cause

entrypoint.sh (pinned 0ff4204d59e8e51228ff73bce53f80d53301dee2, v1.2.5):

set -euo pipefail
...
if [[ "${INPUT_CAPTURE_STDOUT}" == 'true' ]]; then
  echo 'stdout<<EOF' >> "${GITHUB_OUTPUT}"
  "${TARGET}" "$@" | tee -a "${GITHUB_OUTPUT}"
  echo 'EOF' >> "${GITHUB_OUTPUT}"
else
  "${TARGET}" "$@"
fi

With pipefail, if ${TARGET} (drone-ssh, running the user's remote command) exits non-zero, the
whole TARGET | tee pipeline returns non-zero. With set -e also active, the script exits right there
— the next line (echo 'EOF' >> "${GITHUB_OUTPUT}") never runs. The output file ends up with the
opening stdout<<EOF delimiter and partial content, but no closing delimiter, which is exactly what the
runner rejects.

This only shows up on the failure path (remote command exits non-zero) — success runs never hit it,
which is presumably why it's gone unnoticed.

Isolated repro (no SSH needed)

run_entrypoint_snippet() {
  set -euo pipefail
  echo 'stdout<<EOF' >> "${GITHUB_OUTPUT}"
  "$@" | tee -a "${GITHUB_OUTPUT}"
  echo 'EOF' >> "${GITHUB_OUTPUT}"
}
fail_like_remote_command() { echo "some real error"; exit 1; }

GITHUB_OUTPUT=/tmp/mock_output.txt
: > "$GITHUB_OUTPUT"
run_entrypoint_snippet fail_like_remote_command
cat "$GITHUB_OUTPUT"

Output: stdout<<EOF + the echoed content, but no closing EOF line — the script exits with code 1
before reaching it. This mirrors a real production run of ours:
https://github.com/Infoglobo/suporte-producao-publegal-front/actions/runs/30305504299 (job
"Deploy (stg)"), which hit exactly this "Matching delimiter not found 'EOF'" error when the remote
deploy script legitimately failed a healthcheck.

Impact

  • The real error from the remote command gets buried under a second, unrelated runner-level error.
  • Any downstream step that depends on steps.<id>.outputs.stdout being valid on the failure path
    breaks silently (in our case, a diagnostics-extraction step that never runs with useful data).

Suggested fix

Write the closing delimiter unconditionally, regardless of ${TARGET}'s exit code — e.g. capture the
pipe's exit status via ${PIPESTATUS[0]} instead of relying on set -e/pipefail to propagate it, and
explicitly exit with that status only after the closing echo 'EOF' >> "${GITHUB_OUTPUT}":

if [[ "${INPUT_CAPTURE_STDOUT}" == 'true' ]]; then
  echo 'stdout<<EOF' >> "${GITHUB_OUTPUT}"
  set +e
  "${TARGET}" "$@" | tee -a "${GITHUB_OUTPUT}"
  status="${PIPESTATUS[0]}"
  set -e
  echo 'EOF' >> "${GITHUB_OUTPUT}"
  exit "${status}"
else
  "${TARGET}" "$@"
fi

Happy to open a PR with this if useful — wanted to confirm the root cause and preferred fix shape first.

Dominant language
Shell
Stars
6.2k
Forks
680
PR merge metrics
No merged PRs in 30d

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from appleboy/ssh-action

All issues in appleboy/ssh-action

Similar issues

More Shell/Bash issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.