You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@buildstream.apache.org by no...@apache.org on 2020/12/29 12:58:55 UTC

[buildstream] 06/06: Implement new required 'version' specification in project.conf

This is an automated email from the ASF dual-hosted git repository.

not-in-ldap pushed a commit to branch tristan/bst2-separation
in repository https://gitbox.apache.org/repos/asf/buildstream.git

commit 8af144d30d3a743fa946e8579b85f7789b72e1ba
Author: Tristan Van Berkom <tr...@codethink.co.uk>
AuthorDate: Wed Apr 10 19:46:47 2019 +0900

    Implement new required 'version' specification in project.conf
    
    This adds a required field to project.conf to specify the BuildStream
    version required by the project, and this serves two separate purposes
    at once:
    
      A.) It is a more practical method for users to specify the format-version
    
          The "format-version" field requires that users know about which
          format version each YAML feature was added in, and this version
          is separate from the BuildStream version.
    
          As such, it is more difficult to use - the field is still
          preserved and supported, but mostly only useful in order
          to depend on format versions in unstable release periods.
    
      B.) It serves to ensure that the wrong major point version
          of BuildStream is never used with the wrong project.
    
    Changes in this commit include:
    
      * _versions.py: Added BST_API_VERION_MAJOR and BST_API_VERION_MINOR
    
        These include comments about how the fields must be updated when
        work commences on any major or minor point stable release, usually
        on the master branch.
    
      * _project.py: Support parsing the new "version"
    
      * _frontend/app.py: The `bst init` command has been extended to also
        dump the current API version automatically.
    
        This should really be enhanced separately, but since the test cases
        use `bst init` in some places in order to create projects for test
        purposes, I've included the minimal change here and will enhance
        `bst init` separately.
    
      * tests: All tests updated to include a "version: 2.0" specification
        in the project.conf files under test
---
 buildstream2/_frontend/app.py                      |  5 +++-
 buildstream2/_project.py                           | 33 ++++++++++++++++++++--
 buildstream2/_versions.py                          | 25 ++++++++++++++++
 buildstream2/testing/_sourcetests/mirror.py        | 12 ++++++--
 .../project/files/sub-project/project.conf         |  3 +-
 .../testing/_sourcetests/project/project.conf      |  1 +
 .../testing/_sourcetests/track_cross_junction.py   |  1 +
 buildstream2/testing/_utils/__init__.py            |  1 +
 doc/examples/autotools/project.conf                |  4 +--
 doc/examples/developing/project.conf               |  4 +--
 doc/examples/first-project/project.conf            |  4 +--
 doc/examples/flatpak-autotools/project.conf        |  2 ++
 doc/examples/integration-commands/project.conf     |  4 +--
 doc/examples/junctions/autotools/project.conf      |  4 +--
 doc/examples/junctions/project.conf                |  4 +--
 doc/examples/running-commands/project.conf         |  4 +--
 tests/artifactcache/cache_size.py                  |  3 +-
 tests/artifactcache/config.py                      |  3 +-
 tests/artifactcache/expiry/project.conf            |  1 +
 .../artifactcache/junctions/foo/base/project.conf  |  1 +
 tests/artifactcache/junctions/foo/project.conf     |  1 +
 tests/artifactcache/project/project.conf           |  3 +-
 tests/cachekey/cachekey.py                         |  1 +
 tests/cachekey/project/project.conf                |  1 +
 tests/elements/filter.py                           |  5 ++++
 tests/elements/filter/basic/project.conf           |  1 +
 tests/format/assertion/project.conf                |  1 +
 tests/format/dependencies1/project.conf            |  2 +-
 tests/format/dependencies2/project.conf            |  3 +-
 tests/format/include.py                            |  4 +--
 tests/format/include/conditional/project.conf      |  1 +
 .../format/include/eventual_overrides/project.conf |  1 +
 tests/format/include/file/project.conf             |  1 +
 .../include/file_with_subproject/project.conf      |  1 +
 .../file_with_subproject/subproject/project.conf   |  1 +
 tests/format/include/inner/project.conf            |  1 +
 tests/format/include/junction/project.conf         |  1 +
 .../include/junction/subproject/project.conf       |  1 +
 .../format/include/local_to_junction/project.conf  |  1 +
 .../local_to_junction/subproject/project.conf      |  1 +
 tests/format/include/options/project.conf          |  1 +
 .../format/include/overrides-junction/project.conf |  1 +
 .../overrides-junction/subproject/project.conf     |  1 +
 tests/format/include/overrides/project.conf        |  1 +
 .../include/overrides/subproject/project.conf      |  1 +
 tests/format/include/recursive/project.conf        |  1 +
 tests/format/include/string/project.conf           |  1 +
 tests/format/include/sub-include/project.conf      |  1 +
 tests/format/include_composition.py                |  2 +-
 tests/format/junctions/bar/project.conf            |  1 +
 tests/format/junctions/base/project.conf           |  1 +
 tests/format/junctions/conflict/project.conf       |  1 +
 tests/format/junctions/foo/project.conf            |  1 +
 .../junctionA/junctionB/project.conf               |  1 +
 .../inconsistent-names/junctionA/project.conf      |  1 +
 .../junctions/inconsistent-names/project.conf      |  1 +
 tests/format/junctions/invalid/project.conf        |  1 +
 .../junctionA/junctionB/project.conf               |  1 +
 .../missing-element/junctionA/project.conf         |  1 +
 .../format/junctions/missing-element/project.conf  |  1 +
 tests/format/junctions/nested/project.conf         |  1 +
 tests/format/junctions/options-base/project.conf   |  1 +
 .../format/junctions/options-default/project.conf  |  1 +
 .../format/junctions/options-inherit/project.conf  |  1 +
 tests/format/junctions/options/project.conf        |  1 +
 tests/format/junctions/toplevel/project.conf       |  1 +
 .../list-directive-error-element/project.conf      |  1 +
 .../list-directive-error-project/project.conf      |  1 +
 .../format/list-directive-type-error/project.conf  |  1 +
 tests/format/option-arch-alias/project.conf        |  1 +
 tests/format/option-arch-unknown/project.conf      |  1 +
 tests/format/option-arch/project.conf              |  1 +
 tests/format/option-bool/project.conf              |  1 +
 .../option-element-mask-invalid/project.conf       |  1 +
 tests/format/option-element-mask/project.conf      |  1 +
 tests/format/option-enum-missing/project.conf      |  1 +
 tests/format/option-enum/project.conf              |  1 +
 tests/format/option-exports/project.conf           |  1 +
 tests/format/option-flags-missing/project.conf     |  1 +
 tests/format/option-flags/project.conf             |  1 +
 tests/format/option-os/project.conf                |  1 +
 tests/format/option-overrides/project.conf         |  1 +
 .../options/compound-and-condition/project.conf    |  1 +
 .../options/compound-or-condition/project.conf     |  1 +
 tests/format/options/deep-nesting/project.conf     |  1 +
 .../format/options/invalid-condition/project.conf  |  1 +
 .../format/options/invalid-expression/project.conf |  1 +
 .../options/invalid-name-dashes/project.conf       |  1 +
 .../invalid-name-leading-number/project.conf       |  1 +
 .../format/options/invalid-name-plus/project.conf  |  1 +
 .../options/invalid-name-spaces/project.conf       |  1 +
 tests/format/options/invalid-type/project.conf     |  1 +
 .../invalid-variable-name-plus/project.conf        |  1 +
 .../invalid-variable-name-spaces/project.conf      |  1 +
 tests/format/options/nested-condition/project.conf |  1 +
 tests/format/options/simple-condition/project.conf |  1 +
 .../format/options/undefined-variable/project.conf |  1 +
 .../prepend-configure-commands/project.conf        |  1 +
 tests/format/project.py                            |  1 +
 tests/format/project/default/project.conf          |  1 +
 .../format/project/duplicate-plugins/project.conf  |  1 +
 tests/format/project/element-path/project.conf     |  1 +
 tests/format/project/empty-depends/project.conf    |  1 +
 tests/format/project/emptyname/project.conf        |  1 +
 tests/format/project/invalid-yaml/project.conf     |  4 +--
 tests/format/project/invalidname/project.conf      |  1 +
 tests/format/project/local-plugin/project.conf     |  1 +
 tests/format/project/missing-element/project.conf  |  1 +
 tests/format/project/missing-junction/project.conf |  1 +
 tests/format/project/missingname/project.conf      |  1 +
 tests/format/project/overridepath/project.conf     |  1 +
 tests/format/project/plugin-allowed/project.conf   |  1 +
 tests/format/project/plugin-forbidden/project.conf |  1 +
 .../project/plugin-preflight-error/project.conf    |  1 +
 .../project/project-from-subdir/project.conf       |  4 +--
 tests/format/project/refs-options/project.conf     |  1 +
 tests/format/project/unsupported/project.conf      |  1 +
 tests/format/variables.py                          |  2 ++
 .../format/variables/cyclic_variables/project.conf |  1 +
 tests/format/variables/defaults/project.conf       |  3 +-
 .../variables/missing_variables/project.conf       |  3 +-
 tests/format/variables/overrides/project.conf      |  3 +-
 tests/format/variables/protected-vars/project.conf |  1 +
 tests/frontend/__init__.py                         |  1 +
 .../completions/no-element-path/project.conf       |  2 +-
 tests/frontend/completions/project/project.conf    |  3 +-
 .../frontend/completions/sub-folders/project.conf  |  3 +-
 tests/frontend/configurable_warnings.py            |  1 +
 tests/frontend/configuredwarning/project.conf      |  1 +
 tests/frontend/consistencyerror/project.conf       |  1 +
 tests/frontend/cross_junction_workspace.py         |  4 +--
 tests/frontend/exceptions/project.conf             |  3 +-
 tests/frontend/invalid_element_path/project.conf   |  3 +-
 tests/frontend/mirror.py                           |  5 ++++
 tests/frontend/overlaps.py                         |  3 +-
 .../project/files/sub-project/project.conf         |  3 +-
 tests/frontend/project/project.conf                |  3 +-
 tests/frontend/project_default/project.conf        |  3 +-
 tests/frontend/project_fail/project.conf           |  3 +-
 .../project_world/files/sub-project/project.conf   |  3 +-
 tests/frontend/project_world/project.conf          |  3 +-
 .../track-cross-junction/subproject/project.conf   |  1 +
 tests/frontend/track-optional-inline/project.conf  |  2 +-
 .../track-optional-project-refs/project.conf       |  1 +
 tests/frontend/track.py                            |  1 +
 tests/frontend/workspaced-build-dep/project.conf   |  4 +--
 tests/frontend/workspaced-runtime-dep/project.conf |  4 +--
 tests/integration/project/project.conf             |  2 +-
 tests/internals/loader/onefile/project.conf        |  1 +
 .../pluginloading/badversionelement/project.conf   |  1 +
 .../pluginloading/badversionsource/project.conf    |  1 +
 .../pluginloading/customelement/project.conf       |  1 +
 .../pluginloading/customsource/project.conf        |  1 +
 .../deprecationwarnings/project/project.conf       |  4 +--
 tests/remoteexecution/project/project.conf         |  1 +
 tests/sandboxes/missing-command/project.conf       |  1 +
 tests/sandboxes/missing-dependencies/project.conf  |  2 +-
 tests/sourcecache/project/project.conf             |  2 +-
 tests/sources/bzr/project.conf                     |  1 +
 tests/sources/deb.py                               |  1 +
 tests/sources/git.py                               |  5 ++++
 tests/sources/git/project-override/project.conf    |  1 +
 tests/sources/git/template/project.conf            |  1 +
 tests/sources/local/basic/project.conf             |  1 +
 tests/sources/local/directory/project.conf         |  1 +
 tests/sources/local/file-exists/project.conf       |  1 +
 .../local/invalid-relative-path/project.conf       |  1 +
 tests/sources/local/symlink/project.conf           |  1 +
 tests/sources/no-fetch-cached/project.conf         |  2 +-
 tests/sources/ostree/template/project.conf         |  1 +
 tests/sources/patch/basic/project.conf             |  1 +
 .../patch/different-strip-level/project.conf       |  1 +
 .../patch/invalid-relative-path/project.conf       |  1 +
 tests/sources/patch/multiple-patches/project.conf  |  1 +
 .../sources/patch/separate-patch-dir/project.conf  |  1 +
 tests/sources/pip.py                               |  2 +-
 tests/sources/previous_source_access/project.conf  |  2 ++
 tests/sources/project_key_test/project.conf        |  2 +-
 tests/sources/remote.py                            |  2 ++
 tests/sources/tar.py                               |  2 ++
 tests/sources/zip.py                               |  2 ++
 181 files changed, 282 insertions(+), 78 deletions(-)

diff --git a/buildstream2/_frontend/app.py b/buildstream2/_frontend/app.py
index d4ea838..9849367 100644
--- a/buildstream2/_frontend/app.py
+++ b/buildstream2/_frontend/app.py
@@ -36,7 +36,7 @@ from .._project import Project
 from .._exceptions import BstError, StreamError, LoadError, LoadErrorReason, AppError
 from .._message import Message, MessageType, unconditional_messages
 from .._stream import Stream
-from .._versions import BST_FORMAT_VERSION
+from .._versions import BST_FORMAT_VERSION, BST_API_VERSION_MAJOR, BST_API_VERSION_MINOR
 from .. import _yaml
 from .._scheduler import ElementJob, JobStatus
 
@@ -355,6 +355,9 @@ class App():
                 with open(project_path, 'w') as f:
                     f.write("# Unique project name\n" +
                             "name: {}\n\n".format(project_name) +
+                            "# Required BuildStream version\n" +
+                            "version: {}.{}\n\n".format(BST_API_VERSION_MAJOR,
+                                                        BST_API_VERSION_MINOR) +
                             "# Required BuildStream format version\n" +
                             "format-version: {}\n\n".format(format_version) +
                             "# Subdirectory where elements are stored\n" +
diff --git a/buildstream2/_project.py b/buildstream2/_project.py
index 788ebb4..d45cde7 100644
--- a/buildstream2/_project.py
+++ b/buildstream2/_project.py
@@ -40,7 +40,7 @@ from ._elementfactory import ElementFactory
 from ._sourcefactory import SourceFactory
 from .types import CoreWarnings
 from ._projectrefs import ProjectRefs, ProjectRefStorage
-from ._versions import BST_FORMAT_VERSION
+from ._versions import BST_FORMAT_VERSION, BST_API_VERSION_MAJOR, BST_API_VERSION_MINOR
 from ._loader import Loader
 from .element import Element
 from ._message import Message, MessageType
@@ -331,7 +331,7 @@ class Project():
 
     def _validate_node(self, node):
         _yaml.node_validate(node, [
-            'format-version',
+            'version', 'format-version',
             'element-path', 'variables',
             'environment', 'environment-nocache',
             'split-rules', 'elements', 'plugins',
@@ -583,6 +583,10 @@ class Project():
         _yaml.composite(pre_config_node, self._project_conf)
 
         # Assert project's format version early, before validating toplevel keys
+        #
+        # This is optional and allows fine grained control on format additions
+        # in between stable releases.
+        #
         format_version = _yaml.node_get(pre_config_node, int, 'format-version')
         if BST_FORMAT_VERSION < format_version:
             major, minor = utils.get_bst_version()
@@ -591,6 +595,31 @@ class Project():
                 "Project requested format version {}, but BuildStream {}.{} only supports up until format version {}"
                 .format(format_version, major, minor, BST_FORMAT_VERSION))
 
+        # Assert project's API version early, before validating toplevel keys
+        #
+        # This is mandatory (there is no default specified in the default project YAML),
+        # and this is the normal way for specifying the minimal version of BuildStream
+        # required by the project.
+        api_version = _yaml.node_get(pre_config_node, str, 'version')
+        api_versions = api_version.split('.')
+        if not all(v.isdigit() for v in api_versions) or len(api_versions) != 2:
+            p = _yaml.node_get_provenance(pre_config_node, 'version')
+            raise LoadError(
+                LoadErrorReason.INVALID_DATA,
+                "{}: Malformed version specified: {}".format(p, api_version),
+                detail="The required version must be specified as MAJOR.MINOR, " +
+                "the current version is: {}.{}".format(BST_API_VERSION_MAJOR,
+                                                       BST_API_VERSION_MINOR))
+
+        # Major version must match, minor version is minimal bound.
+        if int(api_versions[0]) != BST_API_VERSION_MAJOR or \
+           int(api_versions[1]) > BST_API_VERSION_MINOR:
+            raise LoadError(
+                LoadErrorReason.UNSUPPORTED_PROJECT,
+                "Project requested BuildStream {}.{} and cannot be loaded with BuildStream {}.{}"
+                .format(api_versions[0], api_versions[1],
+                        BST_API_VERSION_MAJOR, BST_API_VERSION_MINOR))
+
         self._validate_node(pre_config_node)
 
         # The project name, element path and option declarations
diff --git a/buildstream2/_versions.py b/buildstream2/_versions.py
index 56fd952..baf821a 100644
--- a/buildstream2/_versions.py
+++ b/buildstream2/_versions.py
@@ -17,6 +17,31 @@
 #  Authors:
 #        Tristan Van Berkom <tr...@codethink.co.uk>
 
+# The API version.
+#
+# This is encoded into BuildStream so that we can perform
+# checks in advance of a release.
+#
+# Rules for updating the versions:
+#
+#    BST_API_VERSION_MAJOR
+#    ~~~~~~~~~~~~~~~~~~~~~
+#    This indicates the main API version, it should only ever
+#    be incremented if we break API again and release BuildStream 3.
+#
+#    BST_API_VERSION_MINOR
+#    ~~~~~~~~~~~~~~~~~~~~~
+#    This should be incremented to the next even number in the master
+#    branch directly after releasing a new stable minor point release.
+#
+#    I.e. after releasing BuildStream 2.0, BST_API_VERSION_MINOR should
+#    be set to 2 in the master branch where we will create development
+#    snapshots of 2.1, leading up to the next feature adding release
+#    of 2.2.
+#
+BST_API_VERSION_MAJOR = 2
+BST_API_VERSION_MINOR = 0
+
 
 # The base BuildStream format version
 #
diff --git a/buildstream2/testing/_sourcetests/mirror.py b/buildstream2/testing/_sourcetests/mirror.py
index 7c4694e..cbc11df 100644
--- a/buildstream2/testing/_sourcetests/mirror.py
+++ b/buildstream2/testing/_sourcetests/mirror.py
@@ -70,6 +70,7 @@ def test_mirror_fetch(cli, tmpdir, datafiles, kind):
 
     project = {
         'name': 'test',
+        'version': '2.0',
         'element-path': 'elements',
         'aliases': {
             alias: upstream_map + "/"
@@ -128,6 +129,7 @@ def test_mirror_fetch_upstream_absent(cli, tmpdir, datafiles, kind):
 
     project = {
         'name': 'test',
+        'version': '2.0',
         'element-path': 'elements',
         'aliases': {
             alias: 'http://www.example.com/'
@@ -184,7 +186,8 @@ def test_mirror_from_includes(cli, tmpdir, datafiles, kind):
     config_project_dir = str(tmpdir.join('config'))
     os.makedirs(config_project_dir, exist_ok=True)
     config_project = {
-        'name': 'config'
+        'name': 'config',
+        'version': '2.0'
     }
     _yaml.dump(config_project, os.path.join(config_project_dir, 'project.conf'))
     extra_mirrors = {
@@ -204,6 +207,7 @@ def test_mirror_from_includes(cli, tmpdir, datafiles, kind):
 
     project = {
         'name': 'test',
+        'version': '2.0',
         'element-path': 'elements',
         'aliases': {
             alias: upstream_map + "/"
@@ -257,7 +261,8 @@ def test_mirror_junction_from_includes(cli, tmpdir, datafiles, kind):
     config_project_dir = str(tmpdir.join('config'))
     os.makedirs(config_project_dir, exist_ok=True)
     config_project = {
-        'name': 'config'
+        'name': 'config',
+        'version': '2.0'
     }
     _yaml.dump(config_project, os.path.join(config_project_dir, 'project.conf'))
     extra_mirrors = {
@@ -277,6 +282,7 @@ def test_mirror_junction_from_includes(cli, tmpdir, datafiles, kind):
 
     project = {
         'name': 'test',
+        'version': '2.0',
         'element-path': 'elements',
         'aliases': {
             alias: upstream_map + "/"
@@ -336,6 +342,7 @@ def test_mirror_track_upstream_present(cli, tmpdir, datafiles, kind):
 
     project = {
         'name': 'test',
+        'version': '2.0',
         'element-path': 'elements',
         'aliases': {
             alias: upstream_map + "/"
@@ -401,6 +408,7 @@ def test_mirror_track_upstream_absent(cli, tmpdir, datafiles, kind):
 
     project = {
         'name': 'test',
+        'version': '2.0',
         'element-path': 'elements',
         'aliases': {
             alias: 'http://www.example.com/'
diff --git a/buildstream2/testing/_sourcetests/project/files/sub-project/project.conf b/buildstream2/testing/_sourcetests/project/files/sub-project/project.conf
index bbb8414..2e22edc 100644
--- a/buildstream2/testing/_sourcetests/project/files/sub-project/project.conf
+++ b/buildstream2/testing/_sourcetests/project/files/sub-project/project.conf
@@ -1,4 +1,3 @@
-# Project config for frontend build test
 name: subtest
-
+version: 2.0
 element-path: elements
diff --git a/buildstream2/testing/_sourcetests/project/project.conf b/buildstream2/testing/_sourcetests/project/project.conf
index 05b68bf..c01635f 100644
--- a/buildstream2/testing/_sourcetests/project/project.conf
+++ b/buildstream2/testing/_sourcetests/project/project.conf
@@ -1,5 +1,6 @@
 # Project config for frontend build test
 name: test
+version: 2.0
 element-path: elements
 aliases:
   alpine: https://bst-integration-test-images.ams3.cdn.digitaloceanspaces.com/
diff --git a/buildstream2/testing/_sourcetests/track_cross_junction.py b/buildstream2/testing/_sourcetests/track_cross_junction.py
index 96f02e3..d4517b9 100644
--- a/buildstream2/testing/_sourcetests/track_cross_junction.py
+++ b/buildstream2/testing/_sourcetests/track_cross_junction.py
@@ -72,6 +72,7 @@ def generate_project(tmpdir, name, config=None):
 
     project_conf = {
         'name': name,
+        'version': '2.0',
         'element-path': 'elements'
     }
     project_conf.update(config)
diff --git a/buildstream2/testing/_utils/__init__.py b/buildstream2/testing/_utils/__init__.py
index 0d1484a..79b1d53 100644
--- a/buildstream2/testing/_utils/__init__.py
+++ b/buildstream2/testing/_utils/__init__.py
@@ -6,5 +6,6 @@ from .junction import generate_junction
 
 def configure_project(path, config):
     config['name'] = 'test'
+    config['version'] = '2.0'
     config['element-path'] = 'elements'
     _yaml.dump(config, os.path.join(path, 'project.conf'))
diff --git a/doc/examples/autotools/project.conf b/doc/examples/autotools/project.conf
index 96e0284..134d6e9 100644
--- a/doc/examples/autotools/project.conf
+++ b/doc/examples/autotools/project.conf
@@ -1,8 +1,8 @@
 # Unique project name
 name: autotools
 
-# Required BuildStream format version
-format-version: 9
+# Required BuildStream version
+version: 2.0
 
 # Subdirectory where elements are stored
 element-path: elements
diff --git a/doc/examples/developing/project.conf b/doc/examples/developing/project.conf
index 1ae2e08..1adafb2 100644
--- a/doc/examples/developing/project.conf
+++ b/doc/examples/developing/project.conf
@@ -1,8 +1,8 @@
 # Unique project name
 name: developing 
 
-# Required BuildStream format version
-format-version: 9
+# Required BuildStream version
+version: 2.0
 
 # Subdirectory where elements are stored
 element-path: elements
diff --git a/doc/examples/first-project/project.conf b/doc/examples/first-project/project.conf
index 2182d35..f423b27 100644
--- a/doc/examples/first-project/project.conf
+++ b/doc/examples/first-project/project.conf
@@ -1,8 +1,8 @@
 # Unique project name
 name: first-project
 
-# Required BuildStream format version
-format-version: 9
+# Required BuildStream version
+version: 2.0
 
 # Subdirectory where elements are stored
 element-path: elements
diff --git a/doc/examples/flatpak-autotools/project.conf b/doc/examples/flatpak-autotools/project.conf
index 401dc56..34faeb7 100644
--- a/doc/examples/flatpak-autotools/project.conf
+++ b/doc/examples/flatpak-autotools/project.conf
@@ -1,5 +1,7 @@
 name: flatpak-autotools
 
+version: 2.0
+
 aliases:
   gnomesdk: https://sdk.gnome.org/
 
diff --git a/doc/examples/integration-commands/project.conf b/doc/examples/integration-commands/project.conf
index 9ae5b2a..7d889a7 100644
--- a/doc/examples/integration-commands/project.conf
+++ b/doc/examples/integration-commands/project.conf
@@ -1,8 +1,8 @@
 # Unique project name
 name: integration-commands
 
-# Required BuildStream format version
-format-version: 9
+# Required BuildStream version
+version: 2.0
 
 # Subdirectory where elements are stored
 element-path: elements
diff --git a/doc/examples/junctions/autotools/project.conf b/doc/examples/junctions/autotools/project.conf
index 2cf5824..9f5f1c8 100644
--- a/doc/examples/junctions/autotools/project.conf
+++ b/doc/examples/junctions/autotools/project.conf
@@ -1,8 +1,8 @@
 # Unique project name
 name: autotools
 
-# Required BuildStream format version
-format-version: 9
+# Required BuildStream version
+version: 2.0
 
 # Subdirectory where elements are stored
 element-path: elements
diff --git a/doc/examples/junctions/project.conf b/doc/examples/junctions/project.conf
index 7f8ca6a..fc1cdec 100644
--- a/doc/examples/junctions/project.conf
+++ b/doc/examples/junctions/project.conf
@@ -1,8 +1,8 @@
 # Unique project name
 name: junctions
 
-# Required BuildStream format version
-format-version: 9
+# Required BuildStream version
+version: 2.0
 
 # Subdirectory where elements are stored
 element-path: elements
diff --git a/doc/examples/running-commands/project.conf b/doc/examples/running-commands/project.conf
index 7127b0d..85e3155 100644
--- a/doc/examples/running-commands/project.conf
+++ b/doc/examples/running-commands/project.conf
@@ -1,8 +1,8 @@
 # Unique project name
 name: running-commands
 
-# Required BuildStream format version
-format-version: 9
+# Required BuildStream version
+version: 2.0
 
 # Subdirectory where elements are stored
 element-path: elements
diff --git a/tests/artifactcache/cache_size.py b/tests/artifactcache/cache_size.py
index 1209802..6479e77 100644
--- a/tests/artifactcache/cache_size.py
+++ b/tests/artifactcache/cache_size.py
@@ -17,7 +17,8 @@ from tests.testutils import create_element_size
 def create_project(project_dir):
     project_file = os.path.join(project_dir, "project.conf")
     project_conf = {
-        "name": "test"
+        "name": "test",
+        "version": "2.0"
     }
     _yaml.dump(project_conf, project_file)
     element_name = "test.bst"
diff --git a/tests/artifactcache/config.py b/tests/artifactcache/config.py
index 1eceef5..c422e8e 100644
--- a/tests/artifactcache/config.py
+++ b/tests/artifactcache/config.py
@@ -90,6 +90,7 @@ def test_artifact_cache_precedence(tmpdir, override_caches, project_caches, user
     # Produce a fake user and project config with the cache configuration.
     user_config, project_config = configure_remote_caches(override_caches, project_caches, user_caches)
     project_config['name'] = 'test'
+    project_config['version'] = '2.0'
 
     user_config_file = str(tmpdir.join('buildstream.conf'))
     _yaml.dump(_yaml.node_sanitize(user_config), filename=user_config_file)
@@ -124,7 +125,7 @@ def test_missing_certs(cli, datafiles, config_key, config_value):
 
     project_conf = {
         'name': 'test',
-
+        'version': '2.0',
         'artifacts': {
             'url': 'https://cache.example.com:12345',
             'push': 'true',
diff --git a/tests/artifactcache/expiry/project.conf b/tests/artifactcache/expiry/project.conf
index 18db7da..2fae7ed 100644
--- a/tests/artifactcache/expiry/project.conf
+++ b/tests/artifactcache/expiry/project.conf
@@ -1,5 +1,6 @@
 # Project config for cache expiry test
 name: test
+version: 2.0
 element-path: elements
 aliases:
   project_dir: file://{project_dir}
diff --git a/tests/artifactcache/junctions/foo/base/project.conf b/tests/artifactcache/junctions/foo/base/project.conf
index 951ea1a..5ab1fe9 100644
--- a/tests/artifactcache/junctions/foo/base/project.conf
+++ b/tests/artifactcache/junctions/foo/base/project.conf
@@ -1 +1,2 @@
 name: base
+version: 2.0
diff --git a/tests/artifactcache/junctions/foo/project.conf b/tests/artifactcache/junctions/foo/project.conf
index 5a240e3..a0b5d61 100644
--- a/tests/artifactcache/junctions/foo/project.conf
+++ b/tests/artifactcache/junctions/foo/project.conf
@@ -1 +1,2 @@
 name: foo
+version: 2.0
diff --git a/tests/artifactcache/project/project.conf b/tests/artifactcache/project/project.conf
index 854e386..7c4d235 100644
--- a/tests/artifactcache/project/project.conf
+++ b/tests/artifactcache/project/project.conf
@@ -1,4 +1,3 @@
-# Project config for frontend build test
 name: test
-
+version: 2.0
 element-path: elements
diff --git a/tests/cachekey/cachekey.py b/tests/cachekey/cachekey.py
index f871f84..fbbadf5 100644
--- a/tests/cachekey/cachekey.py
+++ b/tests/cachekey/cachekey.py
@@ -193,6 +193,7 @@ def test_cache_key_fatal_warnings(cli, tmpdir, first_warnings, second_warnings,
     def run_get_cache_key(project_name, warnings):
         config = {
             'name': project_name,
+            'version': '2.0',
             'element-path': 'elements',
             'fatal-warnings': warnings
         }
diff --git a/tests/cachekey/project/project.conf b/tests/cachekey/project/project.conf
index 49726cd..4fe5d59 100644
--- a/tests/cachekey/project/project.conf
+++ b/tests/cachekey/project/project.conf
@@ -1,2 +1,3 @@
 # Project config for cache key test
 name: cachekey
+version: 2.0
diff --git a/tests/elements/filter.py b/tests/elements/filter.py
index 8da5575..14d2bbc 100644
--- a/tests/elements/filter.py
+++ b/tests/elements/filter.py
@@ -199,6 +199,7 @@ def test_filter_track(datafiles, cli, tmpdir):
 
     project_config = {
         "name": "filter-track-test",
+        "version": "2.0",
         "element-path": "elements",
     }
     project_file = os.path.join(str(tmpdir), "project.conf")
@@ -254,6 +255,7 @@ def test_filter_track_excepted(datafiles, cli, tmpdir):
 
     project_config = {
         "name": "filter-track-test",
+        "version": "2.0",
         "element-path": "elements",
     }
     project_file = os.path.join(str(tmpdir), "project.conf")
@@ -308,6 +310,7 @@ def test_filter_track_multi_to_one(datafiles, cli, tmpdir):
 
     project_config = {
         "name": "filter-track-test",
+        "version": "2.0",
         "element-path": "elements",
     }
     project_file = os.path.join(str(tmpdir), "project.conf")
@@ -364,6 +367,7 @@ def test_filter_track_multi(datafiles, cli, tmpdir):
 
     project_config = {
         "name": "filter-track-test",
+        "version": "2.0",
         "element-path": "elements",
     }
     project_file = os.path.join(str(tmpdir), "project.conf")
@@ -434,6 +438,7 @@ def test_filter_track_multi_exclude(datafiles, cli, tmpdir):
 
     project_config = {
         "name": "filter-track-test",
+        "version": "2.0",
         "element-path": "elements",
     }
     project_file = os.path.join(str(tmpdir), "project.conf")
diff --git a/tests/elements/filter/basic/project.conf b/tests/elements/filter/basic/project.conf
index 418ed02..5752adc 100644
--- a/tests/elements/filter/basic/project.conf
+++ b/tests/elements/filter/basic/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 element-path: elements
 plugins:
 - origin: local
diff --git a/tests/format/assertion/project.conf b/tests/format/assertion/project.conf
index 4c00166..5a1fd09 100644
--- a/tests/format/assertion/project.conf
+++ b/tests/format/assertion/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
   pony:
diff --git a/tests/format/dependencies1/project.conf b/tests/format/dependencies1/project.conf
index fcd60b6..7c4d235 100644
--- a/tests/format/dependencies1/project.conf
+++ b/tests/format/dependencies1/project.conf
@@ -1,3 +1,3 @@
-# Basic project
 name: test
+version: 2.0
 element-path: elements
diff --git a/tests/format/dependencies2/project.conf b/tests/format/dependencies2/project.conf
index 2027cc2..0932d16 100644
--- a/tests/format/dependencies2/project.conf
+++ b/tests/format/dependencies2/project.conf
@@ -1,3 +1,2 @@
-# Basic project configuration that doesnt override anything
-#
 name: pony
+version: 2.0
diff --git a/tests/format/include.py b/tests/format/include.py
index 4b1da92..1143bd4 100644
--- a/tests/format/include.py
+++ b/tests/format/include.py
@@ -32,7 +32,7 @@ def test_include_project_file(cli, datafiles):
 
 
 def test_include_missing_file(cli, tmpdir):
-    tmpdir.join('project.conf').write('{"name": "test"}')
+    tmpdir.join('project.conf').write('{"name": "test", "version": "2.0"}')
     element = tmpdir.join('include_missing_file.bst')
 
     # Normally we would use dicts and _yaml.dump to write such things, but here
@@ -51,7 +51,7 @@ def test_include_missing_file(cli, tmpdir):
 
 
 def test_include_dir(cli, tmpdir):
-    tmpdir.join('project.conf').write('{"name": "test"}')
+    tmpdir.join('project.conf').write('{"name": "test", "version": "2.0"}')
     tmpdir.mkdir('subdir')
     element = tmpdir.join('include_dir.bst')
 
diff --git a/tests/format/include/conditional/project.conf b/tests/format/include/conditional/project.conf
index cb54779..46e3c0b 100644
--- a/tests/format/include/conditional/project.conf
+++ b/tests/format/include/conditional/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
   build_arch:
diff --git a/tests/format/include/eventual_overrides/project.conf b/tests/format/include/eventual_overrides/project.conf
index b327536..91db2ee 100644
--- a/tests/format/include/eventual_overrides/project.conf
+++ b/tests/format/include/eventual_overrides/project.conf
@@ -1 +1,2 @@
 name: test
+version: 2.0
diff --git a/tests/format/include/file/project.conf b/tests/format/include/file/project.conf
index a7791a4..cdcfbc1 100644
--- a/tests/format/include/file/project.conf
+++ b/tests/format/include/file/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 (@):
   - extra_conf.yml
diff --git a/tests/format/include/file_with_subproject/project.conf b/tests/format/include/file_with_subproject/project.conf
index a7791a4..cdcfbc1 100644
--- a/tests/format/include/file_with_subproject/project.conf
+++ b/tests/format/include/file_with_subproject/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 (@):
   - extra_conf.yml
diff --git a/tests/format/include/file_with_subproject/subproject/project.conf b/tests/format/include/file_with_subproject/subproject/project.conf
index 7a66554..733abed 100644
--- a/tests/format/include/file_with_subproject/subproject/project.conf
+++ b/tests/format/include/file_with_subproject/subproject/project.conf
@@ -1 +1,2 @@
 name: test-sub
+version: 2.0
diff --git a/tests/format/include/inner/project.conf b/tests/format/include/inner/project.conf
index 8bdfc42..3cca4c3 100644
--- a/tests/format/include/inner/project.conf
+++ b/tests/format/include/inner/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
   (@):
diff --git a/tests/format/include/junction/project.conf b/tests/format/include/junction/project.conf
index 4836c5f..6a56aaa 100644
--- a/tests/format/include/junction/project.conf
+++ b/tests/format/include/junction/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 (@):
   - junction.bst:extra_conf.yml
diff --git a/tests/format/include/junction/subproject/project.conf b/tests/format/include/junction/subproject/project.conf
index 7a66554..733abed 100644
--- a/tests/format/include/junction/subproject/project.conf
+++ b/tests/format/include/junction/subproject/project.conf
@@ -1 +1,2 @@
 name: test-sub
+version: 2.0
diff --git a/tests/format/include/local_to_junction/project.conf b/tests/format/include/local_to_junction/project.conf
index 4836c5f..6a56aaa 100644
--- a/tests/format/include/local_to_junction/project.conf
+++ b/tests/format/include/local_to_junction/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 (@):
   - junction.bst:extra_conf.yml
diff --git a/tests/format/include/local_to_junction/subproject/project.conf b/tests/format/include/local_to_junction/subproject/project.conf
index 7a66554..733abed 100644
--- a/tests/format/include/local_to_junction/subproject/project.conf
+++ b/tests/format/include/local_to_junction/subproject/project.conf
@@ -1 +1,2 @@
 name: test-sub
+version: 2.0
diff --git a/tests/format/include/options/project.conf b/tests/format/include/options/project.conf
index a7791a4..cdcfbc1 100644
--- a/tests/format/include/options/project.conf
+++ b/tests/format/include/options/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 (@):
   - extra_conf.yml
diff --git a/tests/format/include/overrides-junction/project.conf b/tests/format/include/overrides-junction/project.conf
index d03bec6..e3a0179 100644
--- a/tests/format/include/overrides-junction/project.conf
+++ b/tests/format/include/overrides-junction/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 elements:
   junction:
diff --git a/tests/format/include/overrides-junction/subproject/project.conf b/tests/format/include/overrides-junction/subproject/project.conf
index 7a66554..733abed 100644
--- a/tests/format/include/overrides-junction/subproject/project.conf
+++ b/tests/format/include/overrides-junction/subproject/project.conf
@@ -1 +1,2 @@
 name: test-sub
+version: 2.0
diff --git a/tests/format/include/overrides/project.conf b/tests/format/include/overrides/project.conf
index fa3c757..4bc8f63 100644
--- a/tests/format/include/overrides/project.conf
+++ b/tests/format/include/overrides/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 elements:
   junction:
diff --git a/tests/format/include/overrides/subproject/project.conf b/tests/format/include/overrides/subproject/project.conf
index 7a66554..733abed 100644
--- a/tests/format/include/overrides/subproject/project.conf
+++ b/tests/format/include/overrides/subproject/project.conf
@@ -1 +1,2 @@
 name: test-sub
+version: 2.0
diff --git a/tests/format/include/recursive/project.conf b/tests/format/include/recursive/project.conf
index a7791a4..cdcfbc1 100644
--- a/tests/format/include/recursive/project.conf
+++ b/tests/format/include/recursive/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 (@):
   - extra_conf.yml
diff --git a/tests/format/include/string/project.conf b/tests/format/include/string/project.conf
index 6ee9988..4276b3e 100644
--- a/tests/format/include/string/project.conf
+++ b/tests/format/include/string/project.conf
@@ -1,3 +1,4 @@
 name: test
+version: 2.0
 
 (@): extra_conf.yml
diff --git a/tests/format/include/sub-include/project.conf b/tests/format/include/sub-include/project.conf
index 7f7df84..4dd5b28 100644
--- a/tests/format/include/sub-include/project.conf
+++ b/tests/format/include/sub-include/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 elements:
   manual:
diff --git a/tests/format/include_composition.py b/tests/format/include_composition.py
index 00097ea..2c880dd 100644
--- a/tests/format/include_composition.py
+++ b/tests/format/include_composition.py
@@ -6,7 +6,7 @@ from buildstream2 import _yaml
 
 
 def make_includes(basedir):
-    _yaml.dump({'name': 'test'},
+    _yaml.dump({'name': 'test', 'version': '2.0'},
                os.path.join(basedir, 'project.conf'))
     context = Context()
     project = Project(basedir, context)
diff --git a/tests/format/junctions/bar/project.conf b/tests/format/junctions/bar/project.conf
index f8ed662..a8ef1cc 100644
--- a/tests/format/junctions/bar/project.conf
+++ b/tests/format/junctions/bar/project.conf
@@ -1 +1,2 @@
 name: bar
+version: 2.0
diff --git a/tests/format/junctions/base/project.conf b/tests/format/junctions/base/project.conf
index 951ea1a..5ab1fe9 100644
--- a/tests/format/junctions/base/project.conf
+++ b/tests/format/junctions/base/project.conf
@@ -1 +1,2 @@
 name: base
+version: 2.0
diff --git a/tests/format/junctions/conflict/project.conf b/tests/format/junctions/conflict/project.conf
index 395bb84..fd429e4 100644
--- a/tests/format/junctions/conflict/project.conf
+++ b/tests/format/junctions/conflict/project.conf
@@ -1 +1,2 @@
 name: conflict
+version: 2.0
diff --git a/tests/format/junctions/foo/project.conf b/tests/format/junctions/foo/project.conf
index 5a240e3..a0b5d61 100644
--- a/tests/format/junctions/foo/project.conf
+++ b/tests/format/junctions/foo/project.conf
@@ -1 +1,2 @@
 name: foo
+version: 2.0
diff --git a/tests/format/junctions/inconsistent-names/junctionA/junctionB/project.conf b/tests/format/junctions/inconsistent-names/junctionA/junctionB/project.conf
index 2e96170..9c41e13 100644
--- a/tests/format/junctions/inconsistent-names/junctionA/junctionB/project.conf
+++ b/tests/format/junctions/inconsistent-names/junctionA/junctionB/project.conf
@@ -1,5 +1,6 @@
 # Unique project name
 name: projectB
+version: 2.0
 
 # Subdirectory where elements are stored
 element-path: elements
diff --git a/tests/format/junctions/inconsistent-names/junctionA/project.conf b/tests/format/junctions/inconsistent-names/junctionA/project.conf
index 166c4b7..14924ba 100644
--- a/tests/format/junctions/inconsistent-names/junctionA/project.conf
+++ b/tests/format/junctions/inconsistent-names/junctionA/project.conf
@@ -1,5 +1,6 @@
 # Unique project name
 name: projectA
+version: 2.0
 
 # Subdirectory where elements are stored
 element-path: elements
diff --git a/tests/format/junctions/inconsistent-names/project.conf b/tests/format/junctions/inconsistent-names/project.conf
index 064bbc5..200a970 100644
--- a/tests/format/junctions/inconsistent-names/project.conf
+++ b/tests/format/junctions/inconsistent-names/project.conf
@@ -1,5 +1,6 @@
 # Unique project name
 name: inconsistent-names
+version: 2.0
 
 # Subdirectory where elements are stored
 element-path: elements
diff --git a/tests/format/junctions/invalid/project.conf b/tests/format/junctions/invalid/project.conf
index 38070bf..75ca8e4 100644
--- a/tests/format/junctions/invalid/project.conf
+++ b/tests/format/junctions/invalid/project.conf
@@ -1 +1,2 @@
 name: invalid
+version: 2.0
diff --git a/tests/format/junctions/missing-element/junctionA/junctionB/project.conf b/tests/format/junctions/missing-element/junctionA/junctionB/project.conf
index 41b8d6c..929fcd6 100644
--- a/tests/format/junctions/missing-element/junctionA/junctionB/project.conf
+++ b/tests/format/junctions/missing-element/junctionA/junctionB/project.conf
@@ -1 +1,2 @@
 name: projectB
+version: 2.0
diff --git a/tests/format/junctions/missing-element/junctionA/project.conf b/tests/format/junctions/missing-element/junctionA/project.conf
index 5f6ab28..eb367c6 100644
--- a/tests/format/junctions/missing-element/junctionA/project.conf
+++ b/tests/format/junctions/missing-element/junctionA/project.conf
@@ -1 +1,2 @@
 name: projectA
+version: 2.0
diff --git a/tests/format/junctions/missing-element/project.conf b/tests/format/junctions/missing-element/project.conf
index b327536..91db2ee 100644
--- a/tests/format/junctions/missing-element/project.conf
+++ b/tests/format/junctions/missing-element/project.conf
@@ -1 +1,2 @@
 name: test
+version: 2.0
diff --git a/tests/format/junctions/nested/project.conf b/tests/format/junctions/nested/project.conf
index 551f51c..37e651a 100644
--- a/tests/format/junctions/nested/project.conf
+++ b/tests/format/junctions/nested/project.conf
@@ -1 +1,2 @@
 name: nested
+version: 2.0
diff --git a/tests/format/junctions/options-base/project.conf b/tests/format/junctions/options-base/project.conf
index a98ebd5..a445a66 100644
--- a/tests/format/junctions/options-base/project.conf
+++ b/tests/format/junctions/options-base/project.conf
@@ -1,4 +1,5 @@
 name: options-base
+version: 2.0
 options:
   animal:
     type: enum
diff --git a/tests/format/junctions/options-default/project.conf b/tests/format/junctions/options-default/project.conf
index b9e58a5..f1bc5de 100644
--- a/tests/format/junctions/options-default/project.conf
+++ b/tests/format/junctions/options-default/project.conf
@@ -1 +1,2 @@
 name: options-default
+version: 2.0
diff --git a/tests/format/junctions/options-inherit/project.conf b/tests/format/junctions/options-inherit/project.conf
index 1e0ea44..e9ffe5c 100644
--- a/tests/format/junctions/options-inherit/project.conf
+++ b/tests/format/junctions/options-inherit/project.conf
@@ -1,4 +1,5 @@
 name: options-inherit
+version: 2.0
 options:
   animal:
     type: enum
diff --git a/tests/format/junctions/options/project.conf b/tests/format/junctions/options/project.conf
index de53ae1..b9b9d56 100644
--- a/tests/format/junctions/options/project.conf
+++ b/tests/format/junctions/options/project.conf
@@ -1 +1,2 @@
 name: options
+version: 2.0
diff --git a/tests/format/junctions/toplevel/project.conf b/tests/format/junctions/toplevel/project.conf
index 496c821..acf57b2 100644
--- a/tests/format/junctions/toplevel/project.conf
+++ b/tests/format/junctions/toplevel/project.conf
@@ -1 +1,2 @@
 name: toplevel
+version: 2.0
diff --git a/tests/format/list-directive-error-element/project.conf b/tests/format/list-directive-error-element/project.conf
index b327536..91db2ee 100644
--- a/tests/format/list-directive-error-element/project.conf
+++ b/tests/format/list-directive-error-element/project.conf
@@ -1 +1,2 @@
 name: test
+version: 2.0
diff --git a/tests/format/list-directive-error-project/project.conf b/tests/format/list-directive-error-project/project.conf
index 2d66408..13ca9a8 100644
--- a/tests/format/list-directive-error-project/project.conf
+++ b/tests/format/list-directive-error-project/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 artifacts:
   (>):
diff --git a/tests/format/list-directive-type-error/project.conf b/tests/format/list-directive-type-error/project.conf
index 79f7340..330589f 100644
--- a/tests/format/list-directive-type-error/project.conf
+++ b/tests/format/list-directive-type-error/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
   arch:
diff --git a/tests/format/option-arch-alias/project.conf b/tests/format/option-arch-alias/project.conf
index 47f0945..6f7e1bb 100644
--- a/tests/format/option-arch-alias/project.conf
+++ b/tests/format/option-arch-alias/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
   machine_arch:
diff --git a/tests/format/option-arch-unknown/project.conf b/tests/format/option-arch-unknown/project.conf
index 0827ec3..c3e0ca3 100644
--- a/tests/format/option-arch-unknown/project.conf
+++ b/tests/format/option-arch-unknown/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
   machine_arch:
diff --git a/tests/format/option-arch/project.conf b/tests/format/option-arch/project.conf
index 8b94232..f391552 100644
--- a/tests/format/option-arch/project.conf
+++ b/tests/format/option-arch/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
   machine_arch:
diff --git a/tests/format/option-bool/project.conf b/tests/format/option-bool/project.conf
index a51c4fc..a11d9c8 100644
--- a/tests/format/option-bool/project.conf
+++ b/tests/format/option-bool/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
   pony:
diff --git a/tests/format/option-element-mask-invalid/project.conf b/tests/format/option-element-mask-invalid/project.conf
index a3d3818..a52a15a 100644
--- a/tests/format/option-element-mask-invalid/project.conf
+++ b/tests/format/option-element-mask-invalid/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
   debug_elements:
diff --git a/tests/format/option-element-mask/project.conf b/tests/format/option-element-mask/project.conf
index ede07fb..23c9132 100644
--- a/tests/format/option-element-mask/project.conf
+++ b/tests/format/option-element-mask/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
   debug_elements:
diff --git a/tests/format/option-enum-missing/project.conf b/tests/format/option-enum-missing/project.conf
index d6cd704..9eac7e7 100644
--- a/tests/format/option-enum-missing/project.conf
+++ b/tests/format/option-enum-missing/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
   empty:
diff --git a/tests/format/option-enum/project.conf b/tests/format/option-enum/project.conf
index 0b8ea6d..3cfe5ac 100644
--- a/tests/format/option-enum/project.conf
+++ b/tests/format/option-enum/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
   brother:
diff --git a/tests/format/option-exports/project.conf b/tests/format/option-exports/project.conf
index e81a313..e7fb547 100644
--- a/tests/format/option-exports/project.conf
+++ b/tests/format/option-exports/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
 
diff --git a/tests/format/option-flags-missing/project.conf b/tests/format/option-flags-missing/project.conf
index 6554022..c45ad1f 100644
--- a/tests/format/option-flags-missing/project.conf
+++ b/tests/format/option-flags-missing/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
   empty:
diff --git a/tests/format/option-flags/project.conf b/tests/format/option-flags/project.conf
index 1cab9e3..0a7adaf 100644
--- a/tests/format/option-flags/project.conf
+++ b/tests/format/option-flags/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
   # Include an enum option here so we can compare it
diff --git a/tests/format/option-os/project.conf b/tests/format/option-os/project.conf
index 5edb507..dc9a89c 100644
--- a/tests/format/option-os/project.conf
+++ b/tests/format/option-os/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
   machine_os:
diff --git a/tests/format/option-overrides/project.conf b/tests/format/option-overrides/project.conf
index c8058f0..afc8985 100644
--- a/tests/format/option-overrides/project.conf
+++ b/tests/format/option-overrides/project.conf
@@ -2,6 +2,7 @@
 # in the element overrides.
 #
 name: test
+version: 2.0
 
 options:
   arch:
diff --git a/tests/format/options/compound-and-condition/project.conf b/tests/format/options/compound-and-condition/project.conf
index 650d017..ac4399f 100644
--- a/tests/format/options/compound-and-condition/project.conf
+++ b/tests/format/options/compound-and-condition/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
   debug:
diff --git a/tests/format/options/compound-or-condition/project.conf b/tests/format/options/compound-or-condition/project.conf
index c59cc64..8266d1c 100644
--- a/tests/format/options/compound-or-condition/project.conf
+++ b/tests/format/options/compound-or-condition/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
   debug:
diff --git a/tests/format/options/deep-nesting/project.conf b/tests/format/options/deep-nesting/project.conf
index d912cd1..9d706f5 100644
--- a/tests/format/options/deep-nesting/project.conf
+++ b/tests/format/options/deep-nesting/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 options:
   pony:
     type: bool
diff --git a/tests/format/options/invalid-condition/project.conf b/tests/format/options/invalid-condition/project.conf
index b31f35c..8c5d9a2 100644
--- a/tests/format/options/invalid-condition/project.conf
+++ b/tests/format/options/invalid-condition/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
   opt:
diff --git a/tests/format/options/invalid-expression/project.conf b/tests/format/options/invalid-expression/project.conf
index ee01472..d5c4483 100644
--- a/tests/format/options/invalid-expression/project.conf
+++ b/tests/format/options/invalid-expression/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
   opt:
diff --git a/tests/format/options/invalid-name-dashes/project.conf b/tests/format/options/invalid-name-dashes/project.conf
index 045ce56..965aa75 100644
--- a/tests/format/options/invalid-name-dashes/project.conf
+++ b/tests/format/options/invalid-name-dashes/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
   name-with-dashes:
diff --git a/tests/format/options/invalid-name-leading-number/project.conf b/tests/format/options/invalid-name-leading-number/project.conf
index bb3e2ef..eee2825 100644
--- a/tests/format/options/invalid-name-leading-number/project.conf
+++ b/tests/format/options/invalid-name-leading-number/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
   123number_is_first:
diff --git a/tests/format/options/invalid-name-plus/project.conf b/tests/format/options/invalid-name-plus/project.conf
index d62869e..e060277 100644
--- a/tests/format/options/invalid-name-plus/project.conf
+++ b/tests/format/options/invalid-name-plus/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
   name_with_+:
diff --git a/tests/format/options/invalid-name-spaces/project.conf b/tests/format/options/invalid-name-spaces/project.conf
index 66931e2..f7ed256 100644
--- a/tests/format/options/invalid-name-spaces/project.conf
+++ b/tests/format/options/invalid-name-spaces/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
   name with spaces:
diff --git a/tests/format/options/invalid-type/project.conf b/tests/format/options/invalid-type/project.conf
index b4280cd..653c919 100644
--- a/tests/format/options/invalid-type/project.conf
+++ b/tests/format/options/invalid-type/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
   opt:
diff --git a/tests/format/options/invalid-variable-name-plus/project.conf b/tests/format/options/invalid-variable-name-plus/project.conf
index 5652bb8..c0595e5 100644
--- a/tests/format/options/invalid-variable-name-plus/project.conf
+++ b/tests/format/options/invalid-variable-name-plus/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
   pony:
diff --git a/tests/format/options/invalid-variable-name-spaces/project.conf b/tests/format/options/invalid-variable-name-spaces/project.conf
index 5115115..e14c4de 100644
--- a/tests/format/options/invalid-variable-name-spaces/project.conf
+++ b/tests/format/options/invalid-variable-name-spaces/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
   pony:
diff --git a/tests/format/options/nested-condition/project.conf b/tests/format/options/nested-condition/project.conf
index 104b895..91b730a 100644
--- a/tests/format/options/nested-condition/project.conf
+++ b/tests/format/options/nested-condition/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
   debug:
diff --git a/tests/format/options/simple-condition/project.conf b/tests/format/options/simple-condition/project.conf
index b6bd29f..5afcfbd 100644
--- a/tests/format/options/simple-condition/project.conf
+++ b/tests/format/options/simple-condition/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
   opt:
diff --git a/tests/format/options/undefined-variable/project.conf b/tests/format/options/undefined-variable/project.conf
index d634ef0..b1182ca 100644
--- a/tests/format/options/undefined-variable/project.conf
+++ b/tests/format/options/undefined-variable/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 options:
   pony:
diff --git a/tests/format/project-overrides/prepend-configure-commands/project.conf b/tests/format/project-overrides/prepend-configure-commands/project.conf
index 439a218..3e95b2b 100644
--- a/tests/format/project-overrides/prepend-configure-commands/project.conf
+++ b/tests/format/project-overrides/prepend-configure-commands/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 # Test that prepending to configure-commands works
 elements:
diff --git a/tests/format/project.py b/tests/format/project.py
index 4ddd1d8..e6f4f94 100644
--- a/tests/format/project.py
+++ b/tests/format/project.py
@@ -189,6 +189,7 @@ def test_plugin_no_load_ref(cli, datafiles, ref_storage):
     #
     config = {
         'name': 'test',
+        'version': '2.0',
         'ref-storage': ref_storage,
         'plugins': [
             {
diff --git a/tests/format/project/default/project.conf b/tests/format/project/default/project.conf
index fd3134c..c2c1d5f 100644
--- a/tests/format/project/default/project.conf
+++ b/tests/format/project/default/project.conf
@@ -2,3 +2,4 @@
 #
 
 name: pony
+version: 2.0
diff --git a/tests/format/project/duplicate-plugins/project.conf b/tests/format/project/duplicate-plugins/project.conf
index 4b8f5be..e755c26 100644
--- a/tests/format/project/duplicate-plugins/project.conf
+++ b/tests/format/project/duplicate-plugins/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 plugins:
 - origin: local
diff --git a/tests/format/project/element-path/project.conf b/tests/format/project/element-path/project.conf
index 57e87de..51ffd4b 100644
--- a/tests/format/project/element-path/project.conf
+++ b/tests/format/project/element-path/project.conf
@@ -1,2 +1,3 @@
 name: foo
+version: 2.0
 element-path: elements
diff --git a/tests/format/project/empty-depends/project.conf b/tests/format/project/empty-depends/project.conf
index b327536..91db2ee 100644
--- a/tests/format/project/empty-depends/project.conf
+++ b/tests/format/project/empty-depends/project.conf
@@ -1 +1,2 @@
 name: test
+version: 2.0
diff --git a/tests/format/project/emptyname/project.conf b/tests/format/project/emptyname/project.conf
index 2c5cf07..9e74f92 100644
--- a/tests/format/project/emptyname/project.conf
+++ b/tests/format/project/emptyname/project.conf
@@ -2,3 +2,4 @@
 # this one is an empty string
 #
 name: ''
+version: 2.0
diff --git a/tests/format/project/invalid-yaml/project.conf b/tests/format/project/invalid-yaml/project.conf
index 5f9282b..e6ac02f 100644
--- a/tests/format/project/invalid-yaml/project.conf
+++ b/tests/format/project/invalid-yaml/project.conf
@@ -1,7 +1,5 @@
-# Basic project configuration that doesnt override anything
-#
-
 name: pony
+version: 2.0
 
 variables:
   sbindir: "%{bindir}
diff --git a/tests/format/project/invalidname/project.conf b/tests/format/project/invalidname/project.conf
index 3b064d7..5fec88b 100644
--- a/tests/format/project/invalidname/project.conf
+++ b/tests/format/project/invalidname/project.conf
@@ -2,3 +2,4 @@
 # this one contains a space
 #
 name: Project Name
+version: 2.0
diff --git a/tests/format/project/local-plugin/project.conf b/tests/format/project/local-plugin/project.conf
index 97166e3..b6b6308 100644
--- a/tests/format/project/local-plugin/project.conf
+++ b/tests/format/project/local-plugin/project.conf
@@ -1,4 +1,5 @@
 name: foo
+version: 2.0
 plugins:
 - origin: local
   path: plugins
diff --git a/tests/format/project/missing-element/project.conf b/tests/format/project/missing-element/project.conf
index b327536..91db2ee 100644
--- a/tests/format/project/missing-element/project.conf
+++ b/tests/format/project/missing-element/project.conf
@@ -1 +1,2 @@
 name: test
+version: 2.0
diff --git a/tests/format/project/missing-junction/project.conf b/tests/format/project/missing-junction/project.conf
index b327536..91db2ee 100644
--- a/tests/format/project/missing-junction/project.conf
+++ b/tests/format/project/missing-junction/project.conf
@@ -1 +1,2 @@
 name: test
+version: 2.0
diff --git a/tests/format/project/missingname/project.conf b/tests/format/project/missingname/project.conf
index e69de29..6ec12fe 100644
--- a/tests/format/project/missingname/project.conf
+++ b/tests/format/project/missingname/project.conf
@@ -0,0 +1 @@
+version: 2.0
diff --git a/tests/format/project/overridepath/project.conf b/tests/format/project/overridepath/project.conf
index ef1d01c..730ba19 100644
--- a/tests/format/project/overridepath/project.conf
+++ b/tests/format/project/overridepath/project.conf
@@ -1,6 +1,7 @@
 # A project configuration which overrides the sandbox PATH environment variable
 
 name: foo
+version: 2.0
 
 environment:
   PATH: /bin:/sbin
diff --git a/tests/format/project/plugin-allowed/project.conf b/tests/format/project/plugin-allowed/project.conf
index d49e40d..582fc2e 100644
--- a/tests/format/project/plugin-allowed/project.conf
+++ b/tests/format/project/plugin-allowed/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 plugins:
 - origin: local
diff --git a/tests/format/project/plugin-forbidden/project.conf b/tests/format/project/plugin-forbidden/project.conf
index 39cc3d6..785b02c 100644
--- a/tests/format/project/plugin-forbidden/project.conf
+++ b/tests/format/project/plugin-forbidden/project.conf
@@ -1,2 +1,3 @@
 name: test
+version: 2.0
 
diff --git a/tests/format/project/plugin-preflight-error/project.conf b/tests/format/project/plugin-preflight-error/project.conf
index 20a2344..31dcf12 100644
--- a/tests/format/project/plugin-preflight-error/project.conf
+++ b/tests/format/project/plugin-preflight-error/project.conf
@@ -1,6 +1,7 @@
 # Basic project configuration that doesnt override anything
 #
 name: pony
+version: 2.0
 
 # Whitelist the local test Source "errorplugin" to be loaded
 #
diff --git a/tests/format/project/project-from-subdir/project.conf b/tests/format/project/project-from-subdir/project.conf
index fd3134c..0932d16 100644
--- a/tests/format/project/project-from-subdir/project.conf
+++ b/tests/format/project/project-from-subdir/project.conf
@@ -1,4 +1,2 @@
-# Basic project configuration that doesnt override anything
-#
-
 name: pony
+version: 2.0
diff --git a/tests/format/project/refs-options/project.conf b/tests/format/project/refs-options/project.conf
index a44806d..0163d56 100644
--- a/tests/format/project/refs-options/project.conf
+++ b/tests/format/project/refs-options/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 ref-storage: project.refs
 
 options:
diff --git a/tests/format/project/unsupported/project.conf b/tests/format/project/unsupported/project.conf
index ecd8e06..a66b624 100644
--- a/tests/format/project/unsupported/project.conf
+++ b/tests/format/project/unsupported/project.conf
@@ -1,3 +1,4 @@
 # A project which requires a too new version of the format
 name: foo
+version: 2.0
 format-version: 5000
diff --git a/tests/format/variables.py b/tests/format/variables.py
index 4a954eb..f1185e9 100644
--- a/tests/format/variables.py
+++ b/tests/format/variables.py
@@ -106,6 +106,7 @@ def test_use_of_protected_var_project_conf(cli, datafiles, protected_var):
     project = str(datafiles)
     conf = {
         'name': 'test',
+        'version': '2.0',
         'variables': {
             protected_var: 'some-value'
         }
@@ -134,6 +135,7 @@ def test_use_of_protected_var_element_overrides(cli, datafiles, protected_var):
     project = str(datafiles)
     conf = {
         'name': 'test',
+        'version': '2.0',
         'elements': {
             'manual': {
                 'variables': {
diff --git a/tests/format/variables/cyclic_variables/project.conf b/tests/format/variables/cyclic_variables/project.conf
index b327536..91db2ee 100644
--- a/tests/format/variables/cyclic_variables/project.conf
+++ b/tests/format/variables/cyclic_variables/project.conf
@@ -1 +1,2 @@
 name: test
+version: 2.0
diff --git a/tests/format/variables/defaults/project.conf b/tests/format/variables/defaults/project.conf
index 2027cc2..0932d16 100644
--- a/tests/format/variables/defaults/project.conf
+++ b/tests/format/variables/defaults/project.conf
@@ -1,3 +1,2 @@
-# Basic project configuration that doesnt override anything
-#
 name: pony
+version: 2.0
diff --git a/tests/format/variables/missing_variables/project.conf b/tests/format/variables/missing_variables/project.conf
index 2027cc2..0932d16 100644
--- a/tests/format/variables/missing_variables/project.conf
+++ b/tests/format/variables/missing_variables/project.conf
@@ -1,3 +1,2 @@
-# Basic project configuration that doesnt override anything
-#
 name: pony
+version: 2.0
diff --git a/tests/format/variables/overrides/project.conf b/tests/format/variables/overrides/project.conf
index 2027cc2..0932d16 100644
--- a/tests/format/variables/overrides/project.conf
+++ b/tests/format/variables/overrides/project.conf
@@ -1,3 +1,2 @@
-# Basic project configuration that doesnt override anything
-#
 name: pony
+version: 2.0
diff --git a/tests/format/variables/protected-vars/project.conf b/tests/format/variables/protected-vars/project.conf
index 5a240e3..a0b5d61 100644
--- a/tests/format/variables/protected-vars/project.conf
+++ b/tests/format/variables/protected-vars/project.conf
@@ -1 +1,2 @@
 name: foo
+version: 2.0
diff --git a/tests/frontend/__init__.py b/tests/frontend/__init__.py
index 45da670..7d1ab5f 100644
--- a/tests/frontend/__init__.py
+++ b/tests/frontend/__init__.py
@@ -6,5 +6,6 @@ from buildstream2 import _yaml
 #
 def configure_project(path, config):
     config['name'] = 'test'
+    config['version'] = '2.0'
     config['element-path'] = 'elements'
     _yaml.dump(config, os.path.join(path, 'project.conf'))
diff --git a/tests/frontend/completions/no-element-path/project.conf b/tests/frontend/completions/no-element-path/project.conf
index e7e35e7..91db2ee 100644
--- a/tests/frontend/completions/no-element-path/project.conf
+++ b/tests/frontend/completions/no-element-path/project.conf
@@ -1,2 +1,2 @@
-# Project config for frontend build test
 name: test
+version: 2.0
diff --git a/tests/frontend/completions/project/project.conf b/tests/frontend/completions/project/project.conf
index 854e386..7c4d235 100644
--- a/tests/frontend/completions/project/project.conf
+++ b/tests/frontend/completions/project/project.conf
@@ -1,4 +1,3 @@
-# Project config for frontend build test
 name: test
-
+version: 2.0
 element-path: elements
diff --git a/tests/frontend/completions/sub-folders/project.conf b/tests/frontend/completions/sub-folders/project.conf
index 854e386..7c4d235 100644
--- a/tests/frontend/completions/sub-folders/project.conf
+++ b/tests/frontend/completions/sub-folders/project.conf
@@ -1,4 +1,3 @@
-# Project config for frontend build test
 name: test
-
+version: 2.0
 element-path: elements
diff --git a/tests/frontend/configurable_warnings.py b/tests/frontend/configurable_warnings.py
index 96accf0..7f514cd 100644
--- a/tests/frontend/configurable_warnings.py
+++ b/tests/frontend/configurable_warnings.py
@@ -19,6 +19,7 @@ TOP_DIR = os.path.join(
 def get_project(fatal_warnings):
     return {
         "name": "test",
+        "version": "2.0",
         "element-path": "elements",
         "plugins": [
             {
diff --git a/tests/frontend/configuredwarning/project.conf b/tests/frontend/configuredwarning/project.conf
index c73d217..0b3f325 100644
--- a/tests/frontend/configuredwarning/project.conf
+++ b/tests/frontend/configuredwarning/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 element-path: elements
 plugins:
 - origin: local
diff --git a/tests/frontend/consistencyerror/project.conf b/tests/frontend/consistencyerror/project.conf
index 524a321..cfe7dba 100644
--- a/tests/frontend/consistencyerror/project.conf
+++ b/tests/frontend/consistencyerror/project.conf
@@ -1,6 +1,7 @@
 # Basic project configuration that doesnt override anything
 #
 name: test
+version: 2.0
 
 # Whitelist the local test Sources
 #
diff --git a/tests/frontend/cross_junction_workspace.py b/tests/frontend/cross_junction_workspace.py
index e302b32..5614f6c 100644
--- a/tests/frontend/cross_junction_workspace.py
+++ b/tests/frontend/cross_junction_workspace.py
@@ -13,8 +13,8 @@ def prepare_junction_project(cli, tmpdir):
     os.makedirs(str(main_project))
     os.makedirs(str(sub_project))
 
-    _yaml.dump({'name': 'main'}, str(main_project.join("project.conf")))
-    _yaml.dump({'name': 'sub'}, str(sub_project.join("project.conf")))
+    _yaml.dump({'name': 'main', 'version': '2.0'}, str(main_project.join("project.conf")))
+    _yaml.dump({'name': 'sub', 'version': '2.0'}, str(sub_project.join("project.conf")))
 
     import_dir = tmpdir.join("import")
     os.makedirs(str(import_dir))
diff --git a/tests/frontend/exceptions/project.conf b/tests/frontend/exceptions/project.conf
index 2027cc2..0932d16 100644
--- a/tests/frontend/exceptions/project.conf
+++ b/tests/frontend/exceptions/project.conf
@@ -1,3 +1,2 @@
-# Basic project configuration that doesnt override anything
-#
 name: pony
+version: 2.0
diff --git a/tests/frontend/invalid_element_path/project.conf b/tests/frontend/invalid_element_path/project.conf
index 7b09276..182d84d 100644
--- a/tests/frontend/invalid_element_path/project.conf
+++ b/tests/frontend/invalid_element_path/project.conf
@@ -1,4 +1,3 @@
-# Project config for frontend build test
 name: test
-
+version: 2.0
 elephant-path: elements
diff --git a/tests/frontend/mirror.py b/tests/frontend/mirror.py
index 499375d..01d75bf 100644
--- a/tests/frontend/mirror.py
+++ b/tests/frontend/mirror.py
@@ -41,6 +41,7 @@ def generate_element(output_file):
 def generate_project():
     project = {
         'name': 'test',
+        'version': '2.0',
         'element-path': 'elements',
         'aliases': {
             'foo': 'FOO/',
@@ -132,6 +133,7 @@ def test_mirror_fetch_ref_storage(cli, tmpdir, datafiles, ref_storage, mirror):
 
     project = {
         'name': 'test',
+        'version': '2.0',
         'element-path': 'elements',
         'aliases': {
             alias: upstream_map + "/"
@@ -352,6 +354,7 @@ def test_mirror_git_submodule_fetch(cli, tmpdir, datafiles):
     mirror_map, _ = os.path.split(full_mirror)
     project = {
         'name': 'test',
+        'version': '2.0',
         'element-path': 'elements',
         'aliases': {
             alias: 'http://www.example.com/'
@@ -437,6 +440,7 @@ def test_mirror_fallback_git_only_submodules(cli, tmpdir, datafiles):
 
     project = {
         'name': 'test',
+        'version': '2.0',
         'element-path': 'elements',
         'aliases': {
             alias: upstream_map + "/"
@@ -533,6 +537,7 @@ def test_mirror_fallback_git_with_submodules(cli, tmpdir, datafiles):
 
     project = {
         'name': 'test',
+        'version': '2.0',
         'element-path': 'elements',
         'aliases': {
             alias: upstream_map + "/"
diff --git a/tests/frontend/overlaps.py b/tests/frontend/overlaps.py
index 7cc4930..9e6059b 100644
--- a/tests/frontend/overlaps.py
+++ b/tests/frontend/overlaps.py
@@ -18,7 +18,8 @@ DATA_DIR = os.path.join(
 
 def gen_project(project_dir, fail_on_overlap, use_fatal_warnings=True, project_name="test"):
     template = {
-        "name": project_name
+        "name": project_name,
+        "version": '2.0'
     }
     if use_fatal_warnings:
         template["fatal-warnings"] = [CoreWarnings.OVERLAPS] if fail_on_overlap else []
diff --git a/tests/frontend/project/files/sub-project/project.conf b/tests/frontend/project/files/sub-project/project.conf
index bbb8414..2e22edc 100644
--- a/tests/frontend/project/files/sub-project/project.conf
+++ b/tests/frontend/project/files/sub-project/project.conf
@@ -1,4 +1,3 @@
-# Project config for frontend build test
 name: subtest
-
+version: 2.0
 element-path: elements
diff --git a/tests/frontend/project/project.conf b/tests/frontend/project/project.conf
index ed18221..58f1e09 100644
--- a/tests/frontend/project/project.conf
+++ b/tests/frontend/project/project.conf
@@ -1,6 +1,7 @@
-# Project config for frontend build test
 name: test
 
+version: 2.0
+
 element-path: elements
 
 fatal-warnings:
diff --git a/tests/frontend/project_default/project.conf b/tests/frontend/project_default/project.conf
index 5987c82..80c19f9 100644
--- a/tests/frontend/project_default/project.conf
+++ b/tests/frontend/project_default/project.conf
@@ -1,6 +1,7 @@
-# Project config for frontend build test
 name: test
 
+version: 2.0
+
 element-path: elements
 
 fatal-warnings:
diff --git a/tests/frontend/project_fail/project.conf b/tests/frontend/project_fail/project.conf
index 854e386..7c4d235 100644
--- a/tests/frontend/project_fail/project.conf
+++ b/tests/frontend/project_fail/project.conf
@@ -1,4 +1,3 @@
-# Project config for frontend build test
 name: test
-
+version: 2.0
 element-path: elements
diff --git a/tests/frontend/project_world/files/sub-project/project.conf b/tests/frontend/project_world/files/sub-project/project.conf
index bbb8414..2e22edc 100644
--- a/tests/frontend/project_world/files/sub-project/project.conf
+++ b/tests/frontend/project_world/files/sub-project/project.conf
@@ -1,4 +1,3 @@
-# Project config for frontend build test
 name: subtest
-
+version: 2.0
 element-path: elements
diff --git a/tests/frontend/project_world/project.conf b/tests/frontend/project_world/project.conf
index a7e4a02..3c78eb1 100644
--- a/tests/frontend/project_world/project.conf
+++ b/tests/frontend/project_world/project.conf
@@ -1,6 +1,5 @@
-# Project config for frontend build test
 name: test
-
+version: 2.0
 element-path: elements
 
 fatal-warnings:
diff --git a/tests/frontend/track-cross-junction/subproject/project.conf b/tests/frontend/track-cross-junction/subproject/project.conf
index b327536..91db2ee 100644
--- a/tests/frontend/track-cross-junction/subproject/project.conf
+++ b/tests/frontend/track-cross-junction/subproject/project.conf
@@ -1 +1,2 @@
 name: test
+version: 2.0
diff --git a/tests/frontend/track-optional-inline/project.conf b/tests/frontend/track-optional-inline/project.conf
index 3f02c47..9213770 100644
--- a/tests/frontend/track-optional-inline/project.conf
+++ b/tests/frontend/track-optional-inline/project.conf
@@ -1,5 +1,5 @@
 name: test
-
+version: 2.0
 options:
   test:
     type: bool
diff --git a/tests/frontend/track-optional-project-refs/project.conf b/tests/frontend/track-optional-project-refs/project.conf
index 37fe02c..c740bc1 100644
--- a/tests/frontend/track-optional-project-refs/project.conf
+++ b/tests/frontend/track-optional-project-refs/project.conf
@@ -1,4 +1,5 @@
 name: test
+version: 2.0
 
 ref-storage: project.refs
 
diff --git a/tests/frontend/track.py b/tests/frontend/track.py
index 0eb1e96..8af783d 100644
--- a/tests/frontend/track.py
+++ b/tests/frontend/track.py
@@ -154,6 +154,7 @@ def test_track_cross_junction(cli, tmpdir, datafiles, cross_junction, ref_storag
     #
     project_conf = {
         'name': 'test',
+        'version': '2.0',
         'ref-storage': ref_storage
     }
     _yaml.dump(project_conf, os.path.join(project, 'project.conf'))
diff --git a/tests/frontend/workspaced-build-dep/project.conf b/tests/frontend/workspaced-build-dep/project.conf
index e017957..47da8cf 100644
--- a/tests/frontend/workspaced-build-dep/project.conf
+++ b/tests/frontend/workspaced-build-dep/project.conf
@@ -1,8 +1,8 @@
 # Unique project name
 name: test
 
-# Required BuildStream format version
-format-version: 12
+# Required BuildStream version
+version: 2.0
 
 # Subdirectory where elements are stored
 element-path: elements
diff --git a/tests/frontend/workspaced-runtime-dep/project.conf b/tests/frontend/workspaced-runtime-dep/project.conf
index e017957..47da8cf 100644
--- a/tests/frontend/workspaced-runtime-dep/project.conf
+++ b/tests/frontend/workspaced-runtime-dep/project.conf
@@ -1,8 +1,8 @@
 # Unique project name
 name: test
 
-# Required BuildStream format version
-format-version: 12
+# Required BuildStream version
+version: 2.0
 
 # Subdirectory where elements are stored
 element-path: elements
diff --git a/tests/integration/project/project.conf b/tests/integration/project/project.conf
index ddfe47b..2bece19 100644
--- a/tests/integration/project/project.conf
+++ b/tests/integration/project/project.conf
@@ -1,5 +1,5 @@
-# Project config for frontend build test
 name: test
+version: 2.0
 element-path: elements
 aliases:
   alpine: https://bst-integration-test-images.ams3.cdn.digitaloceanspaces.com/
diff --git a/tests/internals/loader/onefile/project.conf b/tests/internals/loader/onefile/project.conf
index afa0f54..9086b92 100644
--- a/tests/internals/loader/onefile/project.conf
+++ b/tests/internals/loader/onefile/project.conf
@@ -1,2 +1,3 @@
 # Basic project
 name: foo
+version: 2.0
diff --git a/tests/internals/pluginloading/badversionelement/project.conf b/tests/internals/pluginloading/badversionelement/project.conf
index 4f32752..4bbf396 100644
--- a/tests/internals/pluginloading/badversionelement/project.conf
+++ b/tests/internals/pluginloading/badversionelement/project.conf
@@ -1,4 +1,5 @@
 name: pony
+version: 2.0
 element-path: elements
 
 plugins:
diff --git a/tests/internals/pluginloading/badversionsource/project.conf b/tests/internals/pluginloading/badversionsource/project.conf
index 58cf9c5..3755bcc 100644
--- a/tests/internals/pluginloading/badversionsource/project.conf
+++ b/tests/internals/pluginloading/badversionsource/project.conf
@@ -1,4 +1,5 @@
 name: pony
+version: 2.0
 element-path: elements
 
 plugins:
diff --git a/tests/internals/pluginloading/customelement/project.conf b/tests/internals/pluginloading/customelement/project.conf
index bdc9099..6d22507 100644
--- a/tests/internals/pluginloading/customelement/project.conf
+++ b/tests/internals/pluginloading/customelement/project.conf
@@ -1,4 +1,5 @@
 name: pony
+version: 2.0
 element-path: elements
 plugins:
 - origin: local
diff --git a/tests/internals/pluginloading/customsource/project.conf b/tests/internals/pluginloading/customsource/project.conf
index 8205d18..0c5c0d8 100644
--- a/tests/internals/pluginloading/customsource/project.conf
+++ b/tests/internals/pluginloading/customsource/project.conf
@@ -1,4 +1,5 @@
 name: pony
+version: 2.0
 element-path: elements
 plugins:
 - origin: local
diff --git a/tests/plugins/deprecationwarnings/project/project.conf b/tests/plugins/deprecationwarnings/project/project.conf
index 18e368f..1299835 100644
--- a/tests/plugins/deprecationwarnings/project/project.conf
+++ b/tests/plugins/deprecationwarnings/project/project.conf
@@ -1,8 +1,8 @@
 # Unique project name
 name: deprecation-warnings
 
-# Required BuildStream format version
-format-version: 20
+# Required BuildStream version
+version: 2.0
 
 # Subdirectory where elements are stored
 element-path: elements
diff --git a/tests/remoteexecution/project/project.conf b/tests/remoteexecution/project/project.conf
index ddfe47b..c83abf6 100644
--- a/tests/remoteexecution/project/project.conf
+++ b/tests/remoteexecution/project/project.conf
@@ -1,5 +1,6 @@
 # Project config for frontend build test
 name: test
+version: 2.0
 element-path: elements
 aliases:
   alpine: https://bst-integration-test-images.ams3.cdn.digitaloceanspaces.com/
diff --git a/tests/sandboxes/missing-command/project.conf b/tests/sandboxes/missing-command/project.conf
index b327536..91db2ee 100644
--- a/tests/sandboxes/missing-command/project.conf
+++ b/tests/sandboxes/missing-command/project.conf
@@ -1 +1,2 @@
 name: test
+version: 2.0
diff --git a/tests/sandboxes/missing-dependencies/project.conf b/tests/sandboxes/missing-dependencies/project.conf
index 080ab75..1848467 100755
--- a/tests/sandboxes/missing-dependencies/project.conf
+++ b/tests/sandboxes/missing-dependencies/project.conf
@@ -1,4 +1,4 @@
 # Project config for missing dependencies test
 name: test
-
+version: 2.0
 element-path: elements
diff --git a/tests/sourcecache/project/project.conf b/tests/sourcecache/project/project.conf
index 728f3fa..3b578a9 100644
--- a/tests/sourcecache/project/project.conf
+++ b/tests/sourcecache/project/project.conf
@@ -1,5 +1,5 @@
-# Project config for frontend build test
 name: test
+version: 2.0
 
 element-path: elements
 
diff --git a/tests/sources/bzr/project.conf b/tests/sources/bzr/project.conf
index 04b8463..19cd3ee 100644
--- a/tests/sources/bzr/project.conf
+++ b/tests/sources/bzr/project.conf
@@ -1,2 +1,3 @@
 # Basic Project
 name: foo
+version: 2.0
diff --git a/tests/sources/deb.py b/tests/sources/deb.py
index ca44974..21f413d 100644
--- a/tests/sources/deb.py
+++ b/tests/sources/deb.py
@@ -24,6 +24,7 @@ def generate_project(project_dir, tmpdir):
     project_file = os.path.join(project_dir, "project.conf")
     _yaml.dump({
         'name': 'foo',
+        'version': '2.0',
         'aliases': {
             'tmpdir': "file:///" + str(tmpdir)
         }
diff --git a/tests/sources/git.py b/tests/sources/git.py
index 5a4fabd..26c61d1 100644
--- a/tests/sources/git.py
+++ b/tests/sources/git.py
@@ -428,6 +428,7 @@ def test_ref_not_in_track(cli, tmpdir, datafiles, fail):
     if fail == 'error':
         project_template = {
             "name": "foo",
+            "version": "2.0",
             "fatal-warnings": [CoreWarnings.REF_NOT_IN_TRACK]
         }
         _yaml.dump(project_template, os.path.join(project, 'project.conf'))
@@ -471,6 +472,7 @@ def test_unlisted_submodule(cli, tmpdir, datafiles, fail):
     if fail == 'error':
         project_template = {
             "name": "foo",
+            "version": "2.0",
             "fatal-warnings": ['git:unlisted-submodule']
         }
         _yaml.dump(project_template, os.path.join(project, 'project.conf'))
@@ -544,6 +546,7 @@ def test_track_unlisted_submodule(cli, tmpdir, datafiles, fail):
     if fail == 'error':
         project_template = {
             "name": "foo",
+            "version": "2.0",
             "fatal-warnings": ['git:unlisted-submodule']
         }
         _yaml.dump(project_template, os.path.join(project, 'project.conf'))
@@ -607,6 +610,7 @@ def test_invalid_submodule(cli, tmpdir, datafiles, fail):
     if fail == 'error':
         project_template = {
             "name": "foo",
+            "version": "2.0",
             "fatal-warnings": ['git:invalid-submodule']
         }
         _yaml.dump(project_template, os.path.join(project, 'project.conf'))
@@ -679,6 +683,7 @@ def test_track_invalid_submodule(cli, tmpdir, datafiles, fail):
     if fail == 'error':
         project_template = {
             "name": "foo",
+            "version": "2.0",
             "fatal-warnings": ['git:invalid-submodule']
         }
         _yaml.dump(project_template, os.path.join(project, 'project.conf'))
diff --git a/tests/sources/git/project-override/project.conf b/tests/sources/git/project-override/project.conf
index 299992f..ff7035c 100644
--- a/tests/sources/git/project-override/project.conf
+++ b/tests/sources/git/project-override/project.conf
@@ -1,5 +1,6 @@
 # Basic project
 name: foo
+version: 2.0
 sources:
   git:
     config:
diff --git a/tests/sources/git/template/project.conf b/tests/sources/git/template/project.conf
index afa0f54..9086b92 100644
--- a/tests/sources/git/template/project.conf
+++ b/tests/sources/git/template/project.conf
@@ -1,2 +1,3 @@
 # Basic project
 name: foo
+version: 2.0
diff --git a/tests/sources/local/basic/project.conf b/tests/sources/local/basic/project.conf
index afa0f54..9086b92 100644
--- a/tests/sources/local/basic/project.conf
+++ b/tests/sources/local/basic/project.conf
@@ -1,2 +1,3 @@
 # Basic project
 name: foo
+version: 2.0
diff --git a/tests/sources/local/directory/project.conf b/tests/sources/local/directory/project.conf
index afa0f54..9086b92 100644
--- a/tests/sources/local/directory/project.conf
+++ b/tests/sources/local/directory/project.conf
@@ -1,2 +1,3 @@
 # Basic project
 name: foo
+version: 2.0
diff --git a/tests/sources/local/file-exists/project.conf b/tests/sources/local/file-exists/project.conf
index afa0f54..9086b92 100644
--- a/tests/sources/local/file-exists/project.conf
+++ b/tests/sources/local/file-exists/project.conf
@@ -1,2 +1,3 @@
 # Basic project
 name: foo
+version: 2.0
diff --git a/tests/sources/local/invalid-relative-path/project.conf b/tests/sources/local/invalid-relative-path/project.conf
index afa0f54..9086b92 100644
--- a/tests/sources/local/invalid-relative-path/project.conf
+++ b/tests/sources/local/invalid-relative-path/project.conf
@@ -1,2 +1,3 @@
 # Basic project
 name: foo
+version: 2.0
diff --git a/tests/sources/local/symlink/project.conf b/tests/sources/local/symlink/project.conf
index afa0f54..9086b92 100644
--- a/tests/sources/local/symlink/project.conf
+++ b/tests/sources/local/symlink/project.conf
@@ -1,2 +1,3 @@
 # Basic project
 name: foo
+version: 2.0
diff --git a/tests/sources/no-fetch-cached/project.conf b/tests/sources/no-fetch-cached/project.conf
index af0cec1..1983bd4 100644
--- a/tests/sources/no-fetch-cached/project.conf
+++ b/tests/sources/no-fetch-cached/project.conf
@@ -1,6 +1,6 @@
 # Project with local source plugins
 name: no-fetch-cached
-
+version: 2.0
 plugins:
 - origin: local
   path: plugins/sources
diff --git a/tests/sources/ostree/template/project.conf b/tests/sources/ostree/template/project.conf
index afa0f54..9086b92 100644
--- a/tests/sources/ostree/template/project.conf
+++ b/tests/sources/ostree/template/project.conf
@@ -1,2 +1,3 @@
 # Basic project
 name: foo
+version: 2.0
diff --git a/tests/sources/patch/basic/project.conf b/tests/sources/patch/basic/project.conf
index afa0f54..9086b92 100644
--- a/tests/sources/patch/basic/project.conf
+++ b/tests/sources/patch/basic/project.conf
@@ -1,2 +1,3 @@
 # Basic project
 name: foo
+version: 2.0
diff --git a/tests/sources/patch/different-strip-level/project.conf b/tests/sources/patch/different-strip-level/project.conf
index afa0f54..9086b92 100644
--- a/tests/sources/patch/different-strip-level/project.conf
+++ b/tests/sources/patch/different-strip-level/project.conf
@@ -1,2 +1,3 @@
 # Basic project
 name: foo
+version: 2.0
diff --git a/tests/sources/patch/invalid-relative-path/project.conf b/tests/sources/patch/invalid-relative-path/project.conf
index afa0f54..9086b92 100644
--- a/tests/sources/patch/invalid-relative-path/project.conf
+++ b/tests/sources/patch/invalid-relative-path/project.conf
@@ -1,2 +1,3 @@
 # Basic project
 name: foo
+version: 2.0
diff --git a/tests/sources/patch/multiple-patches/project.conf b/tests/sources/patch/multiple-patches/project.conf
index afa0f54..9086b92 100644
--- a/tests/sources/patch/multiple-patches/project.conf
+++ b/tests/sources/patch/multiple-patches/project.conf
@@ -1,2 +1,3 @@
 # Basic project
 name: foo
+version: 2.0
diff --git a/tests/sources/patch/separate-patch-dir/project.conf b/tests/sources/patch/separate-patch-dir/project.conf
index afa0f54..9086b92 100644
--- a/tests/sources/patch/separate-patch-dir/project.conf
+++ b/tests/sources/patch/separate-patch-dir/project.conf
@@ -1,2 +1,3 @@
 # Basic project
 name: foo
+version: 2.0
diff --git a/tests/sources/pip.py b/tests/sources/pip.py
index eba5a5e..467ed20 100644
--- a/tests/sources/pip.py
+++ b/tests/sources/pip.py
@@ -17,7 +17,7 @@ DATA_DIR = os.path.join(
 
 def generate_project(project_dir):
     project_file = os.path.join(project_dir, "project.conf")
-    _yaml.dump({'name': 'foo'}, project_file)
+    _yaml.dump({'name': 'foo', 'version': '2.0'}, project_file)
 
 
 # Test that without ref, consistency is set appropriately.
diff --git a/tests/sources/previous_source_access/project.conf b/tests/sources/previous_source_access/project.conf
index 1749b3d..cdf14a6 100644
--- a/tests/sources/previous_source_access/project.conf
+++ b/tests/sources/previous_source_access/project.conf
@@ -1,6 +1,8 @@
 # Project with local source plugins
 name: foo
 
+version: 2.0
+
 element-path: elements
 
 plugins:
diff --git a/tests/sources/project_key_test/project.conf b/tests/sources/project_key_test/project.conf
index 97ab12c..6eab67a 100644
--- a/tests/sources/project_key_test/project.conf
+++ b/tests/sources/project_key_test/project.conf
@@ -1,5 +1,5 @@
 name: key-test
-
+version: 2.0
 element-path: elements
 
 plugins:
diff --git a/tests/sources/remote.py b/tests/sources/remote.py
index 1b96828..034e05b 100644
--- a/tests/sources/remote.py
+++ b/tests/sources/remote.py
@@ -20,6 +20,7 @@ def generate_project(project_dir, tmpdir):
     project_file = os.path.join(project_dir, "project.conf")
     _yaml.dump({
         'name': 'foo',
+        'version': '2.0',
         'aliases': {
             'tmpdir': "file:///" + str(tmpdir)
         }
@@ -30,6 +31,7 @@ def generate_project_file_server(server, project_dir):
     project_file = os.path.join(project_dir, "project.conf")
     _yaml.dump({
         'name': 'foo',
+        'version': '2.0',
         'aliases': {
             'tmpdir': server.base_url()
         }
diff --git a/tests/sources/tar.py b/tests/sources/tar.py
index 69095fe..a6f1c9f 100644
--- a/tests/sources/tar.py
+++ b/tests/sources/tar.py
@@ -49,6 +49,7 @@ def generate_project(project_dir, tmpdir):
     project_file = os.path.join(project_dir, "project.conf")
     _yaml.dump({
         'name': 'foo',
+        'version': '2.0',
         'aliases': {
             'tmpdir': "file:///" + str(tmpdir)
         }
@@ -59,6 +60,7 @@ def generate_project_file_server(base_url, project_dir):
     project_file = os.path.join(project_dir, "project.conf")
     _yaml.dump({
         'name': 'foo',
+        'version': '2.0',
         'aliases': {
             'tmpdir': base_url
         }
diff --git a/tests/sources/zip.py b/tests/sources/zip.py
index cc1eb25..5086859 100644
--- a/tests/sources/zip.py
+++ b/tests/sources/zip.py
@@ -34,6 +34,7 @@ def generate_project(project_dir, tmpdir):
     project_file = os.path.join(project_dir, "project.conf")
     _yaml.dump({
         'name': 'foo',
+        'version': '2.0',
         'aliases': {
             'tmpdir': "file:///" + str(tmpdir)
         }
@@ -44,6 +45,7 @@ def generate_project_file_server(server, project_dir):
     project_file = os.path.join(project_dir, "project.conf")
     _yaml.dump({
         'name': 'foo',
+        'version': '2.0',
         'aliases': {
             'tmpdir': server.base_url()
         }