Some checks failed
morphit-ci / TypeScript typecheck (sweep all workspaces) (push) Has been cancelled
morphit-ci / apps/web svelte-check (svelte-kit sync + svelte-aware tsc) (push) Has been cancelled
morphit-ci / Integration tests (real Postgres 16) (push) Has been cancelled
morphit-ci / ansible-lint (playbook quality gate) (push) Has been cancelled
morphit-ci / Smoke suite (run-smokes.sh, triple-pulse) (push) Has been cancelled
morphit-release / Build + publish release tarball (push) Has been cancelled
740 lines
30 KiB
Bash
Executable file
740 lines
30 KiB
Bash
Executable file
#!/usr/bin/env bash
|
||
# Morphit — run all tsx-runnable smoke scenarios.
|
||
set -u
|
||
repo="$(cd "$(dirname "$0")/.." && pwd)"
|
||
cd "$repo"
|
||
|
||
# Resolve tsx from the workspace first, then PATH. Mirrors the
|
||
# fallback pattern in scripts/typecheck-sweep.sh — operators who
|
||
# call the smoke runner before `npm install` has fully populated
|
||
# .bin/ get a clearer error than "command not found", and CI
|
||
# workflows that don't prepend node_modules/.bin to PATH still
|
||
# work.
|
||
if [ -x "$repo/node_modules/.bin/tsx" ]; then
|
||
TSX="$repo/node_modules/.bin/tsx"
|
||
elif command -v tsx >/dev/null 2>&1; then
|
||
TSX="$(command -v tsx)"
|
||
else
|
||
echo "ERROR: tsx not found. Run 'npm install' from the repo root." >&2
|
||
exit 2
|
||
fi
|
||
|
||
SMOKES=(
|
||
"apps/indexer:block-handler-smoke"
|
||
"apps/indexer:login-pairing-sse-keepalive-smoke"
|
||
"apps/indexer:rpc-endpoints-probe-smoke"
|
||
"apps/indexer:rpc-probe-failure-reason-smoke"
|
||
"apps/indexer:indexer-config-boot-smoke"
|
||
"apps/indexer:chat-handler-smoke"
|
||
"apps/indexer:push-clickpath-locale-smoke"
|
||
"apps/indexer:chat-sse-order-permlink-smoke"
|
||
"apps/indexer:chat-fast-notification-smoke"
|
||
"apps/indexer:dispatcher-admission-order-smoke"
|
||
"apps/indexer:orderbook-provisional-removal-memory-smoke"
|
||
"apps/indexer:chat-identity-handler-smoke"
|
||
"apps/indexer:order-handler-smoke"
|
||
"apps/indexer:broadcast-chain-proxy-rate-limit-smoke"
|
||
"apps/indexer:broadcast-op-allowlist-smoke"
|
||
"apps/indexer:broadcast-hedge-off-smoke"
|
||
"apps/indexer:asset-network-set-registry-parity-smoke"
|
||
"apps/indexer:feedback-handler-smoke"
|
||
"apps/indexer:feedback-summary-order-owner-parity-smoke"
|
||
"apps/indexer:stranger-fee-handler-smoke"
|
||
"apps/indexer:stranger-fee-pricing-smoke"
|
||
"apps/indexer:api-response-shape-smoke"
|
||
"apps/indexer:body-cap-smoke"
|
||
"apps/indexer:daily-ceiling-persist-smoke"
|
||
"apps/indexer:monero-jitter-smoke"
|
||
"apps/indexer:attestor-eligibility-smoke"
|
||
"apps/indexer:fee-attest-handler-smoke"
|
||
"apps/indexer:fee-reward-copy-consistency-smoke"
|
||
"apps/indexer:btc-min-confirmations-smoke"
|
||
"apps/indexer:explorer-txid-echo-smoke"
|
||
"apps/indexer:featurebid-handler-smoke"
|
||
"apps/indexer:operator-earnings-smoke"
|
||
"apps/indexer:db-password-placeholder-smoke"
|
||
"apps/indexer:indexer-result-shape-smoke"
|
||
"apps/indexer:duplicate-import-smoke"
|
||
"apps/indexer:handler-coverage-smoke"
|
||
"apps/indexer:fee-status-filter-lint"
|
||
"apps/indexer:rss-orderbook-smoke"
|
||
"apps/indexer:rss-orderbook-xml-validate"
|
||
"apps/indexer:rss-orderbook-filters-smoke"
|
||
"apps/indexer:orderbook-side-barter-flip-smoke"
|
||
"apps/indexer:operator-register-handler-smoke"
|
||
"apps/indexer:reconcile-registrations-smoke"
|
||
"apps/indexer:operator-payment-method-handler-smoke"
|
||
"apps/indexer:reserved-keys-parity-smoke"
|
||
"apps/indexer:schema-drift-smoke"
|
||
"apps/indexer:confusables-parity-smoke"
|
||
"apps/indexer:forbidden-char-consistency-smoke"
|
||
"apps/indexer:frontend-chatlink-env-doc-parity-smoke"
|
||
"apps/indexer:federation-probe-smoke"
|
||
"apps/indexer:dns-rebinding-defense-smoke"
|
||
"apps/indexer:instances-stream-smoke"
|
||
"apps/indexer:orderbook-stream-smoke"
|
||
"apps/indexer:orderbook-block-enforcement-smoke"
|
||
"apps/indexer:chat-stream-smoke"
|
||
"apps/indexer:chat-payload-smoke"
|
||
"apps/indexer:head-tailer-validation-parity-smoke"
|
||
"apps/indexer:fastpath-order-scope-smoke"
|
||
"apps/indexer:chat-blurt-verify-smoke"
|
||
"apps/indexer:trade-status-smoke"
|
||
"apps/indexer:listener-dispatch-smoke"
|
||
"apps/indexer:asset-registry-smoke"
|
||
"apps/indexer:handler-test-stand-in-meta-assertion-smoke"
|
||
"apps/indexer:per-asset-rss-feed-parity-smoke"
|
||
"apps/indexer:ansible-env-template-required-vars-smoke"
|
||
"apps/indexer:disabled-assets-parse-smoke"
|
||
"apps/indexer:disabled-payment-methods-parse-smoke"
|
||
"apps/indexer:order-views-smoke"
|
||
"apps/indexer:profile-handler-smoke"
|
||
"apps/indexer:explorer-activity-smoke"
|
||
"apps/indexer:explorer-search-smoke"
|
||
"apps/indexer:explorer-urls-smoke"
|
||
"apps/indexer:loyalty-welcome-smoke"
|
||
"apps/indexer:onion-location-smoke"
|
||
"apps/indexer:pending-feedback-reminders-smoke"
|
||
"apps/indexer:pwa-manifest-smoke"
|
||
"apps/web:posting-verify-smoke"
|
||
"apps/indexer:release-validator-smoke"
|
||
"apps/indexer:treasury-source-smoke"
|
||
"apps/indexer:canonical-treasury-smoke"
|
||
"apps/indexer:treasury-mismatch-probe-smoke"
|
||
"apps/indexer:release-broadcast-smoke"
|
||
"apps/indexer:balance-math-smoke"
|
||
"apps/indexer:payments-smoke"
|
||
"apps/indexer:pnl-smoke"
|
||
"apps/indexer:wif-smoke"
|
||
"apps/indexer:yubikey-protocol-smoke"
|
||
"apps/indexer:clearing-price-history-smoke"
|
||
"apps/indexer:login-pairing-registry-smoke"
|
||
"apps/indexer:schema-migration-coverage-smoke"
|
||
"apps/relay:drain-defense-live-fire"
|
||
"apps/relay:hmac-secret-placeholder-smoke"
|
||
"apps/relay:drainer-defense-smoke"
|
||
"apps/relay:clock-drift-smoke"
|
||
"apps/relay:key-envelope-smoke"
|
||
"apps/relay:push-category-optin-smoke"
|
||
"apps/relay:push-tag-dedup-smoke"
|
||
"apps/relay:notification-latency-budget-smoke"
|
||
"apps/relay:fee-divergence-smoke"
|
||
"apps/relay:ip-bucketing-canonicalization-smoke"
|
||
"apps/relay:trusted-proxy-smoke"
|
||
"apps/relay:squatter-defense-smoke"
|
||
"apps/relay:account-create-op-smoke"
|
||
"apps/relay:vapid-key-validation-smoke"
|
||
"apps/ops-cli:ops-cli-smoke"
|
||
"apps/ops-cli:account-suggestion-smoke"
|
||
"apps/ops-cli:altnet-address-format-smoke"
|
||
"apps/ops-cli:instance-name-quoting-smoke"
|
||
"apps/ops-cli:doctor-smoke"
|
||
"apps/ops-cli:canary-dir-owner-smoke"
|
||
"apps/ops-cli:status-backups-smoke"
|
||
"apps/ops-cli:db-container-detect-smoke"
|
||
"apps/ops-cli:indexer-state-columns-smoke"
|
||
"apps/ops-cli:db-query-columns-smoke"
|
||
"apps/ops-cli:fast-forward-smoke"
|
||
"apps/ops-cli:local-block-smoke"
|
||
"apps/ops-cli:moderation-smoke"
|
||
"apps/ops-cli:moderation-signal-coverage-smoke"
|
||
"apps/indexer:feedback-list-summary-parity-smoke"
|
||
"apps/ops-cli:menu-annotations-smoke"
|
||
"apps/ops-cli:mcp-toggle-smoke"
|
||
"apps/ops-cli:matrix-bot-lifecycle-smoke"
|
||
"apps/ops-cli:matrix-test-command-smoke"
|
||
"apps/ops-cli:rpc-endpoint-probe-smoke"
|
||
"apps/ops-cli:rpc-endpoint-canon-smoke"
|
||
"apps/ops-cli:ssl-smoke"
|
||
"apps/ops-cli:bunkerweb-smoke"
|
||
"apps/ops-cli:health-view-smoke"
|
||
"apps/ops-cli:canary-timestamp-parity-smoke"
|
||
"apps/ops-cli:system-check-os-smoke"
|
||
"apps/ops-cli:register-diagnostics-smoke"
|
||
"apps/ops-cli:offline-account-lookup-smoke"
|
||
"apps/ops-cli:init-smoke"
|
||
"apps/ops-cli:init-progress-smoke"
|
||
"apps/ops-cli:init-resume-wiring-smoke"
|
||
"apps/ops-cli:tor-onion-smoke"
|
||
"apps/ops-cli:i2p-destination-smoke"
|
||
"apps/ops-cli:tor-wizard-wiring-smoke"
|
||
"apps/ops-cli:i2p-wizard-wiring-smoke"
|
||
"apps/ops-cli:edit-smoke"
|
||
"apps/ops-cli:edit-rpc-smoke"
|
||
"apps/ops-cli:edit-active-key-smoke"
|
||
"apps/ops-cli:altkeystore-smoke"
|
||
"apps/ops-cli:alt-address-wizard-smoke"
|
||
"apps/ops-cli:restart-services-smoke"
|
||
"apps/ops-cli:ansible-os-derivative-smoke"
|
||
"packages/operator-config:operator-config-smoke"
|
||
"packages/node-health:node-health-smoke"
|
||
"packages/relay-client:contract-symmetry-smoke"
|
||
"packages/net-defense:net-defense-smoke"
|
||
"packages/rpc-pool:rpc-pool-smoke"
|
||
"apps/indexer:blurt-client-rpc-pool-smoke"
|
||
"apps/indexer:prefetch-in-order-smoke"
|
||
"apps/indexer:btc-quorum-call-integration-smoke"
|
||
"apps/web:balance-bus-smoke"
|
||
"apps/web:chain-op-verify-smoke"
|
||
"apps/web:order-fee-active-auth-smoke"
|
||
"apps/web:pay-blurt-modal-gate-smoke"
|
||
"apps/web:wallet-op-builders-smoke"
|
||
"apps/web:smoke-tsconfig-alias-parity-smoke"
|
||
"apps/web:wallet-power-modal-smoke"
|
||
"apps/web:send-blurt-modal-smoke"
|
||
"apps/web:fee-split-smoke"
|
||
"apps/web:yubikey-error-classifier-smoke"
|
||
"apps/web:fingerprint-smoke"
|
||
"apps/web:chat-self-copy-smoke"
|
||
"apps/web:chat-security-preference-smoke"
|
||
"apps/web:chat-shippable-gating-smoke"
|
||
"apps/web:conversation-order-ref-smoke"
|
||
"apps/web:chat-scroll-to-newest-smoke"
|
||
"apps/web:payment-receipt-presentation-smoke"
|
||
"apps/web:terms-markdown-presentation-smoke"
|
||
"apps/web:order-pay-amount-smoke"
|
||
"apps/web:order-role-smoke"
|
||
"apps/web:terms-markdown-smoke"
|
||
"apps/web:identicon-data-uri-smoke"
|
||
"apps/web:seed-backup-print-one-page-smoke"
|
||
"apps/web:libsodium-not-in-baseline-closure-smoke"
|
||
"apps/web:crypto-blurt-not-in-baseline-closure-smoke"
|
||
"apps/web:split-on-placeholder-smoke"
|
||
"apps/web:voucher-locale-parity-smoke"
|
||
"apps/web:price-model-display-smoke"
|
||
"apps/web:price-model-picker-parity-smoke"
|
||
"apps/web:post-form-grandma-regression-smoke"
|
||
"apps/web:economics-canonical-smoke"
|
||
"apps/web:composite-price-provider-smoke"
|
||
"apps/web:desktop-pairing-crypto-smoke"
|
||
"apps/web:paired-readonly-lifecycle-smoke"
|
||
"apps/web:paired-readonly-affordance-surfaces-smoke"
|
||
"apps/web:asset-tab-completeness-smoke"
|
||
"apps/web:post-edit-multi-network-wired-smoke"
|
||
"apps/web:native-translations-floor-smoke"
|
||
"apps/web:i18n-key-coverage-smoke"
|
||
"apps/web:i18n-dead-key-gate-smoke"
|
||
"apps/web:rss-feed-picker-wiring-smoke"
|
||
"apps/web:rss-dynamic-title-smoke"
|
||
"apps/web:faq-per-tradable-asset-parity-smoke"
|
||
"apps/web:what-is-morphit-asset-enum-smoke"
|
||
"apps/web:operator-doc-per-asset-coverage-smoke"
|
||
"apps/web:what-is-asset-faq-native-locale-floor-smoke"
|
||
"apps/web:per-asset-key-family-native-locale-floor-smoke"
|
||
"apps/web:operator-doc-per-asset-config-example-coverage-smoke"
|
||
"apps/web:env-example-schema-parity-smoke"
|
||
"apps/web:brag-list-kiss-budget-smoke"
|
||
"apps/web:brag-list-trailer-invariants-smoke"
|
||
"apps/web:faq-keys-themed-section-smoke"
|
||
"apps/web:non-zod-env-example-consumer-parity-smoke"
|
||
"apps/web:bunkerweb-cidr-cross-reference-smoke"
|
||
"apps/web:cross-document-value-invariants-smoke"
|
||
"apps/web:operator-doc-section-length-smoke"
|
||
"apps/web:ansible-idempotency-discipline-smoke"
|
||
"apps/web:vitest-must-pass-smoke"
|
||
"apps/web:no-real-time-settimeout-in-tests-smoke"
|
||
"apps/web:untrusted-parseint-safety-smoke"
|
||
"apps/web:fetch-must-have-timeout-smoke"
|
||
"apps/web:seo-routes-i18n-all-locales-smoke"
|
||
"apps/web:per-asset-mandatory-family-i18n-parity-smoke"
|
||
"apps/web:long-form-en-fallback-floor-smoke"
|
||
"apps/web:short-form-en-fallback-floor-smoke"
|
||
"apps/web:service-worker-single-registration-smoke"
|
||
"apps/web:service-worker-dynamic-data-smoke"
|
||
"apps/web:page-title-anchor-smoke"
|
||
"apps/web:upgrade-banner-behavior-smoke"
|
||
"apps/web:dev-routes-prod-gated-smoke"
|
||
"apps/web:i18n-locale-parity-smoke"
|
||
"apps/web:i18n-locale-registry-smoke"
|
||
"apps/web:rtl-handle-and-footer-tasks-smoke"
|
||
"apps/web:explorer-link-lang-prefix-smoke"
|
||
"apps/web:locale-source-of-truth-smoke"
|
||
"apps/web:onboarding-locale-swap-smoke"
|
||
"apps/web:i18n-path-helpers-smoke"
|
||
"apps/web:path-adversarial-smoke"
|
||
"apps/web:no-stale-top-level-routes-smoke"
|
||
"apps/web:no-bare-path-goto-smoke"
|
||
"apps/web:static-asset-link-reload-smoke"
|
||
"apps/web:indexer-url-composition-smoke"
|
||
"apps/matrix-bot:classifier-smoke"
|
||
"apps/matrix-bot:rate-limiter-smoke"
|
||
"apps/matrix-bot:surface-invariant-smoke"
|
||
"apps/mcp-server:mcp-server-smoke"
|
||
"apps/mcp-server:mcp-http-transport-smoke"
|
||
"apps/mcp-server:fetchjson-body-cap-smoke"
|
||
"apps/mcp-server:private-instance-policy-smoke"
|
||
"apps/mcp-server:agent-field-allowlist-smoke"
|
||
"apps/web:canary-template-smoke"
|
||
"packages/asset-registry:asset-registry-smoke"
|
||
".:operations-hardening-smoke"
|
||
".:systemd-unit-install-smoke"
|
||
".:mcp-webpush-install-defaults-smoke"
|
||
".:mcp-tool-name-parity-smoke"
|
||
".:csp-header-consistency-smoke"
|
||
".:price-feed-health-header-strip-smoke"
|
||
".:workspace-membership-smoke"
|
||
".:operator-doc-fenced-path-existence-smoke"
|
||
".:operator-doc-section-ref-smoke"
|
||
".:operator-doc-env-var-parity-smoke"
|
||
".:license-disclosure-smoke"
|
||
".:handler-push-click-path-route-smoke"
|
||
".:fast-badge-push-contract-smoke"
|
||
".:backup-script-posix-safety-smoke"
|
||
".:backup-install-parity-smoke"
|
||
".:chat-inbox-instant-subject-smoke"
|
||
".:health-backup-freshness-smoke"
|
||
".:indexer-public-health-operational-smoke"
|
||
".:postgres-pg-hba-loopback-smoke"
|
||
".:indexer-relay-account-smoke"
|
||
".:ansible-shared-script-dir-smoke"
|
||
".:ansible-offline-apt-gate-smoke"
|
||
".:offline-bundle-git-smoke"
|
||
".:canary-serve-dir-smoke"
|
||
".:reachability-check-smoke"
|
||
".:onion-frontend-target-smoke"
|
||
".:relay-health-probe-smoke"
|
||
".:onion-location-header-smoke"
|
||
".:pwa-install-button-smoke"
|
||
".:hidden-service-origin-smoke"
|
||
".:directory-card-hidden-service-smoke"
|
||
".:tor-routed-probe-smoke"
|
||
".:tor-only-install-smoke"
|
||
".:ansible-aide-deferred-smoke"
|
||
".:moderation-flag-clearance-smoke"
|
||
".:profile-link-glyphs-single-home-smoke"
|
||
".:reserved-name-owner-parity-smoke"
|
||
".:orderbook-freshness-contract-smoke"
|
||
".:orderbook-wire-status-parity-smoke"
|
||
".:sidecar-shell-quoting-smoke"
|
||
".:sidecar-envelope-error-path-smoke"
|
||
".:last-char-tamper-anti-pattern-smoke"
|
||
".:witness-chat-identity-claimed-op-smoke"
|
||
".:no-master-password-in-fee-flows-smoke"
|
||
".:verify-download-smoke"
|
||
".:release-notes-asset-count-parity-smoke"
|
||
".:canary-rpc-failover-smoke"
|
||
".:canary-btc-failover-smoke"
|
||
".:canary-setup-smoke"
|
||
".:now-in-handler-sql-smoke"
|
||
"apps/web:i18n-hardcoded-english-smoke"
|
||
"apps/web:i18n-raw-exception-smoke"
|
||
"apps/web:i18n-html-injection-smoke"
|
||
"apps/web:href-xss-smoke"
|
||
"apps/web:no-bare-internal-href-smoke"
|
||
"apps/web:explorer-urls-multi-smoke"
|
||
"apps/web:active-owner-key-invariants-smoke"
|
||
"apps/web:keygen-public-key-buffer-smoke"
|
||
"apps/web:wif-encode-roundtrip-smoke"
|
||
"apps/web:change-password-layered-rewrap-smoke"
|
||
"apps/web:yubikey-enroll-unlock-smoke"
|
||
"apps/web:yubikey-enroll-verify-smoke"
|
||
"apps/web:yubikey-transport-mock-smoke"
|
||
"apps/web:totp-2fa-enroll-verify-smoke"
|
||
"apps/web:seed-normalize-smoke"
|
||
"apps/web:key-backup-derivation-smoke"
|
||
"apps/web:account-number-detector-smoke"
|
||
"apps/web:i18n-formatters-smoke"
|
||
"apps/web:public-key-display-smoke"
|
||
"apps/web:order-card-smoke"
|
||
"apps/web:order-detail-expired-ui-smoke"
|
||
"apps/web:lazy-import-catch-fallback-smoke"
|
||
"apps/web:chat-pdf-export-smoke"
|
||
"apps/web:display-name-cap-smoke"
|
||
"apps/web:identity-label-policy-smoke"
|
||
"apps/web:onboarding-back-button-smoke"
|
||
"apps/web:user-preferences-smoke"
|
||
"apps/web:a11y-patterns-smoke"
|
||
"apps/web:heading-hierarchy-smoke"
|
||
"apps/web:forgejo-not-gitea-smoke"
|
||
"apps/web:font-assets-present-smoke"
|
||
"apps/web:pair-target-resolve-smoke"
|
||
"apps/web:fee-status-label-coverage-smoke"
|
||
"apps/web:color-contrast-smoke"
|
||
"apps/web:i18n-translation-completeness-smoke"
|
||
"apps/web:sally-walkthrough-smoke"
|
||
"apps/web:persona-walkthrough-smoke"
|
||
"apps/web:mediakit-freshness-smoke"
|
||
"apps/web:wiring-completeness-smoke"
|
||
"apps/web:chat-asset-ticker-narrow-union-parity-smoke"
|
||
"apps/web:network-icon-coverage-smoke"
|
||
"apps/web:payment-method-i18n-parity-smoke"
|
||
"apps/web:payment-filter-shows-all-methods-smoke"
|
||
"apps/web:web-push-wiring-smoke"
|
||
"apps/web:npm-audit-gate-smoke"
|
||
"apps/web:version-consistency-smoke"
|
||
"apps/relay:canonical-message-cross-check-smoke"
|
||
"apps/indexer:anti-snipe-extension-smoke"
|
||
"packages/asset-registry:fee-method-enum-frozen-smoke"
|
||
"packages/asset-registry:fee-split-math-smoke"
|
||
"packages/asset-registry:first-buy-waiver-payment-agnostic-smoke"
|
||
"packages/asset-registry:usdt-trade-only-smoke"
|
||
"packages/asset-registry:usdc-trade-only-smoke"
|
||
"packages/asset-registry:dai-trade-only-smoke"
|
||
"packages/asset-registry:bch-trade-only-smoke"
|
||
"packages/asset-registry:ltc-trade-only-smoke"
|
||
"packages/asset-registry:dash-trade-only-smoke"
|
||
"packages/asset-registry:doge-trade-only-smoke"
|
||
"packages/asset-registry:zec-trade-only-smoke"
|
||
"packages/asset-registry:arrr-trade-only-smoke"
|
||
"packages/asset-registry:dcr-trade-only-smoke"
|
||
"packages/asset-registry:sol-trade-only-smoke"
|
||
"packages/asset-registry:eth-trade-only-smoke"
|
||
"packages/asset-registry:xrp-trade-only-smoke"
|
||
"apps/web:asset-payload-precision-parity-smoke"
|
||
"apps/web:blurt-account-regex-parity-smoke"
|
||
"apps/web:order-expiry-day-floor-smoke"
|
||
".:workspace-typecheck-smoke"
|
||
".:smoke-registration-integrity-smoke"
|
||
".:smoke-pass-line-canonical-smoke"
|
||
"packages/asset-registry:asset-accent-class-uniqueness-smoke"
|
||
"packages/asset-registry:payment-rail-coverage-parity-smoke"
|
||
"packages/asset-registry:address-shape-overlap-smoke"
|
||
"packages/asset-registry:price-provider-coverage-parity-smoke"
|
||
"packages/asset-registry:privacy-features-registry-smoke"
|
||
"apps/web:address-history-helper-smoke"
|
||
"apps/web:amount-jitter-utxo-smoke"
|
||
"apps/web:payjoin-uri-wire-shape-smoke"
|
||
"apps/ops-cli:disabled-assets-wizard-smoke"
|
||
"apps/ops-cli:category-b-descriptions-parity-smoke"
|
||
"apps/ops-cli:ansible-structural-smoke"
|
||
"apps/ops-cli:first-online-smoke"
|
||
"apps/ops-cli:ansible-systemd-user-consistency-smoke"
|
||
"apps/ops-cli:repo-root-bak-recovery-smoke"
|
||
"apps/ops-cli:instance-env-loader-smoke"
|
||
"apps/ops-cli:systemd-js-runtime-af-unix-smoke"
|
||
"apps/ops-cli:refresh-units-smoke"
|
||
"apps/ops-cli:ansible-env-var-consumer-smoke"
|
||
"apps/ops-cli:ansible-lint-smoke"
|
||
"apps/matrix-bot:deps-pin-check"
|
||
"apps/matrix-bot:sidecar-envelope-smoke"
|
||
"apps/matrix-bot:emit-routing-smoke"
|
||
"apps/matrix-bot:self-test-route-smoke"
|
||
"apps/matrix-bot:json-str-injection-smoke"
|
||
"apps/matrix-bot:render-alert-hardening-smoke"
|
||
"apps/matrix-bot:matrix-bot-input-hardening-smoke"
|
||
"apps/matrix-bot:api-response-shape-smoke"
|
||
"apps/matrix-bot:sse-stream-shape-smoke"
|
||
"apps/ops-cli:term-sanitize-smoke"
|
||
"apps/relay:log-sanitize-smoke"
|
||
"apps/indexer:log-sanitize-smoke"
|
||
"apps/ops-cli:workspace-deps-pin-check"
|
||
"apps/ops-cli:upgrade-fetch-hardening-smoke"
|
||
"apps/ops-cli:upgrade-mirror-smoke"
|
||
"apps/ops-cli:indexer-health-metrics-smoke"
|
||
"apps/ops-cli:upgrade-frontend-deploy-smoke"
|
||
"apps/ops-cli:upgrade-backup-prune-smoke"
|
||
"apps/ops-cli:upgrade-schema-reminder-smoke"
|
||
"apps/ops-cli:fastpath-always-on-smoke"
|
||
"apps/ops-cli:upgrade-rebuilds-dist-workspaces-smoke"
|
||
"apps/ops-cli:upgrade-mcp-reachability-smoke"
|
||
"apps/ops-cli:install-invariants-smoke"
|
||
"apps/ops-cli:compiled-bundle-smoke"
|
||
"packages/asset-registry:usdt-network-picker-required-smoke"
|
||
".:brag-list-claim-parity-smoke"
|
||
".:seo-url-consistency-smoke"
|
||
"apps/web:og-fallback-meta-smoke"
|
||
"apps/web:release-tamper-deploy-skew-smoke"
|
||
"apps/web:balance-locale-sign-colors-smoke"
|
||
"apps/web:llms-full-freshness-smoke"
|
||
"apps/web:llms-txt-freshness-smoke"
|
||
"apps/web:build-manifest-release-json-smoke"
|
||
"apps/web:logo-bling-invariants-smoke"
|
||
"apps/web:coin-carousel-invariants-smoke"
|
||
"apps/web:svelte-component-import-coverage-smoke"
|
||
"apps/web:text-input-maxlength-coverage-smoke"
|
||
"apps/web:privacy-asset-sitemap-parity-smoke"
|
||
"apps/web:faq-jsonld-no-markdown-smoke"
|
||
"apps/web:faq-inline-render-smoke"
|
||
"apps/web:faq-glossary-terms-smoke"
|
||
"apps/web:faq-scroll-block-start-smoke"
|
||
"apps/web:footer-alt-network-pills-gated-smoke"
|
||
"apps/web:update-banner-user-consent-smoke"
|
||
"apps/web:nav-arrow-consistency-smoke"
|
||
"apps/web:locked-session-ux-smoke"
|
||
"apps/web:require-live-session-smoke"
|
||
"apps/web:autolock-settings-smoke"
|
||
"apps/web:faq-deeplink-smoke"
|
||
"apps/web:broadcast-same-origin-smoke"
|
||
"apps/web:settings-profile-keys-account-scoped-smoke"
|
||
"apps/web:endpoint-error-classify-smoke"
|
||
"apps/web:address-share-modal-ux-smoke"
|
||
"apps/web:rpc-privacy-routing-smoke"
|
||
"apps/web:onchain-user-privacy-smoke"
|
||
"apps/web:settings-chain-crypto-smoke"
|
||
"apps/web:order-completion-semantics-smoke"
|
||
"apps/relay:push-dedup-survives-delivery-smoke"
|
||
"apps/indexer:profiles-batch-accounts-anchored-smoke"
|
||
"apps/indexer:trade-count-semantics-smoke"
|
||
"apps/web:privacy-headline-length-smoke"
|
||
"apps/web:carrier-registry-invariants-smoke"
|
||
"apps/web:shipping-payload-roundtrip-smoke"
|
||
"apps/web:order-settled-elsewhere-payload-smoke"
|
||
"apps/web:settled-elsewhere-announce-smoke"
|
||
"apps/web:2fa-no-google-recommendation-smoke"
|
||
"apps/web:2fa-recommended-apps-coverage-smoke"
|
||
"apps/web:2fa-locale-parity-smoke"
|
||
"apps/web:comparison-image-freshness-smoke"
|
||
"apps/web:asset-select-coverage-smoke"
|
||
"apps/web:disabled-payment-methods-ui-coverage-smoke"
|
||
"apps/web:footer-contact-flash-smoke"
|
||
"apps/web:endpoint-list-throttle-smoke"
|
||
"apps/web:orderbook-hide-confirm-smoke"
|
||
"apps/web:orderbook-select-stacking-smoke"
|
||
"apps/web:orderbook-live-status-wired-smoke"
|
||
"apps/web:faq-search-grandma-coverage-smoke"
|
||
"apps/web:ip-disclosure-single-source-smoke"
|
||
"apps/web:push-privacy-honesty-smoke"
|
||
"apps/web:identity-label-truncation-smoke"
|
||
"apps/web:block-time-vs-wall-clock-smoke"
|
||
"apps/indexer:rpc-user-agent-smoke"
|
||
"apps/indexer:batch-4xx-single-fallback-smoke"
|
||
"apps/web:chat-inbox-motion-smoke"
|
||
"apps/web:modal-viewport-fit-smoke"
|
||
".:rpc-batch-contract-smoke"
|
||
".:public-doc-drift-smoke"
|
||
"apps/web:import-remember-me-smoke"
|
||
"apps/web:import-account-auto-resolve-smoke"
|
||
"apps/web:accountless-banner-smoke"
|
||
"apps/web:unlock-redirect-next-smoke"
|
||
"apps/web:cross-tab-signout-propagation-smoke"
|
||
"apps/web:update-banner-deployed-version-poll-smoke"
|
||
"apps/web:update-surface-nocache-config-smoke"
|
||
"apps/web:canary-link-no-locale-prefix-smoke"
|
||
"apps/web:chat-unread-count-wired-smoke"
|
||
"apps/web:pay-blurt-modal-errors-smoke"
|
||
"apps/web:chat-realtime-cadence-smoke"
|
||
"apps/web:my-orders-card-cluster-smoke"
|
||
"apps/web:copy-button-green-check-smoke"
|
||
"apps/web:order-detail-posting-retry-smoke"
|
||
"apps/web:txid-hash-clarity-smoke"
|
||
"apps/web:chat-header-reputation-smoke"
|
||
"apps/web:avatar-size-thresholds-smoke"
|
||
"apps/web:storage-key-classification-smoke"
|
||
"apps/web:settings-visibility-scope-smoke"
|
||
"apps/web:order-card-message-visibility-smoke"
|
||
"apps/web:profile-hydrate-retry-smoke"
|
||
"apps/web:order-card-identity-first-paint-smoke"
|
||
"apps/web:identity-no-swap-smoke"
|
||
"apps/web:profile-account-change-reload-smoke"
|
||
"apps/web:profile-freshness-smoke"
|
||
"apps/web:profile-website-url-smoke"
|
||
"apps/web:canary-ascii-and-dates-smoke"
|
||
"apps/web:chat-day-separator-smoke"
|
||
"apps/web:cancel-redirect-and-relist-smoke"
|
||
"apps/web:feature-pills-fiat-smoke"
|
||
"apps/web:support-operator-matrix-removed-smoke"
|
||
"apps/web:featured-bid-history-modal-smoke"
|
||
"apps/web:featured-order-copy-smoke"
|
||
"apps/web:featured-card-reputation-smoke"
|
||
"apps/web:ui-polish-batch-smoke"
|
||
"apps/web:ken-batch-2-smoke"
|
||
"apps/web:pay-now-active-key-smoke"
|
||
"apps/web:chat-notification-wiring-smoke"
|
||
"apps/web:posting-active-upgrade-smoke"
|
||
"apps/web:chat-header-layout-smoke"
|
||
"apps/web:account-binding-smoke"
|
||
"apps/web:eli5-release-blocks-smoke"
|
||
"apps/web:avatar-menu-portal-smoke"
|
||
"apps/web:trust-score-modal-portal-smoke"
|
||
"apps/web:chat-inbox-threading-smoke"
|
||
"apps/web:explorer-download-polish-smoke"
|
||
"apps/web:chat-read-state-threading-smoke"
|
||
"apps/web:no-bare-root-href-in-lang-subtree-smoke"
|
||
"apps/web:balance-via-indexer-not-rpc-smoke"
|
||
"apps/web:account-history-via-indexer-smoke"
|
||
"apps/web:chain-explorer-via-indexer-smoke"
|
||
"apps/web:external-link-hygiene-smoke"
|
||
"apps/web:blurt-image-link-safety-smoke"
|
||
"apps/web:removed-static-asset-guard-smoke"
|
||
"apps/web:login-key-verify-via-indexer-smoke"
|
||
"apps/web:explorer-manual-refresh-smoke"
|
||
"apps/web:explorer-account-card-smoke"
|
||
"apps/web:explorer-op-label-values-parity-smoke"
|
||
"apps/web:explorer-json-highlight-safety-smoke"
|
||
"apps/web:terms-forbidden-char-parity-smoke"
|
||
"apps/web:orderbook-terms-highlight-safety-smoke"
|
||
"apps/web:instances-alt-network-links-smoke"
|
||
"apps/web:blurt-apr-smoke"
|
||
"apps/web:first-trade-buy-blurt-lock-smoke"
|
||
"apps/web:chat-folders-onchain-smoke"
|
||
"apps/web:instances-current-by-origin-smoke"
|
||
"apps/web:chat-thread-model-smoke"
|
||
"apps/web:chat-order-tag-storage-smoke"
|
||
"apps/web:chat-thread-remount-smoke"
|
||
"apps/web:chat-bg-notify-v148-smoke"
|
||
"apps/web:chat-ui-v148-smoke"
|
||
"apps/web:chat-sent-state-smoke"
|
||
"apps/web:chat-notif-default-on-smoke"
|
||
"apps/web:chat-notif-nudge-smoke"
|
||
"apps/web:claim-reward-balance-smoke"
|
||
"apps/web:syndication-first-trade-post-smoke"
|
||
"apps/web:chat-blocks-race-guard-smoke"
|
||
"apps/web:chat-pay-now-flow-smoke"
|
||
"apps/web:chat-own-sent-plaintext-cache-smoke"
|
||
"apps/web:chat-immersive-layout-smoke"
|
||
"apps/web:chat-fastpath-dedup-smoke"
|
||
"apps/indexer:reputation-decay-smoke"
|
||
"apps/indexer:reputation-score-smoke"
|
||
"apps/indexer:posting-key-storage-smoke"
|
||
"apps/indexer:reputation-decay-sql-constant-parity-smoke"
|
||
"apps/indexer:reputation-receipt-shape-smoke"
|
||
"apps/indexer:stablecoin-depeg-detector-smoke"
|
||
"apps/indexer:morphit-native-fetcher-smoke"
|
||
"apps/indexer:price-source-hardening-smoke"
|
||
"apps/indexer:price-primary-fallback-smoke"
|
||
"apps/indexer:price-input-block-enforcement-smoke"
|
||
"apps/indexer:peer-price-monitor-smoke"
|
||
"apps/indexer:price-fetch-util-smoke"
|
||
"apps/indexer:crypto-fetcher-smoke"
|
||
"apps/indexer:fee-tolerance-smoke"
|
||
"apps/indexer:treasury-repin-smoke"
|
||
"apps/indexer:fx-endpoint-smoke"
|
||
"apps/indexer:price-feeds-health-smoke"
|
||
"apps/indexer:fx-source-smoke"
|
||
"apps/indexer:multi-asset-factory-smoke"
|
||
".:spawn-dist-prebuild-coverage-smoke"
|
||
".:lockfile-sync-smoke"
|
||
".:tsx-runtime-dependency-smoke"
|
||
".:ci-workflow-hardening-smoke"
|
||
".:package-files-exist-smoke"
|
||
".:mcp-server-read-only-invariant-smoke"
|
||
".:source-marketing-prose-smoke"
|
||
".:strip-comments-smoke"
|
||
".:no-sandbox-path-smoke"
|
||
".:no-docker-latest-tag-smoke"
|
||
".:wizard-step-count-doc-parity-smoke"
|
||
".:root-shell-then-redirect-smoke"
|
||
".:blurt-noble-signer-recovery-proof"
|
||
".:blurt-noble-tx-signature-proof"
|
||
".:signer-backend-consistency-smoke"
|
||
"apps/web:chat-feedback-cancel-smoke"
|
||
"apps/web:chat-notif-nudge-gate-smoke"
|
||
"apps/web:archived-thread-not-unread-smoke"
|
||
"apps/web:import-eager-self-avatar-smoke"
|
||
"apps/web:order-blog-post-mirror-smoke"
|
||
"apps/web:barter-specific-title-smoke"
|
||
"apps/web:order-title-crypto-ticker-smoke"
|
||
"apps/web:rtl-bidi-smoke"
|
||
".:ipns-release-wiring-smoke"
|
||
".:ipns-dht-rebroadcast-smoke"
|
||
".:ipfs-release-hosting-smoke"
|
||
".:ipfs-selfseed-smoke"
|
||
".:ddns-setup-smoke"
|
||
".:reboot-recovery-smoke"
|
||
".:upgrade-notify-smoke"
|
||
".:matrix-login-smoke"
|
||
".:setup-bootstrap-smoke"
|
||
".:ddns-role-smoke"
|
||
".:ansible-vars-smoke"
|
||
".:save-secrets-smoke"
|
||
".:collect-install-inputs-smoke"
|
||
".:assemble-install-smoke"
|
||
".:relay-keystore-content-smoke"
|
||
".:local-install-smoke"
|
||
".:install-summary-smoke"
|
||
".:smoke-runner-count-extraction-smoke"
|
||
"apps/web:profile-persistent-cache-smoke"
|
||
)
|
||
|
||
total=0
|
||
failed=0
|
||
# Per-invocation tempfile prevents concurrent runs from racing on
|
||
# the same /tmp/smoke.out and producing transient miscounts.
|
||
SMOKE_OUT="$(mktemp -t morphit-smoke.XXXXXX.out)"
|
||
trap 'rm -f "$SMOKE_OUT"' EXIT
|
||
for entry in "${SMOKES[@]}"; do
|
||
dir="${entry%:*}"
|
||
name="${entry##*:}"
|
||
path="$repo/$dir/scripts/$name.ts"
|
||
if [ ! -f "$path" ]; then
|
||
echo " ✗ $name (file missing: $path)"
|
||
failed=$((failed + 1))
|
||
continue
|
||
fi
|
||
# Smoke tsconfig selection (cp63 LL #66; per-workspace override cp448).
|
||
# The repo-root `tsconfig.smoke.json` is the unified default — it merges
|
||
# path aliases from apps/web ($lib, $components, ...) and apps/indexer
|
||
# ($api, $config, ...) so cross-workspace smoke imports resolve, and a
|
||
# smoke that uses no alias doesn't care (tsx ignores the paths block).
|
||
#
|
||
# BUT a few SvelteKit `$`-aliases are PER-APP and genuinely conflict:
|
||
# `$blurt`/`$indexer` mean apps/web/src/lib/{blurt,indexer} in the web
|
||
# app and apps/indexer/src/{blurt,indexer} in the indexer. A single
|
||
# flat `paths` map can't express both, so the root config maps them to
|
||
# the indexer. A workspace that needs its own resolution ships its own
|
||
# `<workspace>/tsconfig.smoke.json` (apps/web does, so its smokes can
|
||
# `import()` a `$blurt/*`-importing web module without the module
|
||
# silently binding the indexer's copy). Prefer the workspace-local
|
||
# config when present, else the unified root config.
|
||
# `smoke-tsconfig-alias-parity-smoke.ts` keeps both in sync with the
|
||
# runtime aliases in svelte.config.js / apps/indexer/tsconfig.json.
|
||
if [ -f "$repo/$dir/tsconfig.smoke.json" ]; then
|
||
TSX_ARGS=(--tsconfig "$repo/$dir/tsconfig.smoke.json")
|
||
elif [ -f "$repo/tsconfig.smoke.json" ]; then
|
||
TSX_ARGS=(--tsconfig "$repo/tsconfig.smoke.json")
|
||
else
|
||
TSX_ARGS=()
|
||
fi
|
||
# Per-smoke wall-clock timeout (cp143). cp142 closed a CI-bomb
|
||
# where `apps/mcp-server/scripts/mcp-server-smoke.ts` hung
|
||
# indefinitely on fresh checkouts (no built dist/main.js → child
|
||
# never produced stdout → smoke waited forever). The cp142 fix
|
||
# was static (lazy-build + meta-smoke), this is the runtime
|
||
# complement: any future smoke that hangs gets converted into a
|
||
# legible "killed after N seconds" failure instead of stalling
|
||
# the whole CI job until the action runner's hard timeout.
|
||
#
|
||
# 240 seconds is the ceiling. The current slow-pole is
|
||
# `apps/web/scripts/vitest-must-pass-smoke.ts` which spawns
|
||
# real `vitest run` invocations across apps/{indexer,relay,web}
|
||
# — 981 unit tests in jsdom — and clocks ~150s on this hardware.
|
||
# 240s gives ~1.6× buffer for slow CI hosts and cold caches.
|
||
# Every other smoke clocks under 15s. If a real smoke ever
|
||
# legitimately approaches 240s, bump this constant AND ask why
|
||
# the smoke got that slow (probably means it's doing too much
|
||
# in one file).
|
||
#
|
||
# Override via MORPHIT_SMOKE_TIMEOUT env var for slower hosts.
|
||
# `timeout` exits 124 on SIGTERM expiry / 137 on SIGKILL,
|
||
# distinguishable from smoke's own non-zero exits.
|
||
SMOKE_TIMEOUT="${MORPHIT_SMOKE_TIMEOUT:-240}"
|
||
if (cd "$repo/$dir" && timeout --signal=TERM --kill-after=5 "$SMOKE_TIMEOUT" "$TSX" "${TSX_ARGS[@]}" "scripts/$name.ts" >"$SMOKE_OUT" 2>&1); then
|
||
# Smokes MUST emit a canonical `✓ all N ...` line so this runner
|
||
# can tally scenarios. Without that line, the smoke is treated as
|
||
# a runner failure rather than silently counted as 0 — see J-1
|
||
# (silent zero counting from empty arithmetic) and J-2 (sally
|
||
# emitted a custom format and was undercounted by 22 for ~20
|
||
# Parts) findings, Part 87.
|
||
# Anchor the count extraction at the line start (^✓ all N) — NOT
|
||
# `.*all `: a greedy `.*all ` matches the "all " inside a smoke NAME
|
||
# like assemble-INSTALL / local-INSTALL and captures an empty count,
|
||
# which mis-reported those two as "no canonical line" on 2026-07-30
|
||
# (they print the line fine; the runner mis-parsed it). grep already
|
||
# guarantees the line begins with `✓ all`.
|
||
n=$(grep "^✓ all" "$SMOKE_OUT" | sed "s/^✓ all \([0-9]*\).*/\1/")
|
||
if [ -z "$n" ] || [ "$n" -eq 0 ] 2>/dev/null; then
|
||
failed=$((failed + 1))
|
||
echo " ✗ $name (passed runner but emitted no canonical '^✓ all N …' line — fix the smoke to print it)"
|
||
tail -30 "$SMOKE_OUT" | sed 's/^/ /'
|
||
continue
|
||
fi
|
||
total=$((total + n))
|
||
else
|
||
exit_code=$?
|
||
failed=$((failed + 1))
|
||
# Distinguish timeout (124/137) from smoke-emitted non-zero.
|
||
if [ "$exit_code" -eq 124 ] || [ "$exit_code" -eq 137 ]; then
|
||
echo " ✗ $name (HUNG — killed after ${SMOKE_TIMEOUT}s; this is the cp142 bug class — see scripts/spawn-dist-prebuild-coverage-smoke.ts)"
|
||
else
|
||
echo " ✗ $name (exit $exit_code)"
|
||
fi
|
||
tail -30 "$SMOKE_OUT" | sed 's/^/ /'
|
||
fi
|
||
done
|
||
|
||
echo
|
||
echo "──────────────────────────────────────────────────────"
|
||
echo "Total: $total scenarios passed, $failed runners failed"
|
||
if [ "$failed" -ne 0 ]; then
|
||
exit 1
|
||
fi
|