Skip to content

Commit 9414888

Browse files
Volodymyr SamoilovVolodymyr Samoilov
authored andcommitted
Initial commit: Production-ready Predictive Maintenance API
0 parents  commit 9414888

82 files changed

Lines changed: 14213 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.

.coveragerc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[run]
2+
omit = src/visualization/*

.dockerignore

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
__pycache__/
2+
*.pyc
3+
*.pyo
4+
*.pyd
5+
.ipynb_checkpoints/
6+
.venv/
7+
venv/
8+
.env
9+
.DS_Store
10+
logs/
11+
.git/
12+
.gitignore
13+
.github/
14+
.pytest_cache/
15+
.coverage
16+
htmlcov/

.github/workflows/ci.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [ "main", "master" ]
6+
pull_request:
7+
branches: [ "main", "master" ]
8+
9+
jobs:
10+
tests:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Checkout
15+
uses: actions/checkout@v4
16+
17+
- name: Set up Python
18+
uses: actions/setup-python@v5
19+
with:
20+
python-version: "3.9"
21+
22+
- name: Install dependencies
23+
run: |
24+
python -m pip install --upgrade pip
25+
pip install -r requirements.txt
26+
27+
- name: Run tests
28+
run: |
29+
pytest -v --cov=src --cov=api --cov-report=term-missing
30+
31+
docker-build:
32+
runs-on: ubuntu-latest
33+
needs: tests
34+
35+
steps:
36+
- name: Checkout
37+
uses: actions/checkout@v4
38+
39+
- name: Build Docker image
40+
run: |
41+
docker build -t pm-api:ci .

.gitignore

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Python
2+
__pycache__/
3+
*.py[cod]
4+
*.pyo
5+
*.pyd
6+
7+
8+
# Jupyter / notebooks
9+
.ipynb_checkpoints/
10+
*.ipynb
11+
12+
# Pytest / coverage
13+
.pytest_cache/
14+
.coverage
15+
htmlcov/
16+
17+
# Logs
18+
logs/
19+
*.log
20+
21+
# Environment / secrets
22+
.env
23+
.env.*
24+
*.env
25+
26+
# OS / Editor
27+
.DS_Store
28+
Thumbs.db
29+
.idea/
30+
.vscode/
31+
32+
# Build artifacts
33+
build/
34+
dist/
35+
*.egg-info/
36+
37+
# Docker
38+
docker-compose.override.yml
39+
40+
# Temporary files
41+
tmp/
42+
.cache/
43+
44+
# IDE
45+
.vscode/
46+
.idea/

Dockerfile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
FROM python:3.9.6-slim
2+
3+
WORKDIR /app
4+
5+
COPY requirements.txt .
6+
RUN pip install --no-cache-dir -r requirements.txt
7+
8+
COPY . .
9+
10+
CMD ["uvicorn", "api.main:app", "--host", "0.0.0.0", "--port", "8000"]

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 Volodymyr Samoilov
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

Makefile

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# =========================
2+
# Predictive Maintenance API
3+
# =========================
4+
5+
IMAGE_NAME ?= pm-api
6+
CONTAINER_NAME ?= pm-api
7+
PORT ?= 8000
8+
9+
API_URL ?= http://127.0.0.1:$(PORT)
10+
11+
12+
help:
13+
@echo "Available commands:"
14+
@echo " make build Build Docker image ($(IMAGE_NAME))"
15+
@echo " make run Run container on port $(PORT)"
16+
@echo " make run-d Run container in background (detached)"
17+
@echo " make stop Stop & remove container ($(CONTAINER_NAME))"
18+
@echo " make rebuild Stop + build + run"
19+
@echo " make clean Remove image + prune build cache"
20+
@echo " make health Call GET /health"
21+
@echo " make predict Call POST /predict (single record)"
22+
@echo " make explain Call POST /explain (top contributors)"
23+
@echo " make explain-plot Call POST /explain/plot -> saves shap.png"
24+
@echo " make test Run all tests (local)"
25+
@echo " make test-cov Run tests with coverage"
26+
@echo " make test-unit Run unit tests only"
27+
@echo " make test-integration Run integration tests only"
28+
@echo " make test-docker Run tests inside Docker"
29+
@echo ""
30+
@echo "Vars:"
31+
@echo " IMAGE_NAME=pm-api PORT=8000 CONTAINER_NAME=pm-api"
32+
33+
# Build Docker image
34+
build:
35+
docker build -t $(IMAGE_NAME) .
36+
37+
# Run container (foreground)
38+
run: stop
39+
docker run --rm \
40+
--name $(CONTAINER_NAME) \
41+
-p $(PORT):8000 \
42+
$(IMAGE_NAME)
43+
44+
# Run container (detached)
45+
run-d: stop
46+
docker run -d \
47+
--name $(CONTAINER_NAME) \
48+
-p $(PORT):8000 \
49+
$(IMAGE_NAME)
50+
@echo "Running: $(CONTAINER_NAME) on $(API_URL)"
51+
52+
53+
54+
# Stop & remove container by name (safe if not running)
55+
stop:
56+
@docker rm -f $(CONTAINER_NAME) >/dev/null 2>&1 || true
57+
@echo "Container $(CONTAINER_NAME) stopped/removed (if existed)."
58+
59+
# Rebuild (stop + build + run-d)
60+
rebuild: stop build run-d
61+
62+
# Healthcheck
63+
health:
64+
curl -s $(API_URL)/health | python3 -m json.tool
65+
66+
# Test /predict
67+
predict:
68+
curl -s -X POST $(API_URL)/predict \
69+
-H "Content-Type: application/json" \
70+
-d '{"Air temperature [K]":300,"Process temperature [K]":310,"Rotational speed [rpm]":1500,"Torque [Nm]":40,"Tool wear [min]":100,"Type":"M"}' \
71+
| python3 -m json.tool
72+
73+
# Test /explain
74+
explain:
75+
curl -s -X POST "$(API_URL)/explain?top_k=8" \
76+
-H "Content-Type: application/json" \
77+
-d '{"Air temperature [K]":300,"Process temperature [K]":310,"Rotational speed [rpm]":1500,"Torque [Nm]":40,"Tool wear [min]":100,"Type":"M"}' \
78+
| python3 -m json.tool
79+
80+
# Test /explain/plot (saves PNG)
81+
explain-plot:
82+
curl -s -X POST $(API_URL)/explain/plot \
83+
-H "Content-Type: application/json" \
84+
-d '{"Air temperature [K]":300,"Process temperature [K]":310,"Rotational speed [rpm]":1500,"Torque [Nm]":40,"Tool wear [min]":100,"Type":"M"}' \
85+
-o shap.png
86+
@echo "Saved SHAP plot to ./shap.png"
87+
88+
89+
# Clean image + build cache
90+
clean: stop
91+
@docker image rm -f $(IMAGE_NAME) >/dev/null 2>&1 || true
92+
@docker builder prune -f >/dev/null 2>&1 || true
93+
@echo "🧹 Cleanup done."
94+
95+
# Run tests inside Docker container
96+
test-docker: build
97+
docker run --rm \
98+
$(IMAGE_NAME) \
99+
pytest -v
100+
101+
test-docker-cov: build
102+
docker run --rm \
103+
$(IMAGE_NAME) \
104+
pytest -v --cov=src --cov=api --cov-report=term-missing

0 commit comments

Comments
 (0)