summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTamara Dahlgren <35777542+tldahlgren@users.noreply.github.com>2023-05-11 20:13:36 -0700
committerGitHub <noreply@github.com>2023-05-11 23:13:36 -0400
commit8e18297cf251f233badb4a530f0a9113b380c850 (patch)
tree2e93d87e04f69bd419bb4242046f4ddf1c770c3c
parentb06d20be19afc9894ec277f9baca17f46d2ff2a6 (diff)
downloadspack-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__.py19
-rw-r--r--lib/spack/spack/environment/environment.py11
-rw-r--r--lib/spack/spack/main.py52
-rw-r--r--lib/spack/spack/test/cmd/concretize.py4
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