fix(ci): harden SSH host setup in API deploy workflow

Add retries for ssh-keyscan and fall back to non-strict host checking for transient network failures so reruns do not fail early before deployment steps.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
penghanyuan
2026-05-14 15:59:19 +02:00
parent 182b2f94d2
commit 6b81e11903

View File

@@ -223,8 +223,31 @@ jobs:
- name: Add server to known hosts
run: |
set -euo pipefail
mkdir -p ~/.ssh
ssh-keyscan -H -p "${SSH_PORT:-22}" "${SSH_HOST}" >> ~/.ssh/known_hosts
touch ~/.ssh/known_hosts
KEYSCAN_OK=0
for i in 1 2 3; do
echo "ssh-keyscan attempt ${i}/3: ${SSH_HOST}:${SSH_PORT:-22}"
if ssh-keyscan -T 10 -H -p "${SSH_PORT:-22}" "${SSH_HOST}" >> ~/.ssh/known_hosts 2>/tmp/ssh-keyscan.err; then
KEYSCAN_OK=1
break
fi
sleep 2
done
if [ "$KEYSCAN_OK" -eq 1 ]; then
echo "SSH_COMMON_OPTS=" >> "$GITHUB_ENV"
else
echo "::warning::ssh-keyscan failed. Falling back to non-strict host checking for this run."
if [ -f /tmp/ssh-keyscan.err ]; then
echo "--- ssh-keyscan stderr ---"
cat /tmp/ssh-keyscan.err || true
echo "--------------------------"
fi
echo "SSH_COMMON_OPTS=-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" >> "$GITHUB_ENV"
fi
- name: Prepare remote candidate release
env:
@@ -238,10 +261,10 @@ jobs:
echo "镜像标签: $IMAGE_TAG"
echo "部署目录: $COMPOSE_DIR/api"
echo "$ALIYUN_CR_PASSWORD" | ssh -p "$SSH_PORT" "$SSH_USER@$SSH_HOST" \
echo "$ALIYUN_CR_PASSWORD" | ssh ${SSH_COMMON_OPTS:-} -p "$SSH_PORT" "$SSH_USER@$SSH_HOST" \
"docker login $REGISTRY --username=$ALIYUN_CR_USERNAME --password-stdin"
ssh -p "$SSH_PORT" "$SSH_USER@$SSH_HOST" "
ssh ${SSH_COMMON_OPTS:-} -p "$SSH_PORT" "$SSH_USER@$SSH_HOST" "
set -euo pipefail
mkdir -p '$COMPOSE_DIR/api'
mkdir -p '$COMPOSE_DIR/api/backups'
@@ -272,10 +295,10 @@ jobs:
fi
echo "上传候选 compose 与环境文件..."
scp -P "$SSH_PORT" ./api/docker-compose.yml "$SSH_USER@$SSH_HOST:$COMPOSE_DIR/api/docker-compose.candidate.yml"
scp -P "$SSH_PORT" "$ENV_SRC" "$SSH_USER@$SSH_HOST:$COMPOSE_DIR/api/.env.candidate"
scp ${SSH_COMMON_OPTS:-} -P "$SSH_PORT" ./api/docker-compose.yml "$SSH_USER@$SSH_HOST:$COMPOSE_DIR/api/docker-compose.candidate.yml"
scp ${SSH_COMMON_OPTS:-} -P "$SSH_PORT" "$ENV_SRC" "$SSH_USER@$SSH_HOST:$COMPOSE_DIR/api/.env.candidate"
ssh -p "$SSH_PORT" "$SSH_USER@$SSH_HOST" "
ssh ${SSH_COMMON_OPTS:-} -p "$SSH_PORT" "$SSH_USER@$SSH_HOST" "
set -euo pipefail
cd '$COMPOSE_DIR/api'
echo '拉取候选镜像: $IMAGE_TAG'
@@ -291,7 +314,7 @@ jobs:
run: |
set -euo pipefail
echo "切换线上版本,容器启动时将自动执行 Alembic..."
ssh -p "$SSH_PORT" "$SSH_USER@$SSH_HOST" "
ssh ${SSH_COMMON_OPTS:-} -p "$SSH_PORT" "$SSH_USER@$SSH_HOST" "
set -euo pipefail
cd '$COMPOSE_DIR/api'
if [ -f '$COMPOSE_FILE' ]; then
@@ -325,7 +348,7 @@ jobs:
- name: Verify deployment
run: |
echo "验证部署状态..."
ssh -p "$SSH_PORT" "$SSH_USER@$SSH_HOST" "
ssh ${SSH_COMMON_OPTS:-} -p "$SSH_PORT" "$SSH_USER@$SSH_HOST" "
set -euo pipefail
cd '$COMPOSE_DIR/api'
docker compose ps