From 7afd13e9be0bf21c2ed3c8b394ec21e8a85da694 Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Wed, 26 Nov 2025 15:19:41 +0100
Subject: [PATCH 1/2] ci: add Cloudflare Pages deployment with noindex headers
---
.../cloudflare-legacy-deployment.yml | 133 ++++++++++++++++++
docs/cloudflare-deploy-runbook.md | 45 ++++++
public/_headers | 2 +
public/robots.txt | 3 +-
4 files changed, 182 insertions(+), 1 deletion(-)
create mode 100644 .github/workflows/cloudflare-legacy-deployment.yml
create mode 100644 docs/cloudflare-deploy-runbook.md
create mode 100644 public/_headers
diff --git a/.github/workflows/cloudflare-legacy-deployment.yml b/.github/workflows/cloudflare-legacy-deployment.yml
new file mode 100644
index 000000000..b57ce98f0
--- /dev/null
+++ b/.github/workflows/cloudflare-legacy-deployment.yml
@@ -0,0 +1,133 @@
+name: Cloudflare Pages Deploy (production)
+
+on:
+ workflow_dispatch:
+ inputs:
+ branch:
+ description: "Git ref/branch to deploy"
+ required: false
+ default: "main"
+ env_prefix:
+ description: "Optional path prefix (e.g., preview/)"
+ required: false
+ default: ""
+
+jobs:
+ build:
+ name: Build
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ env:
+ NODE_VERSION: "20"
+ PUBLIC_URL: /
+ CANONICAL_HOSTNAME: old-app.threshold.network
+ CHAIN_ID: 1
+ ALCHEMY_API_KEY: ${{ secrets.ALCHEMY_API_KEY }}
+ ELECTRUM_PROTOCOL: ${{ secrets.MAINNET_ELECTRUMX_PROTOCOL }}
+ ELECTRUM_HOST: ${{ secrets.MAINNET_ELECTRUMX_HOST }}
+ ELECTRUM_PORT: ${{ secrets.MAINNET_ELECTRUMX_PORT }}
+ SENTRY_DSN: ${{ secrets.MAINNET_SENTRY_DSN }}
+ TRM_SUPPORT: ${{ secrets.TRM_SUPPORT }}
+ WALLET_CONNECT_PROJECT_ID: ${{ secrets.WALLET_CONNECT_PROJECT_ID }}
+ TBTC_SUBGRAPH_API_KEY: ${{ secrets.TBTC_SUBGRAPH_API_KEY }}
+ GOOGLE_TAG_MANAGER_ID: ${{ secrets.GOOGLE_TAG_MANAGER_ID }}
+ GOOGLE_TAG_MANAGER_SUPPORT: true
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ github.event.inputs.branch || 'main' }}
+
+ - uses: actions/setup-node@v3
+ with:
+ node-version: "20"
+ cache: yarn
+
+ - name: Force git to use https
+ run: git config --global url."https://".insteadOf git://
+
+ - name: Install dependencies
+ run: yarn install --ignore-scripts --frozen-lockfile
+
+ - name: Postinstall
+ run: yarn run postinstall
+
+ - name: Build
+ run: |
+ PUBLIC_URL=${PUBLIC_URL} \
+ CANONICAL_HOSTNAME=${CANONICAL_HOSTNAME} \
+ CHAIN_ID=${CHAIN_ID} \
+ ALCHEMY_API_KEY=${ALCHEMY_API_KEY} \
+ ELECTRUM_PROTOCOL=${ELECTRUM_PROTOCOL} \
+ ELECTRUM_HOST=${ELECTRUM_HOST} \
+ ELECTRUM_PORT=${ELECTRUM_PORT} \
+ SENTRY_DSN=${SENTRY_DSN} \
+ TRM_SUPPORT=${TRM_SUPPORT} \
+ WALLET_CONNECT_PROJECT_ID=${WALLET_CONNECT_PROJECT_ID} \
+ TBTC_SUBGRAPH_API_KEY=${TBTC_SUBGRAPH_API_KEY} \
+ GOOGLE_TAG_MANAGER_SUPPORT=${GOOGLE_TAG_MANAGER_SUPPORT} \
+ GOOGLE_TAG_MANAGER_ID=${GOOGLE_TAG_MANAGER_ID} \
+ yarn build
+
+ - uses: actions/upload-artifact@v4
+ with:
+ name: build
+ path: build
+
+ deploy:
+ name: Deploy to Cloudflare Pages
+ needs: build
+ runs-on: ubuntu-latest
+ environment:
+ name: cloudflare-production
+ url: https://token-dashboard-legacy.pages.dev
+ permissions:
+ contents: read
+ env:
+ CF_PAGES_PROJECT: token-dashboard-legacy
+ CLOUDFLARE_API_TOKEN: ${{ secrets.CF_PAGES_API_TOKEN }}
+ CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID || secrets.CF_ACCOUNT_ID }}
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ github.event.inputs.branch || 'main' }}
+
+ - uses: actions/download-artifact@v4
+ with:
+ name: build
+ path: build
+
+ - name: Install wrangler
+ run: npm install -g wrangler@4.50.0
+
+ - name: Deploy
+ env:
+ CF_DEPLOY_BRANCH: ${{ github.event.inputs.branch || 'main' }}
+ CF_DEPLOY_ENV_PREFIX: ${{ github.event.inputs.env_prefix }}
+ run: |
+ set -euo pipefail
+ export CLOUDFLARE_API_TOKEN
+ export CF_API_TOKEN="$CLOUDFLARE_API_TOKEN"
+ export CLOUDFLARE_ACCOUNT_ID
+ if [ -z "$CLOUDFLARE_ACCOUNT_ID" ]; then
+ echo "CLOUDFLARE_ACCOUNT_ID missing" >&2
+ exit 1
+ fi
+ if [ -z "$CF_DEPLOY_ENV_PREFIX" ]; then
+ BRANCH_NAME="$CF_DEPLOY_BRANCH"
+ else
+ BRANCH_NAME="$CF_DEPLOY_ENV_PREFIX"
+ fi
+ wrangler pages deploy build \
+ --project-name ${CF_PAGES_PROJECT} \
+ --branch ${BRANCH_NAME}
+
+ - name: Smoke check (post-deploy)
+ env:
+ SMOKE_URL: https://old-app.threshold.network/overview/network
+ run: |
+ set -euo pipefail
+ echo "Smoke checking ${SMOKE_URL}"
+ curl -I --fail "$SMOKE_URL"
diff --git a/docs/cloudflare-deploy-runbook.md b/docs/cloudflare-deploy-runbook.md
new file mode 100644
index 000000000..74da3d1e4
--- /dev/null
+++ b/docs/cloudflare-deploy-runbook.md
@@ -0,0 +1,45 @@
+# Cloudflare Pages Deploy (token-dashboard-legacy)
+
+## Workflow
+
+- File: `.github/workflows/cloudflare-legacy-deployment.yml`
+- Trigger: `workflow_dispatch` with inputs
+ - `branch` (default `main`)
+ - `env_prefix` (optional path/alias override)
+- Jobs: `Build` (yarn build, artifact upload) → `Deploy` (wrangler pages deploy)
+ → smoke check.
+- Environment gate: `cloudflare-production` (approve in Actions UI).
+
+## Required secrets
+
+- `CF_PAGES_API_TOKEN` (Pages:Edit scope)
+- `CLOUDFLARE_ACCOUNT_ID`
+- Build secrets: `ALCHEMY_API_KEY`, `MAINNET_ELECTRUMX_PROTOCOL`,
+ `MAINNET_ELECTRUMX_HOST`, `MAINNET_ELECTRUMX_PORT`, `MAINNET_SENTRY_DSN`,
+ `TRM_SUPPORT`, `WALLET_CONNECT_PROJECT_ID`, `TBTC_SUBGRAPH_API_KEY`,
+ `GOOGLE_TAG_MANAGER_ID`, `GOOGLE_TAG_MANAGER_SUPPORT` (true/false in workflow
+ env).
+
+## How to deploy
+
+```bash
+# from any machine with gh auth
+gh workflow run cloudflare-legacy-deployment.yml -f branch=main
+# approve the environment prompt in GitHub Actions
+```
+
+- Production URL: https://token-dashboard-legacy.pages.dev
+- Custom domain: https://old-app.threshold.network
+- Post-deploy smoke: curls
+ `https://old-app.threshold.network/overview/network` (fails the job on
+ non-200/301).
+
+## Notes
+
+- Wrangler pinned to 4.50.0.
+- If you need a preview alias, pass `env_prefix=preview/` so Pages uses
+ that alias.
+- Redirects/headers can be added via `_redirects` / `_headers` in the repo.
+- Current legacy deployment is intentionally non-indexable: `_headers` sets
+ `X-Robots-Tag: noindex, nofollow` and `robots.txt` disallows all. Remove these
+ when you want search indexing back.
diff --git a/public/_headers b/public/_headers
new file mode 100644
index 000000000..c01bc2027
--- /dev/null
+++ b/public/_headers
@@ -0,0 +1,2 @@
+/*
+ X-Robots-Tag: noindex, nofollow
diff --git a/public/robots.txt b/public/robots.txt
index e9e57dc4d..9c76deb24 100644
--- a/public/robots.txt
+++ b/public/robots.txt
@@ -1,3 +1,4 @@
# https://www.robotstxt.org/robotstxt.html
+# Block all crawlers for legacy Cloudflare deployment
User-agent: *
-Disallow:
+Disallow: /
From 5af8e93a23346d301f2ad4cce684e2f1900b37af Mon Sep 17 00:00:00 2001
From: Piotr Roslaniec
Date: Sun, 30 Nov 2025 11:24:27 +0100
Subject: [PATCH 2/2] ci(testnet): add cloudflare legacy pages deploy
---
.../cloudflare-legacy-testnet-deployment.yml | 131 ++++++++++++++++++
docs/cloudflare-deploy-runbook.md | 29 ++++
2 files changed, 160 insertions(+)
create mode 100644 .github/workflows/cloudflare-legacy-testnet-deployment.yml
diff --git a/.github/workflows/cloudflare-legacy-testnet-deployment.yml b/.github/workflows/cloudflare-legacy-testnet-deployment.yml
new file mode 100644
index 000000000..a4895870a
--- /dev/null
+++ b/.github/workflows/cloudflare-legacy-testnet-deployment.yml
@@ -0,0 +1,131 @@
+name: Cloudflare Pages Deploy (testnet legacy)
+
+on:
+ workflow_dispatch:
+ inputs:
+ branch:
+ description: "Git ref/branch to deploy"
+ required: false
+ default: "main"
+ env_prefix:
+ description: "Optional path prefix (e.g., preview/)"
+ required: false
+ default: ""
+
+jobs:
+ build:
+ name: Build
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ env:
+ NODE_VERSION: "20"
+ PUBLIC_URL: /
+ CANONICAL_HOSTNAME: testnet-token-dashboard-legacy.pages.dev
+ CHAIN_ID: 11155111
+ ALCHEMY_API_KEY: ${{ secrets.ALCHEMY_API_KEY }}
+ ELECTRUM_PROTOCOL: ${{ secrets.TESTNET_ELECTRUMX_PROTOCOL }}
+ ELECTRUM_HOST: ${{ secrets.TESTNET_ELECTRUMX_HOST }}
+ ELECTRUM_PORT: ${{ secrets.TESTNET_ELECTRUMX_PORT }}
+ SENTRY_SUPPORT: true
+ SENTRY_DSN: ${{ secrets.TESTNET_SENTRY_DSN }}
+ WALLET_CONNECT_PROJECT_ID: ${{ secrets.WALLET_CONNECT_PROJECT_ID }}
+ TBTC_SUBGRAPH_API_KEY: ${{ secrets.TBTC_SUBGRAPH_API_KEY }}
+ DAPP_DEVELOPMENT_TESTNET_CONTRACTS: false
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ github.event.inputs.branch || 'main' }}
+
+ - uses: actions/setup-node@v3
+ with:
+ node-version: "20"
+ cache: yarn
+
+ - name: Force git to use https
+ run: git config --global url."https://".insteadOf git://
+
+ - name: Install dependencies
+ run: yarn install --ignore-scripts --frozen-lockfile
+
+ - name: Postinstall
+ run: yarn run postinstall
+
+ - name: Build
+ run: |
+ PUBLIC_URL=${PUBLIC_URL} \
+ CANONICAL_HOSTNAME=${CANONICAL_HOSTNAME} \
+ CHAIN_ID=${CHAIN_ID} \
+ ALCHEMY_API_KEY=${ALCHEMY_API_KEY} \
+ ELECTRUM_PROTOCOL=${ELECTRUM_PROTOCOL} \
+ ELECTRUM_HOST=${ELECTRUM_HOST} \
+ ELECTRUM_PORT=${ELECTRUM_PORT} \
+ SENTRY_SUPPORT=${SENTRY_SUPPORT} \
+ SENTRY_DSN=${SENTRY_DSN} \
+ WALLET_CONNECT_PROJECT_ID=${WALLET_CONNECT_PROJECT_ID} \
+ TBTC_SUBGRAPH_API_KEY=${TBTC_SUBGRAPH_API_KEY} \
+ DAPP_DEVELOPMENT_TESTNET_CONTRACTS=${DAPP_DEVELOPMENT_TESTNET_CONTRACTS} \
+ yarn build
+
+ - uses: actions/upload-artifact@v4
+ with:
+ name: build
+ path: build
+
+ deploy:
+ name: Deploy to Cloudflare Pages
+ needs: build
+ runs-on: ubuntu-latest
+ environment:
+ name: cloudflare-testnet
+ url: https://testnet-token-dashboard-legacy.pages.dev
+ permissions:
+ contents: read
+ env:
+ CF_PAGES_PROJECT: testnet-token-dashboard-legacy
+ CLOUDFLARE_API_TOKEN: ${{ secrets.CF_PAGES_API_TOKEN }}
+ CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID || secrets.CF_ACCOUNT_ID }}
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ ref: ${{ github.event.inputs.branch || 'main' }}
+
+ - uses: actions/download-artifact@v4
+ with:
+ name: build
+ path: build
+
+ - name: Install wrangler
+ run: npm install -g wrangler@4.50.0
+
+ - name: Deploy
+ env:
+ CF_DEPLOY_BRANCH: ${{ github.event.inputs.branch || 'main' }}
+ CF_DEPLOY_ENV_PREFIX: ${{ github.event.inputs.env_prefix }}
+ run: |
+ set -euo pipefail
+ export CLOUDFLARE_API_TOKEN
+ export CF_API_TOKEN="$CLOUDFLARE_API_TOKEN"
+ export CLOUDFLARE_ACCOUNT_ID
+ if [ -z "$CLOUDFLARE_ACCOUNT_ID" ]; then
+ echo "CLOUDFLARE_ACCOUNT_ID missing" >&2
+ exit 1
+ fi
+ if [ -z "$CF_DEPLOY_ENV_PREFIX" ]; then
+ BRANCH_NAME="$CF_DEPLOY_BRANCH"
+ else
+ BRANCH_NAME="$CF_DEPLOY_ENV_PREFIX"
+ fi
+ wrangler pages deploy build \
+ --project-name ${CF_PAGES_PROJECT} \
+ --branch ${BRANCH_NAME}
+
+ - name: Smoke check (post-deploy)
+ env:
+ SMOKE_URL: https://testnet-token-dashboard-legacy.pages.dev/
+ run: |
+ set -euo pipefail
+ echo "Smoke checking ${SMOKE_URL}"
+ curl -I --fail "$SMOKE_URL"
diff --git a/docs/cloudflare-deploy-runbook.md b/docs/cloudflare-deploy-runbook.md
index 74da3d1e4..062962994 100644
--- a/docs/cloudflare-deploy-runbook.md
+++ b/docs/cloudflare-deploy-runbook.md
@@ -43,3 +43,32 @@ gh workflow run cloudflare-legacy-deployment.yml -f branch=main
- Current legacy deployment is intentionally non-indexable: `_headers` sets
`X-Robots-Tag: noindex, nofollow` and `robots.txt` disallows all. Remove these
when you want search indexing back.
+
+## Testnet workflow (legacy)
+
+- File: `.github/workflows/cloudflare-legacy-testnet-deployment.yml`
+- Trigger: `workflow_dispatch` with inputs
+ - `branch` (default `main`)
+ - `env_prefix` (optional path/alias override)
+- Jobs: `Build` (yarn build, artifact upload) → `Deploy` (wrangler pages deploy)
+ → smoke check.
+- Environment gate: `cloudflare-testnet` (approve in Actions UI).
+- Pages project: `testnet-token-dashboard-legacy`
+- Default domain: https://testnet-token-dashboard-legacy.pages.dev
+- Smoke check: HEAD `https://testnet-token-dashboard-legacy.pages.dev/`
+
+### Required secrets (testnet)
+
+- `CF_PAGES_API_TOKEN`
+- `CLOUDFLARE_ACCOUNT_ID`
+- Build secrets: `ALCHEMY_API_KEY`, `TESTNET_ELECTRUMX_PROTOCOL`,
+ `TESTNET_ELECTRUMX_HOST`, `TESTNET_ELECTRUMX_PORT`, `TESTNET_SENTRY_DSN`,
+ `WALLET_CONNECT_PROJECT_ID`, `TBTC_SUBGRAPH_API_KEY`
+
+### How to deploy (testnet)
+
+```bash
+# from any machine with gh auth
+gh workflow run cloudflare-legacy-testnet-deployment.yml -f branch=main
+# approve the environment prompt in GitHub Actions
+```