Upgrade Weblate from git 2.18 version to latest docker

MAKE A BACKUP FIRST.
Ensure the website runs well before upgrading.

If encountering error ImproperlyConfigured: Requested setting DATA_DIR, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings. when starting server, run export DJANGO_SETTINGS_MODULE=weblate.settings.

Read Generic upgrade instructions from official weblate doc first.

Special instruction for my build: Custom changes to weblate (weblate/trans/formats.py)and translate-toolkit (translate/storage/properties.py)to provide a special “Minecraft Lang File” format. The HTTP server is Gunicorn with Nginx. The operating system is Ubuntu 16.04 and weblate runs on Python 2.7. The database is PostgreSQL 9.5. These softwares will be upgraded or replaced during progress.

Universal step:

Run git fetch --all before git operation to ensure latest code exists.

  1. Read Version specific instructions and follow it.
  2. Stop gunicorn/wsgi and celery worker.
  3. git stash (before 3.0.x)
  4. git reset --hard (before 3.0.x)
  5. git checkout weblate-x.x Usex.x.1 or the latest minor version if it exists for a major version.
  6. git stash pop (before 3.0.x)
  7. pip install -r requirements.txt
  8. find weblate -name '*.pyc' -delete to remove cached compiled bytecode.
  9. Update settings.py to accommodate to settings_example.py.
  10. python manage.py migrate --noinput
  11. follow other manage commands in generic upgrade instructions.
  12. Start the server and check if everything works well.

Version specified steps:

2.18 to 2.19
Nothing special

2.19 to 2.20
Update translate-toolkit to stable/2.3.x and apply the patch before installing weblate requirements.
Missing backports.csv, install it manually.

2.20 to 3.0
BACKUP BEFORE UPGRADING.
pg_dump weblate -U weblate -F t -f 2.20_py27_9.5.tar
Follow special steps in official docs.
From this version, changes to weblate and translate-toolkit is extracted to a single external file. Add the file to PYTHONPATH to let the weblate find it. To let weblate know the “Minecraft Lang File” format, add class path to WEBLATE_FORMATS in settings.py.
Change line 11 in file weblate/trans/migrations/0140_change_project.py from for change in Change.objects.all(): to for change in Change.objects.all().iterator():, or the migration progress will eat an enormous amount of memory, and won’t finish the job, really. Ref: https://www.azavea.com/blog/2017/02/23/strategies-reducing-memory-usage-django-migrations/

3.0 to 3.1
After installing requirements, jellyfish==0.8.1 will be installed, which is not compatible with python 2.7 because of using from itertools import zip_longest. To solve this, install jellyfish==0.6.1 mannually.
Change 'ENGINE': 'django.db.backends.postgresql_psycopg2' to 'ENGINE': 'django.db.backends.postgresql' in DATABASES in settings.py.

3.1 to 3.2
Weblate provided a new base class PropertiesBaseFormat for Java Properties file format. Change the “Minecraft Lang File” format class extending this class.
Start Celery workers manually by celery worker --app weblate --loglevel info --beat

3.3 to 3.4
Start Celery workers manually by ./examples/celery start.
If encountering error: OSError: [Errno 2] No such file or directory: '' when starting Celery worker, downgrade to celery==4.0 and kombu==4.0. Ref: https://github.com/WeblateOrg/weblate/issues/4029

3.6 to 3.7
Run apt install -y pkg-config libcairo2-dev python3-gi python3-gi-cairo gir1.2-gtk-3.0 libgirepository1.0-dev before installing requirements.

3.7 to 3.8
Upgrade six, pip, setuptools before installing requirements, or installing diff-match-patch==20181111 might lead to an error.

3.8 to 3.9
Default setting_example.py use Redis as cache and Celery broker. Start the Redis server before starting the server.

3.9 to 3.10
Celery workers eats memory. To reduce Celery memory usage, change --concurrency parameter to 1. E.g. edit ./weblate/examples/celery file.

3.11 to 4.0
BACKUP BEFORE UPGRADING.
4.0 needs Python 3.6 or above to run. Upgrade to Ubuntu 18.04 to get system-wide Python 3.6. apt update && apt upgrade , reboot, do-release-upgrade. Use pg_dropcluster and pg_upgradecluseter to migrate to PostgreSQL 10.
Weblate needs to be a superuser of PostgreSQL. To do this, su postgres and enter psql cli. Run ALTER USER weblate WITH SUPERUSER, and run \du to check if it works.
If encountering error: FileNotFoundError: [Errno 2] No such file or directory: ” when starting Celery worker again, instead of downgrade Celery, just add $PWD/ after file= in examples/celery. Ref: https://github.com/WeblateOrg/weblate/issues/4029
Remove old Python 2 packages like gunicorn to avoid running Python 2 script accidentally.
Clear Redis by run command redis-cli flushall or the new version of weblate might not understand. Clear data/avatar_cache if the avatar doesn’t show.

Dockerize Weblate

Follow official instruction: https://docs.weblate.org/en/weblate-4.1.1/admin/install/docker.html

  1. Start an empty weblate docker-compose instance and make sure it runs.
  2. Change docker-compose.override.yml to fit old settings.
  3. Upgrade PostgreSQL to the docker version.
  4. Replace weblate files and database to migrate.

Change docker-compose.override.yml

You may need to assign another admin email to avoid errors like CommandError: Multiple users matched given parameters!

Replace weblate files

Copy vcs directory is enough for migration. Ref: https://docs.weblate.org/en/weblate-4.1.1/admin/install.html#migrating-weblate-to-another-server
Write WEBLATE_FORMATS to /app/data/settings-override.py. Ref: https://docs.weblate.org/en/weblate-4.1.1/admin/install/docker.html#custom-configuration-files
Copy files to support “Minecraft Lang File” format to /app/data/python/ to let weblate find it. Ref: https://docs.weblate.org/en/weblate-4.1.1/admin/install/docker.html#adding-own-python-modules

Replace database

Use pg_dump to save old database, and use pg_restore to load.
Drop all tables in database before restore. Ref: https://stackoverflow.com/a/21247009

Version specified steps after dockerize

4.1 to 4.2
Update docker-compose repo. https://github.com/WeblateOrg/docker-compose
PostgreSQL has been upgraded to 12. To upgrade, using a repo suggested in the issue: https://github.com/docker-library/postgres/issues/37#issuecomment-221441743
Follow steps in readme https://github.com/tianon/docker-postgres-upgrade/blob/master/README.md
Prepare folders to save data. Use docker cp to copy all files from PostgreSQL volume to the old data directory, and create an empty directory for new data.
If anything went wrong, clear the new directory before the next try.
Use weblate username to upgrade by run docker run --rm -e PGUSER=weblate -e POSTGRES_INITDB_ARGS="-U weblate" -v DIR:/var/lib/postgresql tianon/postgres-upgrade:11-to-12 --link
Ref: https://github.com/tianon/docker-postgres-upgrade/issues/10#issuecomment-523020113
Note that DIR must be an absolute path.
After upgrading, modify pg_hba.conf or copy this file from the old data directory.
Ref: https://github.com/tianon/docker-postgres-upgrade/issues/16#issuecomment-570917033
Replace PostgreSQL volume content with upgraded data files in new data directory, and pull new version PostgreSQL docker image to finish.
Another issue is weblate is enforcing case insensitive uniqueness for username. Having two user accounts has the same username but case will lead to migration failure. An ideal solution is not possible. Just change one of the account’s username to another as a workaround.
Start PostgreSQL container only by run docker container start weblate-docker_cache_1. Run docker exec -it weblate-docker_database_1 psql -U weblate to log in PostgreSQL cli. To change the username of a certain user, run UPDATE weblate_auth_user set username = 'NewUsername' where username = 'OldUsername';.