#!/usr/bin/env python3 import logging import os import subprocess import sys ZULIP_PATH = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) sys.path.insert(0, ZULIP_PATH) from scripts.lib.setup_path import setup_path from scripts.lib.zulip_tools import ( DEPLOYMENTS_DIR, assert_not_running_as_root, get_config, get_config_file, parse_version_from, ) from version import ZULIP_VERSION as NEW_VERSION assert_not_running_as_root() setup_path() os.environ["DJANGO_SETTINGS_MODULE"] = "zproject.settings" import django from django.db import connection from django.db.migrations.loader import MigrationLoader django.setup() django_pg_version = connection.cursor().connection.server_version // 10000 if os.path.exists("/etc/init.d/postgresql") and os.path.exists("/etc/zulip/zulip.conf"): postgresql_version = int(get_config(get_config_file(), "postgresql", "version", "0")) if postgresql_version == 0: postgresql_version = django_pg_version subprocess.check_call( [ "crudini", "--set", "/etc/zulip/zulip.conf", "postgresql", "version", str(postgresql_version), ] ) elif postgresql_version != django_pg_version: logging.critical( "PostgreSQL version mismatch: %d (running) vs %d (configured)", django_pg_version, postgresql_version, ) logging.info( "/etc/zulip/zulip.conf claims that Zulip is running PostgreSQL\n" "%d, but the server is connected to a PostgreSQL running\n" "version %d. Check the output from pg_lsclusters to verify\n" "which clusters are running, and update /etc/zulip/zulip.conf to match.\n" "\n" "In general, this results from manually upgrading PostgreSQL; you\n" "should follow our instructions for using our tool to do so:\n" "https://zulip.readthedocs.io/en/stable/production/upgrade.html#upgrading-postgresql", postgresql_version, django_pg_version, ) sys.exit(1) if django_pg_version < 13: logging.critical("Unsupported PostgreSQL version: %d", postgresql_version) logging.info( "Please upgrade to PostgreSQL 13 or newer first.\n" "See https://zulip.readthedocs.io/en/stable/production/" "upgrade.html#upgrading-postgresql" ) sys.exit(1) loader = MigrationLoader(connection) missing = set(loader.applied_migrations) # Ignore django-guardian, which we installed until 1.7.0~3134 missing.discard(("guardian", "0001_initial")) # Ignore django.contrib.sites, which we installed until 2.0.0-rc1~984. missing.discard(("sites", "0001_initial")) missing.discard(("sites", "0002_alter_domain_unique")) # These migrations were squashed into 0001, in 6fbddf578a6e through # a21f2d771553, 1.7.0~3135. missing.difference_update( [ ("zerver", "0002_django_1_8"), ("zerver", "0003_custom_indexes"), ("zerver", "0004_userprofile_left_side_userlist"), ("zerver", "0005_auto_20150920_1340"), ("zerver", "0006_zerver_userprofile_email_upper_idx"), ("zerver", "0007_userprofile_is_bot_active_indexes"), ("zerver", "0008_preregistrationuser_upper_email_idx"), ("zerver", "0009_add_missing_migrations"), ("zerver", "0010_delete_streamcolor"), ("zerver", "0011_remove_guardian"), ("zerver", "0012_remove_appledevicetoken"), ("zerver", "0013_realmemoji"), ("zerver", "0014_realm_emoji_url_length"), ("zerver", "0015_attachment"), ("zerver", "0016_realm_create_stream_by_admins_only"), ("zerver", "0017_userprofile_bot_type"), ("zerver", "0018_realm_emoji_message"), ("zerver", "0019_preregistrationuser_realm_creation"), ("zerver", "0020_add_tracking_attachment"), ("zerver", "0021_migrate_attachment_data"), ("zerver", "0022_subscription_pin_to_top"), ("zerver", "0023_userprofile_default_language"), ("zerver", "0024_realm_allow_message_editing"), ("zerver", "0025_realm_message_content_edit_limit"), ("zerver", "0026_delete_mituser"), ("zerver", "0027_realm_default_language"), ("zerver", "0028_userprofile_tos_version"), ] ) # This migration was in python-social-auth, and was mistakenly removed # from its `replaces` in # https://github.com/python-social-auth/social-app-django/pull/25 missing.discard(("default", "0005_auto_20160727_2333")) # This was a typo (twofactor for two_factor) corrected in # https://github.com/jazzband/django-two-factor-auth/pull/642 missing.discard(("twofactor", "0001_squashed_0008_delete_phonedevice")) for key, migration in loader.disk_migrations.items(): missing.discard(key) missing.difference_update(migration.replaces) if not missing: sys.exit(0) print("Migrations which are currently applied, but missing in the new version:") for app, migration_name in sorted(missing): print(f" {app} - {migration_name}") current_version = parse_version_from(os.path.join(DEPLOYMENTS_DIR, "current")) logging.error( "This is not an upgrade -- the current deployment (version %s) " "contains %s database migrations which %s (version %s) does not.", current_version, len(missing), ZULIP_PATH, NEW_VERSION, ) sys.exit(1)