diff --git a/readthedocs/builds/constants.py b/readthedocs/builds/constants.py index 7fd6ce3e5f1..ae0f52fa2a8 100644 --- a/readthedocs/builds/constants.py +++ b/readthedocs/builds/constants.py @@ -5,16 +5,22 @@ BUILD_STATE_TRIGGERED = 'triggered' +BUILD_STATE_PULLING_CACHE = 'pulling-cache' BUILD_STATE_CLONING = 'cloning' BUILD_STATE_INSTALLING = 'installing' BUILD_STATE_BUILDING = 'building' +BUILD_STATE_UPLOADING = 'uploading' +BUILD_STATE_PUSHING_CACHE = 'pushing-cache' BUILD_STATE_FINISHED = 'finished' BUILD_STATE = ( (BUILD_STATE_TRIGGERED, _('Triggered')), + (BUILD_STATE_PULLING_CACHE, _('Pulling cache')), (BUILD_STATE_CLONING, _('Cloning')), (BUILD_STATE_INSTALLING, _('Installing')), (BUILD_STATE_BUILDING, _('Building')), + (BUILD_STATE_UPLOADING, _('Uploading')), + (BUILD_STATE_PUSHING_CACHE, _('Pushing cache')), (BUILD_STATE_FINISHED, _('Finished')), ) 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..46d15cab579 --- /dev/null +++ b/readthedocs/builds/migrations/0015_pulling_cache_build_state.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.11 on 2020-03-24 15:59 + +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'), ('pushing-cache', 'Pushing cache'), ('finished', 'Finished')], default='finished', max_length=55, verbose_name='State'), + ), + ] diff --git a/readthedocs/doc_builder/environments.py b/readthedocs/doc_builder/environments.py index 6f70d51a232..2bff2625b38 100644 --- a/readthedocs/doc_builder/environments.py +++ b/readthedocs/doc_builder/environments.py @@ -662,7 +662,7 @@ def done(self): self.build['state'] == BUILD_STATE_FINISHED ) - def update_build(self, state=None): + def update_build(self, state=None, force=False): """ Record a build by hitting the API. @@ -747,6 +747,8 @@ def update_build(self, state=None): or (self.done and not self.successful) # Otherwise, are we explicitly to not update? or self.update_on_success + # Explicit force the update + or force ) if update_build: try: diff --git a/readthedocs/projects/tasks.py b/readthedocs/projects/tasks.py index e1636a58897..9f5bad52388 100644 --- a/readthedocs/projects/tasks.py +++ b/readthedocs/projects/tasks.py @@ -33,6 +33,9 @@ BUILD_STATE_CLONING, BUILD_STATE_FINISHED, BUILD_STATE_INSTALLING, + BUILD_STATE_PULLING_CACHE, + BUILD_STATE_PUSHING_CACHE, + BUILD_STATE_UPLOADING, BUILD_STATUS_SUCCESS, BUILD_STATUS_FAILURE, LATEST, @@ -93,10 +96,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() @@ -123,10 +128,12 @@ def pull_cached_environment(self): with tarfile.open(fileobj=remote_fd) as tar: tar.extractall(self.project.doc_path) - def push_cached_environment(self): + def push_cached_environment(self, environment): if not self.project.has_feature(feature_id=Feature.CACHED_ENVIRONMENT): return + environment.update_build(state=BUILD_STATE_PUSHING_CACHE) + project_path = self.project.doc_path directories = [ 'checkouts', @@ -362,7 +369,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: @@ -586,7 +593,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) @@ -662,6 +669,7 @@ def run_build(self, record): build=self.build, record=record, environment=env_vars, + update_on_success=False, # Pass ``start_time`` here to not reset the timer start_time=self.build_start_time, @@ -712,6 +720,7 @@ def run_build(self, record): localmedia=bool(outcomes['localmedia']), pdf=bool(outcomes['pdf']), epub=bool(outcomes['epub']), + environment=self.build_env, ) # Finalize build and update web servers @@ -745,7 +754,7 @@ def run_build(self, record): self.send_notifications(self.version.pk, self.build['id'], email=False) # Push cached environment on success for next build - self.push_cached_environment() + self.push_cached_environment(self.build_env) if self.commit: send_external_build_status( @@ -772,6 +781,7 @@ def run_build(self, record): } ) + self.build_env.update_build(BUILD_STATE_FINISHED, force=True) build_complete.send(sender=Build, build=self.build_env.build) @staticmethod @@ -949,6 +959,7 @@ def store_build_artifacts( ) return + environment.update_build(BUILD_STATE_UPLOADING) storage = get_storage_class(settings.RTD_BUILD_MEDIA_STORAGE)() log.info( LOG_TEMPLATE,