Tom Pollard pushed to branch tpollard/829 at BuildStream / buildstream
Commits:
-
30c7dfd1
by Tom Pollard at 2019-01-23T11:57:08Z
3 changed files:
Changes:
... | ... | @@ -507,7 +507,7 @@ def shell(app, element, sysroot, mount, isolate, build_, cli_buildtree, command) |
507 | 507 |
else:
|
508 | 508 |
scope = Scope.RUN
|
509 | 509 |
|
510 |
- use_buildtree = False
|
|
510 |
+ use_buildtree = None
|
|
511 | 511 |
|
512 | 512 |
with app.initialized():
|
513 | 513 |
if not element:
|
... | ... | @@ -515,7 +515,8 @@ def shell(app, element, sysroot, mount, isolate, build_, cli_buildtree, command) |
515 | 515 |
if not element:
|
516 | 516 |
raise AppError('Missing argument "ELEMENT".')
|
517 | 517 |
|
518 |
- dependencies = app.stream.load_selection((element,), selection=PipelineSelection.NONE)
|
|
518 |
+ dependencies = app.stream.load_selection((element,), selection=PipelineSelection.NONE,
|
|
519 |
+ use_artifact_config=True)
|
|
519 | 520 |
element = dependencies[0]
|
520 | 521 |
prompt = app.shell_prompt(element)
|
521 | 522 |
mounts = [
|
... | ... | @@ -524,20 +525,22 @@ def shell(app, element, sysroot, mount, isolate, build_, cli_buildtree, command) |
524 | 525 |
]
|
525 | 526 |
|
526 | 527 |
cached = element._cached_buildtree()
|
527 |
- if cli_buildtree == "always":
|
|
528 |
- if cached:
|
|
529 |
- use_buildtree = True
|
|
530 |
- else:
|
|
531 |
- raise AppError("No buildtree is cached but the use buildtree option was specified")
|
|
532 |
- elif cli_buildtree == "never":
|
|
533 |
- pass
|
|
534 |
- elif cli_buildtree == "try":
|
|
535 |
- use_buildtree = cached
|
|
528 |
+ if cli_buildtree in ("always", "try"):
|
|
529 |
+ use_buildtree = cli_buildtree
|
|
530 |
+ if not cached and use_buildtree == "always":
|
|
531 |
+ click.echo("WARNING: buildtree is not cached locally, will attempt to pull from available remotes",
|
|
532 |
+ err=True)
|
|
536 | 533 |
else:
|
537 |
- if app.interactive and cached:
|
|
538 |
- use_buildtree = bool(click.confirm('Do you want to use the cached buildtree?'))
|
|
534 |
+ # If the value has defaulted to ask and in non interactive mode, don't consider the buildtree, this
|
|
535 |
+ # being the default behaviour of the command
|
|
536 |
+ if app.interactive and cli_buildtree == "ask":
|
|
537 |
+ if cached and bool(click.confirm('Do you want to use the cached buildtree?')):
|
|
538 |
+ use_buildtree = "always"
|
|
539 |
+ elif not cached and bool(click.confirm('Do you want to attempt to pull the cached buildtree?')):
|
|
540 |
+ use_buildtree = "try"
|
|
541 |
+ |
|
539 | 542 |
if use_buildtree and not element._cached_success():
|
540 |
- click.echo("Warning: using a buildtree from a failed build.")
|
|
543 |
+ click.echo("WARNING: using a buildtree from a failed build.", err=True)
|
|
541 | 544 |
|
542 | 545 |
try:
|
543 | 546 |
exitcode = app.stream.shell(element, scope, prompt,
|
... | ... | @@ -127,7 +127,7 @@ class Stream(): |
127 | 127 |
# mounts (list of HostMount): Additional directories to mount into the sandbox
|
128 | 128 |
# isolate (bool): Whether to isolate the environment like we do in builds
|
129 | 129 |
# command (list): An argv to launch in the sandbox, or None
|
130 |
- # usebuildtree (bool): Wheather to use a buildtree as the source.
|
|
130 |
+ # usebuildtree (str): Whether to use a buildtree as the source, given cli option
|
|
131 | 131 |
#
|
132 | 132 |
# Returns:
|
133 | 133 |
# (int): The exit code of the launched shell
|
... | ... | @@ -137,7 +137,7 @@ class Stream(): |
137 | 137 |
mounts=None,
|
138 | 138 |
isolate=False,
|
139 | 139 |
command=None,
|
140 |
- usebuildtree=False):
|
|
140 |
+ usebuildtree=None):
|
|
141 | 141 |
|
142 | 142 |
# Assert we have everything we need built, unless the directory is specified
|
143 | 143 |
# in which case we just blindly trust the directory, using the element
|
... | ... | @@ -152,8 +152,31 @@ class Stream(): |
152 | 152 |
raise StreamError("Elements need to be built or downloaded before staging a shell environment",
|
153 | 153 |
detail="\n".join(missing_deps))
|
154 | 154 |
|
155 |
+ buildtree = False
|
|
156 |
+ # Check if we require a pull queue attempt, with given artifact state and context
|
|
157 |
+ if usebuildtree:
|
|
158 |
+ if not element._cached_buildtree():
|
|
159 |
+ require_buildtree = self._buildtree_pull_required([element])
|
|
160 |
+ # Attempt a pull queue for the given element if remote and context allow it
|
|
161 |
+ if require_buildtree:
|
|
162 |
+ self._message(MessageType.INFO, "Attempting to fetch missing artifact buildtree")
|
|
163 |
+ self._add_queue(PullQueue(self._scheduler))
|
|
164 |
+ self._enqueue_plan(require_buildtree)
|
|
165 |
+ self._run()
|
|
166 |
+ # Now check if the buildtree was successfully fetched
|
|
167 |
+ if element._cached_buildtree():
|
|
168 |
+ buildtree = True
|
|
169 |
+ if not buildtree:
|
|
170 |
+ if usebuildtree == "always":
|
|
171 |
+ raise StreamError("Buildtree is not cached locally or in available remotes")
|
|
172 |
+ else:
|
|
173 |
+ self._message(MessageType.INFO, """Buildtree is not cached locally or in available remotes,
|
|
174 |
+ shell will be loaded without it""")
|
|
175 |
+ else:
|
|
176 |
+ buildtree = True
|
|
177 |
+ |
|
155 | 178 |
return element._shell(scope, directory, mounts=mounts, isolate=isolate, prompt=prompt, command=command,
|
156 |
- usebuildtree=usebuildtree)
|
|
179 |
+ usebuildtree=buildtree)
|
|
157 | 180 |
|
158 | 181 |
# build()
|
159 | 182 |
#
|
... | ... | @@ -101,7 +101,7 @@ def test_buildtree_from_failure(cli_integration, tmpdir, datafiles): |
101 | 101 |
'shell', '--build', element_name, '--use-buildtree', 'always', '--', 'cat', 'test'
|
102 | 102 |
])
|
103 | 103 |
res.assert_success()
|
104 |
- assert "Warning: using a buildtree from a failed build" in res.output
|
|
104 |
+ assert "WARNING: using a buildtree from a failed build" in res.stderr
|
|
105 | 105 |
assert 'Hi' in res.output
|
106 | 106 |
|
107 | 107 |
|
... | ... | @@ -141,7 +141,7 @@ def test_buildtree_pulled(cli, tmpdir, datafiles): |
141 | 141 |
res.assert_success()
|
142 | 142 |
|
143 | 143 |
|
144 |
-# This test checks for correct behaviour if a buildtree is not present.
|
|
144 |
+# This test checks for correct behaviour if a buildtree is not present in the local cache.
|
|
145 | 145 |
@pytest.mark.datafiles(DATA_DIR)
|
146 | 146 |
@pytest.mark.skipif(IS_LINUX and not HAVE_BWRAP, reason='Only available with bubblewrap on Linux')
|
147 | 147 |
def test_buildtree_options(cli, tmpdir, datafiles):
|
... | ... | @@ -156,6 +156,7 @@ def test_buildtree_options(cli, tmpdir, datafiles): |
156 | 156 |
result = cli.run(project=project, args=['build', element_name])
|
157 | 157 |
result.assert_success()
|
158 | 158 |
assert cli.get_element_state(project, element_name) == 'cached'
|
159 |
+ assert share.has_artifact('test', element_name, cli.get_element_key(project, element_name))
|
|
159 | 160 |
|
160 | 161 |
# Discard the cache
|
161 | 162 |
cli.configure({
|
... | ... | @@ -168,8 +169,6 @@ def test_buildtree_options(cli, tmpdir, datafiles): |
168 | 169 |
result = cli.run(project=project, args=['artifact', 'pull', '--deps', 'all', element_name])
|
169 | 170 |
result.assert_success()
|
170 | 171 |
|
171 |
- # The above is the simplest way I know to create a local cache without any buildtrees.
|
|
172 |
- |
|
173 | 172 |
# Check it's not using the cached build tree
|
174 | 173 |
res = cli.run(project=project, args=[
|
175 | 174 |
'shell', '--build', element_name, '--use-buildtree', 'never', '--', 'cat', 'test'
|
... | ... | @@ -177,24 +176,51 @@ def test_buildtree_options(cli, tmpdir, datafiles): |
177 | 176 |
res.assert_shell_error()
|
178 | 177 |
assert 'Hi' not in res.output
|
179 | 178 |
|
180 |
- # Check it's not correctly handling the lack of buildtree
|
|
179 |
+ # Check it's not using the cached build tree, default is to ask, and fall back to not
|
|
180 |
+ # for non interactive behavior
|
|
181 | 181 |
res = cli.run(project=project, args=[
|
182 |
- 'shell', '--build', element_name, '--use-buildtree', 'try', '--', 'cat', 'test'
|
|
182 |
+ 'shell', '--build', element_name, '--', 'cat', 'test'
|
|
183 | 183 |
])
|
184 | 184 |
res.assert_shell_error()
|
185 | 185 |
assert 'Hi' not in res.output
|
186 | 186 |
|
187 |
- # Check it's not using the cached build tree, default is to ask, and fall back to not
|
|
188 |
- # for non interactive behavior
|
|
187 |
+ # Check correctly handling the lack of buildtree, with 'try' not attempting to
|
|
188 |
+ # pull the buildtree as the user context is by default set to not pull them
|
|
189 | 189 |
res = cli.run(project=project, args=[
|
190 |
- 'shell', '--build', element_name, '--', 'cat', 'test'
|
|
190 |
+ 'shell', '--build', element_name, '--use-buildtree', 'try', '--', 'cat', 'test'
|
|
191 | 191 |
])
|
192 |
- res.assert_shell_error()
|
|
193 | 192 |
assert 'Hi' not in res.output
|
193 |
+ assert 'Attempting to fetch missing artifact buildtrees' not in res.stderr
|
|
194 |
+ assert """Buildtree is not cached locally or in available remotes,
|
|
195 |
+ shell will be loaded without it"""
|
|
194 | 196 |
|
195 |
- # Check it's using the cached build tree
|
|
197 |
+ # Check correctly handling the lack of buildtree, with 'try' attempting and succeeding
|
|
198 |
+ # to pull the buildtree as the user context allow the pulling of buildtrees and it is
|
|
199 |
+ # available in the remote
|
|
200 |
+ res = cli.run(project=project, args=[
|
|
201 |
+ '--pull-buildtrees', 'shell', '--build', element_name, '--use-buildtree', 'try', '--', 'cat', 'test'
|
|
202 |
+ ])
|
|
203 |
+ assert 'Attempting to fetch missing artifact buildtree' in res.stderr
|
|
204 |
+ assert 'Hi' in res.output
|
|
205 |
+ shutil.rmtree(os.path.join(os.path.join(cli.directory, 'artifacts2')))
|
|
206 |
+ assert cli.get_element_state(project, element_name) != 'cached'
|
|
207 |
+ |
|
208 |
+ # Check it's not loading the shell at all with always set for the buildtree, when the
|
|
209 |
+ # user context does not allow for buildtree pulling
|
|
210 |
+ result = cli.run(project=project, args=['artifact', 'pull', '--deps', 'all', element_name])
|
|
211 |
+ result.assert_success()
|
|
196 | 212 |
res = cli.run(project=project, args=[
|
197 | 213 |
'shell', '--build', element_name, '--use-buildtree', 'always', '--', 'cat', 'test'
|
198 | 214 |
])
|
199 | 215 |
res.assert_main_error(ErrorDomain.PROG_NOT_FOUND, None)
|
216 |
+ assert 'Buildtree is not cached locally or in available remotes' in res.stderr
|
|
200 | 217 |
assert 'Hi' not in res.output
|
218 |
+ assert 'Attempting to fetch missing artifact buildtree' not in res.stderr
|
|
219 |
+ |
|
220 |
+ # Check that when user context is set to pull buildtrees and a remote has the buildtree,
|
|
221 |
+ # 'always' will attempt and succeed at pulling the missing buildtree.
|
|
222 |
+ res = cli.run(project=project, args=[
|
|
223 |
+ '--pull-buildtrees', 'shell', '--build', element_name, '--use-buildtree', 'always', '--', 'cat', 'test'
|
|
224 |
+ ])
|
|
225 |
+ assert 'Hi' in res.output
|
|
226 |
+ assert 'Attempting to fetch missing artifact buildtree' in res.stderr
|