diff options
author | Tamara Dahlgren <35777542+tldahlgren@users.noreply.github.com> | 2023-05-11 20:13:36 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-11 23:13:36 -0400 |
commit | 8e18297cf251f233badb4a530f0a9113b380c850 (patch) | |
tree | 2e93d87e04f69bd419bb4242046f4ddf1c770c3c | |
parent | b06d20be19afc9894ec277f9baca17f46d2ff2a6 (diff) | |
download | spack-8e18297cf251f233badb4a530f0a9113b380c850.tar.gz spack-8e18297cf251f233badb4a530f0a9113b380c850.tar.bz2 spack-8e18297cf251f233badb4a530f0a9113b380c850.tar.xz spack-8e18297cf251f233badb4a530f0a9113b380c850.zip |
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
-rw-r--r-- | lib/spack/spack/environment/__init__.py | 19 | ||||
-rw-r--r-- | lib/spack/spack/environment/environment.py | 11 | ||||
-rw-r--r-- | lib/spack/spack/main.py | 52 | ||||
-rw-r--r-- | lib/spack/spack/test/cmd/concretize.py | 4 |
4 files changed, 61 insertions, 25 deletions
diff --git a/lib/spack/spack/environment/__init__.py b/lib/spack/spack/environment/__init__.py index 709c386d76..d87355656b 100644 --- a/lib/spack/spack/environment/__init__.py +++ b/lib/spack/spack/environment/__init__.py @@ -16,18 +16,24 @@ Spack environments have existed since Spack ``v0.12.0``, and there have been 4 d 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 @@ now includes build dependencies and a canonical hash of the ``package.py`` file. 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 @@ multiple specs with the same DAG hash (because the DAG hash is now finer-grained { "_meta": { "file-type": "spack-lockfile", - "lockfile-version": 3, - "specfile-version": 2 + "lockfile-version": 4, + "specfile-version": 3 }, "roots": [ { @@ -326,7 +334,6 @@ multiple specs with the same DAG hash (because the DAG hash is now finer-grained } } } - """ from .environment import ( diff --git a/lib/spack/spack/environment/environment.py b/lib/spack/spack/environment/environment.py index 263b30edab..4d0b1da569 100644 --- a/lib/spack/spack/environment/environment.py +++ b/lib/spack/spack/environment/environment.py @@ -31,6 +31,7 @@ import spack.config 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 @@ class Environment: 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 @@ class Environment: "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 diff --git a/lib/spack/spack/main.py b/lib/spack/spack/main.py index 455bd29b9d..2c64d5c8b3 100644 --- a/lib/spack/spack/main.py +++ b/lib/spack/spack/main.py @@ -126,6 +126,36 @@ def add_all_commands(parser): parser.add_command(cmd) +def get_spack_commit(): + """Get the Spack git commit sha. + + Returns: + (str or None) the commit sha if available, otherwise None + """ + git_path = os.path.join(spack.paths.prefix, ".git") + if not os.path.exists(git_path): + return None + + git = spack.util.git.git() + if not git: + return None + + rev = git( + "-C", + spack.paths.prefix, + "rev-parse", + "HEAD", + output=str, + error=os.devnull, + fail_on_error=False, + ) + if git.returncode != 0: + return None + + match = re.match(r"[a-f\d]{7,}$", rev) + return match.group(0) if match else None + + def get_version(): """Get a descriptive version of this instance of Spack. @@ -134,25 +164,9 @@ def get_version(): The commit sha is only added when available. """ version = spack.spack_version - git_path = os.path.join(spack.paths.prefix, ".git") - if os.path.exists(git_path): - git = spack.util.git.git() - if not git: - return version - rev = git( - "-C", - spack.paths.prefix, - "rev-parse", - "HEAD", - output=str, - error=os.devnull, - fail_on_error=False, - ) - if git.returncode != 0: - return version - match = re.match(r"[a-f\d]{7,}$", rev) - if match: - version += " ({0})".format(match.group(0)) + commit = get_spack_commit() + if commit: + version += " ({0})".format(commit) return version diff --git a/lib/spack/spack/test/cmd/concretize.py b/lib/spack/spack/test/cmd/concretize.py index 868da6df61..914f0fe6af 100644 --- a/lib/spack/spack/test/cmd/concretize.py +++ b/lib/spack/spack/test/cmd/concretize.py @@ -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 |