From de92b4ab91b96b0da545ea818f856283b26ba413 Mon Sep 17 00:00:00 2001 From: Baptiste Mispelon Date: Sat, 20 Jan 2024 00:39:05 +0100 Subject: [PATCH] Update to Trac 1.6 and Python 3.8 (finally :tada:) Still running Django 1.11 which is technically not compatible with Python 3.8 but our test suite seems to pass. --- .github/workflows/tests.yml | 9 ++- DjangoPlugin/tracdjangoplugin/plugins.py | 5 +- Dockerfile | 98 ++++++++++++------------ README.rst | 11 ++- docker-compose.yml | 3 +- docker-entrypoint.sh | 4 +- requirements.txt | 19 ++--- 7 files changed, 77 insertions(+), 72 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b67975c..e2cdb10 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -21,17 +21,18 @@ jobs: uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: - python-version: '3.7' + python-version: '3.8' - run: pip install "tinycss2>=1.2.0" - run: python noshadows.py --tests tracdjangoplugin: - runs-on: ubuntu-latest - container: - image: python:2.7.18-buster + runs-on: ubuntu-20.04 steps: - name: Checkout uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.8' - name: Install requirements run: python -m pip install -r requirements.txt - name: Run tests diff --git a/DjangoPlugin/tracdjangoplugin/plugins.py b/DjangoPlugin/tracdjangoplugin/plugins.py index 0b1c2a3..4005964 100644 --- a/DjangoPlugin/tracdjangoplugin/plugins.py +++ b/DjangoPlugin/tracdjangoplugin/plugins.py @@ -1,11 +1,10 @@ -from urlparse import urlparse +from urllib.parse import urlparse from trac.core import Component, implements from trac.web.chrome import INavigationContributor from trac.web.api import IRequestFilter, IRequestHandler, RequestDone from trac.web.auth import LoginModule from trac.wiki.web_ui import WikiModule -from trac.util import Markup from trac.util.html import tag from tracext.github import GitHubBrowser @@ -82,7 +81,7 @@ def get_navigation_items(self, req): ( "mainnav", "custom_reports", - Markup('Reports' % req.href.wiki("Reports")), + tag.a("Reports", href=req.href.wiki("Reports")), ), ] diff --git a/Dockerfile b/Dockerfile index b5aedf8..d8d18af 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,62 +1,62 @@ -# The official python:2.7 image no longer receives automatic rebuilds (it's -# a year old as of October, 2021), so use the latest LTS release of Ubuntu -# that includes Python 2.7 instead. -FROM ubuntu:20.04 - -# Install packages needed to run your application (not build deps). -RUN set -x \ - && RUN_DEPS=" \ - ca-certificates \ - git \ - libpq5 \ - make \ - postgresql-client \ - python2.7 \ - " \ - && apt-get update && apt-get install -y --no-install-recommends $RUN_DEPS \ +# pull official base image +FROM python:3.8-slim-bullseye + +# set work directory +WORKDIR /code + +# set environment varibles +ENV PYTHONDONTWRITEBYTECODE 1 +ENV PYTHONUNBUFFERED 1 + +# getting postgres from PGDG (https://wiki.postgresql.org/wiki/Apt) +# gnupg is required to run apt.postgresql.org.sh +RUN apt-get update \ + && apt-get install --assume-yes --no-install-recommends \ + git \ + gnupg \ + postgresql-common \ + && /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh -y\ + && apt-get install --assume-yes --no-install-recommends postgresql-client-14\ + && apt-get purge --assume-yes --auto-remove gnupg\ && rm -rf /var/lib/apt/lists/* -# Copy requirements -ADD requirements.txt /requirements.txt -ADD DjangoPlugin /DjangoPlugin - -# Install build deps, then run `pip install`, then remove unneeded build deps all in a single step. -# Correct the path to your production requirements file, if needed. -# For installing a python2.7-compatible pip: https://stackoverflow.com/a/54335642/166053 -# Since we are using the system Python, also isolate the code in its own virtualenv. -RUN set -x \ - && BUILD_DEPS=" \ - build-essential \ - libpq-dev \ - python2.7-dev \ - wget \ - " \ - && apt-get update && apt-get install -y --no-install-recommends $BUILD_DEPS \ - && wget -q -O /tmp/get-pip.py https://bootstrap.pypa.io/pip/2.7/get-pip.py \ - && python2.7 /tmp/get-pip.py \ - && rm /tmp/get-pip.py \ - && python2.7 -m pip install virtualenv \ - && virtualenv /venv \ - && /venv/bin/python -m pip install --no-cache-dir -r /requirements.txt \ - \ - && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false $BUILD_DEPS \ +# install deb packages +RUN apt-get update \ + && apt-get install --assume-yes --no-install-recommends \ + make \ && rm -rf /var/lib/apt/lists/* -# Copy application code -RUN mkdir /code/ -WORKDIR /code/ -ADD . /code/ +# install python dependencies +COPY ./requirements.txt ./requirements.txt +COPY ./DjangoPlugin ./DjangoPlugin + +RUN apt-get update \ + && apt-get install --assume-yes --no-install-recommends \ + g++ \ + gcc \ + libc6-dev \ + libpq-dev \ + && python3 -m pip install --no-cache-dir -r requirements.txt \ + && apt-get purge --assume-yes --auto-remove \ + gcc \ + libc6-dev \ + libpq-dev \ + && rm -rf /var/lib/apt/lists/* + +COPY ./docker-entrypoint.sh ./docker-entrypoint.sh +COPY ./Makefile ./Makefile +COPY ./scss ./scss +COPY ./trac-env ./trac-env +RUN make compile-scss +RUN rm -r ./scss -RUN PATH=/venv/bin:${PATH} make compile-scss VOLUME /code/trac-env/files/ -# gunicorn or tracd will listen on this port EXPOSE 9000 - ENV DJANGO_SETTINGS_MODULE=tracdjangoplugin.settings TRAC_ENV=/code/trac-env/ -ENTRYPOINT ["/code/docker-entrypoint.sh"] +ENTRYPOINT ["./docker-entrypoint.sh"] # Start gunicorn -CMD ["/venv/bin/gunicorn", "tracdjangoplugin.wsgi:application", "--bind", "0.0.0.0:9000", "--workers", "8", "--max-requests", "1000"] +CMD ["gunicorn", "tracdjangoplugin.wsgi:application", "--bind", "0.0.0.0:9000", "--workers", "8", "--max-requests", "1000"] diff --git a/README.rst b/README.rst index dac5525..58a1e05 100644 --- a/README.rst +++ b/README.rst @@ -21,6 +21,15 @@ Using Docker * Install Docker * ``pip install docker-compose`` +* Create a ``secrets.json`` file at the root of the repository (next to `Dockerfile`), containing + something like:: + + { + "secret_key": "xyz", + "db_host": "localhost", + "db_password": "secret", + } + * ``docker-compose up --build`` * Follow instructions above to create/load the DB, grant permissions, create the config, etc. For example:: @@ -28,7 +37,7 @@ Using Docker docker-compose up --build export DATABASE_URL=postgres://code.djangoproject:secret@db/code.djangoproject docker-compose exec -T db psql $DATABASE_URL < ../djangoproject.com/tracdb/trac.sql - docker-compose exec trac /venv/bin/trac-admin /code/trac-env/ permission add anonymous TRAC_ADMIN + docker-compose exec trac trac-admin /code/trac-env/ permission add anonymous TRAC_ADMIN Using Podman ------------ diff --git a/docker-compose.yml b/docker-compose.yml index 1c60c10..0c7d586 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,9 +7,10 @@ services: build: context: ./ dockerfile: Dockerfile - command: ["/venv/bin/tracd", "--port", "9000", "-s", "trac-env"] + command: ["gunicorn", "--bind", "0:9000", "--reload", "tracdjangoplugin.wsgi"] environment: - TRAC_INI_database=postgres://code.djangoproject:secret@db/code.djangoproject + - SECRETS_FILE=/code/secrets.json volumes: - ./:/code/ ports: diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index d631cc5..df478f7 100755 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -10,12 +10,12 @@ set -e # database = postgres://... for var in "${!TRAC_INI_@}"; do - sed -i "s;^${var:9} = .*;${var:9} = ${!var};" trac-env/conf/trac.ini + sed -i "s;^${var:9} = .*;${var:9} = ${!var};" /code/trac-env/conf/trac.ini done if [ "x$TRAC_COLLECT_STATIC" = 'xon' ]; then # Collect trac static files to be served by nginx - /venv/bin/trac-admin ./trac-env/ deploy ./static/ + trac-admin /code/trac-env/ deploy ./static/ fi exec "$@" diff --git a/requirements.txt b/requirements.txt index c9a9a7b..ff7ffb9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,22 +1,17 @@ # spam-filter doesn't work without babel (but somehow doesn't list it in its requirements) -Trac[pygments, babel]==1.4.4 +Trac[pygments, babel]==1.6.0 dnspython==1.15 -spambayes == 1.1b1 -psycopg2==2.7.6.1 --no-binary=psycopg2 -docutils==0.14 +psycopg2==2.9.9 --no-binary=psycopg2 Django==1.11.29 -libsass==0.17.0 -Genshi==0.7.7 # still required by some plugins +libsass==0.23.0 # Trac plugins -https://trac.edgewall.org/browser/plugins/1.4/spam-filter?format=zip -# TracXMLRPC from PyPI does not (yet) have a 1.2.0 release (compatible with Trac 1.4) +https://trac.edgewall.org/browser/plugins/trunk/spam-filter?rev=17752&format=zip +# TracXMLRPC from PyPI does not (yet) have a 1.2.0 release (compatible with Trac >=1.4) https://trac-hacks.org/browser/xmlrpcplugin/trunk?rev=18591&format=zip -oauthlib==2.1.0 -requests==2.20.1 -requests-oauthlib==1.0.0 -trac-github==2.3 +# No pypi release compatible with trac 1.6 yet +trac-github[oauth] @ git+https://github.com/bmispelon/trac-github.git@trac-1.6-py3 gunicorn==19.10.0 sentry-sdk==1.11.0