Feature flag to make `readthedocs` theme default on MkDocs docs

Historically, we were using `readthedocs` as default theme for MkDocs
but in https://github.com/rtfd/readthedocs.org/pull/4556 we decided to
change it to get the same behavior when building locally than in Read
the Docs.

This commit adds a Feature flag to keep having the old behavior for
some particular projects so we can add these project and do not break
their documentation (change the theme without asking/reason).
hotfix/featureflag-mkdocs-theme
Manuel Kaufmann 2018-10-24 16:08:45 +02:00 committed by Anthony Johnson
parent b78d1f390c
commit 880a3508ba
No known key found for this signature in database
GPG Key ID: 709FE91423F05AA0
4 changed files with 124 additions and 1 deletions

View File

@ -16,6 +16,7 @@ from django.template import loader as template_loader
from readthedocs.doc_builder.base import BaseBuilder
from readthedocs.doc_builder.exceptions import BuildEnvironmentError
from readthedocs.projects.models import Feature
log = logging.getLogger(__name__)
@ -50,6 +51,23 @@ class BaseMkdocs(BaseBuilder):
self.root_path = self.version.project.checkout_path(self.version.slug)
self.yaml_file = self.get_yaml_config()
# README: historically, the default theme was ``readthedocs`` but in
# https://github.com/rtfd/readthedocs.org/pull/4556 we change it to
# ``mkdocs`` to maintain the same behavior in Read the Docs than
# building locally. Although, we can't apply the this into the Corporate
# site. To keep the same default theme there, we created a Feature flag
# for these project that were building with MkDocs in the Corporate
# site.
if self.project.has_feature(Feature.MKDOCS_THEME_RTD):
self.DEFAULT_THEME_NAME = 'readthedocs'
log.warning(
'Project using readthedocs theme as default for MkDocs: slug=%s',
self.project.slug,
)
else:
self.DEFAULT_THEME_NAME = 'mkdocs'
def get_yaml_config(self):
"""Find the ``mkdocs.yml`` file in the project root."""
mkdoc_path = self.config.mkdocs.configuration
@ -130,6 +148,13 @@ class BaseMkdocs(BaseBuilder):
# This supports using RTD's privacy improvements around analytics
user_config['google_analytics'] = None
# README: make MkDocs to use ``readthedocs`` theme as default if the
# user didn't specify a specific theme manually
if self.project.has_feature(Feature.MKDOCS_THEME_RTD):
if 'theme' not in user_config:
# mkdocs<0.17 syntax
user_config['theme'] = self.DEFAULT_THEME_NAME
# Write the modified mkdocs configuration
yaml.safe_dump(
user_config,

View File

@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.16 on 2018-10-24 07:43
from __future__ import unicode_literals
from django.db import migrations
FEATURE_ID = 'mkdocs_theme_rtd'
def forward_add_feature(apps, schema_editor):
Feature = apps.get_model('projects', 'Feature')
Feature.objects.create(
feature_id=FEATURE_ID,
# Not using ``default_true=True`` because we will do this manually in
# the database from the Corporate site only, since this is not required
# in the Community site
# default_true=True,
)
def reverse_add_feature(apps, schema_editor):
Feature = apps.get_model('projects', 'Feature')
Feature.objects.filter(feature_id=FEATURE_ID).delete()
class Migration(migrations.Migration):
dependencies = [
('projects', '0027_remove_json_with_html_feature'),
]
operations = [
migrations.RunPython(forward_add_feature, reverse_add_feature),
]

View File

@ -1060,6 +1060,7 @@ class Feature(models.Model):
SKIP_SUBMODULES = 'skip_submodules'
DONT_OVERWRITE_SPHINX_CONTEXT = 'dont_overwrite_sphinx_context'
ALLOW_V2_CONFIG_FILE = 'allow_v2_config_file'
MKDOCS_THEME_RTD = 'mkdocs_theme_rtd'
FEATURES = (
(USE_SPHINX_LATEST, _('Use latest version of Sphinx')),
@ -1071,6 +1072,7 @@ class Feature(models.Model):
'Do not overwrite context vars in conf.py with Read the Docs context',)),
(ALLOW_V2_CONFIG_FILE, _(
'Allow to use the v2 of the configuration file')),
(MKDOCS_THEME_RTD, _('Use Read the Docs theme for MkDocs as default theme')),
)
projects = models.ManyToManyField(

View File

@ -20,7 +20,7 @@ from readthedocs.doc_builder.backends.mkdocs import MkdocsHTML
from readthedocs.doc_builder.backends.sphinx import BaseSphinx
from readthedocs.doc_builder.python_environments import Virtualenv
from readthedocs.projects.exceptions import ProjectConfigurationError
from readthedocs.projects.models import Project
from readthedocs.projects.models import Feature, Project
class SphinxBuilderTest(TestCase):
@ -224,6 +224,67 @@ class MkdocsBuilderTest(TestCase):
}
self.assertEqual(builder.get_theme_name(config), 'mydir')
@patch('readthedocs.doc_builder.base.BaseBuilder.run')
@patch('readthedocs.projects.models.Project.checkout_path')
def test_get_theme_name_with_feature_flag(self, checkout_path, run):
tmpdir = tempfile.mkdtemp()
checkout_path.return_value = tmpdir
Feature.objects.get(
feature_id=Feature.MKDOCS_THEME_RTD,
).projects.add(self.project)
python_env = Virtualenv(
version=self.version,
build_env=self.build_env,
config=None,
)
builder = MkdocsHTML(
build_env=self.build_env,
python_env=python_env,
)
self.assertEqual(builder.get_theme_name({}), 'readthedocs')
with patch('readthedocs.doc_builder.backends.mkdocs.yaml') as mock_yaml:
with patch('readthedocs.doc_builder.backends.mkdocs.MkdocsHTML.load_yaml_config') as mock_load_yaml_config:
mock_load_yaml_config.return_value = {'site_name': self.project.name}
builder.append_conf()
mock_yaml.safe_dump.assert_called_once_with(
{
'site_name': mock.ANY,
'docs_dir': mock.ANY,
'extra_javascript': mock.ANY,
'extra_css': mock.ANY,
'google_analytics': mock.ANY,
'theme': 'readthedocs',
},
mock.ANY,
)
mock_yaml.reset_mock()
config = {
'theme': 'customtheme',
}
self.assertEqual(builder.get_theme_name(config), 'customtheme')
with patch('readthedocs.doc_builder.backends.mkdocs.MkdocsHTML.load_yaml_config') as mock_load_yaml_config:
mock_load_yaml_config.return_value = {
'site_name': self.project.name,
'theme': 'customtheme',
}
builder.append_conf()
mock_yaml.safe_dump.assert_called_once_with(
{
'site_name': mock.ANY,
'docs_dir': mock.ANY,
'extra_javascript': mock.ANY,
'extra_css': mock.ANY,
'google_analytics': mock.ANY,
'theme': 'customtheme',
},
mock.ANY,
)
@patch('readthedocs.doc_builder.base.BaseBuilder.run')
@patch('readthedocs.projects.models.Project.checkout_path')
def test_append_conf_create_yaml(self, checkout_path, run):