Skip to content

Commit 04fd0c2

Browse files
authored
Merge pull request #5155 from rtfd/humitos/latest-docker-images
Use latest docker images as default
2 parents 61961b5 + a7770c0 commit 04fd0c2

File tree

4 files changed

+67
-30
lines changed

4 files changed

+67
-30
lines changed

readthedocs/config/config.py

+50-16
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import copy
66
import os
7+
import re
78
from contextlib import contextmanager
89

910
from django.conf import settings
@@ -146,6 +147,8 @@ class BuildConfigBase:
146147
'mkdocs',
147148
'submodules',
148149
]
150+
151+
default_build_image = DOCKER_DEFAULT_VERSION
149152
version = None
150153

151154
def __init__(self, env_config, raw_config, source_file):
@@ -246,6 +249,40 @@ def python_full_version(self):
246249
)
247250
return ver
248251

252+
@property
253+
def valid_build_images(self):
254+
"""
255+
Return all the valid Docker image choices for ``build.image`` option.
256+
257+
The user can use any of this values in the YAML file. These values are
258+
the keys of ``DOCKER_IMAGE_SETTINGS`` Django setting (without the
259+
``readthedocs/build`` part) plus ``stable`` and ``latest``.
260+
"""
261+
images = {'stable', 'latest'}
262+
for k in DOCKER_IMAGE_SETTINGS:
263+
_, version = k.split(':')
264+
if re.fullmatch(r'^[\d\.]+$', version):
265+
images.add(version)
266+
return images
267+
268+
def get_valid_python_versions_for_image(self, build_image):
269+
"""
270+
Return all the valid Python versions for a Docker image.
271+
272+
The Docker image (``build_image``) has to be its complete name, already
273+
validated: ``readthedocs/build:4.0``, not just ``4.0``.
274+
275+
Returns supported versions for the ``DOCKER_DEFAULT_VERSION`` if not
276+
``build_image`` found.
277+
"""
278+
279+
if build_image not in DOCKER_IMAGE_SETTINGS:
280+
build_image = '{}:{}'.format(
281+
DOCKER_DEFAULT_IMAGE,
282+
self.default_build_image,
283+
)
284+
return DOCKER_IMAGE_SETTINGS[build_image]['python']['supported_versions']
285+
249286
def as_dict(self):
250287
config = {}
251288
for name in self.PUBLIC_ATTRIBUTES:
@@ -268,18 +305,23 @@ class BuildConfigV1(BuildConfigBase):
268305
'"python.extra_requirements" section must be a list.'
269306
)
270307

271-
PYTHON_SUPPORTED_VERSIONS = [2, 2.7, 3, 3.5]
272-
DOCKER_SUPPORTED_VERSIONS = ['1.0', '2.0', 'latest']
273-
274308
version = '1'
275309

276310
def get_valid_python_versions(self):
277-
"""Get all valid python versions."""
311+
"""
312+
Return all valid Python versions.
313+
314+
.. note::
315+
316+
It does not take current build image used into account.
317+
"""
278318
try:
279319
return self.env_config['python']['supported_versions']
280320
except (KeyError, TypeError):
281-
pass
282-
return self.PYTHON_SUPPORTED_VERSIONS
321+
versions = set()
322+
for _, options in DOCKER_IMAGE_SETTINGS.items():
323+
versions = versions.union(options['python']['supported_versions'])
324+
return versions
283325

284326
def get_valid_formats(self): # noqa
285327
"""Get all valid documentation formats."""
@@ -339,7 +381,7 @@ def validate_build(self):
339381
with self.catch_validation_error('build'):
340382
build['image'] = validate_choice(
341383
str(_build['image']),
342-
self.DOCKER_SUPPORTED_VERSIONS,
384+
self.valid_build_images,
343385
)
344386
if ':' not in build['image']:
345387
# Prepend proper image name to user's image name
@@ -577,8 +619,6 @@ class BuildConfigV2(BuildConfigBase):
577619

578620
version = '2'
579621
valid_formats = ['htmlzip', 'pdf', 'epub']
580-
valid_build_images = ['1.0', '2.0', '3.0', 'stable', 'latest']
581-
default_build_image = 'latest'
582622
valid_install_method = [PIP, SETUPTOOLS]
583623
valid_sphinx_builders = {
584624
'html': 'sphinx',
@@ -793,13 +833,7 @@ def get_valid_python_versions(self):
793833
This should be called after ``validate_build()``.
794834
"""
795835
build_image = self.build.image
796-
if build_image not in DOCKER_IMAGE_SETTINGS:
797-
build_image = '{}:{}'.format(
798-
DOCKER_DEFAULT_IMAGE,
799-
self.default_build_image,
800-
)
801-
python = DOCKER_IMAGE_SETTINGS[build_image]['python']
802-
return python['supported_versions']
836+
return self.get_valid_python_versions_for_image(build_image)
803837

804838
def validate_doc_types(self):
805839
"""

readthedocs/config/tests/test_config.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -363,8 +363,8 @@ def test_it_validates_wrong_type_right_value(self):
363363
)
364364
build.validate()
365365
assert build.python.version == 3
366-
assert build.python_interpreter == 'python3.5'
367-
assert build.python_full_version == 3.5
366+
assert build.python_interpreter == 'python3.7'
367+
assert build.python_full_version == 3.7
368368

369369
def test_it_validates_env_supported_versions(self):
370370
build = get_build_config(
@@ -483,7 +483,7 @@ def test_it_fails_if_build_is_invalid_option(self, tmpdir):
483483
apply_fs(tmpdir, yaml_config_dir)
484484
build = BuildConfigV1(
485485
{},
486-
{'build': {'image': 3.0}},
486+
{'build': {'image': 3.2}},
487487
source_file=str(tmpdir.join('readthedocs.yml')),
488488
)
489489
with raises(InvalidConfig) as excinfo:
@@ -513,7 +513,7 @@ def test_it_works_on_python_validation(self, tmpdir):
513513
{},
514514
{
515515
'build': {'image': 'latest'},
516-
'python': {'version': '3.3'},
516+
'python': {'version': '3.6'},
517517
},
518518
source_file=str(tmpdir.join('readthedocs.yml')),
519519
)
@@ -538,7 +538,7 @@ def test_default(self, tmpdir):
538538
source_file=str(tmpdir.join('readthedocs.yml')),
539539
)
540540
build.validate()
541-
assert build.build.image == 'readthedocs/build:2.0'
541+
assert build.build.image == 'readthedocs/build:latest'
542542

543543
@pytest.mark.parametrize(
544544
'image', ['latest', 'readthedocs/build:3.0', 'rtd/build:latest'],
@@ -712,7 +712,7 @@ def test_as_dict(tmpdir):
712712
'use_system_site_packages': False,
713713
},
714714
'build': {
715-
'image': 'readthedocs/build:2.0',
715+
'image': 'readthedocs/build:latest',
716716
},
717717
'conda': None,
718718
'sphinx': {

readthedocs/rtd_tests/tests/test_config_integration.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ def test_python_supported_versions_image_latest(self, load_config):
145145
config = load_yaml_config(self.version)
146146
self.assertEqual(
147147
config.get_valid_python_versions(),
148-
[2, 2.7, 3, 3.3, 3.4, 3.5, 3.6],
148+
[2, 2.7, 3, 3.5, 3.6, 3.7],
149149
)
150150

151151
@mock.patch('readthedocs.doc_builder.config.load_config')
@@ -507,7 +507,7 @@ def test_python_version(self, checkout_path, tmpdir):
507507

508508
config = self.get_update_docs_task().config
509509
assert config.python.version == 3
510-
assert config.python_full_version == 3.6
510+
assert config.python_full_version == 3.7
511511

512512
@patch('readthedocs.doc_builder.environments.BuildEnvironment.run')
513513
def test_python_install_requirements(self, run, checkout_path, tmpdir):

readthedocs/settings/base.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ def USE_PROMOS(self): # noqa
274274
# Docker
275275
DOCKER_ENABLE = False
276276
DOCKER_DEFAULT_IMAGE = 'readthedocs/build'
277-
DOCKER_DEFAULT_VERSION = '2.0'
277+
DOCKER_DEFAULT_VERSION = 'latest'
278278
DOCKER_IMAGE = '{}:{}'.format(DOCKER_DEFAULT_IMAGE, DOCKER_DEFAULT_VERSION)
279279
DOCKER_IMAGE_SETTINGS = {
280280
'readthedocs/build:1.0': {
@@ -286,14 +286,17 @@ def USE_PROMOS(self): # noqa
286286
'readthedocs/build:3.0': {
287287
'python': {'supported_versions': [2, 2.7, 3, 3.3, 3.4, 3.5, 3.6]},
288288
},
289-
'readthedocs/build:stable': {
290-
'python': {'supported_versions': [2, 2.7, 3, 3.3, 3.4, 3.5, 3.6]},
291-
},
292-
'readthedocs/build:latest': {
293-
'python': {'supported_versions': [2, 2.7, 3, 3.3, 3.4, 3.5, 3.6]},
289+
'readthedocs/build:4.0': {
290+
'python': {'supported_versions': [2, 2.7, 3, 3.5, 3.6, 3.7]},
294291
},
295292
}
296293

294+
# Alias tagged via ``docker tag`` on the build servers
295+
DOCKER_IMAGE_SETTINGS.update({
296+
'readthedocs/build:stable': DOCKER_IMAGE_SETTINGS.get('readthedocs/build:3.0'),
297+
'readthedocs/build:latest': DOCKER_IMAGE_SETTINGS.get('readthedocs/build:4.0'),
298+
})
299+
297300
# All auth
298301
ACCOUNT_ADAPTER = 'readthedocs.core.adapters.AccountAdapter'
299302
ACCOUNT_EMAIL_REQUIRED = True

0 commit comments

Comments
 (0)