summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbst-marge-bot <marge-bot@buildstream.build>2019-05-06 12:39:37 +0000
committerbst-marge-bot <marge-bot@buildstream.build>2019-05-06 12:39:37 +0000
commit879dca35de4c09a3c05f671ba8cca1aeeb958996 (patch)
treece91b9b748eb45152ed994cc7e27a96f893c6db4
parentcae0f60cfdc1c1c4a69d2b3ea133840c2c5a4d78 (diff)
parent5ecd534cc795d596402ed0e14dde3a7a7ae1d789 (diff)
downloadbuildstream-879dca35de4c09a3c05f671ba8cca1aeeb958996.tar.gz
Merge branch 'tristan/fix-missing-workspace-artifact-1.2' into 'bst-1.2'
element.py: Reset workspace state if last successful build is missing (1.2) See merge request BuildStream/buildstream!1329
-rw-r--r--buildstream/element.py21
-rw-r--r--tests/integration/workspace.py33
-rw-r--r--tests/testutils/runcli.py4
3 files changed, 54 insertions, 4 deletions
diff --git a/buildstream/element.py b/buildstream/element.py
index 898ff0784..b98675720 100644
--- a/buildstream/element.py
+++ b/buildstream/element.py
@@ -699,9 +699,26 @@ class Element(Plugin):
old_dep_keys = {}
workspace = self._get_workspace()
project = self._get_project()
+ context = self._get_context()
if self.__can_build_incrementally() and workspace.last_successful:
- old_dep_keys = self.__get_artifact_metadata_dependencies(workspace.last_successful)
+
+ # Try to perform an incremental build if the last successful
+ # build is still in the artifact cache
+ #
+ if self.__artifacts.contains(self, workspace.last_successful):
+ old_dep_keys = self.__get_artifact_metadata_dependencies(workspace.last_successful)
+ else:
+ # Last successful build is no longer in the artifact cache,
+ # so let's reset it and perform a full build now.
+ workspace.prepared = False
+ workspace.last_successful = None
+
+ self.info("Resetting workspace state, last successful build is no longer in the cache")
+
+ # In case we are staging in the main process
+ if utils._is_main_process():
+ context.get_workspaces().save_config()
for dep in self.dependencies(scope):
# If we are workspaced, and we therefore perform an
@@ -726,7 +743,7 @@ class Element(Plugin):
# In case we are running `bst shell`, this happens in the
# main process and we need to update the workspace config
if utils._is_main_process():
- self._get_context().get_workspaces().save_config()
+ context.get_workspaces().save_config()
result = dep.stage_artifact(sandbox,
path=path,
diff --git a/tests/integration/workspace.py b/tests/integration/workspace.py
index 102d053fc..e30d54df3 100644
--- a/tests/integration/workspace.py
+++ b/tests/integration/workspace.py
@@ -255,3 +255,36 @@ def test_incremental_configure_commands_run_only_once(cli, tmpdir, datafiles):
res = cli.run(project=project, args=['build', element_name])
res.assert_success()
assert not os.path.exists(os.path.join(workspace, 'prepared-again'))
+
+
+# Test that rebuilding an already built workspaced element does
+# not crash after the last successfully built artifact is removed
+# from the cache
+#
+# A user can remove their artifact cache, or manually remove the
+# artifact with `bst artifact delete`, or BuildStream can delete
+# the last successfully built artifact for this workspace as a
+# part of a cleanup job.
+#
+@pytest.mark.integration
+@pytest.mark.datafiles(DATA_DIR)
+def test_workspace_missing_last_successful(cli, datafiles, integration_cache):
+ project = str(datafiles)
+ workspace = os.path.join(cli.directory, 'workspace')
+ element_name = 'workspace/workspace-mount.bst'
+
+ # Open workspace
+ res = cli.run(project=project, args=['workspace', 'open', element_name, workspace])
+ assert res.exit_code == 0
+
+ # Build first, this will record the last successful build in local state
+ res = cli.run(project=project, args=['build', element_name])
+ assert res.exit_code == 0
+
+ # Remove the artifact from the cache, invalidating the last successful build
+ cache_dir = os.path.join(integration_cache, 'artifacts')
+ cli.remove_artifact_from_cache(project, element_name, cache_dir=cache_dir)
+
+ # Build again, ensure we dont crash just because the artifact went missing
+ res = cli.run(project=project, args=['build', element_name])
+ assert res.exit_code == 0
diff --git a/tests/testutils/runcli.py b/tests/testutils/runcli.py
index 805b1192d..06f3f1c3a 100644
--- a/tests/testutils/runcli.py
+++ b/tests/testutils/runcli.py
@@ -218,8 +218,8 @@ class Cli():
cache_dir = os.path.join(project, 'cache', 'artifacts')
cache_dir = os.path.join(cache_dir, 'cas', 'refs', 'heads')
-
- cache_dir = os.path.splitext(os.path.join(cache_dir, 'test', element_name))[0]
+ normal_name = element_name.replace(os.sep, '-')
+ cache_dir = os.path.splitext(os.path.join(cache_dir, 'test', normal_name))[0]
shutil.rmtree(cache_dir)
# run():