Continuous Integration / config (pull_request) Successful in 9s
Continuous Integration / backend-build (pull_request) Successful in 4m57s
Continuous Integration / vulnerability-scan (pull_request) Successful in 4m21s
Continuous Integration / frontend-prepare (pull_request) Successful in 1m28s
Continuous Integration / backend-test (pull_request) Successful in 5m3s
Continuous Integration / frontend-build (pull_request) Successful in 2m10s
Continuous Integration / frontend-test (pull_request) Successful in 4m42s
Continuous Integration / frontend-lint (pull_request) Successful in 1m56s
Continuous Integration / publish-production (pull_request) Skipped
Continuous Integration / deploy-production (pull_request) Skipped
Continuous Integration / publish-test (pull_request) Successful in 6m30s
Deploy (SCP) / deploy (pull_request) Failing after 57s
Continuous Integration / deploy-test (pull_request) Failing after 58s
Every ssh/scp step interpolated ${{ secrets.PI_MAIN_PASSWORD }} and
${{ secrets.PI_MAIN_USERNAME }} directly into the run: shell text.
Gitea/GitHub Actions substitutes that as literal text before bash ever
sees it, so any shell-metacharacter in the password ($, `, ", \) gets
re-interpreted by bash instead of passed through - silently changing
what sshpass actually receives. This plausibly explains a persistent
"Permission denied" even after the username and password length were
both confirmed correct via the debug step (which used env: and so
never hit this).
All five steps now receive SSH_USER/SSH_PASS/SSH_PORT/SSH_HOST via
env:, which bash treats as opaque values with no re-parsing.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015FffvxxJp5wG34Ru48GBig