#!/usr/bin/env bash # Stubbed aws/curl tests for scripts/verify-cloudfront-release.sh. set -euo pipefail ROOT="$(cd "$(dirname "$0")/.." && pwd)" VERIFY="${ROOT}/scripts/verify-cloudfront-release.sh" NEW_HASH="1111111111111111111111111111111111111111111111111111111111111111" INDEX_HTML=$'
\n' INDEX_HASH="$(printf '%s' "${INDEX_HTML}" | python3 -c 'import hashlib,sys; print(hashlib.sha256(sys.stdin.buffer.read()).hexdigest())')" failures=0 assert_exit() { local name="$1" expected="$2" got="$3" log="$4" if [[ "${got}" != "${expected}" ]]; then echo "FAIL: ${name}: expected exit ${expected}, got ${got}" >&2 sed -n '1,80p' "${log}" >&2 failures=$((failures + 1)) else echo "PASS: ${name}" fi } make_stubs() { local bin="$1" mkdir -p "${bin}" cat > "${bin}/aws" << 'AWS' #!/usr/bin/env bash set -euo pipefail cat "${STUB_STATE}/distribution.json" AWS cat > "${bin}/curl" << 'CURL' #!/usr/bin/env bash set -euo pipefail state_dir="${STUB_STATE}" method="GET" url="" dump="" output="" write_out="" args=("$@") i=0 while [[ $i -lt ${#args[@]} ]]; do arg="${args[$i]}" case "${arg}" in -X) i=$((i + 1)); method="${args[$i]}" ;; -D) i=$((i + 1)); dump="${args[$i]}" ;; -o) i=$((i + 1)); output="${args[$i]}" ;; -w) i=$((i + 1)); write_out="${args[$i]}" ;; -H|--max-time|-s|-S|-f|-fsS|-sS) ;; http*) url="${arg}" ;; esac i=$((i + 1)) done if [[ "${method}" == "OPTIONS" ]]; then [[ -n "${dump}" ]] && printf 'HTTP/1.1 204 No Content\nAccess-Control-Allow-Origin: https://dev.seahaven.com\n\n' > "${dump}" [[ -n "${write_out}" ]] && printf '204' exit 0 fi if [[ "${url}" == *"/assets/"* ]]; then [[ -n "${dump}" ]] && printf 'HTTP/1.1 200 OK\nCache-Control: public,max-age=31536000,immutable\n\n' > "${dump}" if [[ -f "${state_dir}/asset.js" ]]; then body="$(cat "${state_dir}/asset.js")" else body='const api="https://api.dev.seahaven.com/api";' fi [[ -n "${output}" ]] && printf '%s' "${body}" > "${output}" [[ -z "${output}" ]] && printf '%s' "${body}" exit 0 fi [[ -n "${dump}" ]] && printf 'HTTP/1.1 200 OK\nCache-Control: no-cache,no-store,must-revalidate\n\n' > "${dump}" if [[ -n "${output}" ]]; then cat "${state_dir}/index.html" > "${output}" else cat "${state_dir}/index.html" fi exit 0 CURL chmod +x "${bin}/aws" "${bin}/curl" } dist_json() { local status="$1" current_path="$2" python3 -c 'import json,sys status, path = sys.argv[1], sys.argv[2] print(json.dumps({ "Distribution": { "Status": status, "DistributionConfig": { "Origins": {"Items": [ {"Id": "current", "OriginPath": path} ]} } } }))' "${status}" "${current_path}" } # 1. Empty origin, then propagates (InProgress -> Deployed, hash already matches). { dir="$(mktemp -d)" make_stubs "${dir}/bin" printf '%s' "${INDEX_HTML}" > "${dir}/index.html" printf 'InProgress\n' > "${dir}/status" cat > "${dir}/bin/aws" << AWS #!/usr/bin/env bash set -euo pipefail status="\$(cat "${dir}/status")" python3 -c 'import json,sys; print(json.dumps({"Distribution":{"Status":sys.argv[1],"DistributionConfig":{"Origins":{"Items":[{"Id":"current","OriginPath":""}]}}}}))' "\${status}" echo Deployed > "${dir}/status" AWS chmod +x "${dir}/bin/aws" export STUB_STATE="${dir}" PATH="${dir}/bin:${PATH}" export DISTRIBUTION_ID="E2CWLM1AFB964P" export EXPECTED_INDEX_SHA256="${INDEX_HASH}" export SITE_URL="https://dev.seahaven.com" export API_URL="https://api.dev.seahaven.com/api" export BUDGET=5 INTERVAL=0 set +e bash "${VERIFY}" > "${dir}/log.txt" 2>&1 code=$? set -e assert_exit "empty-origin-then-propagates" 0 "${code}" "${dir}/log.txt" rm -rf "${dir}" } # 2. Empty origin never propagates (Deployed, stale hash). { dir="$(mktemp -d)" make_stubs "${dir}/bin" dist_json "Deployed" "" > "${dir}/distribution.json" printf 'stale' > "${dir}/index.html" export STUB_STATE="${dir}" PATH="${dir}/bin:${PATH}" export DISTRIBUTION_ID="E2CWLM1AFB964P" export EXPECTED_INDEX_SHA256="${NEW_HASH}" export SITE_URL="https://dev.seahaven.com" export API_URL="https://api.dev.seahaven.com/api" export BUDGET=2 INTERVAL=0 set +e bash "${VERIFY}" > "${dir}/log.txt" 2>&1 code=$? set -e assert_exit "empty-origin-never-propagates" 1 "${code}" "${dir}/log.txt" grep -q "last observed" "${dir}/log.txt" || { echo "FAIL: timeout missing last observed state" >&2; failures=$((failures + 1)); } rm -rf "${dir}" } # 3. Non-empty origin path fails fast. { dir="$(mktemp -d)" make_stubs "${dir}/bin" dist_json "Deployed" "/releases/deadbeef" > "${dir}/distribution.json" printf '%s' "${INDEX_HTML}" > "${dir}/index.html" export STUB_STATE="${dir}" PATH="${dir}/bin:${PATH}" export DISTRIBUTION_ID="E2CWLM1AFB964P" export EXPECTED_INDEX_SHA256="${NEW_HASH}" export SITE_URL="https://dev.seahaven.com" export API_URL="https://api.dev.seahaven.com/api" export BUDGET=2 INTERVAL=0 set +e bash "${VERIFY}" > "${dir}/log.txt" 2>&1 code=$? set -e assert_exit "nonempty-origin-path" 1 "${code}" "${dir}/log.txt" grep -q "origin_path" "${dir}/log.txt" || { echo "FAIL: nonempty origin path did not name origin_path" >&2; failures=$((failures + 1)); } rm -rf "${dir}" } # 4. Never Deployed. { dir="$(mktemp -d)" make_stubs "${dir}/bin" dist_json "InProgress" "" > "${dir}/distribution.json" printf '%s' "${INDEX_HTML}" > "${dir}/index.html" export STUB_STATE="${dir}" PATH="${dir}/bin:${PATH}" export DISTRIBUTION_ID="E2CWLM1AFB964P" export EXPECTED_INDEX_SHA256="${NEW_HASH}" export SITE_URL="https://dev.seahaven.com" export API_URL="https://api.dev.seahaven.com/api" export BUDGET=2 INTERVAL=0 set +e bash "${VERIFY}" > "${dir}/log.txt" 2>&1 code=$? set -e assert_exit "never-deployed" 1 "${code}" "${dir}/log.txt" grep -q "last observed" "${dir}/log.txt" || { echo "FAIL: never-deployed missing last observed state" >&2; failures=$((failures + 1)); } rm -rf "${dir}" } # 5. Hash-matched Deployed release whose JS assets omit the baked API URL. { dir="$(mktemp -d)" make_stubs "${dir}/bin" dist_json "Deployed" "" > "${dir}/distribution.json" printf '%s' "${INDEX_HTML}" > "${dir}/index.html" printf 'const x=1;' > "${dir}/asset.js" export STUB_STATE="${dir}" PATH="${dir}/bin:${PATH}" export DISTRIBUTION_ID="E2CWLM1AFB964P" export EXPECTED_INDEX_SHA256="${INDEX_HASH}" export SITE_URL="https://dev.seahaven.com" export API_URL="https://api.dev.seahaven.com/api" export BUDGET=2 INTERVAL=0 set +e bash "${VERIFY}" > "${dir}/log.txt" 2>&1 code=$? set -e assert_exit "missing-baked-api-url" 1 "${code}" "${dir}/log.txt" grep -q "baked API URL" "${dir}/log.txt" || { echo "FAIL: missing API URL did not name baked API URL" >&2; failures=$((failures + 1)); } rm -rf "${dir}" } # 6. Hash-matched Deployed release whose JS assets contain the staging API URL. { dir="$(mktemp -d)" make_stubs "${dir}/bin" dist_json "Deployed" "" > "${dir}/distribution.json" printf '%s' "${INDEX_HTML}" > "${dir}/index.html" printf 'const api="https://api.staging.seahaven.com/api";' > "${dir}/asset.js" export STUB_STATE="${dir}" PATH="${dir}/bin:${PATH}" export DISTRIBUTION_ID="E2CWLM1AFB964P" export EXPECTED_INDEX_SHA256="${INDEX_HASH}" export SITE_URL="https://dev.seahaven.com" export API_URL="https://api.dev.seahaven.com/api" export BUDGET=2 INTERVAL=0 set +e bash "${VERIFY}" > "${dir}/log.txt" 2>&1 code=$? set -e assert_exit "forbidden-staging-api-url" 1 "${code}" "${dir}/log.txt" grep -q "forbidden URL api.staging.seahaven.com" "${dir}/log.txt" || { echo "FAIL: staging API URL did not name forbidden URL" >&2; failures=$((failures + 1)); } rm -rf "${dir}" } if [[ "${failures}" -ne 0 ]]; then echo "FAIL: ${failures} verify-cloudfront-release cases failed" >&2 exit 1 fi echo "PASS: CloudFront release verify checks"