diff --git a/readthedocs/builds/constants.py b/readthedocs/builds/constants.py index 7fd6ce3e5f1..14c0b6dd7b9 100644 --- a/readthedocs/builds/constants.py +++ b/readthedocs/builds/constants.py @@ -5,6 +5,7 @@ BUILD_STATE_TRIGGERED = 'triggered' +BUILD_STATE_PULLING_CACHE = 'pulling-cache' BUILD_STATE_CLONING = 'cloning' BUILD_STATE_INSTALLING = 'installing' BUILD_STATE_BUILDING = 'building' @@ -12,6 +13,7 @@ BUILD_STATE = ( (BUILD_STATE_TRIGGERED, _('Triggered')), + (BUILD_STATE_PULLING_CACHE, _('Pulling cache')), (BUILD_STATE_CLONING, _('Cloning')), (BUILD_STATE_INSTALLING, _('Installing')), (BUILD_STATE_BUILDING, _('Building')), diff --git a/readthedocs/builds/migrations/0015_pulling_cache_build_state.py b/readthedocs/builds/migrations/0015_pulling_cache_build_state.py new file mode 100644 index 00000000000..63e2779934b --- /dev/null +++ b/readthedocs/builds/migrations/0015_pulling_cache_build_state.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.10 on 2020-03-19 03:38 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('builds', '0014_migrate-doctype-from-project-to-version'), + ] + + operations = [ + migrations.AlterField( + model_name='build', + name='state', + field=models.CharField(choices=[('triggered', 'Triggered'), ('pulling-cache', 'Pulling cache'), ('cloning', 'Cloning'), ('installing', 'Installing'), ('building', 'Building'), ('finished', 'Finished')], default='finished', max_length=55, verbose_name='State'), + ), + ] diff --git a/readthedocs/projects/tasks.py b/readthedocs/projects/tasks.py index 2529e5bf82b..447ddc9b70f 100644 --- a/readthedocs/projects/tasks.py +++ b/readthedocs/projects/tasks.py @@ -33,6 +33,7 @@ BUILD_STATE_CLONING, BUILD_STATE_FINISHED, BUILD_STATE_INSTALLING, + BUILD_STATE_PULLING_CACHE, BUILD_STATUS_SUCCESS, BUILD_STATUS_FAILURE, LATEST, @@ -93,10 +94,12 @@ class CachedEnvironmentMixin: """Mixin that pull/push cached environment to storage.""" - def pull_cached_environment(self): + def pull_cached_environment(self, environment): if not self.project.has_feature(feature_id=Feature.CACHED_ENVIRONMENT): return + environment.update_build(state=BUILD_STATE_PULLING_CACHE) + storage = get_storage_class(settings.RTD_BUILD_ENVIRONMENT_STORAGE)() filename = self.version.get_storage_environment_cache_path() @@ -119,17 +122,9 @@ def pull_cached_environment(self): 'msg': msg, } ) - _, tmp_filename = tempfile.mkstemp(suffix='.tar') remote_fd = storage.open(filename, mode='rb') - with open(tmp_filename, mode='wb') as local_fd: - local_fd.write(remote_fd.read()) - - with tarfile.open(tmp_filename) as tar: - tar.extractall(self.version.project.doc_path) - - # Cleanup the temporary file - if os.path.exists(tmp_filename): - os.remove(tmp_filename) + with tarfile.open(fileobj=remote_fd) as tar: + tar.extracall(self.project.doc_path) def push_cached_environment(self): if not self.project.has_feature(feature_id=Feature.CACHED_ENVIRONMENT): @@ -369,7 +364,7 @@ def run(self, version_pk): # pylint: disable=arguments-differ # repository in this step, and pushing it back will delete # all the other cached things (Python packages, Sphinx, # virtualenv, etc) - self.pull_cached_environment() + self.pull_cached_environment(environment) self.sync_repo(environment) return True except RepositoryError: @@ -591,7 +586,7 @@ def run_setup(self, record=True): raise ProjectBuildsSkippedError try: with self.project.repo_nonblockinglock(version=self.version): - self.pull_cached_environment() + self.pull_cached_environment(environment) self.setup_vcs(environment) except vcs_support_utils.LockTimeout as e: self.task.retry(exc=e, throw=False)