#!/bin/bash # Phase 5 end-to-end against the live endpoint, in a throwaway container. # # RUN IT FROM A NORMAL TERMINAL, NOT FROM INSIDE A CLAUDE SESSION: # # bash .tests/e2e.sh # # Do NOT run it with the `!` prefix in Claude Code. The output is redacted, but # the prompt is not worth risking -- and the whole point of this wrapper is that # the password stays on your side. # # The password is never written to disk, never placed on any command line, and # never printed. It is read from your terminal into a shell variable and handed # to the container through the environment: # # `docker exec -e BOOT_PW` with NO `=value` tells docker to inherit the # variable from this process. Writing `-e BOOT_PW=secret` would put it in # docker's own argv, and /proc//cmdline is world-readable -- the exact # bug this test suite was just fixed to stop doing in dotup. # # What it proves that the unit suite cannot: that a machine which has only ever # seen the public repo can reach the real endpoint, authenticate, clone the # private tier, install bws, render secrets, and end up with no credential in # its logs or its .git/config. set -u C=dotup-e2e INNER=$(dirname "$0")/e2e-private-tier.sh [ -r "$INNER" ] || { echo "missing $INNER"; exit 1; } command -v docker >/dev/null || { echo "docker not installed"; exit 1; } cleanup() { docker rm -f "$C" >/dev/null 2>&1 || :; unset BOOT_PW; } trap cleanup EXIT INT TERM # ---- credentials, from your terminal only ----------------------------------- # No default URL, deliberately. Hardcoding the route here would copy it out of # Bitwarden and into a git repository, where it would then have to be edited # every time the route rotates -- and a stale default is worse than no default, # because it fails looking like a password problem. printf 'Bootstrap URL (paste from Bitwarden): ' >&2 IFS= read -r BOOT_URL [ -n "$BOOT_URL" ] || { echo "no URL given"; exit 1; } printf 'Username [ben]: ' >&2 IFS= read -r BOOT_USER BOOT_USER=${BOOT_USER:-ben} printf 'Password: ' >&2 IFS= read -rs BOOT_PW; printf '\n' >&2 [ -n "$BOOT_PW" ] || { echo "empty password"; exit 1; } export BOOT_URL BOOT_USER BOOT_PW # ---- fail fast: do not spend ten minutes to discover a typo ------------------ # curl -K - reads credentials from stdin rather than argv. printf 'checking the endpoint... ' >&2 code=$(printf 'user = %s:%s\nsilent\nwrite-out = "%%{http_code}"\noutput = "/dev/null"\n' \ "$BOOT_USER" "$BOOT_PW" | curl -K - -m 20 "${BOOT_URL%/}/bootstrap.env" || true) if [ "$code" != 200 ]; then echo "HTTP $code -- wrong password, wrong route, or endpoint down. Nothing was run." >&2 exit 1 fi echo "200" >&2 # ---- the run ---------------------------------------------------------------- # A stock image with nothing preinstalled. If dotup needs a tool, dotup must # install it -- that is half of what is being tested. docker rm -f "$C" >/dev/null 2>&1 || : docker run -d --name "$C" ubuntu:24.04 sleep infinity >/dev/null || exit 1 docker cp "$INNER" "$C":/root/e2e.sh >/dev/null || exit 1 # -e with a bare NAME inherits from this shell. Never NAME=value. docker exec -e BOOT_URL -e BOOT_USER -e BOOT_PW "$C" bash /root/e2e.sh rc=$? echo if [ "$rc" -eq 0 ]; then echo "E2E exited 0" else echo "E2E exited $rc -- the container is left running as $C for inspection." echo "If you shell into it, remember that /tmp/private.log inside contains the" echo "credentials in cleartext: the inner script has a red() redactor, and the" echo "one time it was bypassed for a quick tail, a live password was published" echo "and had to be rotated. Pipe anything you read through it." trap - EXIT INT TERM # leave the container up; still drop the password unset BOOT_PW fi exit "$rc"