From 95c7f05b9a1469b982cbc904f7c7c3d7ed330890 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Sat, 6 Jun 2026 13:04:43 +0100 Subject: [PATCH 1/4] docker: Fix compat with latest patchwork/pyenv image We switched to the Ubuntu 24.04 base image some time back. This includes an ubuntu user that conflicts with the patchwork user we were creating. Simplify this by using the ubuntu user instead. Signed-off-by: Stephen Finucane --- docker-compose-pg.yml | 2 +- docker-compose-sqlite3.yml | 4 ++-- docker-compose.yml | 2 +- tools/docker/Dockerfile | 11 ++++++----- tools/docker/entrypoint.sh | 4 ++-- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/docker-compose-pg.yml b/docker-compose-pg.yml index 3e277e5cf..57db07a24 100644 --- a/docker-compose-pg.yml +++ b/docker-compose-pg.yml @@ -19,7 +19,7 @@ services: depends_on: - db volumes: - - .:/home/patchwork/patchwork/ + - .:/home/ubuntu/patchwork/ ports: - "8000:8000" environment: diff --git a/docker-compose-sqlite3.yml b/docker-compose-sqlite3.yml index 900cb71fd..f3e2622ca 100644 --- a/docker-compose-sqlite3.yml +++ b/docker-compose-sqlite3.yml @@ -9,11 +9,11 @@ services: - GID command: python3 manage.py runserver 0.0.0.0:8000 volumes: - - .:/home/patchwork/patchwork/ + - .:/home/ubuntu/patchwork/ ports: - "8000:8000" environment: - UID - GID - DATABASE_TYPE=sqlite3 - - DATABASE_NAME=/home/patchwork/patchwork/tools/docker/db/db.sqlite3 + - DATABASE_NAME=/home/ubuntu/patchwork/tools/docker/db/db.sqlite3 diff --git a/docker-compose.yml b/docker-compose.yml index 61c61865f..86b03f394 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -24,7 +24,7 @@ services: depends_on: - db volumes: - - .:/home/patchwork/patchwork/ + - .:/home/ubuntu/patchwork/ ports: - "8000:8000" environment: diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile index 6d942492e..ad41bc2bf 100644 --- a/tools/docker/Dockerfile +++ b/tools/docker/Dockerfile @@ -1,16 +1,17 @@ FROM ghcr.io/getpatchwork/pyenv:latest +# Match the host user's UID so the container can write to bind-mounted volumes. +# Ubuntu 24.04 ships with an 'ubuntu' user (UID 1000); we just remap it. ARG UID=1000 ARG GID=1000 +RUN groupmod -g "${GID}" ubuntu && usermod -u "${UID}" ubuntu && chown -R ubuntu:ubuntu /home/ubuntu ARG TZ="Australia/Canberra" ENV DEBIAN_FRONTEND noninteractive ENV PYTHONUNBUFFERED 1 -ENV PROJECT_HOME /home/patchwork/patchwork +ENV PROJECT_HOME /home/ubuntu/patchwork ENV DJANGO_SETTINGS_MODULE patchwork.settings.dev -RUN groupadd -o --gid=$GID patchwork && \ - useradd --uid=$UID --gid=$GID --create-home patchwork RUN rm -f /etc/localtime; ln -s /usr/share/zoneinfo/$TZ /etc/localtime RUN eval "$(pyenv init -)" @@ -37,5 +38,5 @@ RUN pip install -r /opt/requirements-dev.txt COPY tools/docker/entrypoint.sh /usr/local/bin/entrypoint.sh ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] CMD ["python3", "manage.py", "runserver", "0.0.0.0:8000"] -USER patchwork -WORKDIR /home/patchwork/patchwork +USER ubuntu +WORKDIR /home/ubuntu/patchwork diff --git a/tools/docker/entrypoint.sh b/tools/docker/entrypoint.sh index c78c0581f..f141b7235 100755 --- a/tools/docker/entrypoint.sh +++ b/tools/docker/entrypoint.sh @@ -40,13 +40,13 @@ test_database() { # check if patchwork is mounted. Checking if we exist is a # very good start! -if [ ! -f ~patchwork/patchwork/tools/docker/entrypoint.sh ]; then +if [ ! -f ~/patchwork/tools/docker/entrypoint.sh ]; then cat << EOF The patchwork directory doesn't seem to be mounted! Are you using docker-compose? If so, you may need to create an SELinux rule. Refer to the development installation documentation for more information. -If not, you need -v PATH_TO_PATCHWORK:/home/patchwork/patchwork +If not, you need -v PATH_TO_PATCHWORK:/home/ubuntu/patchwork EOF exit 1 fi From 0b479125631bdbed8d9aece2bd00ccc4941c535d Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Sun, 7 Jun 2026 13:09:18 +0100 Subject: [PATCH 2/4] docker: Fix deprecation warning Signed-off-by: Stephen Finucane --- tools/docker/Dockerfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile index ad41bc2bf..82b8ab057 100644 --- a/tools/docker/Dockerfile +++ b/tools/docker/Dockerfile @@ -7,10 +7,10 @@ ARG GID=1000 RUN groupmod -g "${GID}" ubuntu && usermod -u "${UID}" ubuntu && chown -R ubuntu:ubuntu /home/ubuntu ARG TZ="Australia/Canberra" -ENV DEBIAN_FRONTEND noninteractive -ENV PYTHONUNBUFFERED 1 -ENV PROJECT_HOME /home/ubuntu/patchwork -ENV DJANGO_SETTINGS_MODULE patchwork.settings.dev +ENV DEBIAN_FRONTEND=noninteractive +ENV PYTHONUNBUFFERED=1 +ENV PROJECT_HOME=/home/ubuntu/patchwork +ENV DJANGO_SETTINGS_MODULE=patchwork.settings.dev RUN rm -f /etc/localtime; ln -s /usr/share/zoneinfo/$TZ /etc/localtime From b38dc1edada130990894b3b7593d465a7b1d19f8 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Sun, 7 Jun 2026 13:52:29 +0100 Subject: [PATCH 3/4] docker: Use default packages These are also compatible with Debian. Signed-off-by: Stephen Finucane --- tools/docker/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/docker/Dockerfile b/tools/docker/Dockerfile index 82b8ab057..9eac7ea61 100644 --- a/tools/docker/Dockerfile +++ b/tools/docker/Dockerfile @@ -18,10 +18,10 @@ RUN eval "$(pyenv init -)" RUN apt-get update && apt-get install -y --no-install-recommends \ build-essential \ - libmysqlclient-dev \ + default-libmysqlclient-dev \ + default-mysql-client \ libpq-dev \ libsqlite3-dev \ - mysql-client \ postgresql-client \ sqlite3 \ tzdata \ From f1d16ab9259f240353cce9ed8778fddd352ae4ea Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Sat, 6 Jun 2026 12:50:01 +0100 Subject: [PATCH 4/4] docker: Update to latest stable MySQL, PostgreSQL MySQL 9.7 changed the default gtid_mode from OFF to ON (since 9.5). When the MySQL Docker container initialises, the init scripts run with GTID=ON, leaving non-empty GTID_EXECUTED in the binary log even though the final server starts with --gtid-mode=OFF. This causes two problems: 1. mysqldump always includes SET @@GLOBAL.GTID_PURGED when cloning test databases for parallel tests. Restoring this requires SYSTEM_VARIABLES_ADMIN, which was not granted. 2. mysqldump requires PROCESS to dump tablespace information. While PROCESS was being granted, SYSTEM_VARIABLES_ADMIN was missing from the grants, causing clone failures (exit code 5) for Django 6.0's stricter parallel test runner. Fix both issues by: - Running RESET BINARY LOGS AND GTIDS before granting privileges, which clears the GTID state left by the init phase so mysqldump no longer emits GTID_PURGED statements. - Adding SYSTEM_VARIABLES_ADMIN to the privilege grants so that if any GTID state is present (e.g. in future MySQL versions), the restore can set GTID_PURGED. Signed-off-by: Stephen Finucane Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/ci.yaml | 19 +++++++++++++------ docker-compose-pg.yml | 4 ++-- docker-compose.yml | 4 +++- tools/docker/mysql-client.cnf | 6 ++++++ 4 files changed, 24 insertions(+), 9 deletions(-) create mode 100644 tools/docker/mysql-client.cnf diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index da27ae233..c5e7a98d1 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -47,7 +47,7 @@ jobs: MYSQL_ROOT_PASSWORD: root-${{ github.run_id }} services: postgres: - image: postgres:17 + image: postgres:18 env: POSTGRES_DB: ${{ env.DATABASE_NAME }} POSTGRES_PASSWORD: ${{ env.DATABASE_PASSWORD }} @@ -60,7 +60,7 @@ jobs: --health-timeout 5s --health-retries 5 mysql: - image: mysql:8.4 + image: mysql:9.7 env: MYSQL_DATABASE: ${{ env.DATABASE_NAME }} MYSQL_USER: ${{ env.DATABASE_USER }} @@ -98,8 +98,13 @@ jobs: - name: Modify database user permissions (mysql) if: ${{ matrix.db == 'mysql' }} run: | - mysql -h 127.0.0.1 -e "GRANT ALL ON \`test\\_${DATABASE_NAME}%\`.* to '${DATABASE_USER}'@'%';" \ - -uroot -p${MYSQL_ROOT_PASSWORD} + mysql -h 127.0.0.1 -uroot -p${MYSQL_ROOT_PASSWORD} -e \ + "GRANT ALL ON \`test\\_${DATABASE_NAME}%\`.* TO '${DATABASE_USER}'@'%'; + FLUSH PRIVILEGES;" + - name: Configure MySQL client (mysql) + if: ${{ matrix.db == 'mysql' }} + run: | + printf '[mysqldump]\nset-gtid-purged=OFF\nno-tablespaces\n' > ~/.my.cnf - name: Run unit tests (via tox) run: tox docs: @@ -164,8 +169,10 @@ jobs: - name: Modify database user permissions (mysql) if: ${{ matrix.db == 'mysql' }} run: | - docker compose exec -T -- db \ - sh -c "exec mysql -uroot -p\"\${MYSQL_ROOT_PASSWORD}\" -e \"GRANT ALL ON \\\`test\\_\${MYSQL_DATABASE}%\\\`.* to '\${MYSQL_USER}'@'%'; FLUSH PRIVILEGES;\"" + docker compose exec -T -- db sh -c \ + "exec mysql -uroot -p\"\${MYSQL_ROOT_PASSWORD}\" -e \ + \"GRANT ALL ON \\\`test\\_\${MYSQL_DATABASE}%\\\`.* TO '\${MYSQL_USER}'@'%'; + FLUSH PRIVILEGES;\"" - name: Run unittest run: docker compose run -T --rm web tox - name: Test normal startup diff --git a/docker-compose-pg.yml b/docker-compose-pg.yml index 57db07a24..538291a47 100644 --- a/docker-compose-pg.yml +++ b/docker-compose-pg.yml @@ -1,9 +1,9 @@ --- services: db: - image: postgres:17 + image: postgres:18 volumes: - - ./tools/docker/db/postdata:/var/lib/postgresql/data + - ./tools/docker/db/postdata:/var/lib/postgresql environment: - POSTGRES_DB=patchwork - POSTGRES_USER=patchwork diff --git a/docker-compose.yml b/docker-compose.yml index 86b03f394..566fc2626 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,8 @@ --- services: db: - image: mysql:latest + image: mysql:9.7 + command: --gtid-mode=OFF --enforce-gtid-consistency=OFF volumes: - ./tools/docker/db/data:/var/lib/mysql environment: @@ -25,6 +26,7 @@ services: - db volumes: - .:/home/ubuntu/patchwork/ + - ./tools/docker/mysql-client.cnf:/home/ubuntu/.my.cnf:ro ports: - "8000:8000" environment: diff --git a/tools/docker/mysql-client.cnf b/tools/docker/mysql-client.cnf new file mode 100644 index 000000000..2cb12c7cb --- /dev/null +++ b/tools/docker/mysql-client.cnf @@ -0,0 +1,6 @@ +[mysqldump] +# MySQL 9.5+ defaults gtid_mode=ON; suppress GTID state from dumps so that +# parallel test database cloning works without SYSTEM_VARIABLES_ADMIN. +set-gtid-purged=OFF +# Avoid requiring the PROCESS privilege for tablespace metadata. +no-tablespaces