Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions .github/workflows/pull_request.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ jobs:
with:
context: .
push: false
platforms: linux/amd64
load: true
tags: |
ghcr.io/bitgo/advanced-wallets:${{ github.sha }}
build-args: |
Expand All @@ -118,3 +120,72 @@ jobs:
VCS_REF=${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Smoke test image
run: |
set -euo pipefail

IMAGE="ghcr.io/bitgo/advanced-wallets:${GITHUB_SHA}"
NETWORK="advanced-wallets-smoke-${GITHUB_RUN_ID}"
AWM_CONTAINER="advanced-wallets-smoke-awm-${GITHUB_RUN_ID}"
MBE_CONTAINER="advanced-wallets-smoke-mbe-${GITHUB_RUN_ID}"
FAILED="false"

cleanup() {
if [ "${FAILED}" = "true" ]; then
echo "::group::AWM container logs"
docker logs "${AWM_CONTAINER}" || true
echo "::endgroup::"
echo "::group::Master Express container logs"
docker logs "${MBE_CONTAINER}" || true
echo "::endgroup::"
fi
docker rm -f "${AWM_CONTAINER}" >/dev/null 2>&1 || true
docker rm -f "${MBE_CONTAINER}" >/dev/null 2>&1 || true
docker network rm "${NETWORK}" >/dev/null 2>&1 || true
}
trap cleanup EXIT

docker network create "${NETWORK}"

docker run -d --name "${AWM_CONTAINER}" \
--network "${NETWORK}" \
--network-alias advanced-wallet-manager \
-p 127.0.0.1:13080:3080 \
-e APP_MODE=advanced-wallet-manager \
-e ADVANCED_WALLET_MANAGER_PORT=3080 \
-e BIND=0.0.0.0 \
-e TLS_MODE=disabled \
-e KEY_PROVIDER_URL=https://key-provider.invalid \
"${IMAGE}"

docker run -d --name "${MBE_CONTAINER}" \
--network "${NETWORK}" \
-p 127.0.0.1:13081:3081 \
-e APP_MODE=master-express \
-e MASTER_EXPRESS_PORT=3081 \
-e BIND=0.0.0.0 \
-e TLS_MODE=disabled \
-e ADVANCED_WALLET_MANAGER_URL=http://advanced-wallet-manager:3080 \
"${IMAGE}"

wait_for() {
local url="${1}"
local status="none"
for _ in $(seq 1 30); do
if status="$(curl -s -o /dev/null -w '%{http_code}' -X POST "${url}")" && [ "${status}" = "200" ]; then
echo "${url} -> 200"
Comment on lines +174 to +177

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 nit (optional): The smoke test's 30-second limit per health check does not hold. A container that accepts a connection but never answers can stall the PR job for hours. The curl call in wait_for has no --max-time, so one hung request blocks the loop with no limit. Nothing else bounds the step: there is no timeout-minutes, so GitHub's 360-minute job default applies. Fix: pass --max-time (for example --connect-timeout 2 --max-time 5) to the curl in wait_for, and add a timeout-minutes on the step so every check stays bounded.

Why this was flagged

The trigger is a container whose port is open while the app never responds. Two examples are an event loop blocked during startup, and master-express hanging while it waits on an unresponsive AWM (its configured timeout defaults to 305 * 1000 ms in src/initConfig.ts). In wait_for, curl -s -o /dev/null -w '%{http_code}' -X POST "${url}" (pull_request.yaml:177) runs with no --max-time or --connect-timeout, and curl sets no total timeout by default. So the for _ in $(seq 1 30) loop never moves to its next iteration, and the "Timed out waiting" branch and the log dump are never reached. The PR description says each check is "polled up to 30s" and that a timeout fails the job. In fact the job runs until the GitHub default limit (no timeout-minutes is set on the step or job), using up runner minutes and leaving the check unresolved without the logs that cleanup would print. The base branch has no run step, so this hang is new.

Verification: Trigger: a PR's image accepts TCP connections but does not answer a health request. In wait_for, the call is curl -s -o /dev/null -w '%{http_code}' -X POST "${url}" with no --max-time and no --connect-timeout. Nothing else bounds the step: the build-docker-image job and the new step set no timeout-minutes, so GitHub's 360-minute default applies.

return 0
fi
sleep 1
done
echo "Timed out waiting for POST ${url} (last status: ${status})"
FAILED="true"
return 1
}

wait_for "http://127.0.0.1:13080/ping"
wait_for "http://127.0.0.1:13081/advancedwallet/ping"
wait_for "http://127.0.0.1:13081/ping/advancedWalletManager"

echo "Production image smoke checks passed for both application modes."
Loading