Skip to content

Commit fe0e630

Browse files
Added Configuration UI and REST Endpoints (#28)
1 parent c5b53dc commit fe0e630

File tree

73 files changed

+11334
-360
lines changed

Some content is hidden

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

73 files changed

+11334
-360
lines changed

.github/workflows/ci.yml

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,41 @@ jobs:
2626
with:
2727
version: "0.6.11"
2828

29-
- name: Create and activate Python virtual environment
29+
- name: Create and activate virtual environment
3030
run: |
3131
uv venv
3232
source .venv/bin/activate
3333
3434
- name: Run linting and type checking
3535
run: uv run lint
3636

37-
- name: Run tests
38-
run: uv run test
37+
- name: Run tests with coverage
38+
run: uv run test-coverage
3939

40-
- name: Run build steps
40+
- name: Run build
4141
run: uv run build
42+
43+
frontend-quality-checks:
44+
runs-on: ubuntu-latest
45+
timeout-minutes: 5
46+
47+
steps:
48+
- name: Checkout
49+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
50+
51+
- name: Setup Node.js
52+
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4
53+
with:
54+
node-version: '20'
55+
56+
- name: Install dependencies
57+
run: npm install
58+
working-directory: ./frontend
59+
60+
- name: Run linting
61+
run: npm run lint
62+
working-directory: ./frontend
63+
64+
- name: Build frontend
65+
run: npm run build:prod
66+
working-directory: ./frontend

Dockerfile

Lines changed: 0 additions & 42 deletions
This file was deleted.

README.md

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
[![Open Source? Yes!](https://badgen.net/badge/Open%20Source%20%3F/Yes%21/blue?icon=github)](https://github.com/Naereen/badges/)
44

55
## Installation
6-
This project uses [uv](https://docs.astral.sh/uv/) for project management. `uv` is a Python package and project manager that simplifies dependency management, environment creation, and running commands.
7-
8-
For more information about uv, visit the [official documentation](https://docs.astral.sh/uv/).
6+
Follow the steps below to run the project.
97

108
### Prerequisites
119
[uv](https://docs.astral.sh/uv/) - Python package and project manager
@@ -14,27 +12,64 @@ For more information about uv, visit the [official documentation](https://docs.a
1412
- Or install with pip: `pip install uv`
1513
- Or with Homebrew (macOS): `brew install uv`
1614

17-
### Setup python environment
18-
`uv venv` automatically creates a virtual environment with the python version specified in the `pyproject.toml` file.
15+
[node](https://nodejs.org/en/download/) - JavaScript runtime + npm (node package manager)
16+
- Install with Homebrew (macOS): `brew install node`
17+
- Install directly (Windows): https://nodejs.org/en/download/
18+
- Install via apt (Linux): `sudo apt install nodejs npm`
19+
- Install via dnf (Linux): `sudo dnf install nodejs npm`
20+
- Install via pacman (Linux): `sudo pacman -S nodejs npm`
21+
22+
***
1923

24+
### Run the back-end (Python)
25+
26+
Create a virtual environment
2027
```bash
21-
# Create a virtual environment
28+
# In project root
2229
uv venv
2330
source .venv/bin/activate # On Windows: .venv\Scripts\activate
31+
32+
uv sync
2433
```
2534

26-
### Install dependencies
35+
Set the required environment variables -- See [config.py](https://github.com/openremote/service-ml-forecast/blob/main/src/service_ml_forecast/config.py) for all configuration options.
2736
```bash
28-
uv sync
37+
ML_OR_SERVICE_USER=serviceuser
38+
ML_OR_SERVICE_SECRET=secret
39+
```
40+
41+
Start the back-end application
42+
```bash
43+
uv run start
44+
45+
# Exposes the back-end on http://localhost:8000
46+
```
47+
48+
***
49+
50+
### Run the front-end (JavaScript)
51+
Serve the front-end
52+
```bash
53+
cd frontend
54+
npm run serve # Automatically installs dependencies
55+
56+
# Exposes the front-end on http://localhost:8001
2957
```
3058

31-
### Helper Scripts
32-
*Make sure you have created a virtual environment via `uv venv`*
59+
***
60+
61+
### UV Helper Scripts
62+
In project root
3363
- Run linting - `uv run lint`
3464
- Format code - `uv run format`
3565
- Run tests - `uv run test`
3666
- Run the application - `uv run start`
3767

68+
### NPM Helper Scripts
69+
in `/frontend`
70+
- Run linting - `npm run lint`
71+
- Format code - `npm run format`
72+
- Run the application - `npm run serve`
3873

3974
## License
4075

docker/.dockerignore

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Git
2+
.git
3+
.gitignore
4+
.github
5+
6+
# Python
7+
__pycache__
8+
*.py[cod]
9+
*$py.class
10+
*.so
11+
.Python
12+
build/
13+
develop-eggs/
14+
dist/
15+
downloads/
16+
eggs/
17+
.eggs/
18+
lib/
19+
lib64/
20+
parts/
21+
sdist/
22+
var/
23+
wheels/
24+
*.egg-info/
25+
.installed.cfg
26+
*.egg
27+
.pytest_cache/
28+
.coverage
29+
htmlcov/
30+
.tox/
31+
.nox/
32+
.hypothesis/
33+
34+
# Node
35+
node_modules/
36+
npm-debug.log*
37+
yarn-debug.log*
38+
yarn-error.log*
39+
.pnpm-debug.log*
40+
41+
# IDE
42+
.idea/
43+
.vscode/
44+
*.swp
45+
*.swo
46+
47+
# Environment
48+
.env
49+
.env.*
50+
!.env.example
51+
.venv
52+
venv/
53+
ENV/
54+
55+
# Misc
56+
*.log
57+
*.sqlite
58+
*.db
59+
.DS_Store
60+
Thumbs.db

docker/Dockerfile

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# --- Frontend Build Phase -----------------------------------------------------
2+
FROM node:20-slim AS frontend-builder
3+
4+
RUN echo "Starting frontend build phase..."
5+
6+
WORKDIR /app/frontend
7+
8+
COPY frontend/package*.json ./
9+
RUN echo "Installing frontend dependencies..."
10+
RUN npm install
11+
12+
COPY frontend/ ./
13+
14+
# Define build arguments
15+
ARG ML_SERVICE_URL
16+
ARG ML_WEB_ROOT_PATH
17+
18+
RUN ML_SERVICE_URL=${ML_SERVICE_URL:-/services/ml-forecast} \
19+
ML_WEB_ROOT_PATH=${ML_WEB_ROOT_PATH:-/services/ml-forecast/ui} \
20+
npm run build:prod
21+
22+
# --- Python Build Phase -------------------------------------------------------
23+
FROM python:3.13-slim AS builder
24+
25+
RUN echo "Starting Python build phase..."
26+
27+
WORKDIR /app
28+
29+
ENV PYTHONUNBUFFERED=1 \
30+
PYTHONDONTWRITEBYTECODE=1 \
31+
PIP_NO_CACHE_DIR=1 \
32+
PIP_DISABLE_PIP_VERSION_CHECK=1
33+
34+
RUN echo "Installing Python build dependencies..."
35+
RUN apt-get update \
36+
&& apt-get install -y --no-install-recommends \
37+
build-essential \
38+
&& rm -rf /var/lib/apt/lists/*
39+
40+
# Copy project files
41+
COPY pyproject.toml README.md ./
42+
COPY src/ ./src/
43+
COPY scripts/ ./scripts/
44+
45+
# Install project dependencies and clean up
46+
RUN echo "Installing Python project dependencies..."
47+
RUN pip install --no-cache-dir . \
48+
&& apt-get remove -y build-essential \
49+
&& apt-get autoremove -y \
50+
&& rm -rf /var/lib/apt/lists/* \
51+
&& find /usr/local/lib/python3.13 -type d -name '__pycache__' -exec rm -rf {} +
52+
53+
# --- Runtime Phase ------------------------------------------------------------
54+
FROM python:3.13-slim
55+
56+
RUN echo "Starting runtime phase setup..."
57+
58+
WORKDIR /app
59+
60+
# Explicitly declare the ARG for the build process
61+
ARG ML_ENVIRONMENT
62+
63+
ENV PYTHONUNBUFFERED=1 \
64+
PYTHONDONTWRITEBYTECODE=1 \
65+
PYTHONPATH=/app/src \
66+
# Use the ARG, falling back to a default if not provided during build or runtime
67+
ML_ENVIRONMENT=${ML_ENVIRONMENT:-production}
68+
69+
# Install runtime dependencies and clean up
70+
RUN echo "Installing runtime dependencies..."
71+
RUN apt-get update \
72+
&& apt-get install -y --no-install-recommends \
73+
curl \
74+
&& rm -rf /var/lib/apt/lists/*
75+
76+
# Copy installed packages from builder
77+
RUN echo "Copying Python packages from builder..."
78+
COPY --from=builder /usr/local/lib/python3.13/site-packages/ /usr/local/lib/python3.13/site-packages/
79+
COPY --from=builder /usr/local/bin/ /usr/local/bin/
80+
81+
# Copy application code
82+
COPY pyproject.toml ./
83+
COPY src/ ./src/
84+
COPY scripts/ ./scripts/
85+
86+
# Copy frontend build and clean up
87+
RUN echo "Copying frontend build artifacts..."
88+
COPY --from=frontend-builder /app/frontend/dist/ ./deployment/web/dist/
89+
RUN rm -rf /app/frontend
90+
91+
# Create deployment directories (config storage, model storage)
92+
RUN echo "Creating deployment directories..."
93+
RUN mkdir -p ./deployment/data/models ./deployment/data/configs
94+
95+
# Expose port
96+
EXPOSE 8000
97+
98+
# Add health check
99+
HEALTHCHECK --interval=5s --timeout=5s --start-period=30s --retries=3 CMD curl --fail --silent http://localhost:8000/ui || exit 1
100+
101+
RUN echo "Container setup complete! Starting application..."
102+
103+
# Run the application
104+
CMD ["python", "-m", "service_ml_forecast.main"]

docker/docker-compose.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: service-ml-forecast
2+
3+
services:
4+
service-ml-forecast:
5+
build:
6+
context: ..
7+
dockerfile: docker/Dockerfile
8+
args:
9+
ML_SERVICE_URL: ${ML_SERVICE_URL:-/services/ml-forecast} # Url to reach the back-end service, should be the same as ML_API_ROOT_PATH
10+
ML_WEB_ROOT_PATH: ${ML_WEB_ROOT_PATH:-/services/ml-forecast/ui} # Public path for the front-end (e.g. when behind a reverse proxy)
11+
container_name: service-ml-forecast
12+
ports:
13+
- "8000:8000"
14+
environment:
15+
- ML_LOG_LEVEL=${ML_LOG_LEVEL:-INFO} # Log level to use
16+
- ML_ENVIRONMENT=${ML_ENVIRONMENT:-production} # Environment to run the service in
17+
- ML_API_ROOT_PATH=${ML_API_ROOT_PATH:-/services/ml-forecast} # Public path for the back-end (e.g. when behind a reverse proxy)
18+
- ML_OR_URL=${ML_OR_URL:-http://host.docker.internal:8080} # OpenRemote URL
19+
- ML_OR_KEYCLOAK_URL=${ML_OR_KEYCLOAK_URL:-http://host.docker.internal:8081} # OpenRemote Keycloak URL
20+
- ML_OR_SERVICE_USER=${ML_OR_SERVICE_USER:-serviceuser} # OpenRemote service user
21+
- ML_OR_SERVICE_USER_SECRET=${ML_OR_SERVICE_USER_SECRET:-secret} # OpenRemote service user secret
22+
volumes:
23+
# Model storage
24+
- ../deployment/data/models:/app/deployment/data/models
25+
# Config storage
26+
- ../deployment/data/configs:/app/deployment/data/configs
27+
restart: unless-stopped
28+
networks:
29+
- ml-network
30+
extra_hosts:
31+
- "host.docker.internal:host-gateway"
32+
33+
networks:
34+
ml-network:
35+
driver: bridge

frontend/.gitignore

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
pnpm-debug.log*
8+
lerna-debug.log*
9+
10+
node_modules
11+
dist
12+
dist-ssr
13+
*.local
14+
15+
# Editor directories and files
16+
.vscode/*
17+
!.vscode/extensions.json
18+
.idea
19+
.DS_Store
20+
*.suo
21+
*.ntvs*
22+
*.njsproj
23+
*.sln
24+
*.sw?

0 commit comments

Comments
 (0)