Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions src/buildstream/_frontend/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -1302,12 +1302,29 @@ def artifact():
),
help="The dependencies we also want to show",
)
@click.option(
"--artifact-remote",
"artifact_remotes",
type=RemoteSpecType(RemoteSpecPurpose.PULL),
multiple=True,
help="A remote for downloading artifacts (Since: 2.7)",
)
@click.option(
"--ignore-project-artifact-remotes",
is_flag=True,
help="Ignore remote artifact cache servers recommended by projects (Since: 2.7)",
)
@click.argument("artifacts", type=click.Path(), nargs=-1)
@click.pass_obj
def artifact_show(app, deps, artifacts):
"""show the cached state of artifacts"""
def artifact_show(app, deps, artifact_remotes, ignore_project_artifact_remotes, artifacts):
"""Show the cached state of artifacts"""
with app.initialized():
targets = app.stream.artifact_show(artifacts, selection=deps)
targets = app.stream.artifact_show(
artifacts,
selection=deps,
artifact_remotes=artifact_remotes,
ignore_project_artifact_remotes=ignore_project_artifact_remotes,
)
click.echo(app.logger.show_state_of_artifacts(targets))
sys.exit(0)

Expand Down
18 changes: 16 additions & 2 deletions src/buildstream/_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -788,11 +788,25 @@ def _export_artifact(self, tar, location, compression, target, hardlinks, virdir
#
# Args:
# targets (str): Targets to show the cached state of
# artifact_remotes: Artifact cache remotes specified on the commmand line
# ignore_project_artifact_remotes: Whether to ignore artifact remotes specified by projects
#
def artifact_show(self, targets, *, selection=_PipelineSelection.NONE):
def artifact_show(
self,
targets,
*,
selection=_PipelineSelection.NONE,
artifact_remotes: Iterable[RemoteSpec] = (),
ignore_project_artifact_remotes: bool = False,
):
# Obtain list of Element and/or ArtifactElement objects
target_objects = self.load_selection(
targets, selection=selection, connect_artifact_cache=True, load_artifacts=True
targets,
selection=selection,
connect_artifact_cache=True,
load_artifacts=True,
artifact_remotes=artifact_remotes,
ignore_project_artifact_remotes=ignore_project_artifact_remotes,
)

self.query_cache(target_objects)
Expand Down
12 changes: 12 additions & 0 deletions tests/frontend/artifact-show/elements/compose-all.bst
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
kind: compose

depends:
- filename: import-bin.bst
type: build
- filename: import-dev.bst
type: build

config:
# Dont try running the sandbox, we dont have a
# runtime to run anything in this context.
integrate: False
4 changes: 4 additions & 0 deletions tests/frontend/artifact-show/elements/import-bin.bst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
kind: import
sources:
- kind: local
path: files/bin-files
4 changes: 4 additions & 0 deletions tests/frontend/artifact-show/elements/import-dev.bst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
kind: import
sources:
- kind: local
path: files/dev-files
9 changes: 9 additions & 0 deletions tests/frontend/artifact-show/elements/manual.bst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
kind: manual

config:
build-commands:
- echo "hello"

sources:
- kind: local
path: elements/manual.bst
8 changes: 8 additions & 0 deletions tests/frontend/artifact-show/elements/target.bst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
kind: stack
description: |

Main stack target for the bst build test

depends:
- import-bin.bst
- compose-all.bst
3 changes: 3 additions & 0 deletions tests/frontend/artifact-show/files/bin-files/usr/bin/hello
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash

echo "Hello !"
12 changes: 12 additions & 0 deletions tests/frontend/artifact-show/files/dev-files/usr/include/pony.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#ifndef __PONY_H__
#define __PONY_H__

#define PONY_BEGIN "Once upon a time, there was a pony."
#define PONY_END "And they lived happily ever after, the end."

#define MAKE_PONY(story) \
PONY_BEGIN \
story \
PONY_END

#endif /* __PONY_H__ */
10 changes: 10 additions & 0 deletions tests/frontend/artifact-show/project.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Project config for frontend build test
name: test
min-version: 2.0
element-path: elements

plugins:
- origin: pip
package-name: sample-plugins
sources:
- git
97 changes: 91 additions & 6 deletions tests/frontend/artifact_show.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@
from buildstream.exceptions import ErrorDomain
from buildstream._testing import cli # pylint: disable=unused-import
from tests.testutils import create_artifact_share
from . import configure_project


# Project directory
DATA_DIR = os.path.join(
os.path.dirname(os.path.realpath(__file__)),
"project",
"artifact-show",
)
SIMPLE_DIR = os.path.join(
os.path.dirname(os.path.realpath(__file__)),
Expand Down Expand Up @@ -155,18 +156,96 @@ def test_artifact_show_glob(cli, tmpdir, datafiles, pattern, expected_prefixes):

# Test artifact show artifact in remote
@pytest.mark.datafiles(DATA_DIR)
def test_artifact_show_element_available_remotely(cli, tmpdir, datafiles):
@pytest.mark.parametrize("config", ["config-project", "config-user", "config-cli"])
@pytest.mark.parametrize("by_element_name", [True, False], ids=["by-element-name", "by-artifact-name"])
def test_artifact_show_available_remotely(cli, tmpdir, datafiles, config, by_element_name):
project = str(datafiles)
element = "target.bst"

#
# Skip this configuration, BuildStream intentionally ignores the local project.conf
# if an artifact name is specified.
#
if config == "config-project" and not by_element_name:
pytest.skip("No project.conf in context")

# Set up remote and local shares
local_cache = os.path.join(str(tmpdir), "artifacts")
cli.configure(
{
"cachedir": local_cache,
}
)

with create_artifact_share(os.path.join(str(tmpdir), "remote")) as remote:
cli.configure(
extra_cli_args = []
if config == "config-project":
configure_project(
project,
{
"artifacts": [
{
"url": remote.repo,
"push": True,
}
]
},
)
elif config == "config-user":
cli.configure(
{
"artifacts": {"servers": [{"url": remote.repo, "push": True}]},
}
)
else:
extra_cli_args = ["--artifact-remote", remote.repo]

# Build the element
result = cli.run(project=project, args=["build"] + extra_cli_args + [element])
result.assert_success()

artifact_name = cli.get_artifact_name(project, "test", element)

# Make sure it's in the share
assert remote.get_artifact(artifact_name)

# Delete the artifact from the local cache
result = cli.run(project=project, args=["artifact", "delete", element])
result.assert_success()
assert cli.get_element_state(project, element) != "cached"

# Do the artifact show and assert
element_or_artifact = element if by_element_name else artifact_name
result = cli.run(project=project, args=["artifact", "show"] + extra_cli_args + [element_or_artifact])
result.assert_success()
assert "available {}".format(element_or_artifact) in result.output


# Test out --ignore-project-artifact-remotes
@pytest.mark.datafiles(DATA_DIR)
def test_artifact_show_ignore_project_remotes(cli, tmpdir, datafiles):
project = str(datafiles)
element = "target.bst"

# Set up remote and local shares
local_cache = os.path.join(str(tmpdir), "artifacts")
cli.configure(
{
"cachedir": local_cache,
}
)

with create_artifact_share(os.path.join(str(tmpdir), "remote")) as remote:
configure_project(
project,
{
"artifacts": {"servers": [{"url": remote.repo, "push": True}]},
"cachedir": local_cache,
}
"artifacts": [
{
"url": remote.repo,
"push": True,
}
]
},
)

# Build the element
Expand All @@ -181,6 +260,12 @@ def test_artifact_show_element_available_remotely(cli, tmpdir, datafiles):
result.assert_success()
assert cli.get_element_state(project, element) != "cached"

# It is available remotely with the project configured remote
result = cli.run(project=project, args=["artifact", "show", element])
result.assert_success()
assert "available {}".format(element) in result.output

# Ignoring project remotes, it is not found in any remote
result = cli.run(project=project, args=["artifact", "show", "--ignore-project-artifact-remotes", element])
result.assert_success()
assert "not cached {}".format(element) in result.output
Loading