From 1744da8e5330fe6080f0b2527c63e40686b74a89 Mon Sep 17 00:00:00 2001 From: Santos Gallegos Date: Wed, 29 Oct 2025 13:35:35 -0500 Subject: [PATCH 1/3] Set final cutoff date for projects using SSH keys with write access Ref: - https://github.com/readthedocs/readthedocs-corporate/issues/2049 - https://github.com/readthedocs/meta/pull/196 --- readthedocs/doc_builder/director.py | 16 +++++++++++----- readthedocs/notifications/messages.py | 2 +- readthedocs/projects/notifications.py | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/readthedocs/doc_builder/director.py b/readthedocs/doc_builder/director.py index 11de6c27b4f..96d614f7e3e 100644 --- a/readthedocs/doc_builder/director.py +++ b/readthedocs/doc_builder/director.py @@ -8,6 +8,7 @@ * fetching instructions etc. """ +import datetime import os import tarfile @@ -216,12 +217,17 @@ def checkout(self): self.data.api_client.project(self.data.project.pk).patch( {"has_ssh_key_with_write_access": has_ssh_key_with_write_access} ) + + hard_failure = datetime.datetime.now() >= datetime.datetime(2025, 12, 1) if has_ssh_key_with_write_access: - self.attach_notification( - attached_to=f"project/{self.data.project.pk}", - message_id=MESSAGE_PROJECT_SSH_KEY_WITH_WRITE_ACCESS, - dismissable=True, - ) + if hard_failure and settings.RTD_ENFORCE_BROWNOUTS_FOR_DEPRECATIONS: + raise BuildUserError(BuildUserError.SSH_KEY_WITH_WRITE_ACCESS) + else: + self.attach_notification( + attached_to=f"project/{self.data.project.pk}", + message_id=MESSAGE_PROJECT_SSH_KEY_WITH_WRITE_ACCESS, + dismissable=True, + ) identifier = self.data.build_commit or self.data.version.identifier log.info("Checking out.", identifier=identifier) diff --git a/readthedocs/notifications/messages.py b/readthedocs/notifications/messages.py index a2018b91983..d93cfdf1d04 100644 --- a/readthedocs/notifications/messages.py +++ b/readthedocs/notifications/messages.py @@ -226,7 +226,7 @@ def get_rendered_body(self): """ This build has failed because the current deploy key on the repository was created with write permission. For protection against abuse we've restricted use of these deploy keys. - A read-only deploy key will need to be set up before July 31, 2025 to continue building this project. + A read-only deploy key will need to be set up before December 1st, 2025 to continue building this project. Read more about this in our blog post. """ ).strip(), diff --git a/readthedocs/projects/notifications.py b/readthedocs/projects/notifications.py index 9b9e5d43e7a..a6bd1085308 100644 --- a/readthedocs/projects/notifications.py +++ b/readthedocs/projects/notifications.py @@ -186,7 +186,7 @@ """ This project has a deploy key with write access to the repository. For protection against abuse we've restricted use of these deploy keys. - A read-only deploy key will need to be set up before July 31, 2025 to continue building this project. + A read-only deploy key will need to be set up before December 1st, 2025 to continue building this project. Read more about this in our blog post. """ ).strip(), From 11a07a1c319813641933265f66baadbeb45a7ce2 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Wed, 29 Oct 2025 14:01:40 -0500 Subject: [PATCH 2/3] Use timezone-aware datetime for SSH key cutoff date comparison (#12538) Addresses feedback from #12536 to use timezone-aware datetime objects in the SSH key write access deprecation check. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: stsewd <4975310+stsewd@users.noreply.github.com> --- readthedocs/doc_builder/director.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/readthedocs/doc_builder/director.py b/readthedocs/doc_builder/director.py index 96d614f7e3e..81a233b97ec 100644 --- a/readthedocs/doc_builder/director.py +++ b/readthedocs/doc_builder/director.py @@ -218,7 +218,8 @@ def checkout(self): {"has_ssh_key_with_write_access": has_ssh_key_with_write_access} ) - hard_failure = datetime.datetime.now() >= datetime.datetime(2025, 12, 1) + now = datetime.datetime.now(tz=datetime.timezone.utc) + hard_failure = now >= datetime.datetime(2025, 12, 1, 0, 0, 0, tzinfo=datetime.timezone.utc) if has_ssh_key_with_write_access: if hard_failure and settings.RTD_ENFORCE_BROWNOUTS_FOR_DEPRECATIONS: raise BuildUserError(BuildUserError.SSH_KEY_WITH_WRITE_ACCESS) From e111e420da84912f8bb75a63a42b4b7ad4a7cff7 Mon Sep 17 00:00:00 2001 From: Santos Gallegos Date: Wed, 29 Oct 2025 14:02:18 -0500 Subject: [PATCH 3/3] Format --- readthedocs/doc_builder/director.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/readthedocs/doc_builder/director.py b/readthedocs/doc_builder/director.py index 81a233b97ec..ad842e4bdc7 100644 --- a/readthedocs/doc_builder/director.py +++ b/readthedocs/doc_builder/director.py @@ -219,7 +219,9 @@ def checkout(self): ) now = datetime.datetime.now(tz=datetime.timezone.utc) - hard_failure = now >= datetime.datetime(2025, 12, 1, 0, 0, 0, tzinfo=datetime.timezone.utc) + hard_failure = now >= datetime.datetime( + 2025, 12, 1, 0, 0, 0, tzinfo=datetime.timezone.utc + ) if has_ssh_key_with_write_access: if hard_failure and settings.RTD_ENFORCE_BROWNOUTS_FOR_DEPRECATIONS: raise BuildUserError(BuildUserError.SSH_KEY_WITH_WRITE_ACCESS)