Skip to content
Open
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
40 changes: 40 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Dependencies
node_modules/
website/node_modules/
__pycache__/
*.pyc
.pytest_cache/
.venv/
venv/

# Build outputs
website/dist/
*.egg-info/

# Development
.git/
.gitignore
*.md
!README.md

# IDE
.vscode/
.idea/
.claude/

# Environment (secrets)
.env
.env.*
!.env.example

# Logs
*.log
logs/

# Test data
tests/
data/

# Misc
.DS_Store
Thumbs.db
63 changes: 63 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: CI

on:
push:
branches: [main, master]
pull_request:
branches: [main, master]

jobs:
test:
name: pytest (py${{ matrix.python-version }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.11", "3.12"]

steps:
- uses: actions/checkout@v4

- name: Install system dependencies (LevelDB)
run: |
sudo apt-get update
sudo apt-get install -y libleveldb-dev libsnappy-dev

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install Poetry
uses: snok/install-poetry@v1
with:
version: "1.8.3"
virtualenvs-create: true
virtualenvs-in-project: true

- name: Cache Poetry virtualenv
uses: actions/cache@v4
with:
path: .venv
key: poetry-${{ runner.os }}-py${{ matrix.python-version }}-${{ hashFiles('poetry.lock') }}

- name: Install dependencies
run: poetry install --no-interaction --with dev

- name: Run pytest
run: poetry run pytest tests/ -v --tb=short

lint:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install ruff
run: pip install ruff==0.6.9
- name: Run ruff check
run: ruff check datamgmtnode/ tests/ || true
- name: Run ruff format --check
run: ruff format --check datamgmtnode/ tests/ || true
67 changes: 67 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# =============================================================================
# DataMgmt Node - Unified Deployment
# Combines: Static Website (nginx) + Python Node (API + WebSocket)
# =============================================================================

# Stage 1: Build the Astro website
FROM node:22-alpine AS website-builder

WORKDIR /website
COPY website/package*.json ./
RUN npm ci

COPY website/ ./
RUN npm run build


# Stage 2: Python runtime with website
FROM python:3.11-slim

# Install system dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
nginx \
supervisor \
libleveldb-dev \
build-essential \
wget \
&& rm -rf /var/lib/apt/lists/*

# Install Python dependencies via pip (simpler than poetry in Docker)
WORKDIR /app

# Install Python packages
RUN pip install --no-cache-dir \
asyncio==3.4.3 \
cryptography==43.0.0 \
web3==6.20.1 \
aiohttp==3.9.0 \
plyvel==1.5.1 \
python-dotenv==1.0.0 \
kademlia==2.2.3

# Copy DataMgmt Node source
COPY datamgmtnode ./datamgmtnode
COPY contracts ./contracts
COPY plugins ./plugins

# Create data directories
RUN mkdir -p /app/data /var/log/supervisor /var/log/nginx

# Copy website static files
COPY --from=website-builder /website/dist /usr/share/nginx/html

# Copy deployment configuration
COPY deploy/nginx.conf /etc/nginx/nginx.conf
COPY deploy/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY deploy/entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

# Expose port 80 (nginx handles all routing)
EXPOSE 80

# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost/health || exit 1

ENTRYPOINT ["/entrypoint.sh"]
CMD ["supervisord", "-n", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
4 changes: 4 additions & 0 deletions captain-definition
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"schemaVersion": 2,
"dockerfilePath": "./Dockerfile"
}
61 changes: 61 additions & 0 deletions deploy/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/bin/bash
set -e

echo "=========================================="
echo " DataMgmt Node - Starting Services"
echo "=========================================="

# Create required directories
mkdir -p /app/data /var/log/nginx /var/log/supervisor

# Set default environment variables if not provided
export BLOCKCHAIN_TYPE=${BLOCKCHAIN_TYPE:-evm}
export BLOCKCHAIN_URL=${BLOCKCHAIN_URL:-https://sepolia.infura.io/v3/demo}
export DB_PATH=${DB_PATH:-/app/data/nodedb}
export SQLITE_DB_PATH=${SQLITE_DB_PATH:-/app/data/sqlite.db}
export P2P_PORT=${P2P_PORT:-8000}
export PLUGIN_DIR=${PLUGIN_DIR:-/app/plugins}
export NODE_ID=${NODE_ID:-demo-node}
export DATA_DIR=${DATA_DIR:-/app/data}

# API ports (internal use)
export INTERNAL_API_HOST=${INTERNAL_API_HOST:-localhost}
export INTERNAL_API_PORT=${INTERNAL_API_PORT:-8080}
export EXTERNAL_API_HOST=${EXTERNAL_API_HOST:-0.0.0.0}
export EXTERNAL_API_PORT=${EXTERNAL_API_PORT:-8081}

# Generate a random node signature if not provided
if [ -z "$NODE_SIGNATURE" ]; then
export NODE_SIGNATURE=$(python -c "import secrets; print(secrets.token_hex(32))")
fi

# Check for required secrets
if [ -z "$KEY_MASTER_PASSWORD" ]; then
echo "WARNING: KEY_MASTER_PASSWORD not set, using generated value"
export KEY_MASTER_PASSWORD=$(python -c "import secrets; print(secrets.token_urlsafe(32))")
fi

if [ -z "$PRIVATE_KEY" ]; then
echo "WARNING: PRIVATE_KEY not set - using demo key for testnet"
echo "Set PRIVATE_KEY environment variable for production use"
# Demo-only private key for testnet (no real funds)
export PRIVATE_KEY=$(python -c "import secrets; print(secrets.token_hex(32))")
fi

echo ""
echo "Configuration:"
echo " - Blockchain: $BLOCKCHAIN_TYPE"
echo " - Network: $BLOCKCHAIN_URL"
echo " - Node ID: $NODE_ID"
echo " - P2P Port: $P2P_PORT"
echo ""
echo "Endpoints (via nginx on port 80):"
echo " - Website: http://localhost/"
echo " - API: http://localhost/api/"
echo " - WebSocket: ws://localhost/ws"
echo " - Health: http://localhost/health"
echo ""
echo "=========================================="

# Execute the main command
exec "$@"
Loading