Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
268 changes: 134 additions & 134 deletions .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
@@ -1,134 +1,134 @@
name: Build, Push Docker Image and Deploy

on:
push:
branches:
- main
- testing
- production

env:
IMAGE_NAME: midnight-explorer-web
DOCKER_IMAGE: texlabs/midnight-explorer-web

jobs:
# ======================================================
# Job 1: Build & Push Docker Image
# ======================================================
docker:
name: Docker Build and Push
runs-on: ubuntu-24.04

outputs:
tag: ${{ steps.set_tag.outputs.tag }}
container: ${{ steps.set_env.outputs.container }}
env_file: ${{ steps.set_env.outputs.env_file }}

steps:
- name: Checkout
uses: actions/checkout@v4

# -----------------------------
# Set ENV / container / port
# -----------------------------
- name: Set environment config
id: set_env
run: |
if [[ "$GITHUB_REF_NAME" == "production" ]]; then
echo "NODE_ENV=prod" >> $GITHUB_ENV
echo "container=midnight-explorer-web-prod" >> $GITHUB_OUTPUT
echo "env_file=.env.prod" >> $GITHUB_OUTPUT
elif [[ "$GITHUB_REF_NAME" == "testing" ]]; then
echo "NODE_ENV=test" >> $GITHUB_ENV
echo "container=midnight-explorer-web-test" >> $GITHUB_OUTPUT
echo "env_file=.env.test" >> $GITHUB_OUTPUT
else
echo "NODE_ENV=dev" >> $GITHUB_ENV
echo "container=midnight-explorer-web-dev" >> $GITHUB_OUTPUT
echo "env_file=.env.dev" >> $GITHUB_OUTPUT
fi

# -----------------------------
# Set Docker tag
# -----------------------------
- name: Set image tag
id: set_tag
run: |
TAG="${GITHUB_REF_NAME}-$(git rev-parse --short HEAD)"
echo "tag=$TAG" >> $GITHUB_OUTPUT

# -----------------------------
# Login DockerHub (TOKEN)
# -----------------------------
- name: Login DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

# -----------------------------
# Build & Push
# -----------------------------
- name: Build image
run: |
docker build \
--build-arg NODE_ENV=$NODE_ENV \
-t $DOCKER_IMAGE:${{ steps.set_tag.outputs.tag }} .

- name: Push image
run: |
docker push $DOCKER_IMAGE:${{ steps.set_tag.outputs.tag }}

# ======================================================
# Job 2: Deploy to VPS (Blue–Green)
# ======================================================
deploy:
name: Deploy to Remote VPS
runs-on: ubuntu-24.04
needs: docker

steps:
- name: Deploy via SSH
uses: appleboy/ssh-action@v1.2.0
with:
host: ${{ secrets.REMOTE_HOST }}
username: ${{ secrets.REMOTE_USER }}
key: ${{ secrets.REMOTE_SSH_KEY }}
script: |
set -e

IMAGE=${{ env.DOCKER_IMAGE }}
TAG=${{ needs.docker.outputs.tag }}
CONTAINER=${{ needs.docker.outputs.container }}
ENV_FILE=${{ needs.docker.outputs.env_file }}

echo "Deploying $IMAGE:$TAG"
echo "Container: $CONTAINER | Env: $ENV_FILE"

cd midnight-explorer-web

# Pull image
docker pull $IMAGE:$TAG

# Run GREEN container (NO PORT BIND)
docker run -d \
--name ${CONTAINER}-green \
--env-file $ENV_FILE \
--network midnight-net \
--restart unless-stopped \
$IMAGE:$TAG

# Optional: wait & basic health check
sleep 5
docker inspect --format='{{.State.Running}}' ${CONTAINER}-green

# Swap BLUE -> GREEN
docker stop $CONTAINER || true
docker rm $CONTAINER || true
docker rename ${CONTAINER}-green $CONTAINER

# Reload nginx (safe)
docker exec midnight-explorer-web-nginx nginx -s reload || true

# Cleanup
docker image prune -f
# name: Build, Push Docker Image and Deploy

# on:
# push:
# branches:
# - main
# - testing
# - production

# env:
# IMAGE_NAME: midnight-explorer-web
# DOCKER_IMAGE: texlabs/midnight-explorer-web

# jobs:
# # ======================================================
# # Job 1: Build & Push Docker Image
# # ======================================================
# docker:
# name: Docker Build and Push
# runs-on: ubuntu-24.04

# outputs:
# tag: ${{ steps.set_tag.outputs.tag }}
# container: ${{ steps.set_env.outputs.container }}
# env_file: ${{ steps.set_env.outputs.env_file }}

# steps:
# - name: Checkout
# uses: actions/checkout@v4

# # -----------------------------
# # Set ENV / container / port
# # -----------------------------
# - name: Set environment config
# id: set_env
# run: |
# if [[ "$GITHUB_REF_NAME" == "production" ]]; then
# echo "NODE_ENV=prod" >> $GITHUB_ENV
# echo "container=midnight-explorer-web-prod" >> $GITHUB_OUTPUT
# echo "env_file=.env.prod" >> $GITHUB_OUTPUT
# elif [[ "$GITHUB_REF_NAME" == "testing" ]]; then
# echo "NODE_ENV=test" >> $GITHUB_ENV
# echo "container=midnight-explorer-web-test" >> $GITHUB_OUTPUT
# echo "env_file=.env.test" >> $GITHUB_OUTPUT
# else
# echo "NODE_ENV=dev" >> $GITHUB_ENV
# echo "container=midnight-explorer-web-dev" >> $GITHUB_OUTPUT
# echo "env_file=.env.dev" >> $GITHUB_OUTPUT
# fi

# # -----------------------------
# # Set Docker tag
# # -----------------------------
# - name: Set image tag
# id: set_tag
# run: |
# TAG="${GITHUB_REF_NAME}-$(git rev-parse --short HEAD)"
# echo "tag=$TAG" >> $GITHUB_OUTPUT

# # -----------------------------
# # Login DockerHub (TOKEN)
# # -----------------------------
# - name: Login DockerHub
# uses: docker/login-action@v3
# with:
# username: ${{ secrets.DOCKERHUB_USERNAME }}
# password: ${{ secrets.DOCKERHUB_TOKEN }}

# # -----------------------------
# # Build & Push
# # -----------------------------
# - name: Build image
# run: |
# docker build \
# --build-arg NODE_ENV=$NODE_ENV \
# -t $DOCKER_IMAGE:${{ steps.set_tag.outputs.tag }} .

# - name: Push image
# run: |
# docker push $DOCKER_IMAGE:${{ steps.set_tag.outputs.tag }}

# # ======================================================
# # Job 2: Deploy to VPS (Blue–Green)
# # ======================================================
# deploy:
# name: Deploy to Remote VPS
# runs-on: ubuntu-24.04
# needs: docker

# steps:
# - name: Deploy via SSH
# uses: appleboy/ssh-action@v1.2.0
# with:
# host: ${{ secrets.REMOTE_HOST }}
# username: ${{ secrets.REMOTE_USER }}
# key: ${{ secrets.REMOTE_SSH_KEY }}
# script: |
# set -e

# IMAGE=${{ env.DOCKER_IMAGE }}
# TAG=${{ needs.docker.outputs.tag }}
# CONTAINER=${{ needs.docker.outputs.container }}
# ENV_FILE=${{ needs.docker.outputs.env_file }}

# echo "Deploying $IMAGE:$TAG"
# echo "Container: $CONTAINER | Env: $ENV_FILE"

# cd midnight-explorer-web

# # Pull image
# docker pull $IMAGE:$TAG

# # Run GREEN container (NO PORT BIND)
# docker run -d \
# --name ${CONTAINER}-green \
# --env-file $ENV_FILE \
# --network midnight-net \
# --restart unless-stopped \
# $IMAGE:$TAG

# # Optional: wait & basic health check
# sleep 5
# docker inspect --format='{{.State.Running}}' ${CONTAINER}-green

# # Swap BLUE -> GREEN
# docker stop $CONTAINER || true
# docker rm $CONTAINER || true
# docker rename ${CONTAINER}-green $CONTAINER

# # Reload nginx (safe)
# docker exec midnight-explorer-web-nginx nginx -s reload || true

# # Cleanup
# docker image prune -f
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev -p 8080",
"dev": "next dev -p 8081",
"build": "next build",
"start": "next start",
"lint": "next lint"
Expand Down
10 changes: 5 additions & 5 deletions src/components/network-toggle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,16 @@ import { NetworkType, NETWORKS } from "@/lib/constants/common.constants"
// Helper function to detect network from domain
function getNetworkFromDomain(): NetworkType {
if (typeof window === "undefined") return NetworkType.PREPROD

const hostname = window.location.hostname

// Check each network's domains array
for (const [networkType, config] of Object.entries(NETWORKS)) {
if (config.domains.some(domain => hostname.includes(domain))) {
return networkType as NetworkType
}
}

// Default for localhost and other unknown domains
// - localhost:8080 -> PREPROD
// - midnightexplorer.com -> PREPROD (configured in domains)
Expand All @@ -32,7 +32,7 @@ function getNetworkFromDomain(): NetworkType {

export function NetworkToggle() {
const [network, setNetwork] = useState<NetworkType>(NetworkType.PREPROD)

// Detect network on mount based on domain
useEffect(() => {
setNetwork(getNetworkFromDomain())
Expand All @@ -59,7 +59,7 @@ export function NetworkToggle() {
</DropdownMenuTrigger>

{/* Menu xổ xuống */}
<DropdownMenuContent align="end" className="w-[210px]">
<DropdownMenuContent align="end" className="w-[240px]">
{networks.map((networkType) => {
const config = NETWORKS[networkType]
const isCurrentNetwork = network === networkType
Expand Down
8 changes: 4 additions & 4 deletions src/components/recent-blocks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,27 +54,27 @@ export function RecentBlocks({ blocks }: RecentBlocksProps) {
<div className="flex items-center gap-2 flex-1 min-w-0">

<p className="text-sm font-mono text-muted-foreground truncate">
{`${block.hash.slice(0, 15)}...${block.hash.slice(-15)}`}
{block.hash ? `${block.hash.slice(0, 15)}...${block.hash.slice(-15)}` : 'Unknown'}
</p>
<div
onClick={(e) => e.preventDefault()}
className="opacity-50 hover:opacity-100 transition-opacity flex-shrink-0"
>
<CopyButton text={block.hash} className="h-5 w-5" />
<CopyButton text={block.hash || ''} className="h-5 w-5" />
</div>
</div>

{/* AUTHOR */}
<div className="flex items-center justify-end gap-2 flex-1 min-w-0">
<Image src="/images/author.svg" alt="Author" width={25} height={25} />
<span className="text-sm text-muted-foreground truncate">
{`${block.author.slice(0, 12)}...${block.author.slice(-12)}`}
{block.author ? `${block.author.slice(0, 12)}...${block.author.slice(-12)}` : 'Unknown'}
</span>
<div
onClick={(e) => e.preventDefault()}
className="opacity-50 hover:opacity-100 transition-opacity flex-shrink-0"
>
<CopyButton text={block.author} className="h-6 w-6" />
<CopyButton text={block.author || ''} className="h-6 w-6" />
</div>
</div>
</div>
Expand Down
16 changes: 8 additions & 8 deletions src/lib/constants/common.constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,19 +51,19 @@ export const NETWORKS = {
iconColor: "text-purple-400",
enabled: true,
message: undefined,
},
},
[NetworkType.MAINNET]: {
label: "Mainnet",
domain: "midnightexplorer.com",
label: "Mainnet Lite",
domain: "mainnet-lite.midnightexplorer.com",
domains: [
// "midnightexplorer.com",
"mainnet.dev.midnightexplorer.com",
"mainnet.test.midnightexplorer.com",
"mainnet-lite.midnightexplorer.com",
"mainnet-lite.dev.midnightexplorer.com",
"mainnet-lite.test.midnightexplorer.com",
],
color: "text-green-400",
iconColor: "text-green-400",
enabled: false,
message: "Upcoming",
enabled: true,
message: undefined,
},
} as const;

Expand Down