Compare commits

...

4 Commits

Author SHA1 Message Date
11efb6f09c feat: Update readme
All checks were successful
Build Docker / BuildImage (push) Successful in 35s
Check Code Quality / RuffCheck (push) Successful in 44s
2025-11-20 17:48:36 +11:00
ba04fb7c53 fix: Revert docker CI/CD to use correct repo
All checks were successful
Build Docker / BuildImage (push) Successful in 34s
Check Code Quality / RuffCheck (push) Successful in 45s
2025-11-20 15:53:02 +11:00
eb08788f7a feat: Update Dockerfile to use UV and pyproject
All checks were successful
Check Code Quality / RuffCheck (push) Successful in 50s
Build Docker / BuildImage (push) Successful in 1m3s
2025-11-20 15:49:57 +11:00
c7d5b98507 fix: Cleanup code to comply with ruff
Some checks failed
Check Code Quality / RuffCheck (push) Successful in 43s
Build Docker / BuildImage (push) Failing after 1m10s
2025-11-20 15:44:56 +11:00
5 changed files with 67 additions and 45 deletions

View File

@@ -33,9 +33,13 @@ jobs:
tag_num="${tag}-${tag_num}" tag_num="${tag}-${tag_num}"
fi fi
repo=$GITHUB_REPOSITORY
docker build -t nathanwoodburn:$tag_num . repo=${repo#*/}
docker tag nathanwoodburn:$tag_num git.woodburn.au/nathanwoodburn/nathanwoodburn:$tag_num repo=$(echo $repo | tr '[:upper:]' '[:lower:]')
docker push git.woodburn.au/nathanwoodburn/nathanwoodburn:$tag_num echo "container=$repo"
docker tag nathanwoodburn:$tag_num git.woodburn.au/nathanwoodburn/nathanwoodburn:$tag
docker push git.woodburn.au/nathanwoodburn/nathanwoodburn:$tag docker build -t $repo:$tag_num .
docker tag $repo:$tag_num git.woodburn.au/nathanwoodburn/$repo:$tag_num
docker push git.woodburn.au/nathanwoodburn/$repo:$tag_num
docker tag $repo:$tag_num git.woodburn.au/nathanwoodburn/$repo:$tag
docker push git.woodburn.au/nathanwoodburn/$repo:$tag

View File

@@ -1,17 +1,31 @@
FROM --platform=$BUILDPLATFORM python:3.10-alpine AS builder FROM --platform=$BUILDPLATFORM python:3.13-alpine
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
# Install curl for healthcheck
RUN apk add --no-cache curl
# Set working directory
WORKDIR /app WORKDIR /app
COPY requirements.txt /app # Install dependencies
RUN --mount=type=cache,target=/root/.cache/pip \ RUN --mount=type=cache,target=/root/.cache/uv \
python3 -m pip install -r requirements.txt --mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \
uv sync --locked --no-install-project
COPY . /app # Copy the project into the image
ADD . /app
# Optionally mount /data to store the data # Sync the project
# VOLUME /data RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --locked
ENTRYPOINT ["python3"] # Add mount point for data volume
CMD ["main.py"] ENV BASE_DIR=/data
VOLUME /data
FROM builder as dev-envs EXPOSE 5000
ENTRYPOINT ["uv", "run"]
CMD ["main.py"]

View File

@@ -2,18 +2,32 @@
Python3 website template including git actions Python3 website template including git actions
# Development ## Requirements
1. Install requirements - UV
## Development
1. Install project requirements
```bash ```bash
python3 -m pip install -r requirements.txt uv sync
``` ```
2. Run the dev server 2. Run the dev server
```bash ```bash
python3 server.py uv run python3 server.py
```
3. Alternatively use the virtual environment
```bash
source .venv/bin/activate
```
You can exit the environment with `deactivate`
For best development setup, you should install the git hook for pre-commit
```bash
uv run pre-commit install
``` ```
# Production
## Production
Run using the main.py file Run using the main.py file
```bash ```bash
python3 main.py python3 main.py
``` ```

20
main.py
View File

@@ -1,5 +1,3 @@
from flask import Flask
from server import app
import server import server
from gunicorn.app.base import BaseApplication from gunicorn.app.base import BaseApplication
import os import os
@@ -20,23 +18,21 @@ class GunicornApp(BaseApplication):
def load(self): def load(self):
return self.application return self.application
if __name__ == "__main__":
if __name__ == '__main__':
dotenv.load_dotenv() dotenv.load_dotenv()
workers = os.getenv('WORKERS', 1) workers = os.getenv("WORKERS", 1)
threads = os.getenv('THREADS', 2) threads = os.getenv("THREADS", 2)
workers = int(workers) workers = int(workers)
threads = int(threads) threads = int(threads)
options = { options = {
'bind': '0.0.0.0:5000', "bind": "0.0.0.0:5000",
'workers': workers, "workers": workers,
'threads': threads, "threads": threads,
} }
gunicorn_app = GunicornApp(server.app, options) gunicorn_app = GunicornApp(server.app, options)
print(f'Starting server with {workers} workers and {threads} threads', flush=True) print(f"Starting server with {workers} workers and {threads} threads", flush=True)
gunicorn_app.run() gunicorn_app.run()

View File

@@ -1,9 +1,6 @@
from functools import cache
import json
from flask import ( from flask import (
Flask, Flask,
make_response, make_response,
redirect,
request, request,
jsonify, jsonify,
render_template, render_template,
@@ -11,7 +8,6 @@ from flask import (
send_file, send_file,
) )
import os import os
import json
import requests import requests
from datetime import datetime from datetime import datetime
import dotenv import dotenv
@@ -26,6 +22,7 @@ def find(name, path):
if name in files: if name in files:
return os.path.join(root, name) return os.path.join(root, name)
# Assets routes # Assets routes
@app.route("/assets/<path:path>") @app.route("/assets/<path:path>")
def send_assets(path): def send_assets(path):
@@ -74,17 +71,13 @@ def wellknown(path):
# region Main routes # region Main routes
@app.route("/") @app.route("/")
def index(): def index():
# Get current time in the format "dd MMM YYYY hh:mm AM/PM"
# current_datetime = datetime.now().strftime("%d %b %Y %I:%M %p")
# return render_template("index.html", datetime=current_datetime)
# Print the IP address of the requester # Print the IP address of the requester
print(f"Request from IP: {request.remote_addr}") print(f"Request from IP: {request.remote_addr}")
# And the headers # And the headers
print(f"Request headers: {request.headers}") print(f"Request headers: {request.headers}")
# Get current time in the format "dd MMM YYYY hh:mm AM/PM"
current_datetime = datetime.now().strftime("%d %b %Y %I:%M %p")
# return redirect("https://ya.c.woodburn.au") return render_template("index.html", datetime=current_datetime)
@app.route("/<path:path>") @app.route("/<path:path>")
@@ -116,6 +109,7 @@ def catch_all(path: str):
api_requests = 0 api_requests = 0
@app.route("/api/v1/data", methods=["GET"]) @app.route("/api/v1/data", methods=["GET"])
def api_data(): def api_data():
""" """