diff --git a/docs/user/canonical-urls.rst b/docs/user/canonical-urls.rst index 520b9a701ee..eac1a40e8c4 100644 --- a/docs/user/canonical-urls.rst +++ b/docs/user/canonical-urls.rst @@ -34,7 +34,7 @@ The canonical URL takes the following into account: * The default version of your project (usually "latest" or "stable"). * The canonical :doc:`custom domain ` if you have one, - otherwise the default :ref:`subdomain ` will be used. + otherwise the default :ref:`subdomain ` will be used. For example, if you have a project named ``example-docs`` with a custom domain ``https://docs.example.com``, diff --git a/docs/user/custom-domains.rst b/docs/user/custom-domains.rst index 4f2ca51cbfa..3a13b136e05 100644 --- a/docs/user/custom-domains.rst +++ b/docs/user/custom-domains.rst @@ -5,7 +5,7 @@ You can serve your documentation project from your own domain, for instance ``docs.example.com``. This is great for maintaining a consistent brand for your product and its documentation. -.. _default_subdomain: +.. _default-subdomain: .. rubric:: Default subdomains diff --git a/docs/user/reference/environment-variables.rst b/docs/user/reference/environment-variables.rst index 1fe48af3f91..68bbfb532af 100644 --- a/docs/user/reference/environment-variables.rst +++ b/docs/user/reference/environment-variables.rst @@ -44,6 +44,18 @@ All :doc:`build processes ` have the following environment variables au :Example: ``/home/docs/checkouts/readthedocs.org/user_builds/project/envs/version`` +.. envvar:: READTHEDOCS_CANONICAL_URL + + Canonical base URL for the version that is built. + If the project has configured a :doc:`custom domain ` (e.g. ``docs.example.com``) it will be used in the resulting canonical URL. + Otherwise, your project's :ref:`default subdomain ` will be used. + + The path for the language and version is appended to the domain, so the final canonical base URLs can look like the following examples: + + :Example: ``https://docs.example.com/en/latest/`` + :Example: ``https://docs.readthedocs.io/ja/stable/`` + :Example: ``https://example--17.org.readthedocs.build/fr/17/`` + .. seealso:: :doc:`/environment-variables` diff --git a/readthedocs/api/v2/serializers.py b/readthedocs/api/v2/serializers.py index aad6ac57c43..4a26b164e62 100644 --- a/readthedocs/api/v2/serializers.py +++ b/readthedocs/api/v2/serializers.py @@ -5,6 +5,7 @@ from rest_framework import serializers from readthedocs.api.v2.utils import normalize_build_command +from readthedocs.builds.constants import EXTERNAL from readthedocs.builds.models import Build, BuildCommandResult, Version from readthedocs.oauth.models import RemoteOrganization, RemoteRepository from readthedocs.projects.models import Domain, Project @@ -124,11 +125,20 @@ class VersionAdminSerializer(VersionSerializer): """Version serializer that returns admin project data.""" project = ProjectAdminSerializer() + canonical_url = serializers.SerializerMethodField() build_data = serializers.JSONField(required=False, write_only=True) + def get_canonical_url(self, obj): + return obj.project.get_docs_url( + lang_slug=obj.project.language, + version_slug=obj.slug, + external=obj.type == EXTERNAL, + ) + class Meta(VersionSerializer.Meta): fields = VersionSerializer.Meta.fields + [ "build_data", + "canonical_url", ] diff --git a/readthedocs/builds/models.py b/readthedocs/builds/models.py index dc83b11c34b..cf35e24f841 100644 --- a/readthedocs/builds/models.py +++ b/readthedocs/builds/models.py @@ -601,7 +601,8 @@ class Meta: proxy = True def __init__(self, *args, **kwargs): - self.project = APIProject(**kwargs.pop('project', {})) + self.project = APIProject(**kwargs.pop("project", {})) + self.canonical_url = kwargs.pop("canonical_url", None) # These fields only exist on the API return, not on the model, so we'll # remove them to avoid throwing exceptions due to unexpected fields for key in ['resource_uri', 'absolute_url', 'downloads']: diff --git a/readthedocs/doc_builder/director.py b/readthedocs/doc_builder/director.py index f42a5548752..4d8f3edc3dc 100644 --- a/readthedocs/doc_builder/director.py +++ b/readthedocs/doc_builder/director.py @@ -615,6 +615,12 @@ def get_build_env_vars(self): } ) + env.update( + { + "READTHEDOCS_CANONICAL_URL": self.data.version.canonical_url, + } + ) + # Update environment from Project's specific environment variables, # avoiding to expose private environment variables # if the version is external (i.e. a PR build). diff --git a/readthedocs/projects/tests/test_build_tasks.py b/readthedocs/projects/tests/test_build_tasks.py index d9a637edc74..11b7212d60a 100644 --- a/readthedocs/projects/tests/test_build_tasks.py +++ b/readthedocs/projects/tests/test_build_tasks.py @@ -301,6 +301,11 @@ def test_get_env_vars(self, load_yaml_config, build_environment, config, externa # Local and Circle are different values. # We only check it's present, but not its value. READTHEDOCS_VIRTUALENV_PATH=mock.ANY, + READTHEDOCS_CANONICAL_URL=self.project.get_docs_url( + lang_slug=self.project.language, + version_slug=self.version.slug, + external=external, + ), ) if not external: expected_build_env_vars["PRIVATE_TOKEN"] = "a1b2c3" diff --git a/readthedocs/rtd_tests/tests/test_api.py b/readthedocs/rtd_tests/tests/test_api.py index 0063f76ab40..78cbc24983d 100644 --- a/readthedocs/rtd_tests/tests/test_api.py +++ b/readthedocs/rtd_tests/tests/test_api.py @@ -2442,6 +2442,7 @@ def test_get_version_by_id(self): "built": False, "id": 18, "active": True, + "canonical_url": "http://readthedocs.org/docs/pip/en/0.8/", "project": { "analytics_code": None, "analytics_disabled": False,