From afba4aa0f57d5649b9b1ef781946c5cf4e50863d Mon Sep 17 00:00:00 2001 From: Thomas Misilo Date: Fri, 27 Feb 2026 08:56:47 -0600 Subject: [PATCH 1/4] Adding my build pieces --- .dockerignore | 1 + dockerfiles/Dockerfile.ksul | 53 +++++++++++++++++++++++++++++++++++++ dockerfiles/entrypoint.sh | 34 ++++++++++++++++++++++++ requirements.txt | 10 +++---- 4 files changed, 93 insertions(+), 5 deletions(-) create mode 100644 dockerfiles/Dockerfile.ksul create mode 100644 dockerfiles/entrypoint.sh diff --git a/.dockerignore b/.dockerignore index fd59b07ac0..2440d71e7f 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,6 +1,7 @@ db logs/* *.tar.gz +.venv src/files/articles src/files/journals src/files/issues diff --git a/dockerfiles/Dockerfile.ksul b/dockerfiles/Dockerfile.ksul new file mode 100644 index 0000000000..7c846c97a8 --- /dev/null +++ b/dockerfiles/Dockerfile.ksul @@ -0,0 +1,53 @@ +FROM python:3.12-slim AS build +RUN apt-get update && \ + apt-get install -y \ + build-essential \ + git \ + gcc \ + g++ \ + libxml2-dev \ + libmagic-dev \ + libxslt1-dev \ + python3-dev \ + zlib1g-dev \ + libffi-dev \ + libssl-dev \ + libjpeg-dev \ + libsass-dev \ + libsass1 + +COPY requirements.txt . +RUN pip install --prefix=/install -r requirements.txt + +FROM ghcr.io/benoitc/gunicorn:24.1.0 +USER root + +RUN apt-get update && \ + apt-get install -y \ + libmagic-dev \ + libsass1 + +WORKDIR /janeway + +#COPY requirements.txt . +#RUN pip install --no-cache-dir -r requirements.txt +COPY --from=build /install /usr/local + +#RUN find "/vol/janeway/src/plugins/" -print -iname "*requirements.txt" -exec pip3 install -r {} --src /tmp/src \; +#RUN if [ -n "$(ls -A ./lib)" ]; then pip3 install -e lib/*; fi + +COPY --chown=gunicorn:gunicorn . /janeway + +# Copy entrypoint script +COPY dockerfiles/entrypoint.sh /usr/local/bin/docker-entrypoint.sh +RUN chmod +x /usr/local/bin/docker-entrypoint.sh + + +RUN cp src/core/janeway_global_settings.py src/core/settings.py +USER gunicorn + +EXPOSE 8000 +STOPSIGNAL SIGINT +#ENTRYPOINT ["bash"] +ENTRYPOINT ["docker-entrypoint.sh"] +CMD ["gunicorn", "core.wsgi:application", "--bind", "0.0.0.0:8000", "--workers", "3", "--chdir", "/janeway/src"] diff --git a/dockerfiles/entrypoint.sh b/dockerfiles/entrypoint.sh new file mode 100644 index 0000000000..4fb8a5ede0 --- /dev/null +++ b/dockerfiles/entrypoint.sh @@ -0,0 +1,34 @@ +#!/bin/bash +set -e + +# Allow running other commands (e.g., bash for debugging) +if [ "${1:0:1}" = '-' ] || [ -z "${1##*:*}" ]; then + # First arg is a flag or contains ':' (app:callable), run gunicorn + + # Build bind address from GUNICORN_HOST and GUNICORN_PORT, or use GUNICORN_BIND + PORT="${GUNICORN_PORT:-8000}" + BIND="${GUNICORN_BIND:-${GUNICORN_HOST:-0.0.0.0}:${PORT}}" + + # Add bind if not specified in args or GUNICORN_ARGS + if [[ ! " $* $GUNICORN_ARGS " =~ " --bind " ]] && [[ ! " $* $GUNICORN_ARGS " =~ " -b " ]] && [[ ! "$* $GUNICORN_ARGS" =~ --bind= ]] && [[ ! "$* $GUNICORN_ARGS" =~ -b= ]]; then + set -- --bind "$BIND" "$@" + fi + + # Add workers if not specified - default to (2 * CPU_COUNT) + 1 + if [[ ! " $* $GUNICORN_ARGS " =~ " --workers " ]] && [[ ! " $* $GUNICORN_ARGS " =~ " -w " ]] && [[ ! "$* $GUNICORN_ARGS" =~ --workers= ]] && [[ ! "$* $GUNICORN_ARGS" =~ -w= ]]; then + WORKERS="${GUNICORN_WORKERS:-$(( 2 * $(nproc) + 1 ))}" + set -- --workers "$WORKERS" "$@" + fi + + # Append GUNICORN_ARGS if set + if [ -n "$GUNICORN_ARGS" ]; then + exec gunicorn $GUNICORN_ARGS "$@" + fi + + # run build_assets + python /janeway/src/manage.py build_assets + exec gunicorn "$@" +fi + +# Otherwise, run the command as-is (e.g., bash, sh, python) +exec "$@" diff --git a/requirements.txt b/requirements.txt index 957f884dbb..9c391ecb9c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,13 +8,13 @@ crossrefapi==1.5.0 Django==4.2.26 django-bleach==3.1.0 django-bootstrap4==23.2 --e git+https://github.com/openlibhums/django-foundation-form.git@674616f5388fe44c63088671ddea38ed9161a4fd#egg=foundationform +git+https://github.com/openlibhums/django-foundation-form.git@674616f5388fe44c63088671ddea38ed9161a4fd#egg=foundationform django-countries[pyuca]==7.6.1 --e git+https://github.com/openlibhums/django-materializecss-form.git@be094ec283299ee8fd0a1dfe33e73a609fb2f680#egg=django-materializecss-form +git+https://github.com/openlibhums/django-materializecss-form.git@be094ec283299ee8fd0a1dfe33e73a609fb2f680#egg=django-materializecss-form django-debug-toolbar==5.1.0 django-hCaptcha==0.2.0 django-hijack==3.2.1 --e git+https://github.com/BirkbeckCTP/django-mailgun.git@4f01799e01219e83d658f02c876764bf2260337e#egg=django_mailgun +git+https://github.com/BirkbeckCTP/django-mailgun.git@4f01799e01219e83d658f02c876764bf2260337e#egg=django_mailgun django-modeltranslation==0.18.11 django-settings-export==1.2.1 django-recaptcha==3.0.0 @@ -23,8 +23,8 @@ django-simple-history==3.10.1 django-summernote==0.8.20.0 django-tinymce==3.7.1 djangorestframework==3.15.2 --e git+https://github.com/BirkbeckCTP/django-dynamicsites@f439c524cf964d957a75fbec4b23ad03a9a5d159#egg=dynamicsites --e git+https://github.com/BirkbeckCTP/ebooklib@b7005c57602eeea06358ac569a4cf52c630a32ef#egg=ebooklib +git+https://github.com/BirkbeckCTP/django-dynamicsites@f439c524cf964d957a75fbec4b23ad03a9a5d159#egg=dynamicsites +git+https://github.com/BirkbeckCTP/ebooklib@b7005c57602eeea06358ac569a4cf52c630a32ef#egg=ebooklib Faker==17.6.0 freezegun==1.2.0 geoip2==4.8.0 From c138e42361ddd2d8442fbf0f4df6b92a20f3479d Mon Sep 17 00:00:00 2001 From: Sawyer Date: Fri, 27 Feb 2026 11:07:17 -0600 Subject: [PATCH 2/4] feat(plugins): Adding ksulcolors plugin with custom CSS overrides Updates docker entrypoint to run plugin installation on start to ensure static files are copied --- .gitignore | 1 + dockerfiles/entrypoint.sh | 4 +- src/plugins/ksulcolors/__init__.py | 0 src/plugins/ksulcolors/assets/ksul.css | 24 +++++++ src/plugins/ksulcolors/forms.py | 5 ++ src/plugins/ksulcolors/hooks.py | 7 ++ src/plugins/ksulcolors/plugin_settings.py | 69 +++++++++++++++++++ .../templates/ksulcolors/manager.html | 15 ++++ src/plugins/ksulcolors/urls.py | 8 +++ src/plugins/ksulcolors/views.py | 14 ++++ 10 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 src/plugins/ksulcolors/__init__.py create mode 100644 src/plugins/ksulcolors/assets/ksul.css create mode 100644 src/plugins/ksulcolors/forms.py create mode 100644 src/plugins/ksulcolors/hooks.py create mode 100644 src/plugins/ksulcolors/plugin_settings.py create mode 100644 src/plugins/ksulcolors/templates/ksulcolors/manager.html create mode 100644 src/plugins/ksulcolors/urls.py create mode 100644 src/plugins/ksulcolors/views.py diff --git a/.gitignore b/.gitignore index 3223115ac4..8790f41683 100755 --- a/.gitignore +++ b/.gitignore @@ -81,6 +81,7 @@ src/core/settings.py mydatabase node_modules/ src/plugins/* +!src/plugins/ksulcolors/ src/media/profile_images/* # PyCharm diff --git a/dockerfiles/entrypoint.sh b/dockerfiles/entrypoint.sh index 4fb8a5ede0..b50286cb4d 100644 --- a/dockerfiles/entrypoint.sh +++ b/dockerfiles/entrypoint.sh @@ -25,8 +25,10 @@ if [ "${1:0:1}" = '-' ] || [ -z "${1##*:*}" ]; then exec gunicorn $GUNICORN_ARGS "$@" fi - # run build_assets + echo "Preparing Janeway assets..." python /janeway/src/manage.py build_assets + python /janeway/src/manage.py install_plugins ksulcolors + python /janeway/src/manage.py collectstatic --noinput exec gunicorn "$@" fi diff --git a/src/plugins/ksulcolors/__init__.py b/src/plugins/ksulcolors/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/plugins/ksulcolors/assets/ksul.css b/src/plugins/ksulcolors/assets/ksul.css new file mode 100644 index 0000000000..eb76f98486 --- /dev/null +++ b/src/plugins/ksulcolors/assets/ksul.css @@ -0,0 +1,24 @@ +/* Insert CSS Below */ +:root { + --primary-dark-color: #22175b; /* Primary colour used by elements such as buttons */ + --very-dark-primary-color: #22175b; /* Darker primary colour used for contrast or hover effects */ + --primary-light-color: #fff; /* lighter colour or secondary colour */ + --topbar-background-color: #24193d; /* background colour for the top bar of the navigation */ + --menu-foreground-color: #512888; /* font colour used in the menu bar */ + } + + .top-bar .dropdown.menu > li.is-dropdown-submenu-parent > a::after { + border-color: #FFF transparent transparent; + } + + header #main-menu li a { + font-weight: 600; + } + + footer .large-2.logo-wrapper { + display: none; + } + + footer .large-text-right li a { + margin: 0; + } \ No newline at end of file diff --git a/src/plugins/ksulcolors/forms.py b/src/plugins/ksulcolors/forms.py new file mode 100644 index 0000000000..6459616821 --- /dev/null +++ b/src/plugins/ksulcolors/forms.py @@ -0,0 +1,5 @@ +from django import forms + + +class DummyManagerForm(forms.Form): + dummy_field = forms.CharField() diff --git a/src/plugins/ksulcolors/hooks.py b/src/plugins/ksulcolors/hooks.py new file mode 100644 index 0000000000..444922caef --- /dev/null +++ b/src/plugins/ksulcolors/hooks.py @@ -0,0 +1,7 @@ +from django.conf import settings + + +from django.templatetags.static import static + +def inject_css(context): + return f'' diff --git a/src/plugins/ksulcolors/plugin_settings.py b/src/plugins/ksulcolors/plugin_settings.py new file mode 100644 index 0000000000..a8f386ecc7 --- /dev/null +++ b/src/plugins/ksulcolors/plugin_settings.py @@ -0,0 +1,69 @@ +import os +import shutil +from utils import plugins +from django.conf import settings + +PLUGIN_NAME = 'KsulColors Plugin' +DISPLAY_NAME = 'KsulColors' +DESCRIPTION = 'Overrides colors in OLH theme to match KSUL colors' +AUTHOR = 'Sawyer' +VERSION = '0.1' +SHORT_NAME = 'ksulcolors' +MANAGER_URL = 'ksulcolors_manager' +JANEWAY_VERSION = "1.7.0" + +BASE_CSS_PATH = os.path.join( + settings.MEDIA_ROOT, + 'ksulcolors', +) +KSULCOLORS_ASSETS = os.path.join(os.path.dirname(__file__), 'assets') +STATIC_CSS_PATH = os.path.join( + settings.BASE_DIR, + 'static', + 'plugins', + 'ksulcolors', + 'css', +) + + +class KsulcolorsPlugin(plugins.Plugin): + plugin_name = PLUGIN_NAME + display_name = DISPLAY_NAME + description = DESCRIPTION + author = AUTHOR + short_name = SHORT_NAME + manager_url = MANAGER_URL + + version = VERSION + janeway_version = JANEWAY_VERSION + press_wide = True + plugin_group_name = 'plugin:{plugin_name}'.format(plugin_name=SHORT_NAME) + + + +def install(): + KsulcolorsPlugin.install() + os.makedirs(BASE_CSS_PATH, exist_ok=True) + shutil.copy( + os.path.join(KSULCOLORS_ASSETS, 'ksul.css'), + os.path.join(BASE_CSS_PATH, 'ksul.css') + ) + + os.makedirs(STATIC_CSS_PATH, exist_ok=True) + shutil.copy( + os.path.join(KSULCOLORS_ASSETS, 'ksul.css'), + os.path.join(STATIC_CSS_PATH, 'ksul.css') + ) + print('Installed ksulcolors') + +def hook_registry(): + return { + 'base_head_css': + { + 'module': 'plugins.ksulcolors.hooks', + 'function': 'inject_css' + } + } + +def register_for_events(): + pass diff --git a/src/plugins/ksulcolors/templates/ksulcolors/manager.html b/src/plugins/ksulcolors/templates/ksulcolors/manager.html new file mode 100644 index 0000000000..425522bec6 --- /dev/null +++ b/src/plugins/ksulcolors/templates/ksulcolors/manager.html @@ -0,0 +1,15 @@ +{% extends "admin/core/base.html" %} +{% load foundation %} + +{% block title %}KsulColors Manager{% endblock %} + +{% block body %} +
+
+

Management Form

+
+
+ {{ form|foundation }} +
+
+{% endblock body %} \ No newline at end of file diff --git a/src/plugins/ksulcolors/urls.py b/src/plugins/ksulcolors/urls.py new file mode 100644 index 0000000000..9f8862bb66 --- /dev/null +++ b/src/plugins/ksulcolors/urls.py @@ -0,0 +1,8 @@ +from django.urls import re_path + +from plugins.ksulcolors import views + + +urlpatterns = [ + re_path(r'^manager/$', views.manager, name='ksulcolors_manager'), +] diff --git a/src/plugins/ksulcolors/views.py b/src/plugins/ksulcolors/views.py new file mode 100644 index 0000000000..80c9637f22 --- /dev/null +++ b/src/plugins/ksulcolors/views.py @@ -0,0 +1,14 @@ +from django.shortcuts import render + +from plugins.ksulcolors import forms + + +def manager(request): + form = forms.DummyManagerForm() + + template = 'ksulcolors/manager.html' + context = { + 'form': form, + } + + return render(request, template, context) From 05b926f790862baa0f9123eb76469ad1eed4bee8 Mon Sep 17 00:00:00 2001 From: Sawyer Date: Mon, 2 Mar 2026 08:51:53 -0600 Subject: [PATCH 3/4] chore(ksulcolors): update top-bar dropdown menu colors --- src/plugins/ksulcolors/assets/ksul.css | 51 +++++++++++++++++--------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/src/plugins/ksulcolors/assets/ksul.css b/src/plugins/ksulcolors/assets/ksul.css index eb76f98486..dfbad76026 100644 --- a/src/plugins/ksulcolors/assets/ksul.css +++ b/src/plugins/ksulcolors/assets/ksul.css @@ -5,20 +5,37 @@ --primary-light-color: #fff; /* lighter colour or secondary colour */ --topbar-background-color: #24193d; /* background colour for the top bar of the navigation */ --menu-foreground-color: #512888; /* font colour used in the menu bar */ - } - - .top-bar .dropdown.menu > li.is-dropdown-submenu-parent > a::after { - border-color: #FFF transparent transparent; - } - - header #main-menu li a { - font-weight: 600; - } - - footer .large-2.logo-wrapper { - display: none; - } - - footer .large-text-right li a { - margin: 0; - } \ No newline at end of file +} + +.top-bar .dropdown.menu > li.is-dropdown-submenu-parent > a { + color: var(--primary-light-color); +} + +.top-bar .dropdown.menu > li.is-dropdown-submenu-parent > ul.submenu li a { + color: var(--menu-foreground-color); +} + +.dropdown.menu > li.is-dropdown-submenu-parent > a { + color: var(--primary-light-color); + +} + +.top-bar .dropdown.menu > li.is-dropdown-submenu-parent > a::after { + border-color: #FFF transparent transparent; +} + +.dropdown.menu > li.is-dropdown-submenu-parent > ul.submenu > li.is-submenu-item > a { + color: var(--menu-foreground-color); +} + +header #main-menu li a { + font-weight: 600; +} + +footer .large-2.logo-wrapper { + display: none; +} + +footer .large-text-right li a { + margin: 0; +} \ No newline at end of file From ea1bae0adc13b03578bb15ecb682fd47ce731a37 Mon Sep 17 00:00:00 2001 From: Sawyer Date: Mon, 2 Mar 2026 09:53:32 -0600 Subject: [PATCH 4/4] feat(build): add docker build github action --- .github/workflows/deploy-docker.yml | 34 +++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 .github/workflows/deploy-docker.yml diff --git a/.github/workflows/deploy-docker.yml b/.github/workflows/deploy-docker.yml new file mode 100644 index 0000000000..808a8287c1 --- /dev/null +++ b/.github/workflows/deploy-docker.yml @@ -0,0 +1,34 @@ +# Docker image build for hub.docker.com +name: Docker images + +# Run this Build for all pushes to 'main' or tagged releases. +# Also run for PRs to ensure PR doesn't break Docker build process +# NOTE: uses "reusable-docker-build.yml" to actually build each of the Docker images. +on: + push: + branches: + - master + tags: + - 'v**' + pull_request: + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +permissions: + contents: read # to fetch code (actions/checkout) + +jobs: + ################################################################### + # Build/Push the 'kstatelibraries/janeway' image. + ################################################################### + tools: + # Ensure this job never runs on forked repos. It's only executed for 'kstatelibraries/janeway' + if: github.repository == 'kstatelibraries/janeway' + uses: kstatelibraries/.github/.github/workflows/reusable-docker-build.yml@main + with: + build_id: janeway + image_name: kstatelibraries/janeway + dockerfile_path: ./dockerfiles/Dockerfile.ksul + secrets: + DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }} + DOCKER_ACCESS_TOKEN: ${{ secrets.DOCKER_ACCESS_TOKEN }}