#!/usr/bin/env bash set -euo pipefail ROOT="$(cd "$(dirname "$0")/../.." && pwd)" source "$ROOT/tests/kind/lib.sh" USER_KUBECONFIG_BEFORE="$(user_kubeconfig_digest)" SUCCEEDED=false OWNS_FIXTURE=false APP_IMAGE=nuthatch-browser:local LANE=001 LOCAL_PORT=18443 PORT_FORWARD_PID= AUTH_FILE= cleanup() { local status=$? trap - EXIT INT TERM if [[ -n "$PORT_FORWARD_PID" ]]; then kill "$PORT_FORWARD_PID" >/dev/null 2>&1 || true wait "$PORT_FORWARD_PID" 2>/dev/null || true fi if [[ -n "$AUTH_FILE" ]]; then rm -f "$AUTH_FILE" fi if [[ "${NUTHATCH_TESTBED_RETAIN:-0}" = 1 ]] && [[ "$SUCCEEDED" != true ]]; then printf 'retained kubeconfig: %s\n' "$KUBECONFIG_PATH" printf 'retained context: %s\n' "$CONTEXT" exit "$status" fi if [[ "$OWNS_FIXTURE" = true ]]; then destroy_fixture || status=1 fi if [[ "$(user_kubeconfig_digest)" != "$USER_KUBECONFIG_BEFORE" ]]; then printf 'user kubeconfig changed unexpectedly\n' >&2 status=1 fi exit "$status" } trap cleanup EXIT trap 'exit 130' INT trap 'exit 143' TERM render_application() { local profile_file="$1" local oidc_secret oidc_secret="$(<"$profile_file.oidc-secret")" sed \ -e "s|@@LANE@@|$LANE|g" \ -e "s|@@APP_IMAGE@@|$APP_IMAGE|g" \ -e "s|@@PG_CONN@@|$(sed -n 's/^NUTHATCH_PG_CONN=//p' "$profile_file")|g" \ -e "s|@@REDIS_URL@@|$(sed -n 's/^NUTHATCH_REDIS_URL=//p' "$profile_file")|g" \ -e "s|@@OIDC_ISSUER@@|$(sed -n 's/^NUTHATCH_OIDC_ISSUER=//p' "$profile_file")|g" \ -e "s|@@OIDC_CLIENT_ID@@|$(sed -n 's/^NUTHATCH_OIDC_CLIENT_ID=//p' "$profile_file")|g" \ -e "s|@@OIDC_ADDITIONAL_AUDIENCES@@|$(sed -n 's/^NUTHATCH_OIDC_ADDITIONAL_AUDIENCES=//p' "$profile_file")|g" \ -e "s|@@OIDC_CLIENT_SECRET@@|$oidc_secret|g" \ -e "s|@@S3_ENDPOINT@@|$(sed -n 's/^NUTHATCH_S3_ENDPOINT=//p' "$profile_file")|g" \ -e "s|@@S3_REGION@@|$(sed -n 's/^NUTHATCH_S3_REGION=//p' "$profile_file")|g" \ -e "s|@@S3_BUCKET@@|$(sed -n 's/^NUTHATCH_S3_BUCKET=//p' "$profile_file")|g" \ -e "s|@@S3_ACCESS_KEY@@|$(sed -n 's/^NUTHATCH_S3_ACCESS_KEY=//p' "$profile_file")|g" \ -e "s|@@S3_SECRET_KEY@@|$(sed -n 's/^NUTHATCH_S3_SECRET_KEY=//p' "$profile_file")|g" \ "$ROOT/deploy/kubernetes/nuthatch.yaml.in" >"$RUNTIME/browser-app-$LANE.yaml" sed -i \ -e 's/NUTHATCH_BROWSE_PAGE_SIZE: "200"/NUTHATCH_BROWSE_PAGE_SIZE: "20"/' \ -e 's/NUTHATCH_SEARCH_MAX_KEYS: "500"/NUTHATCH_SEARCH_MAX_KEYS: "3"/' \ -e 's/NUTHATCH_DELETE_PAGE_SIZE: "100"/NUTHATCH_DELETE_PAGE_SIZE: "2"/' \ "$RUNTIME/browser-app-$LANE.yaml" } npm --prefix "$ROOT/web" exec -- playwright install chromium acquire_fixture_lock OWNS_FIXTURE=true setup_fixture durable coordination oidc target source "$RUNTIME/fixture.env" "$NUTHATCH_REAL_NERDCTL" --namespace "$NERDCTL_NAMESPACE" build \ --file "$ROOT/Dockerfile" \ --target test-runtime \ --tag "$APP_IMAGE" \ "$ROOT" load_local_image "$APP_IMAGE" "$NERDCTL_NAMESPACE" profile="$(write_lane_profile "$LANE" redis keycloak garage)" render_application "$RUNTIME/$profile.env" kube apply --filename "$RUNTIME/browser-app-$LANE.yaml" >/dev/null kube --namespace "$FIXTURE_NAMESPACE" rollout status \ "deployment/nuthatch-$LANE" --timeout=180s AUTH_FILE="$RUNTIME/browser-auth.json" NUTHATCH_JWT_SECRET="synthetic-kind-session-jwt-secret-$LANE" \ cabal run nuthatch-browser-session-fixture --offline -- "$AUTH_FILE" >/dev/null chmod 600 "$AUTH_FILE" kube --namespace "$FIXTURE_NAMESPACE" port-forward \ --address 127.0.0.1 "service/nuthatch-$LANE" "$LOCAL_PORT:8080" \ >"$RUNTIME/browser-port-forward.log" 2>&1 & PORT_FORWARD_PID=$! for _ in $(seq 1 60); do if curl --fail --insecure --silent \ "https://127.0.0.1:$LOCAL_PORT/healthz" >/dev/null; then break fi if ! kill -0 "$PORT_FORWARD_PID" 2>/dev/null; then printf 'browser port-forward exited before becoming ready\n' >&2 exit 1 fi sleep 1 done curl --fail --insecure --silent \ "https://127.0.0.1:$LOCAL_PORT/healthz" >/dev/null NUTHATCH_BROWSER_BASE_URL="https://127.0.0.1:$LOCAL_PORT" \ NUTHATCH_BROWSER_AUTH_FILE="$AUTH_FILE" \ npm --prefix "$ROOT/web" run test:browser kube --namespace "$FIXTURE_NAMESPACE" delete \ "deployment/nuthatch-$LANE" \ "service/nuthatch-$LANE" \ "configmap/nuthatch-$LANE" \ "secret/nuthatch-$LANE" \ --ignore-not-found >/dev/null cleanup_lane_state "$LANE" redis keycloak garage cleanup_lane_resources browser-reference "$profile" SUCCEEDED=true printf 'Nuthatch production browser gate passed\n'