diff --git a/buildbot_nix/__init__.py b/buildbot_nix/__init__.py index d86f31b..f2d683e 100644 --- a/buildbot_nix/__init__.py +++ b/buildbot_nix/__init__.py @@ -8,6 +8,7 @@ from collections.abc import Generator from dataclasses import dataclass, field from pathlib import Path from typing import TYPE_CHECKING, Any +import tempfile import buildbot from buildbot.configurators import ConfiguratorBase @@ -367,13 +368,18 @@ class NixEvalCommand(buildstep.ShellMixin, steps.BuildStep): every attribute. """ - def __init__(self, supported_systems: list[str], **kwargs: Any) -> None: + def __init__(self, supported_systems: list[str], incoming_ref_filename: str, **kwargs: Any) -> None: kwargs = self.setupShellMixin(kwargs) super().__init__(**kwargs) + self.incoming_ref_filename = incoming_ref_filename self.observer = logobserver.BufferLogObserver() self.addLogObserver("stdio", self.observer) self.supported_systems = supported_systems + def __del__(self): + # Cleanup the incoming ref parameter file. + os.unlink(self.incoming_ref_filename) + @defer.inlineCallbacks def run(self) -> Generator[Any, object, Any]: # run nix-eval-jobs --flake .#$FLAKE_TARGET_ATTRIBUTE_FOR_JOBS to generate the dict of stages @@ -453,17 +459,29 @@ class NixEvalCommand(buildstep.ShellMixin, steps.BuildStep): return result -def make_job_evaluator(name: str, settings: EvaluatorSettings, flake: bool) -> NixEvalCommand: +def make_job_evaluator(name: str, settings: EvaluatorSettings, flake: bool, incoming_ref_data: dict[str, Any]) -> NixEvalCommand: actual_command = [] + try: + eval_parameter_json_repr = json.dumps(incoming_ref_data) + except ValueError as e: + msg = f"Failed to serialize incoming ref data for {name}" + raise BuildbotNixError(msg) from e + + eval_parameter_json_fp = tempfile.NamedTemporaryFile(delete_on_close=False) + eval_parameter_json_fp.write(eval_parameter_json_repr.encode('utf8')) + eval_parameter_json_fp.close() + if flake: actual_command += ["--flake", f".#{FLAKE_TARGET_ATTRIBUTE_FOR_JOBS}"] else: - actual_command += ["--expr", "import ./.ci/buildbot.nix"] + actual_command += ["--expr", + f"import ./.ci/buildbot.nix {{ incoming_ref_data = builtins.fromJSON (builtins.readFile {eval_parameter_json_fp.name}); }}"] return NixEvalCommand( env={}, name=name, + incoming_ref_filename=eval_parameter_json_fp.name, supported_systems=settings.supported_systems, command=[ "nix-eval-jobs", @@ -504,6 +522,14 @@ class NixConfigure(buildstep.CommandMixin, steps.BuildStep): except Exception: configure_log: Log = yield self.addLog("stdio") + # This information can be passed at job evaluation time + # to skip some jobs, e.g. expensive jobs, etc. + incoming_ref_data = { + # TODO: please just denormalize it properly. + 'event': { + key: value for (key, (value, _)) in self.getProperties().asDict().items() if key.startswith('event.') + } + } # Takes precedence. configure_log.addStdout("checking if there's a .ci/buildbot.nix...\n") ci_buildbot_defn_exists = yield self.pathExists('build/.ci/buildbot.nix') @@ -514,7 +540,8 @@ class NixConfigure(buildstep.CommandMixin, steps.BuildStep): make_job_evaluator( "evaluate `.ci/buildbot.nix` jobs", self.evaluator_settings, - False + False, + incoming_ref_data ) ] ) @@ -527,7 +554,8 @@ class NixConfigure(buildstep.CommandMixin, steps.BuildStep): make_job_evaluator( "evaluate `flake.nix` jobs", self.evaluator_settings, - True + True, + incoming_ref_data ) ] )