[Notes] [Git][BuildStream/buildstream][juerg/remote] 8 commits: element.py: Do not save workspace on failed build



Title: GitLab

Jonathan Maw pushed to branch juerg/remote at BuildStream / buildstream

Commits:

4 changed files:

Changes:

  • buildstream/element.py
    ... ... @@ -212,7 +212,7 @@ class Element(Plugin):
    212 212
             self.__staged_sources_directory = None  # Location where Element.stage_sources() was called
    
    213 213
             self.__tainted = None                   # Whether the artifact is tainted and should not be shared
    
    214 214
             self.__required = False                 # Whether the artifact is required in the current session
    
    215
    -        self.__build_result = None              # The result of assembling this Element
    
    215
    +        self.__build_result = None              # The result of assembling this Element (success, description, detail)
    
    216 216
             self._build_log_path = None            # The path of the build log for this Element
    
    217 217
     
    
    218 218
             # hash tables of loaded artifact metadata, hashed by key
    
    ... ... @@ -1316,7 +1316,8 @@ class Element(Plugin):
    1316 1316
         #
    
    1317 1317
         @contextmanager
    
    1318 1318
         def _prepare_sandbox(self, scope, directory, deps='run', integrate=True):
    
    1319
    -        with self.__sandbox(directory, config=self.__sandbox_config) as sandbox:
    
    1319
    +        # bst shell and bst checkout require a local sandbox.
    
    1320
    +        with self.__sandbox(directory, config=self.__sandbox_config, allow_remote=False) as sandbox:
    
    1320 1321
     
    
    1321 1322
                 # Configure always comes first, and we need it.
    
    1322 1323
                 self.configure_sandbox(sandbox)
    
    ... ... @@ -1479,11 +1480,13 @@ class Element(Plugin):
    1479 1480
     
    
    1480 1481
             self._update_state()
    
    1481 1482
     
    
    1482
    -        if self._get_workspace() and self._cached():
    
    1483
    +        if self._get_workspace() and self._cached_success():
    
    1484
    +            assert utils._is_main_process(), \
    
    1485
    +                "Attempted to save workspace configuration from child process"
    
    1483 1486
                 #
    
    1484 1487
                 # Note that this block can only happen in the
    
    1485
    -            # main process, since `self._cached()` cannot
    
    1486
    -            # be true when assembly is completed in the task.
    
    1488
    +            # main process, since `self._cached_success()` cannot
    
    1489
    +            # be true when assembly is successful in the task.
    
    1487 1490
                 #
    
    1488 1491
                 # For this reason, it is safe to update and
    
    1489 1492
                 # save the workspaces configuration
    
    ... ... @@ -2147,17 +2150,18 @@ class Element(Plugin):
    2147 2150
         #    stdout (fileobject): The stream for stdout for the sandbox
    
    2148 2151
         #    stderr (fileobject): The stream for stderr for the sandbox
    
    2149 2152
         #    config (SandboxConfig): The SandboxConfig object
    
    2153
    +    #    allow_remote (bool): Whether the sandbox is allowed to be remote
    
    2150 2154
         #
    
    2151 2155
         # Yields:
    
    2152 2156
         #    (Sandbox): A usable sandbox
    
    2153 2157
         #
    
    2154 2158
         @contextmanager
    
    2155
    -    def __sandbox(self, directory, stdout=None, stderr=None, config=None):
    
    2159
    +    def __sandbox(self, directory, stdout=None, stderr=None, config=None, allow_remote=True):
    
    2156 2160
             context = self._get_context()
    
    2157 2161
             project = self._get_project()
    
    2158 2162
             platform = Platform.get_platform()
    
    2159 2163
     
    
    2160
    -        if directory is not None and self.__use_remote_execution():
    
    2164
    +        if directory is not None and allow_remote and self.__use_remote_execution():
    
    2161 2165
     
    
    2162 2166
                 self.info("Using a remote sandbox for artifact {} with directory '{}'".format(self.name, directory))
    
    2163 2167
     
    
    ... ... @@ -2171,7 +2175,7 @@ class Element(Plugin):
    2171 2175
                 yield sandbox
    
    2172 2176
     
    
    2173 2177
             elif directory is not None and os.path.exists(directory):
    
    2174
    -            if self.__remote_execution_url:
    
    2178
    +            if allow_remote and self.__remote_execution_url:
    
    2175 2179
                     self.warn("Artifact {} is configured to use remote execution but element plugin does not support it."
    
    2176 2180
                               .format(self.name), detail="Element plugin '{kind}' does not support virtual directories."
    
    2177 2181
                               .format(kind=self.get_kind()), warning_token="remote-failure")
    
    ... ... @@ -2191,7 +2195,8 @@ class Element(Plugin):
    2191 2195
                 rootdir = tempfile.mkdtemp(prefix="{}-".format(self.normal_name), dir=context.builddir)
    
    2192 2196
     
    
    2193 2197
                 # Recursive contextmanager...
    
    2194
    -            with self.__sandbox(rootdir, stdout=stdout, stderr=stderr, config=config) as sandbox:
    
    2198
    +            with self.__sandbox(rootdir, stdout=stdout, stderr=stderr, config=config,
    
    2199
    +                                allow_remote=allow_remote) as sandbox:
    
    2195 2200
                     yield sandbox
    
    2196 2201
     
    
    2197 2202
                 # Cleanup the build dir
    

  • buildstream/utils.py
    ... ... @@ -686,7 +686,7 @@ def _force_rmtree(rootpath, **kwargs):
    686 686
     
    
    687 687
         try:
    
    688 688
             shutil.rmtree(rootpath, **kwargs)
    
    689
    -    except shutil.Error as e:
    
    689
    +    except OSError as e:
    
    690 690
             raise UtilError("Failed to remove cache directory '{}': {}"
    
    691 691
                             .format(rootpath, e))
    
    692 692
     
    

  • contrib/bst-docker-import
    1
    +#!/bin/bash
    
    2
    +#
    
    3
    +#  Copyright 2018 Bloomberg Finance LP
    
    4
    +#
    
    5
    +#  This program is free software; you can redistribute it and/or
    
    6
    +#  modify it under the terms of the GNU Lesser General Public
    
    7
    +#  License as published by the Free Software Foundation; either
    
    8
    +#  version 2 of the License, or (at your option) any later version.
    
    9
    +#
    
    10
    +#  This library is distributed in the hope that it will be useful,
    
    11
    +#  but WITHOUT ANY WARRANTY; without even the implied warranty of
    
    12
    +#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    
    13
    +#  Lesser General Public License for more details.
    
    14
    +#
    
    15
    +#  You should have received a copy of the GNU Lesser General Public
    
    16
    +#  License along with this library. If not, see <http://www.gnu.org/licenses/>.
    
    17
    +#
    
    18
    +#  Authors:
    
    19
    +#        Chadnan Singh <csingh43 bloomberg net>
    
    20
    +
    
    21
    +# This is a helper script to generate Docker images using checkouts of
    
    22
    +# BuildStream elements.
    
    23
    +
    
    24
    +usage() {
    
    25
    +    cat <<EOF
    
    26
    +
    
    27
    +USAGE: $(basename "$0") [-c BST_CMD] [-m MESSAGE] [-t TAG] [-h] ELEMENT
    
    28
    +
    
    29
    +Create a Docker image from bst checkout of an element.
    
    30
    +
    
    31
    +OPTIONS:
    
    32
    +    -c BST_CMD    Path to BuildStream command (default: bst).
    
    33
    +    -m MESSAGE    Commit message for the imported image.
    
    34
    +    -t TAG        Tag of the imported image.
    
    35
    +    -h            Print this help text and exit.
    
    36
    +
    
    37
    +EXAMPLES:
    
    38
    +
    
    39
    +    # Import hello.bst as a Docker image with tag "bst-hello" and message "hello"
    
    40
    +    $(basename "$0") -m hello -t bst-hello hello.bst
    
    41
    +
    
    42
    +    # Import hello.bst as a Docker image with tag "bst-hello" using bst-here
    
    43
    +    $(basename "$0") -c bst-here -t bst-hello hello.bst
    
    44
    +
    
    45
    +EOF
    
    46
    +    exit "$1"
    
    47
    +}
    
    48
    +
    
    49
    +die() {
    
    50
    +    echo "FATAL: $1" >&2
    
    51
    +    exit 1
    
    52
    +}
    
    53
    +
    
    54
    +bst_cmd=bst
    
    55
    +docker_import_cmd=(docker import)
    
    56
    +docker_image_tag=
    
    57
    +
    
    58
    +while getopts c:m:t:h arg
    
    59
    +do
    
    60
    +    case $arg in
    
    61
    +    c)
    
    62
    +        bst_cmd="$OPTARG"
    
    63
    +        ;;
    
    64
    +    m)
    
    65
    +        docker_import_cmd+=('-m' "$OPTARG")
    
    66
    +        ;;
    
    67
    +    t)
    
    68
    +        docker_image_tag="$OPTARG"
    
    69
    +        ;;
    
    70
    +    h)
    
    71
    +        usage 0
    
    72
    +        ;;
    
    73
    +    \?)
    
    74
    +        usage 1
    
    75
    +    esac
    
    76
    +done
    
    77
    +
    
    78
    +shift $((OPTIND-1))
    
    79
    +if [[ "$#" != 1 ]]; then
    
    80
    +    echo "$0: No element specified" >&2
    
    81
    +    usage 1
    
    82
    +fi
    
    83
    +element="$1"
    
    84
    +
    
    85
    +# Dump to a temporary file in the current directory.
    
    86
    +# NOTE: We use current directory to try to ensure compatibility with scripts
    
    87
    +# like bst-here, assuming that the current working directory is mounted
    
    88
    +# inside the container.
    
    89
    +
    
    90
    +checkout_tar="bst-checkout-$(basename "$element")-$RANDOM.tar"
    
    91
    +
    
    92
    +echo "INFO: Checking out $element ..." >&2
    
    93
    +$bst_cmd checkout --tar "$element" "$checkout_tar" || die "Failed to checkout $element"
    
    94
    +echo "INFO: Successfully checked out $element" >&2
    
    95
    +
    
    96
    +echo "INFO: Importing Docker image ..."
    
    97
    +"${docker_import_cmd[@]}" "$checkout_tar" "$docker_image_tag" || die "Failed to import Docker image from tarball"
    
    98
    +echo "INFO: Successfully import Docker image $docker_image_tag"
    
    99
    +
    
    100
    +echo "INFO: Cleaning up ..."
    
    101
    +rm "$checkout_tar" || die "Failed to remove $checkout_tar"
    
    102
    +echo "INFO: Clean up finished"

  • tests/frontend/workspace.py
    ... ... @@ -43,7 +43,8 @@ DATA_DIR = os.path.join(
    43 43
     )
    
    44 44
     
    
    45 45
     
    
    46
    -def open_workspace(cli, tmpdir, datafiles, kind, track, suffix='', workspace_dir=None, project_path=None):
    
    46
    +def open_workspace(cli, tmpdir, datafiles, kind, track, suffix='', workspace_dir=None,
    
    47
    +                   project_path=None, element_attrs=None):
    
    47 48
         if not workspace_dir:
    
    48 49
             workspace_dir = os.path.join(str(tmpdir), 'workspace{}'.format(suffix))
    
    49 50
         if not project_path:
    
    ... ... @@ -69,6 +70,8 @@ def open_workspace(cli, tmpdir, datafiles, kind, track, suffix='', workspace_dir
    69 70
                 repo.source_config(ref=ref)
    
    70 71
             ]
    
    71 72
         }
    
    73
    +    if element_attrs:
    
    74
    +        element = {**element, **element_attrs}
    
    72 75
         _yaml.dump(element,
    
    73 76
                    os.path.join(element_path,
    
    74 77
                                 element_name))
    
    ... ... @@ -854,3 +857,22 @@ def test_cache_key_workspace_in_dependencies(cli, tmpdir, datafiles, strict):
    854 857
     
    
    855 858
         # Check that the original /usr/bin/hello is not in the checkout
    
    856 859
         assert not os.path.exists(os.path.join(checkout, 'usr', 'bin', 'hello'))
    
    860
    +
    
    861
    +
    
    862
    +@pytest.mark.datafiles(DATA_DIR)
    
    863
    +def test_multiple_failed_builds(cli, tmpdir, datafiles):
    
    864
    +    element_config = {
    
    865
    +        "kind": "manual",
    
    866
    +        "config": {
    
    867
    +            "configure-commands": [
    
    868
    +                "unknown_command_that_will_fail"
    
    869
    +            ]
    
    870
    +        }
    
    871
    +    }
    
    872
    +    element_name, project, _ = open_workspace(cli, tmpdir, datafiles,
    
    873
    +                                              "git", False, element_attrs=element_config)
    
    874
    +
    
    875
    +    for _ in range(2):
    
    876
    +        result = cli.run(project=project, args=["build", element_name])
    
    877
    +        assert "BUG" not in result.stderr
    
    878
    +        assert cli.get_element_state(project, element_name) != "cached"



  • [Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]