summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Pollard <tom.pollard@codethink.co.uk>2019-01-30 16:18:17 +0000
committerTom Pollard <tom.pollard@codethink.co.uk>2019-01-30 17:58:54 +0000
commit7166ff850c71c5a3f90f39d227b9ae4d6bf5e682 (patch)
tree976ed3f99de35bfe44e25d0d2ce56934b6bcdabf
parent7256bb0c117c5bbb0bbe5b95350015a8612feb13 (diff)
downloadbuildstream-tpollard/buildremote.tar.gz
Add --remote, -r option to bst build, inline with pull & pushtpollard/buildremote
Providing a remote will limit build's pull/push remote actions to the given remote specifically, ignoring those defined via user or project configuration.
-rw-r--r--NEWS4
-rw-r--r--buildstream/_frontend/cli.py7
-rw-r--r--buildstream/_stream.py14
-rw-r--r--tests/frontend/completions.py3
-rw-r--r--tests/frontend/pull.py58
-rw-r--r--tests/frontend/push.py30
6 files changed, 111 insertions, 5 deletions
diff --git a/NEWS b/NEWS
index 449a23ff1..7343d00e5 100644
--- a/NEWS
+++ b/NEWS
@@ -122,6 +122,10 @@ buildstream 1.3.1
'shell', 'show', 'source-checkout', 'track', 'workspace close' and 'workspace reset'
commands are affected.
+ o bst 'build' now has '--remote, -r' option, inline with bst 'push' & 'build'.
+ Providing a remote will limit build's pull/push remote actions to the given
+ remote specifically, ignoring those defined via user or project configuration.
+
=================
buildstream 1.1.5
diff --git a/buildstream/_frontend/cli.py b/buildstream/_frontend/cli.py
index 163a05790..5c1d0d8b0 100644
--- a/buildstream/_frontend/cli.py
+++ b/buildstream/_frontend/cli.py
@@ -338,10 +338,12 @@ def init(app, project_name, format_version, element_path, force):
help="Allow tracking to cross junction boundaries")
@click.option('--track-save', default=False, is_flag=True,
help="Deprecated: This is ignored")
+@click.option('--remote', '-r', default=None,
+ help="The URL of the remote cache (defaults to the first configured cache)")
@click.argument('elements', nargs=-1,
type=click.Path(readable=False))
@click.pass_obj
-def build(app, elements, all_, track_, track_save, track_all, track_except, track_cross_junctions):
+def build(app, elements, all_, track_, track_save, track_all, track_except, track_cross_junctions, remote):
"""Build elements in a pipeline
Specifying no elements will result in building the default targets
@@ -376,7 +378,8 @@ def build(app, elements, all_, track_, track_save, track_all, track_except, trac
track_except=track_except,
track_cross_junctions=track_cross_junctions,
ignore_junction_targets=ignore_junction_targets,
- build_all=all_)
+ build_all=all_,
+ remote=remote)
##################################################################
diff --git a/buildstream/_stream.py b/buildstream/_stream.py
index af736c96a..588780558 100644
--- a/buildstream/_stream.py
+++ b/buildstream/_stream.py
@@ -197,26 +197,36 @@ class Stream():
# ignore_junction_targets (bool): Whether junction targets should be filtered out
# build_all (bool): Whether to build all elements, or only those
# which are required to build the target.
+ # remote (str): The URL of a specific remote server to push to, or None
+ #
+ # If `remote` specified as None, then regular configuration will be used
+ # to determine where to push artifacts to.
#
def build(self, targets, *,
track_targets=None,
track_except=None,
track_cross_junctions=False,
ignore_junction_targets=False,
- build_all=False):
+ build_all=False,
+ remote=None):
if build_all:
selection = PipelineSelection.ALL
else:
selection = PipelineSelection.PLAN
+ use_config = True
+ if remote:
+ use_config = False
+
elements, track_elements = \
self._load(targets, track_targets,
selection=selection, track_selection=PipelineSelection.ALL,
track_except_targets=track_except,
track_cross_junctions=track_cross_junctions,
ignore_junction_targets=ignore_junction_targets,
- use_artifact_config=True,
+ use_artifact_config=use_config,
+ artifact_remote_url=remote,
fetch_subprojects=True,
dynamic_plan=True)
diff --git a/tests/frontend/completions.py b/tests/frontend/completions.py
index 007064f89..93b908f60 100644
--- a/tests/frontend/completions.py
+++ b/tests/frontend/completions.py
@@ -141,7 +141,8 @@ def test_commands(cli, cmd, word_idx, expected):
('bst --no-colors build -', 3, ['--all ', '--track ', '--track-all ',
'--track-except ',
'--track-cross-junctions ', '-J ',
- '--track-save ']),
+ '--track-save ',
+ '--remote ', '-r ']),
# Test the behavior of completing after an option that has a
# parameter that cannot be completed, vs an option that has
diff --git a/tests/frontend/pull.py b/tests/frontend/pull.py
index 20b740948..e512be8fc 100644
--- a/tests/frontend/pull.py
+++ b/tests/frontend/pull.py
@@ -408,3 +408,61 @@ def test_pull_missing_notifies_user(caplog, cli, tmpdir, datafiles):
assert "INFO Remote ({}) does not have".format(share.repo) in result.stderr
assert "SKIPPED Pull" in result.stderr
+
+
+@pytest.mark.datafiles(DATA_DIR)
+def test_build_remote_option(caplog, cli, tmpdir, datafiles):
+ project = os.path.join(datafiles.dirname, datafiles.basename)
+ caplog.set_level(1)
+
+ with create_artifact_share(os.path.join(str(tmpdir), 'artifactshare1')) as shareuser,\
+ create_artifact_share(os.path.join(str(tmpdir), 'artifactshare2')) as shareproject,\
+ create_artifact_share(os.path.join(str(tmpdir), 'artifactshare3')) as sharecli:
+
+ # Add shareproject repo url to project.conf
+ with open(os.path.join(project, "project.conf"), "a") as projconf:
+ projconf.write("artifacts:\n url: {}\n push: True".format(shareproject.repo))
+
+ # Configure shareuser remote in user conf
+ cli.configure({
+ 'artifacts': {'url': shareuser.repo, 'push': True}
+ })
+
+ # Push the artifacts to the shareuser and shareproject remotes
+
+ result = cli.run(project=project, args=['build', 'target.bst'])
+
+ # Assert that shareuser and shareproject have the artfifacts cached,
+ # but sharecli doesn't, then delete local cache
+ result.assert_success()
+ all_elements = ['target.bst', 'import-bin.bst', 'compose-all.bst']
+ for element_name in all_elements:
+ assert element_name in result.get_pushed_elements()
+ assert_not_shared(cli, sharecli, project, element_name)
+ assert_shared(cli, shareuser, project, element_name)
+ assert_shared(cli, shareproject, project, element_name)
+ cli.remove_artifact_from_cache(project, element_name)
+
+ # Now check that a build with cli set as sharecli results in nothing being pulled,
+ # as it doesn't have them cached and shareuser/shareproject should be ignored. This
+ # wil however result in the artifacts being built and pushed to it
+
+ result = cli.run(project=project, args=['build', '--remote', sharecli.repo, 'target.bst'])
+
+ result.assert_success()
+ for element_name in all_elements:
+ assert element_name not in result.get_pulled_elements()
+ assert_shared(cli, sharecli, project, element_name)
+ cli.remove_artifact_from_cache(project, element_name)
+
+ # Now check that a clean build with cli set as sharecli should result in artifacts only
+ # being pulled from it, as that was provided via the cli and is populated
+
+ result = cli.run(project=project, args=['build', '--remote', sharecli.repo, 'target.bst'])
+
+ result.assert_success()
+ for element_name in all_elements:
+ assert element_name in result.get_pulled_elements()
+ assert shareproject.repo not in result.stderr
+ assert shareuser.repo not in result.stderr
+ assert sharecli.repo in result.stderr
diff --git a/tests/frontend/push.py b/tests/frontend/push.py
index f3f9b52f1..729df9ae9 100644
--- a/tests/frontend/push.py
+++ b/tests/frontend/push.py
@@ -416,3 +416,33 @@ def test_push_already_cached(caplog, cli, tmpdir, datafiles):
assert not result.get_pushed_elements(), "No elements should have been pushed since the cache was populated"
assert "INFO Remote ({}) already has ".format(share.repo) in result.stderr
assert "SKIPPED Push" in result.stderr
+
+
+@pytest.mark.datafiles(DATA_DIR)
+def test_build_remote_option(caplog, cli, tmpdir, datafiles):
+ project = os.path.join(datafiles.dirname, datafiles.basename)
+ caplog.set_level(1)
+
+ with create_artifact_share(os.path.join(str(tmpdir), 'artifactshare1')) as shareuser,\
+ create_artifact_share(os.path.join(str(tmpdir), 'artifactshare2')) as shareproject,\
+ create_artifact_share(os.path.join(str(tmpdir), 'artifactshare3')) as sharecli:
+
+ # Add shareproject repo url to project.conf
+ with open(os.path.join(project, "project.conf"), "a") as projconf:
+ projconf.write("artifacts:\n url: {}\n push: True".format(shareproject.repo))
+
+ # Configure shareuser remote in user conf
+ cli.configure({
+ 'artifacts': {'url': shareuser.repo, 'push': True}
+ })
+
+ result = cli.run(project=project, args=['build', '--remote', sharecli.repo, 'target.bst'])
+
+ # Artifacts should have only been pushed to sharecli, as that was provided via the cli
+ result.assert_success()
+ all_elements = ['target.bst', 'import-bin.bst', 'compose-all.bst']
+ for element_name in all_elements:
+ assert element_name in result.get_pushed_elements()
+ assert_shared(cli, sharecli, project, element_name)
+ assert_not_shared(cli, shareuser, project, element_name)
+ assert_not_shared(cli, shareproject, project, element_name)