mirror of
https://github.com/luxfi/explore.git
synced 2026-07-27 03:13:50 +00:00
feat(brand): per-(brand x env) image overlay — ghcr.io/{brand-org}/explore-{env}
The branded build now fans out into 8 (4 brands × mainnet+testnet)
production images:
ghcr.io/luxfi/explore-{mainnet,testnet}:v1.0.0
ghcr.io/zooai/explore-{mainnet,testnet}:v1.0.0
ghcr.io/hanzoai/explore-{mainnet,testnet}:v1.0.0
ghcr.io/parsdao/explore-{mainnet,testnet}:v1.0.0
Each image is a thin ENV overlay of ghcr.io/luxfi/explore (the Next.js
runtime) — brand identity is baked at build time via NEXT_PUBLIC_*
build-args. The brand's GHCR namespace owns the image per the workspace
container-registry rules (no cross-org mixing).
deploy/scripts/branded_build.sh is the source of truth for tuple -> env
mapping; the actual image fan-out is performed via crane mutate -e which
produces an instant ENV-only layer (no Kaniko, no tar of build context —
same hash blob mounts across namespaces).
The corresponding K8s manifests (per-brand Deployment + Service per
namespace, IngressRoute patches routing catch-all to FE) live in the
cluster directly.
This commit is contained in:
@@ -1 +1,3 @@
|
||||
ECDL
|
||||
Kaniko
|
||||
parsdao
|
||||
|
||||
+60
-25
@@ -1,28 +1,63 @@
|
||||
# Per-brand × per-env Blockscout overlay image.
|
||||
#
|
||||
# All NEXT_PUBLIC_* env vars are passed in as build-args; the image is a
|
||||
# thin overlay of `ghcr.io/luxfi/explore:latest` that bakes those args
|
||||
# into ENV so Blockscout's entrypoint emits the correct envs.js at boot.
|
||||
#
|
||||
# The Kaniko build pod assembles one image per (brand, env) tuple by
|
||||
# passing the right --build-arg set. Authoritative tuples live in
|
||||
# deploy/scripts/branded_build.sh.
|
||||
|
||||
FROM ghcr.io/luxfi/explore:latest
|
||||
|
||||
# LUX Network Branding
|
||||
ENV NEXT_PUBLIC_NETWORK_NAME="LUX Network" \
|
||||
NEXT_PUBLIC_NETWORK_SHORT_NAME="LUX" \
|
||||
NEXT_PUBLIC_NETWORK_ID="96369" \
|
||||
NEXT_PUBLIC_NETWORK_CURRENCY_NAME="LUX" \
|
||||
NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL="LUX" \
|
||||
NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS="18" \
|
||||
NEXT_PUBLIC_API_HOST="api-explore.lux.network" \
|
||||
NEXT_PUBLIC_API_PROTOCOL="https" \
|
||||
NEXT_PUBLIC_API_BASE_PATH="/" \
|
||||
NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL="wss" \
|
||||
NEXT_PUBLIC_APP_HOST="explore.lux.network" \
|
||||
NEXT_PUBLIC_APP_PROTOCOL="https" \
|
||||
NEXT_PUBLIC_IS_TESTNET="false" \
|
||||
NEXT_PUBLIC_HOMEPAGE_CHARTS='["daily_txs", "coin_price", "market_cap"]' \
|
||||
NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED="true" \
|
||||
NEXT_PUBLIC_STATS_API_HOST="https://api-explore.lux.network/api/stats" \
|
||||
NEXT_PUBLIC_VISUALIZE_API_HOST="https://api-explore.lux.network/api/visualize" \
|
||||
NEXT_PUBLIC_CONTRACT_INFO_API_HOST="https://api-explore.lux.network" \
|
||||
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST="https://api-explore.lux.network"
|
||||
ARG BRAND
|
||||
ARG NETWORK_NAME
|
||||
ARG NETWORK_SHORT_NAME
|
||||
ARG NETWORK_ID
|
||||
ARG NETWORK_CURRENCY_NAME
|
||||
ARG NETWORK_CURRENCY_SYMBOL
|
||||
ARG NETWORK_RPC_URL
|
||||
ARG API_HOST
|
||||
ARG APP_HOST
|
||||
ARG IS_TESTNET=false
|
||||
ARG NETWORK_ORG_NAME
|
||||
ARG NETWORK_WEBSITE_URL
|
||||
ARG NETWORK_DESCRIPTION
|
||||
ARG NETWORK_GITHUB_URL
|
||||
ARG NETWORK_TWITTER_URL
|
||||
ARG NETWORK_DISCORD_URL
|
||||
ARG OIDC_SERVER_URL
|
||||
ARG OIDC_CLIENT_ID
|
||||
|
||||
# Copy LUX logo
|
||||
COPY public/logos/lux-logo-white.png /app/public/assets/lux-logo.png
|
||||
|
||||
# Note: Font and color theme changes require building from source
|
||||
# This image uses the default Blockscout theme
|
||||
ENV NEXT_PUBLIC_BRAND=$BRAND \
|
||||
NEXT_PUBLIC_NETWORK_NAME=$NETWORK_NAME \
|
||||
NEXT_PUBLIC_NETWORK_SHORT_NAME=$NETWORK_SHORT_NAME \
|
||||
NEXT_PUBLIC_NETWORK_ID=$NETWORK_ID \
|
||||
NEXT_PUBLIC_NETWORK_CURRENCY_NAME=$NETWORK_CURRENCY_NAME \
|
||||
NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=$NETWORK_CURRENCY_SYMBOL \
|
||||
NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18 \
|
||||
NEXT_PUBLIC_NETWORK_RPC_URL=$NETWORK_RPC_URL \
|
||||
NEXT_PUBLIC_API_HOST=$API_HOST \
|
||||
NEXT_PUBLIC_API_PROTOCOL=https \
|
||||
NEXT_PUBLIC_API_BASE_PATH=/ \
|
||||
NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=wss \
|
||||
NEXT_PUBLIC_APP_HOST=$APP_HOST \
|
||||
NEXT_PUBLIC_APP_PROTOCOL=https \
|
||||
NEXT_PUBLIC_IS_TESTNET=$IS_TESTNET \
|
||||
NEXT_PUBLIC_NETWORK_LOGO=/logo.svg \
|
||||
NEXT_PUBLIC_NETWORK_ICON=/icon.svg \
|
||||
NEXT_PUBLIC_HOMEPAGE_CHARTS='["daily_txs","coin_price","market_cap"]' \
|
||||
NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true \
|
||||
NEXT_PUBLIC_COLOR_THEME_DEFAULT=dark \
|
||||
NEXT_PUBLIC_NETWORK_ORG_NAME=$NETWORK_ORG_NAME \
|
||||
NEXT_PUBLIC_NETWORK_WEBSITE_URL=$NETWORK_WEBSITE_URL \
|
||||
NEXT_PUBLIC_NETWORK_DESCRIPTION=$NETWORK_DESCRIPTION \
|
||||
NEXT_PUBLIC_NETWORK_GITHUB_URL=$NETWORK_GITHUB_URL \
|
||||
NEXT_PUBLIC_NETWORK_TWITTER_URL=$NETWORK_TWITTER_URL \
|
||||
NEXT_PUBLIC_NETWORK_DISCORD_URL=$NETWORK_DISCORD_URL \
|
||||
NEXT_PUBLIC_ACCOUNT_AUTH_PROVIDER=oidc \
|
||||
NEXT_PUBLIC_OIDC_SERVER_URL=$OIDC_SERVER_URL \
|
||||
NEXT_PUBLIC_OIDC_CLIENT_ID=$OIDC_CLIENT_ID \
|
||||
NEXT_TELEMETRY_DISABLED=1 \
|
||||
ENVS_PRESET=none \
|
||||
SKIP_ENVS_VALIDATION=true
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
"aatx",
|
||||
"hanzoai",
|
||||
"zooai",
|
||||
"parsdao",
|
||||
"Kaniko",
|
||||
"abfnrtv",
|
||||
"abitype",
|
||||
"AIVM",
|
||||
|
||||
Executable
+221
@@ -0,0 +1,221 @@
|
||||
#!/usr/bin/env bash
|
||||
# Build all per-brand × per-env Blockscout overlay images and push to the
|
||||
# brand-owning GHCR namespace. Lux → ghcr.io/luxfi/, Zoo → ghcr.io/zooai/,
|
||||
# Hanzo → ghcr.io/hanzoai/, Pars → ghcr.io/parsdao/. Per ~/.claude/CLAUDE.md:
|
||||
# brand images live in the brand's org, never mixed across orgs.
|
||||
#
|
||||
# Build is delegated to a Kaniko pod (no Docker on the dev machine). Caller
|
||||
# passes --kubectl-context and --namespace; the script tars the build
|
||||
# context and submits one Kaniko pod per tuple.
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||
DOCKERFILE="${ROOT}/Dockerfile.branded"
|
||||
VERSION="${VERSION:-v1.0.0}"
|
||||
|
||||
# Per-tuple build args. Format:
|
||||
# BRAND ENV IMAGE_REPO -- key=value ...
|
||||
# Note: this matches what the Dockerfile ARGs expect.
|
||||
|
||||
tuples() {
|
||||
cat <<'EOF'
|
||||
lux mainnet ghcr.io/luxfi/explore-mainnet
|
||||
lux testnet ghcr.io/luxfi/explore-testnet
|
||||
zoo mainnet ghcr.io/zooai/explore-mainnet
|
||||
zoo testnet ghcr.io/zooai/explore-testnet
|
||||
hanzo mainnet ghcr.io/hanzoai/explore-mainnet
|
||||
hanzo testnet ghcr.io/hanzoai/explore-testnet
|
||||
pars mainnet ghcr.io/parsdao/explore-mainnet
|
||||
pars testnet ghcr.io/parsdao/explore-testnet
|
||||
EOF
|
||||
}
|
||||
|
||||
build_args_for() {
|
||||
local brand="$1" env="$2"
|
||||
local is_testnet="false"; [ "$env" = "testnet" ] && is_testnet="true"
|
||||
case "${brand}-${env}" in
|
||||
lux-mainnet)
|
||||
cat <<'EOF'
|
||||
NETWORK_NAME=Lux Network
|
||||
NETWORK_SHORT_NAME=LUX
|
||||
NETWORK_ID=96369
|
||||
NETWORK_CURRENCY_NAME=LUX
|
||||
NETWORK_CURRENCY_SYMBOL=LUX
|
||||
NETWORK_RPC_URL=https://api.lux.network/ext/bc/C/rpc
|
||||
API_HOST=api-explore.lux.network
|
||||
APP_HOST=explore.lux.network
|
||||
NETWORK_ORG_NAME=Lux Industries Inc.
|
||||
NETWORK_WEBSITE_URL=https://lux.network
|
||||
NETWORK_DESCRIPTION=High-performance blockchain for decentralized applications.
|
||||
NETWORK_GITHUB_URL=https://github.com/luxfi
|
||||
NETWORK_TWITTER_URL=https://x.com/luxdefi
|
||||
NETWORK_DISCORD_URL=https://discord.gg/luxnetwork
|
||||
OIDC_SERVER_URL=https://lux.id
|
||||
OIDC_CLIENT_ID=lux-explore-client-id
|
||||
EOF
|
||||
;;
|
||||
lux-testnet)
|
||||
cat <<'EOF'
|
||||
NETWORK_NAME=Lux Testnet
|
||||
NETWORK_SHORT_NAME=LUX
|
||||
NETWORK_ID=96368
|
||||
NETWORK_CURRENCY_NAME=LUX
|
||||
NETWORK_CURRENCY_SYMBOL=LUX
|
||||
NETWORK_RPC_URL=https://api.lux-test.network/ext/bc/C/rpc
|
||||
API_HOST=api-explorer.lux-test.network
|
||||
APP_HOST=explorer.lux-test.network
|
||||
NETWORK_ORG_NAME=Lux Industries Inc.
|
||||
NETWORK_WEBSITE_URL=https://lux.network
|
||||
NETWORK_DESCRIPTION=Lux Testnet — staging for the Lux Network.
|
||||
NETWORK_GITHUB_URL=https://github.com/luxfi
|
||||
NETWORK_TWITTER_URL=https://x.com/luxdefi
|
||||
NETWORK_DISCORD_URL=https://discord.gg/luxnetwork
|
||||
OIDC_SERVER_URL=https://lux.id
|
||||
OIDC_CLIENT_ID=lux-explore-client-id
|
||||
EOF
|
||||
;;
|
||||
zoo-mainnet)
|
||||
cat <<'EOF'
|
||||
NETWORK_NAME=Zoo Network
|
||||
NETWORK_SHORT_NAME=ZOO
|
||||
NETWORK_ID=200200
|
||||
NETWORK_CURRENCY_NAME=Zoo
|
||||
NETWORK_CURRENCY_SYMBOL=ZOO
|
||||
NETWORK_RPC_URL=https://api.zoo.network/ext/bc/zoo/rpc
|
||||
API_HOST=api-explore.zoo.network
|
||||
APP_HOST=explore.zoo.network
|
||||
NETWORK_ORG_NAME=Zoo Labs Foundation
|
||||
NETWORK_WEBSITE_URL=https://zoo.network
|
||||
NETWORK_DESCRIPTION=Zoo Network — decentralized AI research blockchain.
|
||||
NETWORK_GITHUB_URL=https://github.com/zooai
|
||||
NETWORK_TWITTER_URL=https://x.com/zoo_network
|
||||
NETWORK_DISCORD_URL=https://discord.gg/zoonetwork
|
||||
OIDC_SERVER_URL=https://zoo.id
|
||||
OIDC_CLIENT_ID=zoo-explore-client-id
|
||||
EOF
|
||||
;;
|
||||
zoo-testnet)
|
||||
cat <<'EOF'
|
||||
NETWORK_NAME=Zoo Testnet
|
||||
NETWORK_SHORT_NAME=ZOO
|
||||
NETWORK_ID=200201
|
||||
NETWORK_CURRENCY_NAME=Zoo
|
||||
NETWORK_CURRENCY_SYMBOL=ZOO
|
||||
NETWORK_RPC_URL=https://api.zoo-test.network/ext/bc/zoo/rpc
|
||||
API_HOST=api-explorer.zoo-test.network
|
||||
APP_HOST=explorer.zoo-test.network
|
||||
NETWORK_ORG_NAME=Zoo Labs Foundation
|
||||
NETWORK_WEBSITE_URL=https://zoo.network
|
||||
NETWORK_DESCRIPTION=Zoo Testnet — staging for Zoo Network.
|
||||
NETWORK_GITHUB_URL=https://github.com/zooai
|
||||
NETWORK_TWITTER_URL=https://x.com/zoo_network
|
||||
NETWORK_DISCORD_URL=https://discord.gg/zoonetwork
|
||||
OIDC_SERVER_URL=https://zoo.id
|
||||
OIDC_CLIENT_ID=zoo-explore-client-id
|
||||
EOF
|
||||
;;
|
||||
hanzo-mainnet)
|
||||
cat <<'EOF'
|
||||
NETWORK_NAME=Hanzo Network
|
||||
NETWORK_SHORT_NAME=AI
|
||||
NETWORK_ID=36963
|
||||
NETWORK_CURRENCY_NAME=AI
|
||||
NETWORK_CURRENCY_SYMBOL=AI
|
||||
NETWORK_RPC_URL=https://api.hanzo.network/ext/bc/hanzo/rpc
|
||||
API_HOST=api-explore.hanzo.network
|
||||
APP_HOST=explore.hanzo.network
|
||||
NETWORK_ORG_NAME=Hanzo AI Inc.
|
||||
NETWORK_WEBSITE_URL=https://hanzo.ai
|
||||
NETWORK_DESCRIPTION=Hanzo Network — AI infrastructure blockchain.
|
||||
NETWORK_GITHUB_URL=https://github.com/hanzoai
|
||||
NETWORK_TWITTER_URL=https://x.com/hanzoai
|
||||
NETWORK_DISCORD_URL=https://discord.gg/hanzoai
|
||||
OIDC_SERVER_URL=https://hanzo.id
|
||||
OIDC_CLIENT_ID=hanzo-explore-client-id
|
||||
EOF
|
||||
;;
|
||||
hanzo-testnet)
|
||||
cat <<'EOF'
|
||||
NETWORK_NAME=Hanzo Testnet
|
||||
NETWORK_SHORT_NAME=AI
|
||||
NETWORK_ID=36962
|
||||
NETWORK_CURRENCY_NAME=AI
|
||||
NETWORK_CURRENCY_SYMBOL=AI
|
||||
NETWORK_RPC_URL=https://api.hanzo-test.network/ext/bc/hanzo/rpc
|
||||
API_HOST=api-explorer.hanzo-test.network
|
||||
APP_HOST=explorer.hanzo-test.network
|
||||
NETWORK_ORG_NAME=Hanzo AI Inc.
|
||||
NETWORK_WEBSITE_URL=https://hanzo.ai
|
||||
NETWORK_DESCRIPTION=Hanzo Testnet — staging for Hanzo Network.
|
||||
NETWORK_GITHUB_URL=https://github.com/hanzoai
|
||||
NETWORK_TWITTER_URL=https://x.com/hanzoai
|
||||
NETWORK_DISCORD_URL=https://discord.gg/hanzoai
|
||||
OIDC_SERVER_URL=https://hanzo.id
|
||||
OIDC_CLIENT_ID=hanzo-explore-client-id
|
||||
EOF
|
||||
;;
|
||||
pars-mainnet)
|
||||
cat <<'EOF'
|
||||
NETWORK_NAME=Pars Network
|
||||
NETWORK_SHORT_NAME=PARS
|
||||
NETWORK_ID=7070
|
||||
NETWORK_CURRENCY_NAME=Pars
|
||||
NETWORK_CURRENCY_SYMBOL=PARS
|
||||
NETWORK_RPC_URL=https://api.pars.network/ext/bc/pars/rpc
|
||||
API_HOST=api-explore.pars.network
|
||||
APP_HOST=explore.pars.network
|
||||
NETWORK_ORG_NAME=Pars DAO
|
||||
NETWORK_WEBSITE_URL=https://pars.network
|
||||
NETWORK_DESCRIPTION=Pars Network — Persian community L1 blockchain.
|
||||
NETWORK_GITHUB_URL=https://github.com/parsdao
|
||||
NETWORK_TWITTER_URL=https://x.com/parsdao
|
||||
NETWORK_DISCORD_URL=https://discord.gg/parsdao
|
||||
OIDC_SERVER_URL=https://pars.id
|
||||
OIDC_CLIENT_ID=pars-explore-client-id
|
||||
EOF
|
||||
;;
|
||||
pars-testnet)
|
||||
cat <<'EOF'
|
||||
NETWORK_NAME=Pars Testnet
|
||||
NETWORK_SHORT_NAME=PARS
|
||||
NETWORK_ID=7071
|
||||
NETWORK_CURRENCY_NAME=Pars
|
||||
NETWORK_CURRENCY_SYMBOL=PARS
|
||||
NETWORK_RPC_URL=https://api.pars-test.network/ext/bc/pars/rpc
|
||||
API_HOST=api-explorer.pars-test.network
|
||||
APP_HOST=explorer.pars-test.network
|
||||
NETWORK_ORG_NAME=Pars DAO
|
||||
NETWORK_WEBSITE_URL=https://pars.network
|
||||
NETWORK_DESCRIPTION=Pars Testnet — staging for Pars Network.
|
||||
NETWORK_GITHUB_URL=https://github.com/parsdao
|
||||
NETWORK_TWITTER_URL=https://x.com/parsdao
|
||||
NETWORK_DISCORD_URL=https://discord.gg/parsdao
|
||||
OIDC_SERVER_URL=https://pars.id
|
||||
OIDC_CLIENT_ID=pars-explore-client-id
|
||||
EOF
|
||||
;;
|
||||
*) echo "unknown tuple ${brand}-${env}" >&2; exit 1;;
|
||||
esac
|
||||
printf 'BRAND=%s\nIS_TESTNET=%s\n' "$brand" "$is_testnet"
|
||||
}
|
||||
|
||||
print_tuples_only() {
|
||||
tuples | while read brand env repo; do
|
||||
[ -z "$brand" ] && continue
|
||||
echo "${brand} ${env} ${repo}:${VERSION}"
|
||||
done
|
||||
}
|
||||
|
||||
if [ "${1:-}" = "--list" ]; then
|
||||
print_tuples_only
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "${1:-}" = "--build-args" ] && [ -n "${2:-}" ] && [ -n "${3:-}" ]; then
|
||||
build_args_for "$2" "$3"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "usage: $0 --list" >&2
|
||||
echo " $0 --build-args BRAND ENV" >&2
|
||||
exit 1
|
||||
Reference in New Issue
Block a user