[Notes] [Git][BuildStream/buildstream][richardmaw/artifact-log] 3 commits: cli: Add artifact log command



Title: GitLab

richardmaw-codethink pushed to branch richardmaw/artifact-log at BuildStream / buildstream

Commits:

3 changed files:

Changes:

  • NEWS
    1
    +===============
    
    2
    +buildstream 1.4
    
    3
    +===============
    
    4
    +
    
    5
    +  o Added `bst artifact log` subcommand for viewing build logs.
    
    6
    +
    
    1 7
     =================
    
    2 8
     buildstream 1.3.1
    
    3 9
     =================
    

  • buildstream/_frontend/cli.py
    ... ... @@ -852,3 +852,53 @@ def source_bundle(app, element, force, directory,
    852 852
     def artifact():
    
    853 853
         """Manipulate cached Artifacts"""
    
    854 854
         pass
    
    855
    +
    
    856
    +
    
    857
    +################################################################
    
    858
    +#                     Artifact Log Command                     #
    
    859
    +################################################################
    
    860
    +@artifact.command(name='log', short_help="Show logs of an artifact")
    
    861
    +@click.option('-e', '--element', 'elements', help="Show logs for artifacts of this element",
    
    862
    +              type=click.Path(readable=False), multiple=True, required=False)
    
    863
    +@click.argument('artifacts', type=click.Path(), nargs=-1)
    
    864
    +@click.pass_obj
    
    865
    +def artifact_log(app, elements, artifacts):
    
    866
    +    """Show logs of all artifacts"""
    
    867
    +    from tempfile import TemporaryDirectory
    
    868
    +    from .._exceptions import CASError
    
    869
    +    from .._message import MessageType
    
    870
    +    from .._pipeline import PipelineSelection
    
    871
    +
    
    872
    +    with app.initialized():
    
    873
    +        cache = app.context.artifactcache
    
    874
    +
    
    875
    +        extractdirs = []
    
    876
    +        if artifacts:
    
    877
    +            for ref in artifacts:
    
    878
    +                try:
    
    879
    +                    # NOTE: This duplicates logic from ArtifactCache in a
    
    880
    +                    # fragile way to avoid having to extract the contents of
    
    881
    +                    # the whole artifact just to see its logs, since it'll be
    
    882
    +                    # extracted for other uses amortising the cost of
    
    883
    +                    # extracting the other content.
    
    884
    +                    destdir = cache.cas.extract(ref, os.path.join(cache.extractdir, os.path.dirname(ref)))
    
    885
    +                    extractdirs.append(destdir)
    
    886
    +                except CASError as e:
    
    887
    +                    app._message(MessageType.WARN, "Artifact {} is not cached".format(ref), detail=str(e))
    
    888
    +                    continue
    
    889
    +        if elements:
    
    890
    +            elements = app.stream.load_selection(elements, selection=PipelineSelection.NONE)
    
    891
    +            for element in elements:
    
    892
    +                if not element._cached():
    
    893
    +                    app._message(MessageType.WARN, "Element {} is not cached".format(element))
    
    894
    +                    continue
    
    895
    +                destdir = cache.extract(element, element._get_cache_key())
    
    896
    +                extractdirs.append(destdir)
    
    897
    +
    
    898
    +        for extractdir in extractdirs:
    
    899
    +            logsdir = os.path.join(extractdir, "logs")
    
    900
    +            for log in (os.path.join(logsdir, log) for log in os.listdir(logsdir)):
    
    901
    +                # NOTE: Should click gain the ability to pass files to the pager this can be optimised.
    
    902
    +                with open(log) as f:
    
    903
    +                    data = f.read()
    
    904
    +                    click.echo_via_pager(data)

  • tests/integration/artifact.py
    1
    +#
    
    2
    +#  Copyright (C) 2018 Codethink Limited
    
    3
    +#  Copyright (C) 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: Richard Maw <richard maw codethink co uk>
    
    19
    +#
    
    20
    +
    
    21
    +import os
    
    22
    +import pytest
    
    23
    +
    
    24
    +from tests.testutils import cli_integration as cli
    
    25
    +
    
    26
    +
    
    27
    +pytestmark = pytest.mark.integration
    
    28
    +
    
    29
    +
    
    30
    +# Project directory
    
    31
    +DATA_DIR = os.path.join(
    
    32
    +    os.path.dirname(os.path.realpath(__file__)),
    
    33
    +    "project",
    
    34
    +)
    
    35
    +
    
    36
    +
    
    37
    +@pytest.mark.integration
    
    38
    +@pytest.mark.datafiles(DATA_DIR)
    
    39
    +def test_artifact_log(cli, tmpdir, datafiles):
    
    40
    +    project = os.path.join(datafiles.dirname, datafiles.basename)
    
    41
    +
    
    42
    +    # Get the cache key of our test element
    
    43
    +    result = cli.run(project=project, silent=True, args=[
    
    44
    +        '--no-colors',
    
    45
    +        'show', '--deps', 'none', '--format', '%{full-key}',
    
    46
    +        'base.bst'
    
    47
    +    ])
    
    48
    +    key = result.output.strip()
    
    49
    +
    
    50
    +    # Ensure we have an artifact to read
    
    51
    +    result = cli.run(project=project, args=['build', 'base.bst'])
    
    52
    +    assert result.exit_code == 0
    
    53
    +
    
    54
    +    # Read the log via the element name
    
    55
    +    result = cli.run(project=project, args=['artifact', 'log', '-e', 'base.bst'])
    
    56
    +    assert result.exit_code == 0
    
    57
    +    log = result.output
    
    58
    +
    
    59
    +    # Read the log via the key
    
    60
    +    result = cli.run(project=project, args=['artifact', 'log', 'test/base/' + key])
    
    61
    +    assert result.exit_code == 0
    
    62
    +    assert log == result.output



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