Skip to content

Commit 4cd618d

Browse files
committed
squash version 0.1.0-alpha.1
0 parents  commit 4cd618d

97 files changed

Lines changed: 28423 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/push-image.yaml

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
name: Push Docker Image
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
tags:
8+
- 'v*'
9+
10+
env:
11+
IMAGE_NAME: pypsa-app
12+
REGISTRY: ghcr.io
13+
14+
jobs:
15+
push-full-image:
16+
name: Build and push full image
17+
runs-on: ubuntu-latest
18+
permissions:
19+
contents: read
20+
packages: write
21+
22+
steps:
23+
- name: Checkout repository
24+
uses: actions/checkout@v4
25+
26+
- name: Set up Docker Buildx
27+
uses: docker/setup-buildx-action@v3
28+
29+
- name: Log in to GitHub Container Registry
30+
uses: docker/login-action@v3
31+
with:
32+
registry: ${{ env.REGISTRY }}
33+
username: ${{ github.repository_owner }}
34+
password: ${{ secrets.GITHUB_TOKEN }}
35+
36+
- name: Extract metadata for Docker
37+
id: meta
38+
uses: docker/metadata-action@v5
39+
with:
40+
images: ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}
41+
tags: |
42+
type=ref,event=branch
43+
type=ref,event=tag
44+
type=semver,pattern={{version}}
45+
type=semver,pattern={{major}}.{{minor}}
46+
type=sha,prefix=
47+
type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/v') }}
48+
49+
- name: Build and push full Docker image
50+
uses: docker/build-push-action@v5
51+
with:
52+
context: .
53+
file: ./Dockerfile
54+
target: full
55+
push: true
56+
tags: ${{ steps.meta.outputs.tags }}
57+
labels: ${{ steps.meta.outputs.labels }}
58+
cache-from: type=gha
59+
cache-to: type=gha,mode=max
60+
platforms: linux/amd64
61+
62+
- name: Image summary
63+
run: |
64+
echo "### Docker Image Built and Pushed :rocket:" >> $GITHUB_STEP_SUMMARY
65+
echo "" >> $GITHUB_STEP_SUMMARY
66+
echo "**Image**: \`${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}\`" >> $GITHUB_STEP_SUMMARY
67+
echo "" >> $GITHUB_STEP_SUMMARY
68+
echo "**Tags**:" >> $GITHUB_STEP_SUMMARY
69+
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
70+
echo "${{ steps.meta.outputs.tags }}" >> $GITHUB_STEP_SUMMARY
71+
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY

.gitignore

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# Data
2+
data
3+
4+
# Environment variables
5+
.env
6+
.env.local
7+
.env.*.local
8+
.env.dev-server
9+
10+
# Compose
11+
compose.dev-server.yaml
12+
13+
# Python
14+
__pycache__/
15+
*.py[cod]
16+
*$py.class
17+
*.so
18+
.Python
19+
build/
20+
develop-eggs/
21+
dist/
22+
downloads/
23+
eggs/
24+
.eggs/
25+
lib/
26+
lib64/
27+
parts/
28+
sdist/
29+
var/
30+
wheels/
31+
*.egg-info/
32+
.installed.cfg
33+
*.egg
34+
35+
# Virtual environments
36+
venv/
37+
ENV/
38+
env/
39+
.venv
40+
41+
# Agents
42+
.claude
43+
AGENTS.md
44+
.mcp.json
45+
46+
# IDEs
47+
.vscode/
48+
.idea/
49+
*.swp
50+
*.swo
51+
*~
52+
.DS_Store
53+
54+
# Database
55+
*.db
56+
*.sqlite
57+
*.sqlite3
58+
59+
# Logs
60+
*.log
61+
logs/
62+
63+
# Testing
64+
.coverage
65+
.pytest_cache/
66+
htmlcov/
67+
68+
# Docker
69+
.dockerignore
70+
compose/compose.prod.yaml
71+
compose/.env
72+
73+
# Alembic
74+
alembic/versions/*.pyc
75+
76+
# Frontend
77+
node_modules/
78+
npm-debug.log*
79+
yarn-debug.log*
80+
yarn-error.log*
81+
.pnpm-debug.log*
82+
83+
# Frontend build outputs
84+
frontend/app/build/
85+
frontend/app/.svelte-kit/
86+
frontend/map/dist/
87+
88+
# Vite cache
89+
.vite/
90+
frontend/.vite/
91+
92+
# Backend static files
93+
src/pypsa_app/backend/static/app/
94+
src/pypsa_app/backend/static/map/

.pre-commit-config.yaml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
repos:
2+
- repo: https://github.com/pre-commit/pre-commit-hooks
3+
rev: v6.0.0
4+
hooks:
5+
- id: trailing-whitespace
6+
- id: end-of-file-fixer
7+
- id: check-yaml
8+
- id: check-json
9+
- id: check-toml
10+
- id: check-added-large-files
11+
args: ["--maxkb=1000"]
12+
- id: check-merge-conflict
13+
- id: check-case-conflict
14+
- id: mixed-line-ending
15+
16+
# Python - Ruff
17+
- repo: https://github.com/astral-sh/ruff-pre-commit
18+
rev: v0.14.4
19+
hooks:
20+
# Run the linter
21+
- id: ruff
22+
args: [--fix]
23+
# Run the formatter
24+
- id: ruff-format

.python-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.13

Dockerfile

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# Stage 1: Builder stage
2+
FROM python:3.13-slim AS builder
3+
4+
WORKDIR /app
5+
6+
RUN apt-get update && apt-get install -y \
7+
gcc \
8+
g++ \
9+
git \
10+
curl \
11+
libhdf5-dev \
12+
libnetcdf-dev \
13+
&& rm -rf /var/lib/apt/lists/*
14+
15+
ADD https://astral.sh/uv/install.sh /uv-installer.sh
16+
RUN sh /uv-installer.sh && rm /uv-installer.sh
17+
18+
ENV PATH="/root/.local/bin:$PATH"
19+
20+
COPY pyproject.toml uv.lock MANIFEST.in ./
21+
COPY src/ src/
22+
23+
# Sync dependencies with uv
24+
RUN uv sync --frozen --extra full --no-dev
25+
26+
# Stage 2: Runtime stage (pypsa-app backend)
27+
FROM python:3.13-slim AS backend
28+
29+
WORKDIR /app
30+
31+
# Install minimal runtime libraries
32+
RUN apt-get update && apt-get install -y \
33+
libhdf5-310 \
34+
libnetcdf22 \
35+
&& rm -rf /var/lib/apt/lists/*
36+
37+
# Copy from builder stage
38+
COPY --from=builder /root/.local/bin/uv /usr/local/bin/uv
39+
COPY --from=builder /app/.venv /app/.venv
40+
COPY --from=builder /app/src /app/src
41+
42+
COPY pyproject.toml uv.lock MANIFEST.in ./
43+
44+
# Create non-root user for running the application
45+
RUN groupadd -r appuser -g 1000 && \
46+
useradd -r -u 1000 -g appuser -m -s /bin/bash appuser
47+
48+
RUN mkdir -p /data/networks && \
49+
chown -R appuser:appuser /app /data
50+
51+
USER appuser
52+
53+
ENV DATA_DIR=/data
54+
ENV PATH="/app/.venv/bin:$PATH"
55+
56+
EXPOSE 8000
57+
58+
CMD ["pypsa-app", "serve"]
59+
60+
61+
# Stage 3: Build Svelte frontend (main app)
62+
FROM node:22-alpine AS app-builder
63+
64+
WORKDIR /frontend
65+
66+
# Use Docker-compatible build paths
67+
ENV DOCKER_BUILD=true
68+
ENV DATA_DIR=/data
69+
70+
COPY frontend/app/package*.json ./
71+
COPY frontend/app/ ./
72+
73+
RUN npm ci && \
74+
npm run build && \
75+
npm cache clean --force
76+
77+
78+
# Stage 4: Build map page with Kepler.gl and React (/network/map)
79+
FROM node:22-alpine AS map-builder
80+
81+
WORKDIR /map
82+
83+
# Use Docker-compatible build paths
84+
ENV DOCKER_BUILD=true
85+
ENV DATA_DIR=/data
86+
87+
COPY frontend/map/package*.json ./
88+
COPY frontend/map/ ./
89+
90+
RUN npm ci && \
91+
npm run build && \
92+
npm cache clean --force
93+
94+
95+
# Stage 5: Full stack (adds built frontends to backend base)
96+
FROM backend AS full
97+
98+
COPY --from=app-builder /frontend/build/ src/pypsa_app/backend/static/app/
99+
COPY --from=map-builder /map/dist/ src/pypsa_app/backend/static/map/
100+
101+
# Copy package.json files for version detection
102+
COPY --from=app-builder /frontend/package.json frontend/app/package.json
103+
COPY --from=map-builder /map/package.json frontend/map/package.json

MANIFEST.in

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Include static frontend files
2+
graft src/pypsa_app/backend/static
3+
4+
# Include documentation
5+
include README.md
6+
include LICENSE
7+
include *.md
8+
9+
# Exclude development files
10+
global-exclude __pycache__
11+
global-exclude *.py[co]
12+
global-exclude .DS_Store
13+
global-exclude *.swp
14+
global-exclude *.swo
15+
16+
# Exclude build artifacts
17+
prune frontend/node_modules
18+
prune frontend/build
19+
prune backend
20+
prune data
21+
prune .venv
22+
prune dist

compose/.env.example

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Needs to be set only for compose.full.yaml/ compose.dev.yaml
2+
# For all available settings, check the docs
3+
4+
# Application Configuration
5+
# -------------------------
6+
7+
APP_PORT=8000
8+
9+
# Map Configuration (Optional)
10+
# -----------------------------
11+
12+
# To use the interactive Network map, a mapbox token is needed
13+
VITE_MAPBOX_TOKEN=your_mapbox_token_here
14+
15+
# Database Configuration
16+
# ----------------------
17+
18+
POSTGRES_HOST=postgres
19+
POSTGRES_DB=pypsa_app
20+
POSTGRES_USER=pypsa_app
21+
POSTGRES_PASSWORD=changeme
22+
POSTGRES_PORT=5432
23+
24+
# Authentication Configuration (Optional)
25+
# ---------------------------------------
26+
27+
# Enable authentication (default: false)
28+
# All other authentication variables are only needed when ENABLE_AUTH=true
29+
ENABLE_AUTH=false
30+
31+
BASE_URL=http://localhost:5173 # or your production URL
32+
33+
# GitHub OAuth Application Credentials
34+
# Required when ENABLE_AUTH=true
35+
# Create a GitHub OAuth App at: https://github.com/settings/developers
36+
# - Homepage URL: <BASE_URL>
37+
# - Authorization callback URL: <BASE_URL>/api/v1/auth/callback
38+
GITHUB_CLIENT_ID=your_client_id_here
39+
GITHUB_CLIENT_SECRET=your_client_secret_here
40+
41+
# Session configuration
42+
# Generate a secure key with: openssl rand -base64 32
43+
SESSION_SECRET_KEY=your_session_secret_here

0 commit comments

Comments
 (0)