diff --git a/readthedocs/doc_builder/exceptions.py b/readthedocs/doc_builder/exceptions.py index 2ffa216bad4..abc7783522d 100644 --- a/readthedocs/doc_builder/exceptions.py +++ b/readthedocs/doc_builder/exceptions.py @@ -50,6 +50,7 @@ class BuildUserError(BuildBaseException): BUILD_COMMANDS_IN_BETA = "build:user:build-commands-config-key-in-beta" BUILD_TIME_OUT = "build:user:time-out" BUILD_EXCESSIVE_MEMORY = "build:user:excessive-memory" + VCS_DEPRECATED = "build:vcs:deprecated" class BuildMaxConcurrencyError(BuildUserError): diff --git a/readthedocs/notifications/messages.py b/readthedocs/notifications/messages.py index ed963a52831..b359fb15b59 100644 --- a/readthedocs/notifications/messages.py +++ b/readthedocs/notifications/messages.py @@ -188,6 +188,19 @@ def get_rendered_body(self): ), type=ERROR, ), + Message( + id=BuildUserError.VCS_DEPRECATED, + header=_("Build used a deprecated VCS is not supported: {{vcs}}."), + body=_( + textwrap.dedent( + """ + {{vcs}} VCS is not supported anymore. + Read more about this in our blog post Dropping support for Subversion, Mercurial, and Bazaar. + """ + ).strip(), + ), + type=ERROR, + ), Message( id=BuildAppError.BUILD_DOCKER_UNKNOWN_ERROR, header=_("Build terminated due to unknown error."), diff --git a/readthedocs/vcs_support/backends/bzr.py b/readthedocs/vcs_support/backends/bzr.py index a065ed1b870..bbe63bd5422 100644 --- a/readthedocs/vcs_support/backends/bzr.py +++ b/readthedocs/vcs_support/backends/bzr.py @@ -3,13 +3,14 @@ import csv import re from io import StringIO + from django.conf import settings from readthedocs.projects.exceptions import RepositoryError -from readthedocs.vcs_support.base import BaseVCS, VCSVersion +from readthedocs.vcs_support.base import BaseVCS, Deprecated, VCSVersion -class Backend(BaseVCS): +class Backend(Deprecated, BaseVCS): """Bazaar VCS backend.""" diff --git a/readthedocs/vcs_support/backends/hg.py b/readthedocs/vcs_support/backends/hg.py index fda4a4b7e27..6bf2e9cfc74 100644 --- a/readthedocs/vcs_support/backends/hg.py +++ b/readthedocs/vcs_support/backends/hg.py @@ -2,10 +2,10 @@ from django.conf import settings from readthedocs.projects.exceptions import RepositoryError -from readthedocs.vcs_support.base import BaseVCS, VCSVersion +from readthedocs.vcs_support.base import BaseVCS, Deprecated, VCSVersion -class Backend(BaseVCS): +class Backend(Deprecated, BaseVCS): """Mercurial VCS backend.""" diff --git a/readthedocs/vcs_support/backends/svn.py b/readthedocs/vcs_support/backends/svn.py index 83ed38c4757..dc220610e8d 100644 --- a/readthedocs/vcs_support/backends/svn.py +++ b/readthedocs/vcs_support/backends/svn.py @@ -6,10 +6,10 @@ from django.conf import settings from readthedocs.projects.exceptions import RepositoryError -from readthedocs.vcs_support.base import BaseVCS, VCSVersion +from readthedocs.vcs_support.base import BaseVCS, Deprecated, VCSVersion -class Backend(BaseVCS): +class Backend(Deprecated, BaseVCS): """Subversion VCS backend.""" diff --git a/readthedocs/vcs_support/base.py b/readthedocs/vcs_support/base.py index 678224303c2..5d79a9e7ca4 100644 --- a/readthedocs/vcs_support/base.py +++ b/readthedocs/vcs_support/base.py @@ -1,6 +1,8 @@ """Base classes for VCS backends.""" +import datetime import os +import pytz import structlog from readthedocs.core.utils.filesystem import safe_rmtree @@ -33,6 +35,46 @@ def __repr__(self): ) +class Deprecated: + def __init__(self, *args, **kwargs): + tzinfo = pytz.timezone("America/Los_Angeles") + now = datetime.datetime.now(tz=tzinfo) + + # Brownout dates as published in https://about.readthedocs.com/blog/2024/02/drop-support-for-subversion-mercurial-bazaar/ + # fmt: off + disabled = any([ + # 12 hours browndate + datetime.datetime(2024, 4, 1, 0, 0, 0, tzinfo=tzinfo) < now < datetime.datetime(2024, 4, 1, 12, 0, 0, tzinfo=tzinfo), + # 24 hours browndate + datetime.datetime(2024, 5, 6, 0, 0, 0, tzinfo=tzinfo) < now < datetime.datetime(2024, 5, 7, 0, 0, 0, tzinfo=tzinfo), + # 48 hours browndate + datetime.datetime(2024, 5, 20, 0, 0, 0, tzinfo=tzinfo) < now < datetime.datetime(2024, 5, 22, 0, 0, 0, tzinfo=tzinfo), + # Deprecated after June 3 + datetime.datetime(2024, 6, 3, 0, 0, 0, tzinfo=tzinfo) < now, + ]) + # fmt: on + + if disabled: + from .backends import bzr, hg, svn + + vcs = None + if isinstance(self, bzr.Backend): + vcs = "Bazaar" + elif isinstance(self, svn.Backend): + vcs = "Subversion" + elif isinstance(self, hg.Backend): + vcs = "Mercurial" + + raise BuildUserError( + message_id=BuildUserError.VCS_DEPRECATED, + format_values={ + "vcs": vcs, + }, + ) + + super().__init__(*args, **kwargs) + + class BaseVCS: """