Skip to content

Commit 3e3f68d

Browse files
committed
Merge branch 'add-docker-image-option'
2 parents 1a4bba1 + b36cc99 commit 3e3f68d

File tree

7 files changed

+87
-56
lines changed

7 files changed

+87
-56
lines changed

docs/yaml-config.rst

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,40 @@ The file option specified the Conda `environment file`_ to use.
6969
7070
.. note:: Conda is only supported via the YAML file.
7171

72+
73+
build
74+
~~~~~
75+
76+
The ``build`` block configures specific aspects of the documentation build.
77+
78+
.. _yaml_build_image:
79+
80+
build.image
81+
```````````
82+
83+
84+
* Default: :djangosetting:`DOCKER_IMAGE`
85+
* Options: ``1.0``, ``2.0``, ``latest``
86+
87+
The build image to use for specific builds.
88+
This lets users specify a more experimental build image,
89+
if they want to be on the cutting edge.
90+
91+
Certain Python versions require a certain build image,
92+
as defined here::
93+
94+
* `'1.0': 2, 2.7, 3, 3.4`
95+
* `'2.0': 2, 2.7, 3, 3.5`
96+
* `'latest': 2, 2.7, 3, 3.3, 3.4, 3.5, 3.6`
97+
98+
.. code-block:: yaml
99+
100+
build:
101+
image: latest
102+
103+
python:
104+
version: 3.6
105+
72106
python
73107
~~~~~~
74108

@@ -85,15 +119,12 @@ This is the version of Python to use when building your documentation. If you
85119
specify only the major version of Python, the highest supported minor version
86120
will be selected.
87121

88-
The supported Python versions depends on the version of the build image your
89-
project is using. The default build image that is used to build documentation
90-
contains support for Python ``2.7`` and ``3.5``.
91-
92-
There is also an image in testing that supports Python versions ``2.7``,
93-
``3.3``, ``3.4``, ``3.5``, and ``3.6``. If you would like access to this build
94-
image, you can sign up for beta access here:
122+
.. warning::
95123

96-
https://goo.gl/forms/AKEoeWHixlzVfqKT2
124+
The supported Python versions depends on the version of the build image your
125+
project is using. The default build image that is used to build documentation
126+
contains support for Python ``2.7`` and ``3.5``.
127+
See the :ref:`yaml_build_image` for more information on supported Python versions.
97128

98129
.. code-block:: yaml
99130

readthedocs/doc_builder/config.py

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from readthedocs_build.config import load as load_config
99
from readthedocs_build.config import BuildConfig, ConfigError, InvalidConfig
1010

11-
from .constants import DOCKER_BUILD_IMAGES, DOCKER_IMAGE
11+
from .constants import DOCKER_IMAGE_SETTINGS, DOCKER_IMAGE
1212

1313

1414
class ConfigWrapper(object):
@@ -113,6 +113,13 @@ def formats(self):
113113
formats += ['pdf']
114114
return formats
115115

116+
@property
117+
def build_image(self):
118+
if self._project.container_image:
119+
# Allow us to override per-project still
120+
return self._project.container_image
121+
return self._yaml_config['build']['image']
122+
116123
# Not implemented until we figure out how to keep in sync with the webs.
117124
# Probably needs to be version-specific as well, not project.
118125
# @property
@@ -131,19 +138,21 @@ def load_yaml_config(version):
131138
parsing consistent between projects.
132139
"""
133140
checkout_path = version.project.checkout_path(version.slug)
134-
env_config = {}
135141

136142
# Get build image to set up the python version validation. Pass in the
137143
# build image python limitations to the loaded config so that the versions
138144
# can be rejected at validation
139-
build_image = DOCKER_BUILD_IMAGES.get(
140-
version.project.container_image,
141-
DOCKER_BUILD_IMAGES.get(DOCKER_IMAGE, None),
142-
)
143-
if build_image:
144-
env_config = {
145-
'python': build_image['python'],
145+
146+
img_name = version.project.container_image or DOCKER_IMAGE
147+
env_config = {
148+
'build': {
149+
'image': img_name,
146150
}
151+
}
152+
img_settings = DOCKER_IMAGE_SETTINGS.get(img_name, None)
153+
if img_settings:
154+
env_config.update(img_settings)
155+
env_config['DOCKER_IMAGE_SETTINGS'] = img_settings
147156

148157
try:
149158
sphinx_env_config = env_config.copy()

readthedocs/doc_builder/constants.py

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@
44
from __future__ import (
55
absolute_import, division, print_function, unicode_literals)
66

7+
import logging
78
import os
89
import re
910

1011
from django.conf import settings
1112

13+
log = logging.getLogger(__name__)
14+
1215
SPHINX_TEMPLATE_DIR = os.path.join(
1316
settings.SITE_ROOT,
1417
'readthedocs',
@@ -33,24 +36,17 @@
3336
)
3437
DOCKER_VERSION = getattr(settings, 'DOCKER_VERSION', 'auto')
3538
DOCKER_IMAGE = getattr(settings, 'DOCKER_IMAGE', 'readthedocs/build:2.0')
39+
DOCKER_IMAGE_SETTINGS = getattr(settings, 'DOCKER_IMAGE_SETTINGS', {})
40+
41+
old_config = getattr(settings, 'DOCKER_BUILD_IMAGES', None)
42+
if old_config:
43+
log.warning('Old config detected, DOCKER_BUILD_IMAGES->DOCKER_IMAGE_SETTINGS')
44+
DOCKER_IMAGE_SETTINGS.update(old_config)
45+
3646
DOCKER_LIMITS = {'memory': '200m', 'time': 600}
3747
DOCKER_LIMITS.update(getattr(settings, 'DOCKER_LIMITS', {}))
3848

3949
DOCKER_TIMEOUT_EXIT_CODE = 42
4050
DOCKER_OOM_EXIT_CODE = 137
4151

4252
DOCKER_HOSTNAME_MAX_LEN = 64
43-
44-
# Build images
45-
DOCKER_BUILD_IMAGES = {
46-
'readthedocs/build:1.0': {
47-
'python': {'supported_versions': [2, 2.7, 3, 3.4]},
48-
},
49-
'readthedocs/build:2.0': {
50-
'python': {'supported_versions': [2, 2.7, 3, 3.5]},
51-
},
52-
'readthedocs/build:latest': {
53-
'python': {'supported_versions': [2, 2.7, 3, 3.3, 3.4, 3.5, 3.6]},
54-
},
55-
}
56-
DOCKER_BUILD_IMAGES.update(getattr(settings, 'DOCKER_BUILD_IMAGES', {}))

readthedocs/doc_builder/environments.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,11 +300,12 @@ class BuildEnvironment(object):
300300
successful
301301
"""
302302

303-
def __init__(self, project=None, version=None, build=None, record=True,
304-
environment=None, update_on_success=True):
303+
def __init__(self, project=None, version=None, build=None, config=None,
304+
record=True, environment=None, update_on_success=True):
305305
self.project = project
306306
self.version = version
307307
self.build = build
308+
self.config = config
308309
self.record = record
309310
self.environment = environment or {}
310311
self.update_on_success = update_on_success
@@ -535,6 +536,8 @@ def __init__(self, *args, **kwargs):
535536
project_name=self.project.slug,
536537
)[:DOCKER_HOSTNAME_MAX_LEN]
537538
)
539+
if self.config and self.config.build_image:
540+
self.container_image = self.config.build_image
538541
if self.project.container_mem_limit:
539542
self.container_mem_limit = self.project.container_mem_limit
540543
if self.project.container_time_limit:

readthedocs/projects/tasks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ def run_build(self, docker=False, record=True):
250250
env_cls = DockerEnvironment
251251
else:
252252
env_cls = LocalEnvironment
253-
self.build_env = env_cls(project=self.project, version=self.version,
253+
self.build_env = env_cls(project=self.project, version=self.version, config=self.config,
254254
build=self.build, record=record, environment=env_vars)
255255

256256
# Environment used for building code, usually with Docker

readthedocs/rtd_tests/tests/test_config_wrapper.py

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -54,45 +54,37 @@ def test_python_supported_versions_default_image_1_0(self, load_config):
5454
self.assertEqual(load_config.call_count, 1)
5555
load_config.assert_has_calls([
5656
mock.call(path=mock.ANY, env_config={
57-
'python': {'supported_versions': [2, 2.7, 3, 3.4]},
57+
'build': {'image': 'readthedocs/build:1.0'},
5858
'type': 'sphinx',
5959
'output_base': '',
6060
'name': mock.ANY
6161
}),
6262
])
6363
self.assertEqual(config.python_version, 2)
6464

65+
def test_python_supported_versions_image_1_0(self, load_config):
66+
load_config.side_effect = create_load()
67+
self.project.container_image = 'readthedocs/build:1.0'
68+
self.project.save()
69+
config = load_yaml_config(self.version)
70+
self.assertEqual(config._yaml_config.get_valid_python_versions(),
71+
[2, 2.7, 3, 3.4])
72+
6573
def test_python_supported_versions_image_2_0(self, load_config):
6674
load_config.side_effect = create_load()
6775
self.project.container_image = 'readthedocs/build:2.0'
6876
self.project.save()
6977
config = load_yaml_config(self.version)
70-
self.assertEqual(load_config.call_count, 1)
71-
load_config.assert_has_calls([
72-
mock.call(path=mock.ANY, env_config={
73-
'python': {'supported_versions': [2, 2.7, 3, 3.5]},
74-
'type': 'sphinx',
75-
'output_base': '',
76-
'name': mock.ANY
77-
}),
78-
])
79-
self.assertEqual(config.python_version, 2)
78+
self.assertEqual(config._yaml_config.get_valid_python_versions(),
79+
[2, 2.7, 3, 3.5])
8080

8181
def test_python_supported_versions_image_latest(self, load_config):
8282
load_config.side_effect = create_load()
8383
self.project.container_image = 'readthedocs/build:latest'
8484
self.project.save()
8585
config = load_yaml_config(self.version)
86-
self.assertEqual(load_config.call_count, 1)
87-
load_config.assert_has_calls([
88-
mock.call(path=mock.ANY, env_config={
89-
'python': {'supported_versions': [2, 2.7, 3, 3.3, 3.4, 3.5, 3.6]},
90-
'type': 'sphinx',
91-
'output_base': '',
92-
'name': mock.ANY
93-
}),
94-
])
95-
self.assertEqual(config.python_version, 2)
86+
self.assertEqual(config._yaml_config.get_valid_python_versions(),
87+
[2, 2.7, 3, 3.3, 3.4, 3.5, 3.6])
9688

9789
def test_python_default_version(self, load_config):
9890
load_config.side_effect = create_load()

requirements/pip.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ mkdocs==0.14.0
1010
django==1.9.12
1111
six==1.10.0
1212
future==0.16.0
13-
readthedocs-build==2.0.7
13+
readthedocs-build==2.0.8
1414

1515
django-tastypie==0.13.0
1616
django-haystack==2.6.0

0 commit comments

Comments
 (0)