mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-04-28 03:20:11 +00:00
Add Pulse Cloud public signup smoke
This commit is contained in:
parent
4fb67cd547
commit
88683cc32f
5 changed files with 191 additions and 22 deletions
|
|
@ -96,6 +96,7 @@ Companion drill:
|
|||
`go test ./internal/hosted/... -count=1`
|
||||
`go test ./internal/api -run 'TestHostedLifecycle|TestHostedOrgAdminHandlers|TestHostedSignupSuccess|TestHostedSignupValidationFailures|TestHostedSignupHostedModeGate|TestHostedSignupRateLimit|TestHostedSignupRateLimit_NoProvisioningSideEffects|TestHostedSignupCleanupOnRBACFailure|TestHostedSignupFailsClosedWithoutPublicURL|TestStripeWebhook_' -count=1`
|
||||
`cd frontend-modern && npx vitest run src/pages/__tests__/HostedSignup.test.tsx src/components/Settings/__tests__/BillingAdminPanel.test.tsx src/components/Settings/__tests__/OrganizationBillingPanel.test.tsx`
|
||||
`EXPECT_PUBLIC_SIGNUP_ENABLED=false scripts/run_cloud_public_signup_smoke.sh` while public signup is intentionally closed, or `EXPECT_PUBLIC_SIGNUP_ENABLED=true scripts/run_cloud_public_signup_smoke.sh` during the GA launch window when public signup is expected to be live.
|
||||
- Manual scenario:
|
||||
1. Start from a real hosted Pulse signup or an existing hosted tenant.
|
||||
2. Confirm the user can authenticate into the hosted Pulse app and reach a
|
||||
|
|
|
|||
|
|
@ -68,26 +68,27 @@ server-side update execution surfaces.
|
|||
46. `scripts/release_control/release_promotion_policy_support.py`
|
||||
47. `scripts/release_control/resolve_release_promotion.py`
|
||||
48. `scripts/release_ldflags.sh`
|
||||
49. `scripts/run_demo_public_browser_smoke.sh`
|
||||
50. `scripts/demo_public_browser_smoke.cjs`
|
||||
51. `scripts/run_hosted_staging_smoke.sh`
|
||||
52. `scripts/trigger-release-dry-run.sh`
|
||||
53. `scripts/trigger-release.sh`
|
||||
54. `scripts/toggle-mock.sh`
|
||||
55. `deploy/helm/pulse/`
|
||||
56. `tests/integration/playwright.config.ts`
|
||||
57. `tests/integration/QUICK_START.md`
|
||||
58. `tests/integration/README.md`
|
||||
59. `tests/integration/scripts/bootstrap-hosted-mobile-onboarding.mjs`
|
||||
60. `tests/integration/scripts/hosted-mobile-token-runtime.mjs`
|
||||
61. `tests/integration/scripts/hosted-tenant-runtime.mjs`
|
||||
62. `tests/integration/scripts/managed-dev-runtime.mjs`
|
||||
63. `tests/integration/scripts/relay-mobile-token-helper.go`
|
||||
64. `tests/integration/tests/helpers.ts`
|
||||
65. `tests/integration/tests/runtime-defaults.ts`
|
||||
66. `docker-compose.yml`
|
||||
67. `scripts/install-docker.sh`
|
||||
68. `scripts/validate-published-release.sh`
|
||||
49. `scripts/run_cloud_public_signup_smoke.sh`
|
||||
50. `scripts/run_demo_public_browser_smoke.sh`
|
||||
51. `scripts/demo_public_browser_smoke.cjs`
|
||||
52. `scripts/run_hosted_staging_smoke.sh`
|
||||
53. `scripts/trigger-release-dry-run.sh`
|
||||
54. `scripts/trigger-release.sh`
|
||||
55. `scripts/toggle-mock.sh`
|
||||
56. `deploy/helm/pulse/`
|
||||
57. `tests/integration/playwright.config.ts`
|
||||
58. `tests/integration/QUICK_START.md`
|
||||
59. `tests/integration/README.md`
|
||||
60. `tests/integration/scripts/bootstrap-hosted-mobile-onboarding.mjs`
|
||||
61. `tests/integration/scripts/hosted-mobile-token-runtime.mjs`
|
||||
62. `tests/integration/scripts/hosted-tenant-runtime.mjs`
|
||||
63. `tests/integration/scripts/managed-dev-runtime.mjs`
|
||||
64. `tests/integration/scripts/relay-mobile-token-helper.go`
|
||||
65. `tests/integration/tests/helpers.ts`
|
||||
66. `tests/integration/tests/runtime-defaults.ts`
|
||||
67. `docker-compose.yml`
|
||||
68. `scripts/install-docker.sh`
|
||||
69. `scripts/validate-published-release.sh`
|
||||
69. `scripts/validate-release.sh`
|
||||
70. `scripts/release_asset_common.sh`
|
||||
71. `scripts/backfill-release-assets.sh`
|
||||
|
|
@ -174,8 +175,13 @@ server-side update execution surfaces.
|
|||
External helper binaries fetched by governed release workflows are part of
|
||||
the same supply-chain boundary and must be checksum-verified before they are
|
||||
executed.
|
||||
8. Add or change operator-facing hosted tenant runtime canary rollout, batch runtime contract reconciliation, canonical hosted route/public URL generation, or control-plane runtime-registry reconciliation through `cmd/pulse-control-plane/main.go`, `internal/cloudcp/docker/manager.go`, `internal/cloudcp/docker/labels.go`, and `internal/cloudcp/tenant_runtime_rollout.go`
|
||||
9. Add or change the canonical hosted staging smoke operator path through `scripts/run_hosted_staging_smoke.sh`, `tests/integration/scripts/bootstrap-hosted-mobile-onboarding.mjs`, `tests/integration/scripts/hosted-mobile-token-runtime.mjs`, `tests/integration/scripts/hosted-tenant-runtime.mjs`, and `tests/integration/scripts/relay-mobile-token-helper.go`
|
||||
8. Add or change the non-secret Pulse Cloud public signup route smoke through
|
||||
`scripts/run_cloud_public_signup_smoke.sh`. That smoke must prove either
|
||||
the open signup route contract or the intentionally closed redirect contract,
|
||||
and valid magic-link probes must remain opt-in so routine public checks do
|
||||
not send email accidentally.
|
||||
9. Add or change operator-facing hosted tenant runtime canary rollout, batch runtime contract reconciliation, canonical hosted route/public URL generation, or control-plane runtime-registry reconciliation through `cmd/pulse-control-plane/main.go`, `internal/cloudcp/docker/manager.go`, `internal/cloudcp/docker/labels.go`, and `internal/cloudcp/tenant_runtime_rollout.go`
|
||||
10. Add or change the canonical hosted staging smoke operator path through `scripts/run_hosted_staging_smoke.sh`, `tests/integration/scripts/bootstrap-hosted-mobile-onboarding.mjs`, `tests/integration/scripts/hosted-mobile-token-runtime.mjs`, `tests/integration/scripts/hosted-tenant-runtime.mjs`, and `tests/integration/scripts/relay-mobile-token-helper.go`
|
||||
|
||||
## Forbidden Paths
|
||||
|
||||
|
|
|
|||
|
|
@ -2569,6 +2569,7 @@
|
|||
"scripts/release_control/render_release_body.py",
|
||||
"scripts/release_control/resolve_release_promotion.py",
|
||||
"scripts/release_ldflags.sh",
|
||||
"scripts/run_cloud_public_signup_smoke.sh",
|
||||
"scripts/run_demo_public_browser_smoke.sh",
|
||||
"scripts/run_hosted_staging_smoke.sh",
|
||||
"scripts/toggle-mock.sh",
|
||||
|
|
@ -2698,6 +2699,19 @@
|
|||
"scripts/installtests/release_ldflags_test.go"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cloud-public-signup-smoke-runtime",
|
||||
"label": "Cloud public signup smoke proof",
|
||||
"match_prefixes": [],
|
||||
"match_files": [
|
||||
"scripts/run_cloud_public_signup_smoke.sh"
|
||||
],
|
||||
"allow_same_subsystem_tests": false,
|
||||
"test_prefixes": [],
|
||||
"exact_files": [
|
||||
"scripts/tests/test-cloud-public-signup-smoke.sh"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "demo-public-browser-smoke-runtime",
|
||||
"label": "demo public browser smoke proof",
|
||||
|
|
|
|||
133
scripts/run_cloud_public_signup_smoke.sh
Executable file
133
scripts/run_cloud_public_signup_smoke.sh
Executable file
|
|
@ -0,0 +1,133 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
DOMAIN="${DOMAIN:-cloud.pulserelay.pro}"
|
||||
PULSE_CLOUD_BASE_URL="${PULSE_CLOUD_BASE_URL:-https://${DOMAIN}}"
|
||||
EXPECT_PUBLIC_SIGNUP_ENABLED="${EXPECT_PUBLIC_SIGNUP_ENABLED:-true}"
|
||||
PUBLIC_SIGNUP_CLOSED_REDIRECT_URL="${PUBLIC_SIGNUP_CLOSED_REDIRECT_URL:-https://pulserelay.pro/}"
|
||||
CHECK_MAGIC_LINK_VALID_PROBE="${CHECK_MAGIC_LINK_VALID_PROBE:-false}"
|
||||
CURL_TIMEOUT="${CURL_TIMEOUT:-15}"
|
||||
|
||||
BASE_URL="${PULSE_CLOUD_BASE_URL%/}"
|
||||
FAILURES=0
|
||||
|
||||
pass() {
|
||||
echo "[PASS] $*"
|
||||
}
|
||||
|
||||
fail() {
|
||||
echo "[FAIL] $*"
|
||||
FAILURES=$((FAILURES + 1))
|
||||
}
|
||||
|
||||
info() {
|
||||
echo "[INFO] $*"
|
||||
}
|
||||
|
||||
http_code() {
|
||||
local method="$1"
|
||||
local path="$2"
|
||||
shift 2
|
||||
curl -sS --max-time "${CURL_TIMEOUT}" -o /dev/null -w "%{http_code}" -X "${method}" "$@" "${BASE_URL}${path}"
|
||||
}
|
||||
|
||||
http_status_and_redirect() {
|
||||
local method="$1"
|
||||
local path="$2"
|
||||
shift 2
|
||||
curl -sS --max-time "${CURL_TIMEOUT}" -o /dev/null -w "%{http_code} %{redirect_url}" -X "${method}" "$@" "${BASE_URL}${path}"
|
||||
}
|
||||
|
||||
expect_code() {
|
||||
local method="$1"
|
||||
local path="$2"
|
||||
local expected="$3"
|
||||
shift 3
|
||||
local code
|
||||
code="$(http_code "${method}" "${path}" "$@")"
|
||||
if [[ "${code}" == "${expected}" ]]; then
|
||||
pass "${method} ${path} returns ${expected}"
|
||||
else
|
||||
fail "${method} ${path} expected ${expected}, got ${code}"
|
||||
fi
|
||||
}
|
||||
|
||||
expect_redirect() {
|
||||
local method="$1"
|
||||
local path="$2"
|
||||
local expected_code="$3"
|
||||
shift 3
|
||||
local code redirect_url
|
||||
read -r code redirect_url <<<"$(http_status_and_redirect "${method}" "${path}" "$@")"
|
||||
if [[ "${code}" == "${expected_code}" && "${redirect_url}" == "${PUBLIC_SIGNUP_CLOSED_REDIRECT_URL}" ]]; then
|
||||
pass "${method} ${path} returns ${expected_code} to ${PUBLIC_SIGNUP_CLOSED_REDIRECT_URL}"
|
||||
else
|
||||
fail "${method} ${path} expected ${expected_code} to ${PUBLIC_SIGNUP_CLOSED_REDIRECT_URL}, got ${code} to ${redirect_url:-<none>}"
|
||||
fi
|
||||
}
|
||||
|
||||
check_shared_public_floor() {
|
||||
info "Checking shared public control-plane floor at ${BASE_URL}"
|
||||
expect_code GET /healthz 200
|
||||
expect_code GET /readyz 200
|
||||
expect_code POST /api/stripe/webhook 400
|
||||
}
|
||||
|
||||
check_closed_signup_contract() {
|
||||
info "Checking intentionally closed public signup contract"
|
||||
expect_redirect GET /signup 302
|
||||
expect_redirect GET /cloud/signup 302
|
||||
expect_redirect GET /signup/complete 302
|
||||
expect_redirect GET /cloud/signup/complete 302
|
||||
expect_redirect GET /api/public/signup 302
|
||||
expect_redirect POST /api/public/signup 307 -H "Content-Type: application/json" --data '{"email":"not-an-email","org_name":"Acme"}'
|
||||
expect_code POST /api/public/magic-link/request 400 -H "Content-Type: application/json" --data '{"email":"not-an-email"}'
|
||||
}
|
||||
|
||||
check_open_signup_contract() {
|
||||
info "Checking live public signup contract"
|
||||
expect_code GET /signup 200
|
||||
expect_code GET /cloud/signup 200
|
||||
expect_code GET /signup/complete 200
|
||||
expect_code GET /cloud/signup/complete 200
|
||||
expect_code GET /api/public/signup 405
|
||||
expect_code POST /api/public/signup 400 -H "Content-Type: application/json" --data '{"email":"not-an-email","org_name":"Acme"}'
|
||||
expect_code POST /api/public/magic-link/request 400 -H "Content-Type: application/json" --data '{"email":"not-an-email"}'
|
||||
|
||||
if [[ "${CHECK_MAGIC_LINK_VALID_PROBE}" == "true" ]]; then
|
||||
expect_code POST /api/public/magic-link/request 200 -H "Content-Type: application/json" --data '{"email":"owner@example.com"}'
|
||||
else
|
||||
info "Skipping valid magic-link probe (CHECK_MAGIC_LINK_VALID_PROBE=${CHECK_MAGIC_LINK_VALID_PROBE})"
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
if ! command -v curl >/dev/null 2>&1; then
|
||||
echo "curl is required for Pulse Cloud public signup smoke" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local expected_state
|
||||
expected_state="$(echo "${EXPECT_PUBLIC_SIGNUP_ENABLED}" | tr '[:upper:]' '[:lower:]')"
|
||||
check_shared_public_floor
|
||||
|
||||
case "${expected_state}" in
|
||||
true)
|
||||
check_open_signup_contract
|
||||
;;
|
||||
false)
|
||||
check_closed_signup_contract
|
||||
;;
|
||||
*)
|
||||
fail "EXPECT_PUBLIC_SIGNUP_ENABLED must be true or false (got '${EXPECT_PUBLIC_SIGNUP_ENABLED}')"
|
||||
;;
|
||||
esac
|
||||
|
||||
echo
|
||||
echo "Summary: failures=${FAILURES}"
|
||||
if (( FAILURES > 0 )); then
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
15
scripts/tests/test-cloud-public-signup-smoke.sh
Executable file
15
scripts/tests/test-cloud-public-signup-smoke.sh
Executable file
|
|
@ -0,0 +1,15 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||
SMOKE="${ROOT_DIR}/scripts/run_cloud_public_signup_smoke.sh"
|
||||
|
||||
bash -n "${SMOKE}"
|
||||
|
||||
grep -q 'EXPECT_PUBLIC_SIGNUP_ENABLED' "${SMOKE}"
|
||||
grep -q 'PUBLIC_SIGNUP_CLOSED_REDIRECT_URL' "${SMOKE}"
|
||||
grep -q 'CHECK_MAGIC_LINK_VALID_PROBE' "${SMOKE}"
|
||||
grep -q 'check_closed_signup_contract' "${SMOKE}"
|
||||
grep -q 'check_open_signup_contract' "${SMOKE}"
|
||||
|
||||
echo "cloud public signup smoke checks passed"
|
||||
Loading…
Add table
Add a link
Reference in a new issue