From 2de277910b765b125dae37c6c83998a6b44823aa Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Fri, 13 Jun 2025 11:46:02 +0200 Subject: [PATCH 01/13] Add support for specifying repo and commit of the builtin repo --- stackinator/builder.py | 77 ++++++++++++++++++++++++++++++-- stackinator/schema/config.json | 16 +++++++ stackinator/templates/repos.yaml | 3 +- 3 files changed, 91 insertions(+), 5 deletions(-) diff --git a/stackinator/builder.py b/stackinator/builder.py index 66d50a5d..34dcb44f 100644 --- a/stackinator/builder.py +++ b/stackinator/builder.py @@ -169,6 +169,68 @@ def generate(self, recipe): store_path.mkdir(exist_ok=True) tmp_path.mkdir(exist_ok=True) + ################## + # check out the version of spack-packages + spack_packages = recipe.config["spack_packages"] + spack_packages_path = self.path / "spack-packages" + + # Clone the spack-packages repository if it has not already been checked + # out + if not (spack_packages_path / ".git").is_dir(): + self._logger.info(f'spack-packages: clone repository {spack_packages["repo"]}') + + # clone the repository + capture = subprocess.run( + ["git", "clone", "--filter=tree:0", spack_packages["repo"], spack_packages_path], + shell=False, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + ) + self._logger.debug(capture.stdout.decode("utf-8")) + + if capture.returncode != 0: + self._logger.error(f'error cloning the repository {spack_packages["repo"]}') + capture.check_returncode() + + # Fetch the specific branch + if spack_packages["commit"]: + self._logger.info(f'spack-packages: fetch branch/commit {spack_packages["commit"]}') + capture = subprocess.run( + ["git", "-C", spack_packages_path, "fetch", "origin", spack_packages["commit"]], + shell=False, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + ) + self._logger.debug(capture.stdout.decode("utf-8")) + + if capture.returncode != 0: + self._logger.debug(f'unable to change to the fetch {spack_packages["commit"]}') + capture.check_returncode() + + # Check out a branch or commit if one was specified + if spack["commit"]: + self._logger.info(f'spack-packages: checkout branch/commit {spack_packages["commit"]}') + capture = subprocess.run( + ["git", "-C", spack_packages_path, "checkout", spack_packages["commit"]], + shell=False, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + ) + self._logger.debug(capture.stdout.decode("utf-8")) + + if capture.returncode != 0: + self._logger.debug(f'unable to change to the requested commit {spack_packages["commit"]}') + capture.check_returncode() + + # get the spack commit + spack_packages_git_commit_result = subprocess.run( + ["git", "-C", spack_packages_path, "rev-parse", "HEAD"], + shell=False, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + ################## + # check out the version of spack spack_version = recipe.spack_version self._logger.debug(f"spack version for templates: {spack_version}") @@ -229,13 +291,16 @@ def generate(self, recipe): capture.check_returncode() # get the spack commit - git_commit_result = subprocess.run( + spack_git_commit_result = subprocess.run( ["git", "-C", spack_path, "rev-parse", "HEAD"], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) spack_meta = { "ref": spack["commit"], - "commit": git_commit_result.stdout.strip().decode("utf-8"), + "commit": spack_git_commit_result.stdout.strip().decode("utf-8"), "url": spack["repo"], + "packages_ref": spack_packages["commit"], + "packages_commit": spack_packages_git_commit_result.stdout.strip().decode("utf-8"), + "packages_url": spack_packages["repo"], } # load the jinja templating environment @@ -415,7 +480,7 @@ def generate(self, recipe): # Delete the store/repo path, if it already exists. # Do this so that incremental builds (though not officially supported) won't break if a repo is updated. repo_dst = store_path / "repo" - self._logger.debug(f"creating the stack spack prepo in {repo_dst}") + self._logger.debug(f"creating the stack spack repo in {repo_dst}") if repo_dst.exists(): self._logger.debug(f"{repo_dst} exists ... deleting") shutil.rmtree(repo_dst) @@ -439,7 +504,11 @@ def generate(self, recipe): repos_yaml_template = jinja_env.get_template("repos.yaml") with (config_path / "repos.yaml").open("w") as f: repo_path = recipe.mount / "repo" - f.write(repos_yaml_template.render(repo_path=repo_path.as_posix(), verbose=False)) + f.write( + repos_yaml_template.render( + repo_path=repo_path.as_posix(), builtin_repo_path=spack_packages_path.as_posix(), verbose=False + ) + ) f.write("\n") # Iterate over the source repositories copying their contents to the consolidated repo in the uenv. diff --git a/stackinator/schema/config.json b/stackinator/schema/config.json index df63fa70..cb142ceb 100644 --- a/stackinator/schema/config.json +++ b/stackinator/schema/config.json @@ -28,6 +28,22 @@ } } }, + "spack_packages" : { + "type" : "object", + "additionalProperties": false, + "properties" : { + "repo": { + "type": "string" + }, + "commit": { + "oneOf": [ + {"type" : "string"}, + {"type" : "null"} + ], + "default": null + } + } + }, "mirror" : { "type" : "object", "additionalProperties": false, diff --git a/stackinator/templates/repos.yaml b/stackinator/templates/repos.yaml index 514838b0..3cf34f26 100644 --- a/stackinator/templates/repos.yaml +++ b/stackinator/templates/repos.yaml @@ -1,2 +1,3 @@ repos: -- {{ repo_path }} + alps: {{ repo_path }} + builtin: {{ builtin_repo_path }} From a460f93ea426e5bcabdaa851ad0aa52a8151a348 Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Fri, 13 Jun 2025 12:06:23 +0200 Subject: [PATCH 02/13] Fix builtin repo path --- stackinator/builder.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stackinator/builder.py b/stackinator/builder.py index 34dcb44f..124a4859 100644 --- a/stackinator/builder.py +++ b/stackinator/builder.py @@ -504,9 +504,10 @@ def generate(self, recipe): repos_yaml_template = jinja_env.get_template("repos.yaml") with (config_path / "repos.yaml").open("w") as f: repo_path = recipe.mount / "repo" + builtin_repo_path = recipe.mount / "spack-packages" f.write( repos_yaml_template.render( - repo_path=repo_path.as_posix(), builtin_repo_path=spack_packages_path.as_posix(), verbose=False + repo_path=repo_path.as_posix(), builtin_repo_path=builtin_repo_path.as_posix(), verbose=False ) ) f.write("\n") From 1f921fa2ccc17c242cf469d3ca53d4f7fdc3eec5 Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Fri, 13 Jun 2025 12:09:37 +0200 Subject: [PATCH 03/13] Fix spack_packages["commit"] --- stackinator/builder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stackinator/builder.py b/stackinator/builder.py index 124a4859..9450107b 100644 --- a/stackinator/builder.py +++ b/stackinator/builder.py @@ -208,7 +208,7 @@ def generate(self, recipe): capture.check_returncode() # Check out a branch or commit if one was specified - if spack["commit"]: + if spack_packages["commit"]: self._logger.info(f'spack-packages: checkout branch/commit {spack_packages["commit"]}') capture = subprocess.run( ["git", "-C", spack_packages_path, "checkout", spack_packages["commit"]], From 69603e3400cec44ffb52efb72401f7ec8747d159 Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Fri, 13 Jun 2025 13:54:40 +0200 Subject: [PATCH 04/13] Put spack-packages in uenv --- stackinator/builder.py | 4 ++-- stackinator/templates/repos.yaml | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/stackinator/builder.py b/stackinator/builder.py index 9450107b..a843e758 100644 --- a/stackinator/builder.py +++ b/stackinator/builder.py @@ -172,7 +172,7 @@ def generate(self, recipe): ################## # check out the version of spack-packages spack_packages = recipe.config["spack_packages"] - spack_packages_path = self.path / "spack-packages" + spack_packages_path = store_path / "spack-packages" # Clone the spack-packages repository if it has not already been checked # out @@ -507,7 +507,7 @@ def generate(self, recipe): builtin_repo_path = recipe.mount / "spack-packages" f.write( repos_yaml_template.render( - repo_path=repo_path.as_posix(), builtin_repo_path=builtin_repo_path.as_posix(), verbose=False + repo_path=repo_path.as_posix(), builtin_repo_path=builtin_repo_path.as_posix(), builtin_repo_git_repo=spack_packages["repo"], verbose=False ) ) f.write("\n") diff --git a/stackinator/templates/repos.yaml b/stackinator/templates/repos.yaml index 3cf34f26..4a36c423 100644 --- a/stackinator/templates/repos.yaml +++ b/stackinator/templates/repos.yaml @@ -1,3 +1,5 @@ repos: alps: {{ repo_path }} - builtin: {{ builtin_repo_path }} + builtin: + destination: {{ builtin_repo_path }} + git: {{ builtin_repo_git_repo }} From 63634e97264af94e8294434789b76a806bb30723 Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Tue, 17 Jun 2025 16:43:51 +0200 Subject: [PATCH 05/13] Move spack_packages to under spack:packages in yaml schema --- stackinator/builder.py | 101 +++++++++++++++++---------------- stackinator/schema/config.json | 32 +++++------ 2 files changed, 67 insertions(+), 66 deletions(-) diff --git a/stackinator/builder.py b/stackinator/builder.py index a843e758..8e2e5978 100644 --- a/stackinator/builder.py +++ b/stackinator/builder.py @@ -169,19 +169,25 @@ def generate(self, recipe): store_path.mkdir(exist_ok=True) tmp_path.mkdir(exist_ok=True) - ################## - # check out the version of spack-packages - spack_packages = recipe.config["spack_packages"] - spack_packages_path = store_path / "spack-packages" + # check out the version of spack + spack_version = recipe.spack_version + self._logger.debug(f"spack version for templates: {spack_version}") + spack = recipe.config["spack"] + spack_path = self.path / "spack" - # Clone the spack-packages repository if it has not already been checked - # out - if not (spack_packages_path / ".git").is_dir(): - self._logger.info(f'spack-packages: clone repository {spack_packages["repo"]}') + # set general build and configuration meta data for the project + self.configuration_meta = recipe + + # set the environment view meta data + self.environment_meta = recipe + + # Clone the spack repository if it has not already been checked out + if not (spack_path / ".git").is_dir(): + self._logger.info(f"spack: clone repository {spack['repo']}") # clone the repository capture = subprocess.run( - ["git", "clone", "--filter=tree:0", spack_packages["repo"], spack_packages_path], + ["git", "clone", "--filter=tree:0", spack["repo"], spack_path], shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -189,14 +195,14 @@ def generate(self, recipe): self._logger.debug(capture.stdout.decode("utf-8")) if capture.returncode != 0: - self._logger.error(f'error cloning the repository {spack_packages["repo"]}') + self._logger.error(f"error cloning the repository {spack['repo']}") capture.check_returncode() # Fetch the specific branch - if spack_packages["commit"]: - self._logger.info(f'spack-packages: fetch branch/commit {spack_packages["commit"]}') + if spack["commit"]: + self._logger.info(f"spack: fetch branch/commit {spack['commit']}") capture = subprocess.run( - ["git", "-C", spack_packages_path, "fetch", "origin", spack_packages["commit"]], + ["git", "-C", spack_path, "fetch", "origin", spack["commit"]], shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -204,14 +210,14 @@ def generate(self, recipe): self._logger.debug(capture.stdout.decode("utf-8")) if capture.returncode != 0: - self._logger.debug(f'unable to change to the fetch {spack_packages["commit"]}') + self._logger.debug(f"unable to change to the fetch {spack['commit']}") capture.check_returncode() # Check out a branch or commit if one was specified - if spack_packages["commit"]: - self._logger.info(f'spack-packages: checkout branch/commit {spack_packages["commit"]}') + if spack["commit"]: + self._logger.info(f"spack: checkout branch/commit {spack['commit']}") capture = subprocess.run( - ["git", "-C", spack_packages_path, "checkout", spack_packages["commit"]], + ["git", "-C", spack_path, "checkout", spack["commit"]], shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -219,37 +225,27 @@ def generate(self, recipe): self._logger.debug(capture.stdout.decode("utf-8")) if capture.returncode != 0: - self._logger.debug(f'unable to change to the requested commit {spack_packages["commit"]}') + self._logger.debug(f"unable to change to the requested commit {spack['commit']}") capture.check_returncode() # get the spack commit - spack_packages_git_commit_result = subprocess.run( - ["git", "-C", spack_packages_path, "rev-parse", "HEAD"], - shell=False, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + spack_git_commit_result = subprocess.run( + ["git", "-C", spack_path, "rev-parse", "HEAD"], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) - ################## - # check out the version of spack - spack_version = recipe.spack_version - self._logger.debug(f"spack version for templates: {spack_version}") - spack = recipe.config["spack"] - spack_path = self.path / "spack" - - # set general build and configuration meta data for the project - self.configuration_meta = recipe - - # set the environment view meta data - self.environment_meta = recipe + ################## + # check out the version of spack-packages + spack_packages = spack["packages"] + spack_packages_path = self.path / "spack-packages" - # Clone the spack repository if it has not already been checked out - if not (spack_path / ".git").is_dir(): - self._logger.info(f"spack: clone repository {spack['repo']}") + # Clone the spack-packages repository if it has not already been checked + # out + if not (spack_packages_path / ".git").is_dir(): + self._logger.info(f'spack-packages: clone repository {spack_packages["repo"]}') # clone the repository capture = subprocess.run( - ["git", "clone", "--filter=tree:0", spack["repo"], spack_path], + ["git", "clone", "--filter=tree:0", spack_packages["repo"], spack_packages_path], shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -257,14 +253,14 @@ def generate(self, recipe): self._logger.debug(capture.stdout.decode("utf-8")) if capture.returncode != 0: - self._logger.error(f"error cloning the repository {spack['repo']}") + self._logger.error(f'error cloning the repository {spack_packages["repo"]}') capture.check_returncode() # Fetch the specific branch - if spack["commit"]: - self._logger.info(f"spack: fetch branch/commit {spack['commit']}") + if spack_packages["commit"]: + self._logger.info(f'spack-packages: fetch branch/commit {spack_packages["commit"]}') capture = subprocess.run( - ["git", "-C", spack_path, "fetch", "origin", spack["commit"]], + ["git", "-C", spack_packages_path, "fetch", "origin", spack_packages["commit"]], shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -272,14 +268,14 @@ def generate(self, recipe): self._logger.debug(capture.stdout.decode("utf-8")) if capture.returncode != 0: - self._logger.debug(f"unable to change to the fetch {spack['commit']}") + self._logger.debug(f'unable to change to the fetch {spack_packages["commit"]}') capture.check_returncode() # Check out a branch or commit if one was specified - if spack["commit"]: - self._logger.info(f"spack: checkout branch/commit {spack['commit']}") + if spack_packages["commit"]: + self._logger.info(f'spack-packages: checkout branch/commit {spack_packages["commit"]}') capture = subprocess.run( - ["git", "-C", spack_path, "checkout", spack["commit"]], + ["git", "-C", spack_packages_path, "checkout", spack_packages["commit"]], shell=False, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, @@ -287,13 +283,18 @@ def generate(self, recipe): self._logger.debug(capture.stdout.decode("utf-8")) if capture.returncode != 0: - self._logger.debug(f"unable to change to the requested commit {spack['commit']}") + self._logger.debug(f'unable to change to the requested commit {spack_packages["commit"]}') capture.check_returncode() # get the spack commit - spack_git_commit_result = subprocess.run( - ["git", "-C", spack_path, "rev-parse", "HEAD"], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE + spack_packages_git_commit_result = subprocess.run( + ["git", "-C", spack_packages_path, "rev-parse", "HEAD"], + shell=False, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, ) + ################## + spack_meta = { "ref": spack["commit"], "commit": spack_git_commit_result.stdout.strip().decode("utf-8"), diff --git a/stackinator/schema/config.json b/stackinator/schema/config.json index cb142ceb..66780bf5 100644 --- a/stackinator/schema/config.json +++ b/stackinator/schema/config.json @@ -25,23 +25,23 @@ {"type" : "null"} ], "default": null - } - } - }, - "spack_packages" : { - "type" : "object", - "additionalProperties": false, - "properties" : { - "repo": { - "type": "string" }, - "commit": { - "oneOf": [ - {"type" : "string"}, - {"type" : "null"} - ], - "default": null - } + "packages" : { + "type" : "object", + "additionalProperties": false, + "properties" : { + "repo": { + "type": "string" + }, + "commit": { + "oneOf": [ + {"type" : "string"}, + {"type" : "null"} + ], + "default": null + } + } + }, } }, "mirror" : { From 60ffe1b25708b4d99f1cd7f3d744c4b9d7124100 Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Thu, 19 Jun 2025 12:06:59 +0200 Subject: [PATCH 06/13] Fix config.yaml schema --- stackinator/schema/config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stackinator/schema/config.json b/stackinator/schema/config.json index 66780bf5..49fae9b4 100644 --- a/stackinator/schema/config.json +++ b/stackinator/schema/config.json @@ -41,7 +41,7 @@ "default": null } } - }, + } } }, "mirror" : { From cfdebb817831eae5a7916ade4d352e0a60072a35 Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Thu, 19 Jun 2025 13:11:26 +0200 Subject: [PATCH 07/13] Add helper function for cloning git repos --- stackinator/builder.py | 207 ++++++++++++++++++----------------------- 1 file changed, 92 insertions(+), 115 deletions(-) diff --git a/stackinator/builder.py b/stackinator/builder.py index 8e2e5978..52588a4d 100644 --- a/stackinator/builder.py +++ b/stackinator/builder.py @@ -172,8 +172,6 @@ def generate(self, recipe): # check out the version of spack spack_version = recipe.spack_version self._logger.debug(f"spack version for templates: {spack_version}") - spack = recipe.config["spack"] - spack_path = self.path / "spack" # set general build and configuration meta data for the project self.configuration_meta = recipe @@ -181,127 +179,36 @@ def generate(self, recipe): # set the environment view meta data self.environment_meta = recipe - # Clone the spack repository if it has not already been checked out - if not (spack_path / ".git").is_dir(): - self._logger.info(f"spack: clone repository {spack['repo']}") - - # clone the repository - capture = subprocess.run( - ["git", "clone", "--filter=tree:0", spack["repo"], spack_path], - shell=False, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - ) - self._logger.debug(capture.stdout.decode("utf-8")) - - if capture.returncode != 0: - self._logger.error(f"error cloning the repository {spack['repo']}") - capture.check_returncode() - - # Fetch the specific branch - if spack["commit"]: - self._logger.info(f"spack: fetch branch/commit {spack['commit']}") - capture = subprocess.run( - ["git", "-C", spack_path, "fetch", "origin", spack["commit"]], - shell=False, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - ) - self._logger.debug(capture.stdout.decode("utf-8")) - - if capture.returncode != 0: - self._logger.debug(f"unable to change to the fetch {spack['commit']}") - capture.check_returncode() - - # Check out a branch or commit if one was specified - if spack["commit"]: - self._logger.info(f"spack: checkout branch/commit {spack['commit']}") - capture = subprocess.run( - ["git", "-C", spack_path, "checkout", spack["commit"]], - shell=False, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - ) - self._logger.debug(capture.stdout.decode("utf-8")) - - if capture.returncode != 0: - self._logger.debug(f"unable to change to the requested commit {spack['commit']}") - capture.check_returncode() + # Clone the spack repository and check out commit if one was given + spack = recipe.config["spack"] + spack_repo = spack["repo"] + spack_commit = spack["commit"] + spack_path = self.path / "spack" - # get the spack commit - spack_git_commit_result = subprocess.run( - ["git", "-C", spack_path, "rev-parse", "HEAD"], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE + spack_git_commit_result = self._git_clone( + "spack", spack_repo, spack_commit, spack_path ) - ################## - # check out the version of spack-packages + # Clone the spack-packages repository and check out commit if one was given spack_packages = spack["packages"] + spack_packages_repo = spack_packages["repo"] + spack_packages_commit = spack_packages["commit"] spack_packages_path = self.path / "spack-packages" - # Clone the spack-packages repository if it has not already been checked - # out - if not (spack_packages_path / ".git").is_dir(): - self._logger.info(f'spack-packages: clone repository {spack_packages["repo"]}') - - # clone the repository - capture = subprocess.run( - ["git", "clone", "--filter=tree:0", spack_packages["repo"], spack_packages_path], - shell=False, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - ) - self._logger.debug(capture.stdout.decode("utf-8")) - - if capture.returncode != 0: - self._logger.error(f'error cloning the repository {spack_packages["repo"]}') - capture.check_returncode() - - # Fetch the specific branch - if spack_packages["commit"]: - self._logger.info(f'spack-packages: fetch branch/commit {spack_packages["commit"]}') - capture = subprocess.run( - ["git", "-C", spack_packages_path, "fetch", "origin", spack_packages["commit"]], - shell=False, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - ) - self._logger.debug(capture.stdout.decode("utf-8")) - - if capture.returncode != 0: - self._logger.debug(f'unable to change to the fetch {spack_packages["commit"]}') - capture.check_returncode() - - # Check out a branch or commit if one was specified - if spack_packages["commit"]: - self._logger.info(f'spack-packages: checkout branch/commit {spack_packages["commit"]}') - capture = subprocess.run( - ["git", "-C", spack_packages_path, "checkout", spack_packages["commit"]], - shell=False, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - ) - self._logger.debug(capture.stdout.decode("utf-8")) - - if capture.returncode != 0: - self._logger.debug(f'unable to change to the requested commit {spack_packages["commit"]}') - capture.check_returncode() - - # get the spack commit - spack_packages_git_commit_result = subprocess.run( - ["git", "-C", spack_packages_path, "rev-parse", "HEAD"], - shell=False, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + spack_packages_git_commit_result = self._git_clone( + "spack-packages", + spack_packages_repo, + spack_packages_commit, + spack_packages_path, ) - ################## spack_meta = { - "ref": spack["commit"], - "commit": spack_git_commit_result.stdout.strip().decode("utf-8"), - "url": spack["repo"], - "packages_ref": spack_packages["commit"], - "packages_commit": spack_packages_git_commit_result.stdout.strip().decode("utf-8"), - "packages_url": spack_packages["repo"], + "url": spack_repo, + "ref": spack_commit, + "commit": spack_git_commit_result, + "packages_url": spack_packages_repo, + "packages_ref": spack_packages_commit, + "packages_commit": spack_packages_git_commit_result, } # load the jinja templating environment @@ -508,7 +415,10 @@ def generate(self, recipe): builtin_repo_path = recipe.mount / "spack-packages" f.write( repos_yaml_template.render( - repo_path=repo_path.as_posix(), builtin_repo_path=builtin_repo_path.as_posix(), builtin_repo_git_repo=spack_packages["repo"], verbose=False + repo_path=repo_path.as_posix(), + builtin_repo_path=builtin_repo_path.as_posix(), + builtin_repo_git_repo=spack_packages_repo, + verbose=False, ) ) f.write("\n") @@ -625,3 +535,70 @@ def generate(self, recipe): ) ) f.write("\n") + + + def _git_clone(self, name, repo, commit, path): + if not (path / ".git").is_dir(): + self._logger.info(f"{name}: clone repository {repo} to {path}") + + # clone the repository + capture = subprocess.run( + ["git", "clone", "--filter=tree:0", repo, path], + shell=False, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + ) + self._logger.debug(capture.stdout.decode("utf-8")) + + if capture.returncode != 0: + self._logger.error(f"error cloning the repository {repo}") + capture.check_returncode() + else: + self._logger.info(f"{name}: {repo} already cloned to {path}") + + if commit: + # Fetch the specific branch + self._logger.info(f"{name}: fetching {commit}") + capture = subprocess.run( + ["git", "-C", path, "fetch", "origin", commit], + shell=False, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + ) + self._logger.debug(capture.stdout.decode("utf-8")) + + if capture.returncode != 0: + self._logger.debug(f"unable to fetch {commit}") + capture.check_returncode() + + # Check out the specific branch + self._logger.info(f"{name}: checking out {commit}") + capture = subprocess.run( + ["git", "-C", path, "checkout", commit], + shell=False, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + ) + self._logger.debug(capture.stdout.decode("utf-8")) + + if capture.returncode != 0: + self._logger.debug(f"unable to change to the requested commit {commit}") + capture.check_returncode() + else: + self._logger.info(f"{name}: no commit set") + + # get the commit + git_commit_result = ( + subprocess.run( + ["git", "-C", path, "rev-parse", "HEAD"], + shell=False, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + .stdout.strip() + .decode("utf-8") + ) + + self._logger.info(f"{name}: commit hash is {git_commit_result}") + + return git_commit_result From 6fd55221b47b2321868d81d6e29bcc408b0a55f8 Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Thu, 19 Jun 2025 13:35:30 +0200 Subject: [PATCH 08/13] Pass spack-packages repo information to spack view environment variables --- stackinator/etc/envvars.py | 18 ++++++++++++++++-- stackinator/templates/Makefile | 2 +- unittests/test-envvars.sh | 2 +- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/stackinator/etc/envvars.py b/stackinator/etc/envvars.py index f008ded1..94c8b91e 100755 --- a/stackinator/etc/envvars.py +++ b/stackinator/etc/envvars.py @@ -542,6 +542,11 @@ def meta_impl(args): if args.spack is not None: spack_url, spack_ref, spack_commit = args.spack.split(",") + spack_packages_url = None + spack_packages_ref = None + spack_packages_commit = None + if args.spack_packages is not None: + spack_packages_url, spack_packages_ref, spack_packages_commit = args.spack_packages.split(",") spack_path = f"{args.mount}/config".replace("//", "/") meta["views"]["spack"] = { "activate": "/dev/null", @@ -554,9 +559,12 @@ def meta_impl(args): "list": {}, "scalar": { "UENV_SPACK_CONFIG_PATH": spack_path, + "UENV_SPACK_URL": spack_url, "UENV_SPACK_REF": spack_ref, "UENV_SPACK_COMMIT": spack_commit, - "UENV_SPACK_URL": spack_url, + "UENV_SPACK_PACKAGES_URL": spack_packages_url, + "UENV_SPACK_PACKAGES_REF": spack_packages_ref, + "UENV_SPACK_PACKAGES_COMMIT": spack_packages_commit, }, }, }, @@ -594,7 +602,13 @@ def meta_impl(args): uenv_parser.add_argument("--modules", help="configure a module view", action="store_true") uenv_parser.add_argument( "--spack", - help='configure a spack view. Format is "spack_url,git_ref,git_commit"', + help='configure a spack repository metadata. Format is "spack_url,git_ref,git_commit"', + type=str, + default=None, + ) + uenv_parser.add_argument( + "--spack-packages", + help='configure spack-packages repository metadata. Format is "spack_url,git_ref,git_commit"', type=str, default=None, ) diff --git a/stackinator/templates/Makefile b/stackinator/templates/Makefile index de2d352e..d4c1a1ae 100644 --- a/stackinator/templates/Makefile +++ b/stackinator/templates/Makefile @@ -69,7 +69,7 @@ modules-done: environments generate-config env-meta: generate-config environments{% if modules %} modules-done{% endif %} - $(SANDBOX) $(BUILD_ROOT)/envvars.py uenv {% if modules %}--modules{% endif %} --spack='{{ spack_meta.url }},{{ spack_meta.ref }},{{ spack_meta.commit }}' $(STORE) + $(SANDBOX) $(BUILD_ROOT)/envvars.py uenv {% if modules %}--modules{% endif %} --spack='{{ spack_meta.url }},{{ spack_meta.ref }},{{ spack_meta.commit }}' --spack-packages='{{ spack_meta.packages_url }},{{ spack_meta.packages_ref }},{{ spack_meta.packages_commit }}' $(STORE) touch env-meta post-install: env-meta diff --git a/unittests/test-envvars.sh b/unittests/test-envvars.sh index c8fa1e27..79e98fba 100755 --- a/unittests/test-envvars.sh +++ b/unittests/test-envvars.sh @@ -36,7 +36,7 @@ find $scratch_path -name env.json echo "===== running final meta data stage ${mount_path}" -../stackinator/etc/envvars.py uenv ${mount_path}/ --modules --spack="https://github.com/spack/spack.git,releases/v0.20" +../stackinator/etc/envvars.py uenv ${mount_path}/ --modules --spack="https://github.com/spack/spack.git,releases/v0.20" --spack-packages="https://github.com/spack/spack.git,develop" echo echo "===== develop" From b55198c34615a0b5a8e4518e7de3ef956c2a24ad Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Thu, 19 Jun 2025 13:42:37 +0200 Subject: [PATCH 09/13] Fix formatting --- stackinator/builder.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/stackinator/builder.py b/stackinator/builder.py index 52588a4d..d2931ca4 100644 --- a/stackinator/builder.py +++ b/stackinator/builder.py @@ -185,9 +185,7 @@ def generate(self, recipe): spack_commit = spack["commit"] spack_path = self.path / "spack" - spack_git_commit_result = self._git_clone( - "spack", spack_repo, spack_commit, spack_path - ) + spack_git_commit_result = self._git_clone("spack", spack_repo, spack_commit, spack_path) # Clone the spack-packages repository and check out commit if one was given spack_packages = spack["packages"] @@ -536,7 +534,6 @@ def generate(self, recipe): ) f.write("\n") - def _git_clone(self, name, repo, commit, path): if not (path / ".git").is_dir(): self._logger.info(f"{name}: clone repository {repo} to {path}") From d2e3bc9dfc454ef2c9dc87a3de6619edce1a3a10 Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Thu, 19 Jun 2025 14:05:37 +0200 Subject: [PATCH 10/13] Copy only package repo from spack-packages to squashfs --- stackinator/builder.py | 9 +++++++-- stackinator/templates/repos.yaml | 4 +--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/stackinator/builder.py b/stackinator/builder.py index d2931ca4..e80c4c74 100644 --- a/stackinator/builder.py +++ b/stackinator/builder.py @@ -397,7 +397,7 @@ def generate(self, recipe): self._logger.debug(f"created the repo packages path {pkg_dst}") # create the repository step 2: create the repo.yaml file that - # configures the repo. + # configures alps and builtin repos with (repo_dst / "repo.yaml").open("w") as f: f.write( """\ @@ -415,7 +415,6 @@ def generate(self, recipe): repos_yaml_template.render( repo_path=repo_path.as_posix(), builtin_repo_path=builtin_repo_path.as_posix(), - builtin_repo_git_repo=spack_packages_repo, verbose=False, ) ) @@ -436,6 +435,12 @@ def generate(self, recipe): elif dst.exists(): self._logger.debug(f" NOT installing package {pkg_path}") + # Copy the builtin repo to store + spack_packages_builtin_path = spack_packages_path / "repos" / "spack_repo" / "builtin" + spack_packages_store_path = store_path / "spack-packages" + self._logger.debug(f"copying builtin repo from {spack_packages_builtin_path} to {spack_packages_store_path}") + install(spack_packages_builtin_path, spack_packages_store_path) + # Generate the makefile and spack.yaml files that describe the compilers compiler_files = recipe.compiler_files compiler_path = self.path / "compilers" diff --git a/stackinator/templates/repos.yaml b/stackinator/templates/repos.yaml index 4a36c423..dfc1c9f6 100644 --- a/stackinator/templates/repos.yaml +++ b/stackinator/templates/repos.yaml @@ -1,5 +1,3 @@ repos: alps: {{ repo_path }} - builtin: - destination: {{ builtin_repo_path }} - git: {{ builtin_repo_git_repo }} + builtin: {{ builtin_repo_path }}/repos/spack_repo/builtin From 92c132a050186fb6813ee09032c3ecc75c10c117 Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Thu, 19 Jun 2025 14:54:28 +0200 Subject: [PATCH 11/13] Delete spack-packages repo in store if it already exists --- stackinator/builder.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/stackinator/builder.py b/stackinator/builder.py index e80c4c74..51d4f3a8 100644 --- a/stackinator/builder.py +++ b/stackinator/builder.py @@ -435,10 +435,13 @@ def generate(self, recipe): elif dst.exists(): self._logger.debug(f" NOT installing package {pkg_path}") - # Copy the builtin repo to store + # Copy the builtin repo to store, delete if it already exists. spack_packages_builtin_path = spack_packages_path / "repos" / "spack_repo" / "builtin" spack_packages_store_path = store_path / "spack-packages" self._logger.debug(f"copying builtin repo from {spack_packages_builtin_path} to {spack_packages_store_path}") + if spack_packages_store_path.exists(): + self._logger.debug(f"{spack_packages_store_path} exists ... deleting") + shutil.rmtree(spack_packages_store_path) install(spack_packages_builtin_path, spack_packages_store_path) # Generate the makefile and spack.yaml files that describe the compilers From 68e11fc74edf8fb4165aa1a26a26b4c152c444df Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Thu, 19 Jun 2025 17:14:08 +0200 Subject: [PATCH 12/13] Put both alps and builtin repos under repos directory in squashfs --- stackinator/builder.py | 9 +++++---- stackinator/templates/repos.yaml | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/stackinator/builder.py b/stackinator/builder.py index 51d4f3a8..89e3e4d2 100644 --- a/stackinator/builder.py +++ b/stackinator/builder.py @@ -385,7 +385,8 @@ def generate(self, recipe): # Delete the store/repo path, if it already exists. # Do this so that incremental builds (though not officially supported) won't break if a repo is updated. - repo_dst = store_path / "repo" + repos_path = store_path / "repos" + repo_dst = repos_path / "alps" self._logger.debug(f"creating the stack spack repo in {repo_dst}") if repo_dst.exists(): self._logger.debug(f"{repo_dst} exists ... deleting") @@ -409,8 +410,8 @@ def generate(self, recipe): # create the repository step 2: create the repos.yaml file in build_path/config repos_yaml_template = jinja_env.get_template("repos.yaml") with (config_path / "repos.yaml").open("w") as f: - repo_path = recipe.mount / "repo" - builtin_repo_path = recipe.mount / "spack-packages" + repo_path = recipe.mount / "repos" / "alps" + builtin_repo_path = recipe.mount / "repos" / "builtin" f.write( repos_yaml_template.render( repo_path=repo_path.as_posix(), @@ -437,7 +438,7 @@ def generate(self, recipe): # Copy the builtin repo to store, delete if it already exists. spack_packages_builtin_path = spack_packages_path / "repos" / "spack_repo" / "builtin" - spack_packages_store_path = store_path / "spack-packages" + spack_packages_store_path = store_path / "repos" / "builtin" self._logger.debug(f"copying builtin repo from {spack_packages_builtin_path} to {spack_packages_store_path}") if spack_packages_store_path.exists(): self._logger.debug(f"{spack_packages_store_path} exists ... deleting") diff --git a/stackinator/templates/repos.yaml b/stackinator/templates/repos.yaml index dfc1c9f6..3cf34f26 100644 --- a/stackinator/templates/repos.yaml +++ b/stackinator/templates/repos.yaml @@ -1,3 +1,3 @@ repos: alps: {{ repo_path }} - builtin: {{ builtin_repo_path }}/repos/spack_repo/builtin + builtin: {{ builtin_repo_path }} From 40276d8cff6240d0cfc399db21bdd9130cde2728 Mon Sep 17 00:00:00 2001 From: Mikael Simberg Date: Mon, 23 Jun 2025 16:39:01 +0200 Subject: [PATCH 13/13] Fix builtin repo --- stackinator/builder.py | 8 ++++---- stackinator/templates/Makefile | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/stackinator/builder.py b/stackinator/builder.py index 89e3e4d2..ae960ef1 100644 --- a/stackinator/builder.py +++ b/stackinator/builder.py @@ -351,7 +351,7 @@ def generate(self, recipe): # 2. cluster-config/repos.yaml # - if the repos.yaml file exists it will contain a list of relative paths # to search for package - # 1. spack/var/spack/repos/builtin + # 1. builtin repo # Build a list of repos with packages to install. repos = [] @@ -411,7 +411,7 @@ def generate(self, recipe): repos_yaml_template = jinja_env.get_template("repos.yaml") with (config_path / "repos.yaml").open("w") as f: repo_path = recipe.mount / "repos" / "alps" - builtin_repo_path = recipe.mount / "repos" / "builtin" + builtin_repo_path = recipe.mount / "repos" / "spack_repo" / "builtin" f.write( repos_yaml_template.render( repo_path=repo_path.as_posix(), @@ -437,8 +437,8 @@ def generate(self, recipe): self._logger.debug(f" NOT installing package {pkg_path}") # Copy the builtin repo to store, delete if it already exists. - spack_packages_builtin_path = spack_packages_path / "repos" / "spack_repo" / "builtin" - spack_packages_store_path = store_path / "repos" / "builtin" + spack_packages_builtin_path = spack_packages_path / "repos" / "spack_repo" + spack_packages_store_path = store_path / "repos" / "spack_repo" self._logger.debug(f"copying builtin repo from {spack_packages_builtin_path} to {spack_packages_store_path}") if spack_packages_store_path.exists(): self._logger.debug(f"{spack_packages_store_path} exists ... deleting") diff --git a/stackinator/templates/Makefile b/stackinator/templates/Makefile index d4c1a1ae..82e7fbd4 100644 --- a/stackinator/templates/Makefile +++ b/stackinator/templates/Makefile @@ -81,7 +81,7 @@ post-install: env-meta # Create a squashfs file from the installed software. store.squashfs: post-install # clean up the __pycache__ paths in the repo - $(SANDBOX) find $(STORE)/repo -type d -name __pycache__ -exec rm -r {} + + $(SANDBOX) find $(STORE)/repos -type d -name __pycache__ -exec rm -r {} + $(SANDBOX) chmod -R a+rX $(STORE) $(SANDBOX) env -u SOURCE_DATE_EPOCH "$$($(SANDBOX) $(SPACK_HELPER) -e ./compilers/bootstrap find --format='{prefix}' squashfs | head -n1)/bin/mksquashfs" $(STORE) $@ -force-uid nobody -force-gid nobody -all-time $$(date +%s) -no-recovery -noappend -Xcompression-level 3