feat: Add initial code
All checks were successful
Build Docker / BuildImage (push) Successful in 1m2s

This commit is contained in:
Nathan Woodburn 2024-09-13 10:26:36 +10:00
parent e6eb62021e
commit 579539ccb8
Signed by: nathanwoodburn
GPG Key ID: 203B000478AD0EF1
11 changed files with 308 additions and 0 deletions

View File

@ -0,0 +1,46 @@
name: Build Docker
run-name: Build Docker Images
on:
push:
jobs:
BuildImage:
runs-on: [ubuntu-latest, amd]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install Docker
run : |
apt-get install ca-certificates curl gnupg
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg
echo "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
apt-get update
apt-get install docker-ce-cli -y
- name: Build Docker image
run : |
echo "${{ secrets.DOCKERGIT_TOKEN }}" | docker login git.woodburn.au -u nathanwoodburn --password-stdin
echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}"
tag=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}
tag=${tag//\//-}
tag_num=${GITHUB_RUN_NUMBER}
echo "tag_num=$tag_num"
if [[ "$tag" == "main" ]]; then
tag="latest"
else
tag_num="${tag}-${tag_num}"
fi
repo=$GITHUB_REPOSITORY
repo=${repo#*/}
repo=$(echo $repo | tr '[:upper:]' '[:lower:]')
echo "container=$repo"
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

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
__pycache__/
.env
.vs/

17
Dockerfile Normal file
View File

@ -0,0 +1,17 @@
FROM --platform=$BUILDPLATFORM python:3.10-alpine AS builder
WORKDIR /app
COPY requirements.txt /app
RUN --mount=type=cache,target=/root/.cache/pip \
python3 -m pip install -r requirements.txt
COPY . /app
# Optionally mount /data to store the data
# VOLUME /data
ENTRYPOINT ["python3"]
CMD ["main.py"]
FROM builder as dev-envs

42
main.py Normal file
View File

@ -0,0 +1,42 @@
from flask import Flask
from server import app
import server
from gunicorn.app.base import BaseApplication
import os
import dotenv
class GunicornApp(BaseApplication):
def __init__(self, app, options=None):
self.options = options or {}
self.application = app
super().__init__()
def load_config(self):
for key, value in self.options.items():
if key in self.cfg.settings and value is not None:
self.cfg.set(key.lower(), value)
def load(self):
return self.application
if __name__ == '__main__':
dotenv.load_dotenv()
workers = os.getenv('WORKERS', 1)
threads = os.getenv('THREADS', 2)
workers = int(workers)
threads = int(threads)
options = {
'bind': '0.0.0.0:5000',
'workers': workers,
'threads': threads,
}
gunicorn_app = GunicornApp(server.app, options)
print(f'Starting server with {workers} workers and {threads} threads', flush=True)
gunicorn_app.run()

4
requirements.txt Normal file
View File

@ -0,0 +1,4 @@
flask
gunicorn
requests
python-dotenv

114
server.py Normal file
View File

@ -0,0 +1,114 @@
from functools import cache
import json
from flask import (
Flask,
make_response,
redirect,
request,
jsonify,
render_template,
send_from_directory,
send_file,
)
import os
import json
import requests
from datetime import datetime
import dotenv
dotenv.load_dotenv()
app = Flask(__name__)
def find(name, path):
for root, dirs, files in os.walk(path):
if name in files:
return os.path.join(root, name)
# Assets routes
@app.route("/assets/<path:path>")
def send_assets(path):
if path.endswith(".json"):
return send_from_directory(
"templates/assets", path, mimetype="application/json"
)
if os.path.isfile("templates/assets/" + path):
return send_from_directory("templates/assets", path)
# Try looking in one of the directories
filename: str = path.split("/")[-1]
if (
filename.endswith(".png")
or filename.endswith(".jpg")
or filename.endswith(".jpeg")
or filename.endswith(".svg")
):
if os.path.isfile("templates/assets/img/" + filename):
return send_from_directory("templates/assets/img", filename)
if os.path.isfile("templates/assets/img/favicon/" + filename):
return send_from_directory("templates/assets/img/favicon", filename)
return render_template("404.html"), 404
# region Special routes
@app.route("/favicon.png")
def faviconPNG():
return send_from_directory("templates/assets/img", "favicon.png")
@app.route("/.well-known/<path:path>")
def wellknown(path):
# Try to proxy to https://nathan.woodburn.au/.well-known/
req = requests.get(f"https://nathan.woodburn.au/.well-known/{path}")
return make_response(
req.content, 200, {"Content-Type": req.headers["Content-Type"]}
)
# endregion
# region Main routes
@app.route("/")
def index():
return render_template("index.html")
@app.route("/<path:path>")
def catch_all(path: str):
if os.path.isfile("templates/" + path):
return render_template(path)
# Try with .html
if os.path.isfile("templates/" + path + ".html"):
return render_template(path + ".html")
if os.path.isfile("templates/" + path.strip("/") + ".html"):
return render_template(path.strip("/") + ".html")
# Try to find a file matching
if path.count("/") < 1:
# Try to find a file matching
filename = find(path, "templates")
if filename:
return send_file(filename)
return render_template("404.html"), 404
# endregion
# region Error Catching
# 404 catch all
@app.errorhandler(404)
def not_found(e):
return render_template("404.html"), 404
# endregion
if __name__ == "__main__":
app.run(debug=True, port=5000, host="0.0.0.0")

21
templates/404.html Normal file
View File

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Nathan.Woodburn/</title>
<link rel="icon" href="/assets/img/favicon.png" type="image/png">
<link rel="stylesheet" href="/assets/css/404.css">
</head>
<body>
<div class="spacer"></div>
<div class="centre">
<h1>404 | Page not found</h1>
<p>Sorry, the page you are looking for does not exist.</p>
<p><a href="/">Go back to the homepage</a></p>
</div>
</body>
</html>

View File

@ -0,0 +1,20 @@
body {
background-color: #000000;
color: #ffffff;
}
h1 {
font-size: 50px;
margin: 0;
padding: 0;
}
.centre {
margin-top: 10%;
text-align: center;
}
a {
color: #ffffff;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}

View File

@ -0,0 +1,20 @@
body {
background-color: #000000;
color: #ffffff;
}
h1 {
font-size: 50px;
margin: 0;
padding: 0;
}
.centre {
margin-top: 10%;
text-align: center;
}
a {
color: #ffffff;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

19
templates/index.html Normal file
View File

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Nathan.Woodburn/</title>
<link rel="icon" href="/assets/img/favicon.png" type="image/png">
<link rel="stylesheet" href="/assets/css/index.css">
</head>
<body>
<div class="spacer"></div>
<div class="centre">
<h1>Nathan.Woodburn/</h1>
</div>
</body>
</html>