Environments: store spack version/commit in spack.lock (#32801)
Add a section to the lock file to track the Spack version/commit that produced an environment. This should (eventually) enhance reproducibility, though we do not currently do anything with the information. It just adds to provenance at the moment. Changes include: - [x] adding the version/commit to `spack.lock` - [x] refactor `spack.main.get_version() - [x] fix a couple of environment lock file-related typos
This commit is contained in:
		| @@ -16,18 +16,24 @@ | ||||
| The high-level format of a Spack lockfile hasn't changed much between versions, but the | ||||
| contents have.  Lockfiles are JSON-formatted and their top-level sections are: | ||||
| 
 | ||||
|   1. ``_meta`` (object): this contains deatails about the file format, including: | ||||
|   1. ``_meta`` (object): this contains details about the file format, including: | ||||
|       * ``file-type``: always ``"spack-lockfile"`` | ||||
|       * ``lockfile-version``: an integer representing the lockfile format version | ||||
|       * ``specfile-version``: an integer representing the spec format version (since | ||||
|         ``v0.17``) | ||||
| 
 | ||||
|   2. ``roots`` (list): an ordered list of records representing the roots of the Spack | ||||
|   2. ``spack`` (object): optional, this identifies information about Spack | ||||
|       used to concretize the environment: | ||||
|       * ``type``: required, identifies form Spack version took (e.g., ``git``, ``release``) | ||||
|       * ``commit``: the commit if the version is from git | ||||
|       * ``version``: the Spack version | ||||
| 
 | ||||
|   3. ``roots`` (list): an ordered list of records representing the roots of the Spack | ||||
|       environment. Each has two fields: | ||||
|       * ``hash``: a Spack spec hash uniquely identifying the concrete root spec | ||||
|       * ``spec``: a string representation of the abstract spec that was concretized | ||||
| 
 | ||||
| 3. ``concrete_specs``: a dictionary containing the specs in the environment. | ||||
|   4. ``concrete_specs``: a dictionary containing the specs in the environment. | ||||
| 
 | ||||
| Compatibility | ||||
| ------------- | ||||
| @@ -271,6 +277,8 @@ | ||||
| Dependencies are keyed by ``hash`` (DAG hash) as well. There are no more ``build_hash`` | ||||
| fields in the specs, and there are no more issues with lockfiles being able to store | ||||
| multiple specs with the same DAG hash (because the DAG hash is now finer-grained). | ||||
| An optional ``spack`` property may be included to track version information, such as | ||||
| the commit or version. | ||||
| 
 | ||||
| 
 | ||||
| .. code-block:: json | ||||
| @@ -278,8 +286,8 @@ | ||||
|     { | ||||
|         "_meta": { | ||||
|             "file-type": "spack-lockfile", | ||||
|             "lockfile-version": 3, | ||||
|             "specfile-version": 2 | ||||
|             "lockfile-version": 4, | ||||
|             "specfile-version": 3 | ||||
|         }, | ||||
|         "roots": [ | ||||
|             { | ||||
| @@ -326,7 +334,6 @@ | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| """ | ||||
| 
 | ||||
| from .environment import ( | ||||
|   | ||||
| @@ -31,6 +31,7 @@ | ||||
| import spack.error | ||||
| import spack.hash_types as ht | ||||
| import spack.hooks | ||||
| import spack.main | ||||
| import spack.paths | ||||
| import spack.repo | ||||
| import spack.schema.env | ||||
| @@ -2072,6 +2073,14 @@ def _to_lockfile_dict(self): | ||||
| 
 | ||||
|         hash_spec_list = zip(self.concretized_order, self.concretized_user_specs) | ||||
| 
 | ||||
|         spack_dict = {"version": spack.spack_version} | ||||
|         spack_commit = spack.main.get_spack_commit() | ||||
|         if spack_commit: | ||||
|             spack_dict["type"] = "git" | ||||
|             spack_dict["commit"] = spack_commit | ||||
|         else: | ||||
|             spack_dict["type"] = "release" | ||||
| 
 | ||||
|         # this is the lockfile we'll write out | ||||
|         data = { | ||||
|             # metadata about the format | ||||
| @@ -2080,6 +2089,8 @@ def _to_lockfile_dict(self): | ||||
|                 "lockfile-version": lockfile_format_version, | ||||
|                 "specfile-version": spack.spec.SPECFILE_FORMAT_VERSION, | ||||
|             }, | ||||
|             # spack version information | ||||
|             "spack": spack_dict, | ||||
|             # users specs + hashes are the 'roots' of the environment | ||||
|             "roots": [{"hash": h, "spec": str(s)} for h, s in hash_spec_list], | ||||
|             # Concrete specs by hash, including dependencies | ||||
|   | ||||
| @@ -126,19 +126,20 @@ def add_all_commands(parser): | ||||
|         parser.add_command(cmd) | ||||
| 
 | ||||
| 
 | ||||
| def get_version(): | ||||
|     """Get a descriptive version of this instance of Spack. | ||||
| def get_spack_commit(): | ||||
|     """Get the Spack git commit sha. | ||||
| 
 | ||||
|     Outputs '<PEP440 version> (<git commit sha>)'. | ||||
| 
 | ||||
|     The commit sha is only added when available. | ||||
|     Returns: | ||||
|         (str or None) the commit sha if available, otherwise None | ||||
|     """ | ||||
|     version = spack.spack_version | ||||
|     git_path = os.path.join(spack.paths.prefix, ".git") | ||||
|     if os.path.exists(git_path): | ||||
|     if not os.path.exists(git_path): | ||||
|         return None | ||||
| 
 | ||||
|     git = spack.util.git.git() | ||||
|     if not git: | ||||
|             return version | ||||
|         return None | ||||
| 
 | ||||
|     rev = git( | ||||
|         "-C", | ||||
|         spack.paths.prefix, | ||||
| @@ -149,10 +150,23 @@ def get_version(): | ||||
|         fail_on_error=False, | ||||
|     ) | ||||
|     if git.returncode != 0: | ||||
|             return version | ||||
|         return None | ||||
| 
 | ||||
|     match = re.match(r"[a-f\d]{7,}$", rev) | ||||
|         if match: | ||||
|             version += " ({0})".format(match.group(0)) | ||||
|     return match.group(0) if match else None | ||||
| 
 | ||||
| 
 | ||||
| def get_version(): | ||||
|     """Get a descriptive version of this instance of Spack. | ||||
| 
 | ||||
|     Outputs '<PEP440 version> (<git commit sha>)'. | ||||
| 
 | ||||
|     The commit sha is only added when available. | ||||
|     """ | ||||
|     version = spack.spack_version | ||||
|     commit = get_spack_commit() | ||||
|     if commit: | ||||
|         version += " ({0})".format(commit) | ||||
| 
 | ||||
|     return version | ||||
| 
 | ||||
|   | ||||
| @@ -7,6 +7,7 @@ | ||||
| import pytest | ||||
| 
 | ||||
| import spack.environment as ev | ||||
| from spack import spack_version | ||||
| from spack.main import SpackCommand | ||||
| 
 | ||||
| pytestmark = pytest.mark.usefixtures("config", "mutable_mock_repo") | ||||
| @@ -54,3 +55,6 @@ def test_concretize_root_test_dependencies_are_concretized(unify, mutable_mock_e | ||||
|         add("b") | ||||
|         concretize("--test", "root") | ||||
|         assert e.matching_spec("test-dependency") | ||||
| 
 | ||||
|         data = e._to_lockfile_dict() | ||||
|         assert data["spack"]["version"] == spack_version | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Tamara Dahlgren
					Tamara Dahlgren