Commit d1c6ea97 authored by Benjamin Schubert's avatar Benjamin Schubert Committed by Benjamin Schubert
Browse files

Don't cache sandbox errors

Sandbox errors (like missing host tools) are dependent on the host
system and rarely on what is actually done.

It is therefore better to not cache them as they are subject to
change between two runs.

Also add test to ensure sandbox failure are not cached
parent d153453c
Loading
Loading
Loading
Loading
Loading
+103 −89
Original line number Diff line number Diff line
@@ -85,7 +85,8 @@ import shutil
from . import _yaml
from ._variables import Variables
from ._versions import BST_CORE_ARTIFACT_VERSION
from ._exceptions import BstError, LoadError, LoadErrorReason, ImplError, ErrorDomain
from ._exceptions import BstError, LoadError, LoadErrorReason, ImplError, \
    ErrorDomain, SandboxError
from .utils import UtilError
from . import Plugin, Consistency, Scope
from . import SandboxFlags
@@ -1554,6 +1555,8 @@ class Element(Plugin):

                # Call the abstract plugin methods
                collect = None
                save_artifacts = True

                try:
                    # Step 1 - Configure
                    self.configure_sandbox(sandbox)
@@ -1565,6 +1568,9 @@ class Element(Plugin):
                    collect = self.assemble(sandbox)  # pylint: disable=assignment-from-no-return
                    self.__set_build_result(success=True, description="succeeded")
                except BstError as e:
                    if isinstance(e, SandboxError):
                        save_artifacts = False

                    # Shelling into a sandbox is useful to debug this error
                    e.sandbox = True

@@ -1592,6 +1598,17 @@ class Element(Plugin):
                    self.__set_build_result(success=False, description=str(e), detail=e.detail)
                    raise
                finally:
                    if save_artifacts:
                        artifact_size = self._cache_artifact(rootdir, sandbox, context, collect)
                    else:
                        artifact_size = None

                    # Finally cleanup the build dir
                    cleanup_rootdir()

        return artifact_size

    def _cache_artifact(self, rootdir, sandbox, context, collect):
        if collect is not None:
            try:
                sandbox_vroot = sandbox.get_virtual_directory()
@@ -1681,9 +1698,6 @@ class Element(Plugin):
                "unable to collect artifact contents"
                .format(collect))

                    # Finally cleanup the build dir
                    cleanup_rootdir()

        return artifact_size

    def _get_build_log(self):
+39 −0
Original line number Diff line number Diff line
@@ -4,6 +4,8 @@ import pytest
from buildstream import _yaml
from buildstream._exceptions import ErrorDomain

from conftest import clean_platform_cache

from tests.testutils import cli_integration as cli, create_artifact_share
from tests.testutils.site import IS_LINUX

@@ -158,3 +160,40 @@ def test_push_cached_fail(cli, tmpdir, datafiles, on_error):
        assert cli.get_element_state(project, 'element.bst') == 'failed'
        # This element should have been pushed to the remote
        assert share.has_artifact('test', 'element.bst', cli.get_element_key(project, 'element.bst'))


@pytest.mark.skipif(not IS_LINUX, reason='Only available on linux')
@pytest.mark.datafiles(DATA_DIR)
def test_host_tools_errors_are_not_cached(cli, tmpdir, datafiles):
    project = os.path.join(datafiles.dirname, datafiles.basename)
    element_path = os.path.join(project, 'elements', 'element.bst')

    # Write out our test target
    element = {
        'kind': 'script',
        'depends': [
            {
                'filename': 'base.bst',
                'type': 'build',
            },
        ],
        'config': {
            'commands': [
                'true',
            ],
        },
    }
    _yaml.dump(element, element_path)

    # Build without access to host tools, this will fail
    result1 = cli.run(project=project, args=['build', 'element.bst'], env={'PATH': ''})
    result1.assert_task_error(ErrorDomain.SANDBOX, 'unavailable-local-sandbox')
    assert cli.get_element_state(project, 'element.bst') == 'buildable'

    # clean the cache before running again
    clean_platform_cache()

    # When rebuilding, this should work
    result2 = cli.run(project=project, args=['build', 'element.bst'])
    result2.assert_success()
    assert cli.get_element_state(project, 'element.bst') == 'cached'