diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5bc7847..db26866 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -30,6 +30,15 @@ jobs: run: | # Launch the project from docker-compose.yml and wait up to # 30s for its built-in health check to return "healthy" - docker compose -f compose.yml -f compose.test.yml up --wait --wait-timeout 30 - docker compose -f compose.yml run --entrypoint "" web pytest + set -eu + + if ! docker compose -f compose.yml -f compose.test.yml up --wait --wait-timeout 30; then + echo "Project failed to become healthy" >&2 + echo "Logs:" + docker compose -f compose.yml -f compose.test.yml logs + exit 1 + fi + docker compose -f compose.yml down + + docker compose -f compose.yml run --entrypoint "" web pytest diff --git a/Dockerfile b/Dockerfile index 27f89e5..b60bc18 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,22 +1,15 @@ -FROM ubuntu:20.04 +FROM python:3.14-alpine # Maintainer of the docker image, not the code! LABEL maintainer="Ian Hinder " ARG DEBIAN_FRONTEND=noninteractive -RUN apt-get update -y && \ - apt-get install -y \ - python3 \ - python3-pip \ - python3-requests \ - pkg-config \ - graphviz \ - libgraphviz-dev \ - libxslt1-dev \ - curl && \ - rm -rf /var/lib/apt/lists/* -# Note: the ordering of these packages matters as libgraphviz-dev requires python3-pip +RUN apk add build-base + +RUN apk add graphviz graphviz-dev + +RUN apk add curl COPY ./requirements.txt /app/requirements.txt diff --git a/application.py b/application.py index 611d0c6..310e85a 100644 --- a/application.py +++ b/application.py @@ -47,10 +47,9 @@ app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1) os.environ['PATH'] = os.environ['PATH'] + ':/usr/local/bin' -os.environ['GV_FILE_PATH'] = os.path.abspath(os.path.join(os.path.dirname(__file__), 'static/images/')) + '/' +IMAGE_FILE_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), 'static/images')) print('PATH: ' + os.environ['PATH'], file=sys.stderr) -print('GV_FILE_PATH: ' + os.environ['GV_FILE_PATH'], file=sys.stderr) class TitleNotFoundException(Exception): pass @@ -141,14 +140,14 @@ def get_graph_string(graph): # URL to an image, only the file path. for image in images: image_filename = image.attrib['{http://www.w3.org/1999/xlink}href'] - image_url = url_for('static', filename = 'images/' + image_filename) + image_url = url_for('static', filename = 'images/' + image_filename.replace(f"{IMAGE_FILE_PATH}/","")) image.attrib['{http://www.w3.org/1999/xlink}href'] = image_url return etree.tostring(svg_obj, pretty_print = True).decode('utf-8') def get_image_files(): image_files = [] - image_dir = os.environ['GV_FILE_PATH'] + image_dir = IMAGE_FILE_PATH for root, sub_folders, files in os.walk(image_dir): for filename in files: @@ -177,7 +176,7 @@ def build_graph(name, results, topics): # check added for _ in name e.g. Anja Le_Blanc; that is: convert _ to space myperson= person.replace(' ', '\n') - graph.add_node(person, label = myperson.replace('_' , ' '), fontname = 'Helvetica', fixedsize = True, imagescale = True, width = '1.5', height = '1.5', fontcolor = 'white', shape = 'circle', style = 'filled', color = '#303030', URL = url_for('show_person', name = person), image = image_file) + graph.add_node(person, label = myperson.replace('_' , ' '), fontname = 'Helvetica', fixedsize = True, imagescale = True, width = '1.5', height = '1.5', fontcolor = 'white', shape = 'circle', style = 'filled', color = '#303030', URL = url_for('show_person', name = person), image = f"{IMAGE_FILE_PATH}/{image_file}") interests = people[person]['interests'] for interest in interests: @@ -188,7 +187,7 @@ def build_graph(name, results, topics): color = '#105060EE' shape = 'ellipse' - label = re.sub('\(.*\)', '', interest) + label = re.sub(r'\(.*\)', '', interest) graph.add_node(interest, label = label, style = 'filled', fontname = 'Helvetica', shape = shape, color = color, fontcolor = 'white', URL = url_for('show_topic', name = interest)) graph.add_edge(person, interest, color = '#00000050') @@ -202,7 +201,7 @@ def build_graph(name, results, topics): color = '#701050EE' shape = 'ellipse' - label = re.sub('\(.*\)', '', technology) + label = re.sub(r'\(.*\)', '', technology) graph.add_node(technology, label = label, style = 'filled', fontname = 'Helvetica', shape = shape, color = color, fontcolor = 'white') graph.add_edge(person, technology, color = '#00000050') diff --git a/requirements.in b/requirements.in index 55fd06b..0843eb5 100644 --- a/requirements.in +++ b/requirements.in @@ -1,13 +1,7 @@ -Click Flask -itsdangerous -Jinja2 lxml -MarkupSafe natsort pygraphviz -pyparsing pytest urllib3 -Werkzeug pip-tools diff --git a/requirements.txt b/requirements.txt index eea93e4..373d648 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,41 +1,30 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.14 # by the following command: # # pip-compile # -blinker==1.8.2 +blinker==1.9.0 # via flask -build==1.2.2.post1 +build==1.3.0 # via pip-tools -click==8.1.8 +click==8.3.1 # via - # -r requirements.in # flask # pip-tools -exceptiongroup==1.3.0 - # via pytest -flask==3.0.3 +flask==3.1.2 # via -r requirements.in -importlib-metadata==8.5.0 - # via - # build - # flask -iniconfig==2.1.0 +iniconfig==2.3.0 # via pytest itsdangerous==2.2.0 - # via - # -r requirements.in - # flask + # via flask jinja2==3.1.6 - # via - # -r requirements.in - # flask + # via flask lxml==6.0.2 # via -r requirements.in -markupsafe==2.1.5 +markupsafe==3.0.3 # via - # -r requirements.in + # flask # jinja2 # werkzeug natsort==8.4.0 @@ -44,37 +33,26 @@ packaging==25.0 # via # build # pytest -pip-tools==7.5.0 +pip-tools==7.5.2 # via -r requirements.in -pluggy==1.5.0 +pluggy==1.6.0 # via pytest -pygraphviz==1.11 - # via -r requirements.in -pyparsing==3.1.4 +pygments==2.19.2 + # via pytest +pygraphviz==1.14 # via -r requirements.in pyproject-hooks==1.2.0 # via # build # pip-tools -pytest==8.3.5 +pytest==9.0.1 # via -r requirements.in -tomli==2.2.1 - # via - # build - # pip-tools - # pytest -typing-extensions==4.13.2 - # via exceptiongroup -urllib3==2.2.3 +urllib3==2.5.0 # via -r requirements.in -werkzeug==3.0.6 - # via - # -r requirements.in - # flask +werkzeug==3.1.4 + # via flask wheel==0.45.1 # via pip-tools -zipp==3.20.2 - # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: # pip