Jürg Billeter pushed to branch issue-638-validate-all-files at BuildStream / buildstream
Commits:
-
d1b6b5cb
by Jürg Billeter at 2019-01-24T13:10:42Z
-
b49283ef
by Phillip Smyth at 2019-01-24T13:10:42Z
-
4490fa74
by Jürg Billeter at 2019-01-24T13:10:42Z
-
5db382be
by Jürg Billeter at 2019-01-24T13:10:42Z
-
d5159785
by Jürg Billeter at 2019-01-24T13:10:42Z
-
f1be3d47
by Phillip Smyth at 2019-01-24T13:10:42Z
26 changed files:
- NEWS
- doc/source/format_project.rst
- tests/frontend/buildcheckout.py
- tests/frontend/fetch.py
- + tests/frontend/project_default/elements/target.bst
- + tests/frontend/project_default/elements/target2.bst
- + tests/frontend/project_default/project.conf
- + tests/frontend/project_fail/elements/compose-all.bst
- + tests/frontend/project_fail/elements/import-dev.bst
- + tests/frontend/project_fail/elements/target.bst
- + tests/frontend/project_fail/files/dev-files/usr/include/pony.h
- + tests/frontend/project_fail/project.conf
- + tests/frontend/project_world/elements/checkout-deps.bst
- + tests/frontend/project_world/elements/compose-all.bst
- + tests/frontend/project_world/elements/compose-exclude-dev.bst
- + tests/frontend/project_world/elements/compose-include-bin.bst
- + tests/frontend/project_world/elements/import-bin.bst
- + tests/frontend/project_world/elements/import-dev.bst
- + tests/frontend/project_world/elements/rebuild-target.bst
- + tests/frontend/project_world/elements/target.bst
- + tests/frontend/project_world/files/sub-project/elements/import-etc.bst
- + tests/frontend/project_world/files/sub-project/files/etc-files/etc/animal.conf
- + tests/frontend/project_world/files/sub-project/project.conf
- + tests/frontend/project_world/project.conf
- tests/frontend/pull.py
- tests/frontend/show.py
Changes:
... | ... | @@ -30,6 +30,10 @@ buildstream 1.3.1 |
30 | 30 |
specific. Recommendation if you are building in Linux is to use the
|
31 | 31 |
ones being used in freedesktop-sdk project, for example
|
32 | 32 |
|
33 |
+ o Running commands without elements specified will now attempt to use
|
|
34 |
+ the default targets defined in the project configuration.
|
|
35 |
+ If no default target is defined, all elements in the project will be used.
|
|
36 |
+ |
|
33 | 37 |
o All elements must now be suffixed with `.bst`
|
34 | 38 |
Attempting to use an element that does not have the `.bst` extension,
|
35 | 39 |
will result in a warning.
|
... | ... | @@ -945,6 +945,38 @@ Host side environment variable expansion is also supported: |
945 | 945 |
- '${XDG_RUNTIME_DIR}/pulse/native'
|
946 | 946 |
|
947 | 947 |
|
948 |
+.. _project_default_targets:
|
|
949 |
+ |
|
950 |
+Default targets
|
|
951 |
+---------------
|
|
952 |
+When running BuildStream commands from a project directory or subdirectory
|
|
953 |
+without specifying any target elements on the command line, the default targets
|
|
954 |
+of the project will be used. The default targets can be configured in the
|
|
955 |
+``defaults`` section as follows:
|
|
956 |
+ |
|
957 |
+.. code:: yaml
|
|
958 |
+ |
|
959 |
+ defaults:
|
|
960 |
+ |
|
961 |
+ targets:
|
|
962 |
+ - app.bst
|
|
963 |
+ |
|
964 |
+If no default targets are configured in ``project.conf``, BuildStream commands
|
|
965 |
+will default to all ``.bst`` files in the configured element path.
|
|
966 |
+ |
|
967 |
+Commands that cannot support junctions as target elements (``bst build``,
|
|
968 |
+``bst artifact push``, and ``bst artifact pull``) ignore junctions in the list
|
|
969 |
+of default targets.
|
|
970 |
+ |
|
971 |
+When running BuildStream commands from a workspace directory (that is not a
|
|
972 |
+BuildStream project directory), project default targets are not used and the
|
|
973 |
+workspace element will be used as the default target instead.
|
|
974 |
+ |
|
975 |
+.. note::
|
|
976 |
+ |
|
977 |
+ The ``targets`` configuration is available since :ref:`format version 21 <project_format_version>`
|
|
978 |
+ |
|
979 |
+ |
|
948 | 980 |
.. _project_builtin_defaults:
|
949 | 981 |
|
950 | 982 |
Builtin defaults
|
... | ... | @@ -2,6 +2,7 @@ import os |
2 | 2 |
import tarfile
|
3 | 3 |
import hashlib
|
4 | 4 |
import pytest
|
5 |
+import subprocess
|
|
5 | 6 |
from tests.testutils import cli, create_repo, ALL_REPO_KINDS, generate_junction
|
6 | 7 |
from tests.testutils.site import IS_WINDOWS
|
7 | 8 |
|
... | ... | @@ -61,6 +62,35 @@ def test_build_checkout(datafiles, cli, strict, hardlinks): |
61 | 62 |
assert os.path.exists(filename)
|
62 | 63 |
|
63 | 64 |
|
65 |
+@pytest.mark.datafiles(DATA_DIR + "_world")
|
|
66 |
+def test_build_default_all(datafiles, cli):
|
|
67 |
+ project = os.path.join(datafiles.dirname, datafiles.basename)
|
|
68 |
+ result = cli.run(project=project, silent=True, args=['build'])
|
|
69 |
+ |
|
70 |
+ result.assert_success()
|
|
71 |
+ target_dir = os.path.join(cli.directory, DATA_DIR + "_world", "elements")
|
|
72 |
+ output_dir = os.path.join(cli.directory, "logs", "test")
|
|
73 |
+ |
|
74 |
+ expected = subprocess.Popen(('ls', target_dir), stdout=subprocess.PIPE)
|
|
75 |
+ expected = subprocess.check_output(("wc", "-w"), stdin=expected.stdout)
|
|
76 |
+ |
|
77 |
+ results = subprocess.Popen(('ls', output_dir), stdout=subprocess.PIPE)
|
|
78 |
+ results = subprocess.check_output(("wc", "-w"), stdin=results.stdout)
|
|
79 |
+ |
|
80 |
+ assert results == expected
|
|
81 |
+ |
|
82 |
+ |
|
83 |
+@pytest.mark.datafiles(DATA_DIR + "_default")
|
|
84 |
+def test_build_default(cli, datafiles):
|
|
85 |
+ project = os.path.join(datafiles.dirname, datafiles.basename)
|
|
86 |
+ result = cli.run(project=project, silent=True, args=['build'])
|
|
87 |
+ |
|
88 |
+ result.assert_success()
|
|
89 |
+ results = cli.get_element_state(project, "target2.bst")
|
|
90 |
+ expected = "cached"
|
|
91 |
+ assert results == expected
|
|
92 |
+ |
|
93 |
+ |
|
64 | 94 |
@pytest.mark.datafiles(DATA_DIR)
|
65 | 95 |
@pytest.mark.parametrize("strict,hardlinks", [
|
66 | 96 |
("non-strict", "hardlinks"),
|
... | ... | @@ -550,6 +580,53 @@ def test_build_checkout_junction(cli, tmpdir, datafiles): |
550 | 580 |
assert contents == 'animal=Pony\n'
|
551 | 581 |
|
552 | 582 |
|
583 |
+# Test that default targets work with projects with junctions
|
|
584 |
+@pytest.mark.datafiles(DATA_DIR + "_world")
|
|
585 |
+def test_build_checkout_junction_default_targets(cli, tmpdir, datafiles):
|
|
586 |
+ project = os.path.join(datafiles.dirname, datafiles.basename)
|
|
587 |
+ subproject_path = os.path.join(project, 'files', 'sub-project')
|
|
588 |
+ junction_path = os.path.join(project, 'elements', 'junction.bst')
|
|
589 |
+ element_path = os.path.join(project, 'elements', 'junction-dep.bst')
|
|
590 |
+ checkout = os.path.join(cli.directory, 'checkout')
|
|
591 |
+ |
|
592 |
+ # Create a repo to hold the subproject and generate a junction element for it
|
|
593 |
+ ref = generate_junction(tmpdir, subproject_path, junction_path)
|
|
594 |
+ |
|
595 |
+ # Create a stack element to depend on a cross junction element
|
|
596 |
+ #
|
|
597 |
+ element = {
|
|
598 |
+ 'kind': 'stack',
|
|
599 |
+ 'depends': [
|
|
600 |
+ {
|
|
601 |
+ 'junction': 'junction.bst',
|
|
602 |
+ 'filename': 'import-etc.bst'
|
|
603 |
+ }
|
|
604 |
+ ]
|
|
605 |
+ }
|
|
606 |
+ _yaml.dump(element, element_path)
|
|
607 |
+ |
|
608 |
+ # Now try to build it, this should automatically result in fetching
|
|
609 |
+ # the junction itself at load time.
|
|
610 |
+ result = cli.run(project=project, args=['build'])
|
|
611 |
+ result.assert_success()
|
|
612 |
+ |
|
613 |
+ # Assert that it's cached now
|
|
614 |
+ assert cli.get_element_state(project, 'junction-dep.bst') == 'cached'
|
|
615 |
+ |
|
616 |
+ # Now check it out
|
|
617 |
+ result = cli.run(project=project, args=[
|
|
618 |
+ 'artifact', 'checkout', 'junction-dep.bst', '--directory', checkout
|
|
619 |
+ ])
|
|
620 |
+ result.assert_success()
|
|
621 |
+ |
|
622 |
+ # Assert the content of /etc/animal.conf
|
|
623 |
+ filename = os.path.join(checkout, 'etc', 'animal.conf')
|
|
624 |
+ assert os.path.exists(filename)
|
|
625 |
+ with open(filename, 'r') as f:
|
|
626 |
+ contents = f.read()
|
|
627 |
+ assert contents == 'animal=Pony\n'
|
|
628 |
+ |
|
629 |
+ |
|
553 | 630 |
@pytest.mark.datafiles(DATA_DIR)
|
554 | 631 |
def test_build_checkout_workspaced_junction(cli, tmpdir, datafiles):
|
555 | 632 |
project = os.path.join(datafiles.dirname, datafiles.basename)
|
... | ... | @@ -49,6 +49,41 @@ def test_fetch(cli, tmpdir, datafiles, kind): |
49 | 49 |
assert cli.get_element_state(project, element_name) == 'buildable'
|
50 | 50 |
|
51 | 51 |
|
52 |
+@pytest.mark.datafiles(os.path.join(TOP_DIR, 'project_world'))
|
|
53 |
+def test_fetch_default_targets(cli, tmpdir, datafiles):
|
|
54 |
+ project = os.path.join(datafiles.dirname, datafiles.basename)
|
|
55 |
+ element_path = os.path.join(project, 'elements')
|
|
56 |
+ element_name = 'fetch-test.bst'
|
|
57 |
+ |
|
58 |
+ # Create our repo object of the given source type with
|
|
59 |
+ # the bin files, and then collect the initial ref.
|
|
60 |
+ #
|
|
61 |
+ repo = create_repo('git', str(tmpdir))
|
|
62 |
+ ref = repo.create(project)
|
|
63 |
+ |
|
64 |
+ # Write out our test target
|
|
65 |
+ element = {
|
|
66 |
+ 'kind': 'import',
|
|
67 |
+ 'sources': [
|
|
68 |
+ repo.source_config(ref=ref)
|
|
69 |
+ ]
|
|
70 |
+ }
|
|
71 |
+ _yaml.dump(element,
|
|
72 |
+ os.path.join(element_path,
|
|
73 |
+ element_name))
|
|
74 |
+ |
|
75 |
+ # Assert that a fetch is needed
|
|
76 |
+ assert cli.get_element_state(project, element_name) == 'fetch needed'
|
|
77 |
+ |
|
78 |
+ # Now try to fetch it, using the default target feature
|
|
79 |
+ result = cli.run(project=project, args=['source', 'fetch'])
|
|
80 |
+ result.assert_success()
|
|
81 |
+ |
|
82 |
+ # Assert that we are now buildable because the source is
|
|
83 |
+ # now cached.
|
|
84 |
+ assert cli.get_element_state(project, element_name) == 'buildable'
|
|
85 |
+ |
|
86 |
+ |
|
52 | 87 |
@pytest.mark.datafiles(os.path.join(TOP_DIR, 'consistencyerror'))
|
53 | 88 |
def test_fetch_consistency_error(cli, tmpdir, datafiles):
|
54 | 89 |
project = os.path.join(datafiles.dirname, datafiles.basename)
|
1 |
+kind: stack
|
|
2 |
+description: |
|
|
3 |
+ |
|
4 |
+ Main stack target for the bst build test
|
1 |
+kind: stack
|
|
2 |
+description: |
|
|
3 |
+ |
|
4 |
+ Main stack target for the bst build test
|
1 |
+# Project config for frontend build test
|
|
2 |
+name: test
|
|
3 |
+ |
|
4 |
+element-path: elements
|
|
5 |
+ |
|
6 |
+fatal-warnings:
|
|
7 |
+- bad-element-suffix
|
|
8 |
+ |
|
9 |
+defaults:
|
|
10 |
+ targets:
|
|
11 |
+ - target2.bst
|
1 |
+kind: compose
|
|
2 |
+ |
|
3 |
+depends:
|
|
4 |
+- fileNAME: import-dev.bst
|
|
5 |
+ type: build
|
|
6 |
+ |
|
7 |
+config:
|
|
8 |
+ # Dont try running the sandbox, we dont have a
|
|
9 |
+ # runtime to run anything in this context.
|
|
10 |
+ integrate: False
|
1 |
+kind: import
|
|
2 |
+sources:
|
|
3 |
+- kind: local
|
|
4 |
+ path: files/dev-files
|
1 |
+kind: stack
|
|
2 |
+description: |
|
|
3 |
+ |
|
4 |
+ Main stack target for the bst build test
|
|
5 |
+ |
|
6 |
+depends:
|
|
7 |
+- compose-all.bst
|
1 |
+#ifndef __PONY_H__
|
|
2 |
+#define __PONY_H__
|
|
3 |
+ |
|
4 |
+#define PONY_BEGIN "Once upon a time, there was a pony."
|
|
5 |
+#define PONY_END "And they lived happily ever after, the end."
|
|
6 |
+ |
|
7 |
+#define MAKE_PONY(story) \
|
|
8 |
+ PONY_BEGIN \
|
|
9 |
+ story \
|
|
10 |
+ PONY_END
|
|
11 |
+ |
|
12 |
+#endif /* __PONY_H__ */
|
1 |
+# Project config for frontend build test
|
|
2 |
+name: test
|
|
3 |
+ |
|
4 |
+element-path: elements
|
1 |
+kind: stack
|
|
2 |
+description: It is important for this element to have both build and runtime dependencies
|
|
3 |
+depends:
|
|
4 |
+- filename: import-dev.bst
|
|
5 |
+ type: build
|
|
6 |
+- filename: import-bin.bst
|
|
7 |
+ type: runtime
|
1 |
+kind: compose
|
|
2 |
+ |
|
3 |
+depends:
|
|
4 |
+- filename: import-bin.bst
|
|
5 |
+ type: build
|
|
6 |
+- filename: import-dev.bst
|
|
7 |
+ type: build
|
|
8 |
+ |
|
9 |
+config:
|
|
10 |
+ # Dont try running the sandbox, we dont have a
|
|
11 |
+ # runtime to run anything in this context.
|
|
12 |
+ integrate: False
|
1 |
+kind: compose
|
|
2 |
+ |
|
3 |
+depends:
|
|
4 |
+- filename: import-bin.bst
|
|
5 |
+ type: build
|
|
6 |
+- filename: import-dev.bst
|
|
7 |
+ type: build
|
|
8 |
+ |
|
9 |
+config:
|
|
10 |
+ # Dont try running the sandbox, we dont have a
|
|
11 |
+ # runtime to run anything in this context.
|
|
12 |
+ integrate: False
|
|
13 |
+ |
|
14 |
+ # Exclude the dev domain
|
|
15 |
+ exclude:
|
|
16 |
+ - devel
|
1 |
+kind: compose
|
|
2 |
+ |
|
3 |
+depends:
|
|
4 |
+- filename: import-bin.bst
|
|
5 |
+ type: build
|
|
6 |
+- filename: import-dev.bst
|
|
7 |
+ type: build
|
|
8 |
+ |
|
9 |
+config:
|
|
10 |
+ # Dont try running the sandbox, we dont have a
|
|
11 |
+ # runtime to run anything in this context.
|
|
12 |
+ integrate: False
|
|
13 |
+ |
|
14 |
+ # Only include the runtim
|
|
15 |
+ include:
|
|
16 |
+ - runtime
|
1 |
+kind: stack
|
1 |
+kind: stack
|
1 |
+kind: compose
|
|
2 |
+ |
|
3 |
+build-depends:
|
|
4 |
+- target.bst
|
1 |
+kind: stack
|
|
2 |
+description: |
|
|
3 |
+ |
|
4 |
+ Main stack target for the bst build test
|
|
5 |
+ |
|
6 |
+depends:
|
|
7 |
+- import-bin.bst
|
|
8 |
+- compose-all.bst
|
1 |
+kind: import
|
|
2 |
+sources:
|
|
3 |
+- kind: local
|
|
4 |
+ path: files/etc-files
|
1 |
+animal=Pony
|
1 |
+# Project config for frontend build test
|
|
2 |
+name: subtest
|
|
3 |
+ |
|
4 |
+element-path: elements
|
1 |
+# Project config for frontend build test
|
|
2 |
+name: test
|
|
3 |
+ |
|
4 |
+element-path: elements
|
|
5 |
+ |
|
6 |
+fatal-warnings:
|
|
7 |
+- bad-element-suffix
|
... | ... | @@ -78,6 +78,56 @@ def test_push_pull_all(cli, tmpdir, datafiles): |
78 | 78 |
assert not any(states[e] != 'cached' for e in all_elements)
|
79 | 79 |
|
80 | 80 |
|
81 |
+# Tests that:
|
|
82 |
+#
|
|
83 |
+# * `bst push` (default targets) pushes all built elements to configured 'push' cache
|
|
84 |
+# * `bst pull` (default targets) downloads everything from cache after local deletion
|
|
85 |
+#
|
|
86 |
+@pytest.mark.datafiles(DATA_DIR + '_world')
|
|
87 |
+def test_push_pull_default_targets(cli, tmpdir, datafiles):
|
|
88 |
+ project = os.path.join(datafiles.dirname, datafiles.basename)
|
|
89 |
+ |
|
90 |
+ with create_artifact_share(os.path.join(str(tmpdir), 'artifactshare')) as share:
|
|
91 |
+ |
|
92 |
+ # First build the target elements
|
|
93 |
+ cli.configure({
|
|
94 |
+ 'artifacts': {'url': share.repo}
|
|
95 |
+ })
|
|
96 |
+ result = cli.run(project=project, args=['build'])
|
|
97 |
+ result.assert_success()
|
|
98 |
+ assert cli.get_element_state(project, 'target.bst') == 'cached'
|
|
99 |
+ |
|
100 |
+ # Push all elements
|
|
101 |
+ cli.configure({
|
|
102 |
+ 'artifacts': {'url': share.repo, 'push': True}
|
|
103 |
+ })
|
|
104 |
+ result = cli.run(project=project, args=['artifact', 'push'])
|
|
105 |
+ result.assert_success()
|
|
106 |
+ |
|
107 |
+ # Assert that everything is now cached in the remote.
|
|
108 |
+ all_elements = ['target.bst', 'import-bin.bst', 'import-dev.bst', 'compose-all.bst']
|
|
109 |
+ for element_name in all_elements:
|
|
110 |
+ assert_shared(cli, share, project, element_name)
|
|
111 |
+ |
|
112 |
+ # Now we've pushed, delete the user's local artifact cache
|
|
113 |
+ # directory and try to redownload it from the share
|
|
114 |
+ #
|
|
115 |
+ artifacts = os.path.join(cli.directory, 'artifacts')
|
|
116 |
+ shutil.rmtree(artifacts)
|
|
117 |
+ |
|
118 |
+ # Assert that nothing is cached locally anymore
|
|
119 |
+ states = cli.get_element_states(project, all_elements)
|
|
120 |
+ assert not any(states[e] == 'cached' for e in all_elements)
|
|
121 |
+ |
|
122 |
+ # Now try bst pull
|
|
123 |
+ result = cli.run(project=project, args=['artifact', 'pull'])
|
|
124 |
+ result.assert_success()
|
|
125 |
+ |
|
126 |
+ # And assert that it's again in the local cache, without having built
|
|
127 |
+ states = cli.get_element_states(project, all_elements)
|
|
128 |
+ assert not any(states[e] != 'cached' for e in all_elements)
|
|
129 |
+ |
|
130 |
+ |
|
81 | 131 |
# Tests that:
|
82 | 132 |
#
|
83 | 133 |
# * `bst build` pushes all build elements ONLY to configured 'push' cache
|
... | ... | @@ -45,6 +45,27 @@ def test_show_invalid_element_path(cli, datafiles): |
45 | 45 |
'show',
|
46 | 46 |
"foo.bst"])
|
47 | 47 |
|
48 |
+ |
|
49 |
+@pytest.mark.datafiles(os.path.join(DATA_DIR, 'project_default'))
|
|
50 |
+def test_show_default(cli, datafiles):
|
|
51 |
+ project = os.path.join(datafiles.dirname, datafiles.basename)
|
|
52 |
+ result = cli.run(project=project, silent=True, args=[
|
|
53 |
+ 'show'])
|
|
54 |
+ |
|
55 |
+ result.assert_success()
|
|
56 |
+ |
|
57 |
+ # Get the result output of "[state sha element]" and turn into a list
|
|
58 |
+ results = result.output.strip().split(" ")
|
|
59 |
+ expected = 'target2.bst'
|
|
60 |
+ assert results[2] == expected
|
|
61 |
+ |
|
62 |
+ |
|
63 |
+@pytest.mark.datafiles(os.path.join(DATA_DIR, 'project_fail'))
|
|
64 |
+def test_show_fail(cli, datafiles):
|
|
65 |
+ project = os.path.join(datafiles.dirname, datafiles.basename)
|
|
66 |
+ result = cli.run(project=project, silent=True, args=[
|
|
67 |
+ 'show'])
|
|
68 |
+ |
|
48 | 69 |
result.assert_main_error(ErrorDomain.LOAD, LoadErrorReason.INVALID_DATA)
|
49 | 70 |
|
50 | 71 |
|