From cd6cbe8792f038fc7a27d37c0804afa0a244eca9 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Tue, 21 Nov 2023 11:13:16 +0100 Subject: runactions: New --- rtemsspec/packagebuildfactory.py | 2 + rtemsspec/runactions.py | 314 +++++++++++++++++++++ .../spec-packagebuild/qdp/output/run-actions.yml | 13 + .../tests/spec-packagebuild/qdp/package-build.yml | 2 + .../spec-packagebuild/qdp/steps/run-actions.yml | 282 ++++++++++++++++++ rtemsspec/tests/test_packagebuild.py | 14 + rtemsspec/util.py | 42 ++- spec-qdp/spec/qdp-action-copy-and-substitute.yml | 42 +++ spec-qdp/spec/qdp-action-create-ini-file.yml | 35 +++ .../spec/qdp-action-directory-state-add-files.yml | 34 +++ ...-action-directory-state-add-tarfile-members.yml | 43 +++ .../spec/qdp-action-directory-state-add-tree.yml | 49 ++++ spec-qdp/spec/qdp-action-directory-state-clear.yml | 26 ++ .../spec/qdp-action-directory-state-copy-tree.yml | 49 ++++ .../spec/qdp-action-directory-state-move-tree.yml | 49 ++++ spec-qdp/spec/qdp-action-list.yml | 16 ++ spec-qdp/spec/qdp-action-mkdir.yml | 35 +++ .../spec/qdp-action-remove-empty-directories.yml | 28 ++ spec-qdp/spec/qdp-action-remove-glob.yml | 38 +++ spec-qdp/spec/qdp-action-remove-tree.yml | 30 ++ spec-qdp/spec/qdp-action-remove.yml | 31 ++ spec-qdp/spec/qdp-action-subprocess-env-list.yml | 16 ++ spec-qdp/spec/qdp-action-subprocess-env.yml | 33 +++ spec-qdp/spec/qdp-action-subprocess.yml | 42 +++ spec-qdp/spec/qdp-action-touch.yml | 30 ++ spec-qdp/spec/qdp-action.yml | 26 ++ spec-qdp/spec/qdp-ini-file-key-value-pair-list.yml | 16 ++ spec-qdp/spec/qdp-ini-file-key-value-pair.yml | 31 ++ spec-qdp/spec/qdp-ini-file-section-list.yml | 16 ++ spec-qdp/spec/qdp-ini-file-section.yml | 29 ++ spec-qdp/spec/qdp-run-actions.yml | 31 ++ 31 files changed, 1442 insertions(+), 2 deletions(-) create mode 100644 rtemsspec/runactions.py create mode 100644 rtemsspec/tests/spec-packagebuild/qdp/output/run-actions.yml create mode 100644 rtemsspec/tests/spec-packagebuild/qdp/steps/run-actions.yml create mode 100644 spec-qdp/spec/qdp-action-copy-and-substitute.yml create mode 100644 spec-qdp/spec/qdp-action-create-ini-file.yml create mode 100644 spec-qdp/spec/qdp-action-directory-state-add-files.yml create mode 100644 spec-qdp/spec/qdp-action-directory-state-add-tarfile-members.yml create mode 100644 spec-qdp/spec/qdp-action-directory-state-add-tree.yml create mode 100644 spec-qdp/spec/qdp-action-directory-state-clear.yml create mode 100644 spec-qdp/spec/qdp-action-directory-state-copy-tree.yml create mode 100644 spec-qdp/spec/qdp-action-directory-state-move-tree.yml create mode 100644 spec-qdp/spec/qdp-action-list.yml create mode 100644 spec-qdp/spec/qdp-action-mkdir.yml create mode 100644 spec-qdp/spec/qdp-action-remove-empty-directories.yml create mode 100644 spec-qdp/spec/qdp-action-remove-glob.yml create mode 100644 spec-qdp/spec/qdp-action-remove-tree.yml create mode 100644 spec-qdp/spec/qdp-action-remove.yml create mode 100644 spec-qdp/spec/qdp-action-subprocess-env-list.yml create mode 100644 spec-qdp/spec/qdp-action-subprocess-env.yml create mode 100644 spec-qdp/spec/qdp-action-subprocess.yml create mode 100644 spec-qdp/spec/qdp-action-touch.yml create mode 100644 spec-qdp/spec/qdp-action.yml create mode 100644 spec-qdp/spec/qdp-ini-file-key-value-pair-list.yml create mode 100644 spec-qdp/spec/qdp-ini-file-key-value-pair.yml create mode 100644 spec-qdp/spec/qdp-ini-file-section-list.yml create mode 100644 spec-qdp/spec/qdp-ini-file-section.yml create mode 100644 spec-qdp/spec/qdp-run-actions.yml diff --git a/rtemsspec/packagebuildfactory.py b/rtemsspec/packagebuildfactory.py index ef4a950b..600c58de 100644 --- a/rtemsspec/packagebuildfactory.py +++ b/rtemsspec/packagebuildfactory.py @@ -27,12 +27,14 @@ from rtemsspec.archiver import Archiver from rtemsspec.directorystate import DirectoryState from rtemsspec.packagebuild import BuildItemFactory, PackageVariant +from rtemsspec.runactions import RunActions def create_build_item_factory() -> BuildItemFactory: """ Creates the default build item factory. """ factory = BuildItemFactory() factory.add_constructor("qdp/build-step/archive", Archiver) + factory.add_constructor("qdp/build-step/run-actions", RunActions) factory.add_constructor("qdp/directory-state/generic", DirectoryState) factory.add_constructor("qdp/directory-state/repository", DirectoryState) factory.add_constructor("qdp/directory-state/unpacked-archive", diff --git a/rtemsspec/runactions.py b/rtemsspec/runactions.py new file mode 100644 index 00000000..1da507cd --- /dev/null +++ b/rtemsspec/runactions.py @@ -0,0 +1,314 @@ +# SPDX-License-Identifier: BSD-2-Clause +""" This module provides a build step to run actions. """ + +# Copyright (C) 2022, 2023 embedded brains GmbH (http://www.embedded-brains.de) +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +import copy +import os +import logging +from pathlib import Path +import shutil +import subprocess +from typing import Any, Dict, List, Optional, Union + +from rtemsspec.directorystate import DirectoryState +from rtemsspec.items import Item, ItemGetValueContext, is_enabled +from rtemsspec.packagebuild import BuildItem, PackageBuildDirector +from rtemsspec.util import copy_and_substitute, remove_empty_directories + + +def _env_clear(item: "RunActions", env: Dict, _action: Dict[str, str]) -> None: + logging.info("%s: env: clear", item.uid) + env.clear() + + +def _env_path_append(item: "RunActions", env: Dict, action: Dict[str, + str]) -> None: + name = action["name"] + value = action["value"] + logging.info("%s: env: append '%s' to %s", item.uid, value, name) + env[name] = f"{env[name]}:{value}" + + +def _env_path_prepend(item: "RunActions", env: Dict, + action: Dict[str, str]) -> None: + name = action["name"] + value = action["value"] + logging.info("%s: env: prepend '%s' to %s", item.uid, value, name) + env[name] = f"{value}:{env[name]}" + + +def _env_set(item: "RunActions", env: Dict, action: Dict[str, str]) -> None: + name = action["name"] + value = action["value"] + logging.info("%s: env: %s = '%s'", item.uid, name, value) + env[name] = value + + +def _env_unset(item: "RunActions", env: Dict, action: Dict[str, str]) -> None: + name = action["name"] + logging.info("%s: env: unset %s", item.uid, name) + del env[name] + + +_ENV_ACTIONS = { + "clear": _env_clear, + "path-append": _env_path_append, + "path-prepend": _env_path_prepend, + "set": _env_set, + "unset": _env_unset +} + + +def _get_host_processor_count(_ctx: ItemGetValueContext) -> str: + count = os.cpu_count() + return str(count if count is not None else 1) + + +class RunActions(BuildItem): + """ Runs actions. """ + + def __init__(self, director: PackageBuildDirector, item: Item): + super().__init__(director, item) + self.mapper.add_get_value(f"{self.item.type}:/host-processor-count", + _get_host_processor_count) + + def run(self): + for index, action in enumerate(self["actions"]): + action_type = action["action"] + logging.info("%s: run action %i: %s", self.uid, index, action_type) + if is_enabled(self.enabled_set, action["enabled-by"]): + output_name = action.get("output-name", None) + if output_name is None: + output = None + else: + try: + output = self.output(output_name) + except ValueError: + continue + RunActions._ACTIONS[action_type](self, action, output) + + def _copy_and_substitute(self, action: Dict, + output: Optional[DirectoryState]) -> None: + assert isinstance(output, DirectoryState) + input_state = self.input(action["input-name"]) + assert isinstance(input_state, DirectoryState) + source = action["source"] + source_base = input_state.directory + target_base = output.directory + if source is None: + prefix = action["target"] + if prefix is None: + prefix = "." + targets: List[str] = [] + for source_file in input_state: + tail = os.path.relpath(source_file, source_base) + target_file = os.path.join(target_base, prefix, tail) + targets.append(tail) + copy_and_substitute(source_file, target_file, self.mapper, + self.uid) + output.add_files(targets) + else: + source_file = os.path.join(source_base, source) + target = action["target"] + if target is None: + target_file = output.file + else: + output.add_files([target]) + target_file = os.path.join(target_base, target) + copy_and_substitute(source_file, target_file, self.mapper, + self.uid) + + def _create_ini_file(self, action: Dict, + output: Optional[DirectoryState]) -> None: + assert isinstance(output, DirectoryState) + target = action["target"] + if target is None: + target = output.file + else: + output.add_files([target]) + target = os.path.join(output.directory, target) + logging.info("%s: create: %s", self.uid, target) + os.makedirs(os.path.dirname(target), exist_ok=True) + with open(target, "w", encoding="utf-8") as dst: + for section in action["sections"]: + if not is_enabled(self.enabled_set, section["enabled-by"]): + continue + dst.write(f"[{section['name']}]\n") + for key_value in section["key-value-pairs"]: + if not is_enabled(self.enabled_set, + key_value["enabled-by"]): + continue + dst.write(f"{key_value['key']} = {key_value['value']}\n") + + def _directory_state_clear(self, _action: Dict, + output: Optional[DirectoryState]) -> None: + assert isinstance(output, DirectoryState) + output.clear() + + def _directory_state_add_files(self, action: Dict, + output: Optional[DirectoryState]) -> None: + assert isinstance(output, DirectoryState) + root = Path(action["path"]).absolute() + pattern = action["pattern"] + logging.info("%s: add files matching '%s' in: %s", self.uid, pattern, + root) + base = output.directory + output.add_files( + [os.path.relpath(path, base) for path in root.glob(pattern)]) + + def _directory_state_add_tarfile_members( + self, action: Dict, output: Optional[DirectoryState]) -> None: + assert isinstance(output, DirectoryState) + root = Path(action["search-path"]) + pattern = action["pattern"] + logging.info("%s: search for tarfiles matching '%s' in: %s", self.uid, + pattern, root) + for path in root.glob(pattern): + output.add_tarfile_members(path, action["prefix-path"], + action["extract"]) + + def _directory_state_tree_op(self, action: Dict, + output: Optional[DirectoryState], + tree_op: Any) -> None: + assert isinstance(output, DirectoryState) + root = Path(action["root"]).absolute() + prefix = action["prefix"] + if prefix is None: + prefix = "." + tree_op(output, root, prefix, action["excludes"]) + + def _directory_state_add_tree(self, action: Dict, + output: Optional[DirectoryState]) -> None: + self._directory_state_tree_op(action, output, DirectoryState.add_tree) + + def _directory_state_copy_tree(self, action: Dict, + output: Optional[DirectoryState]) -> None: + self._directory_state_tree_op(action, output, DirectoryState.copy_tree) + + def _directory_state_move_tree(self, action: Dict, + output: Optional[DirectoryState]) -> None: + self._directory_state_tree_op(action, output, DirectoryState.move_tree) + + def _process(self, action: Dict, + _output: Optional[DirectoryState]) -> None: + env: Union[Dict, None] = None + env_actions = action["env"] + if env_actions: + logging.info("%s: env: modify", self.uid) + env = copy.deepcopy(os.environ.copy()) + for env_action in env_actions: + _ENV_ACTIONS[env_action["action"]](self, env, env_action) + cmd = action["command"] + cwd = action["working-directory"] + logging.info("%s: run in '%s': %s", self.uid, cwd, + " ".join(f"'{i}'" for i in cmd)) + status = subprocess.run(cmd, env=env, check=False, cwd=cwd) + expected_return_code = action["expected-return-code"] + if expected_return_code is not None: + assert status.returncode == expected_return_code + + def _mkdir(self, action: Dict, _output: Optional[DirectoryState]) -> None: + path = Path(action["path"]) + logging.info("%s: make directory: %s", self.uid, path) + path.mkdir(parents=action["parents"], exist_ok=action["exist-ok"]) + + def _remove_path(self, path: Path) -> None: + if path.is_dir(): + logging.info("%s: remove directory: %s", self.uid, path) + path.rmdir() + else: + logging.info("%s: unlink file: %s", self.uid, path) + path.unlink() + + def _remove(self, action: Dict, _output: Optional[DirectoryState]) -> None: + path = Path(action["path"]) + if action["missing-ok"]: + try: + self._remove_path(path) + except FileNotFoundError: + pass + else: + self._remove_path(path) + + def _remove_empty_directories(self, action: Dict, + _output: Optional[DirectoryState]) -> None: + remove_empty_directories(self.uid, action["path"]) + + def _remove_glob(self, action: Dict, + _output: Optional[DirectoryState]) -> None: + root = Path(action["path"]) + for pattern in action["patterns"]: + logging.info( + "%s: remove files and directories matching with '%s' in: %s", + self.uid, pattern, root) + for path in root.glob(pattern): + if path.is_dir(): + if action["remove-tree"]: + logging.info("%s: remove directory tree: %s", self.uid, + path) + shutil.rmtree(path) + else: + logging.info("%s: remove directory: %s", self.uid, + path) + path.rmdir() + else: + logging.info("%s: remove file: %s", self.uid, path) + path.unlink() + + def _remove_tree(self, action: Dict, + _output: Optional[DirectoryState]) -> None: + path = action["path"] + logging.info("%s: remove directory tree: %s", self.uid, path) + if action["missing-ok"]: + try: + shutil.rmtree(path) + except FileNotFoundError: + pass + else: + shutil.rmtree(path) + + def _touch(self, action: Dict, _output: Optional[DirectoryState]) -> None: + path = Path(action["path"]) + logging.info("%s: touch file: %s", self.uid, path) + path.touch(exist_ok=action["exist-ok"]) + + _ACTIONS = { + "copy-and-substitute": _copy_and_substitute, + "create-ini-file": _create_ini_file, + "directory-state-add-files": _directory_state_add_files, + "directory-state-add-tarfile-members": + _directory_state_add_tarfile_members, + "directory-state-add-tree": _directory_state_add_tree, + "directory-state-clear": _directory_state_clear, + "directory-state-copy-tree": _directory_state_copy_tree, + "directory-state-move-tree": _directory_state_move_tree, + "mkdir": _mkdir, + "remove": _remove, + "remove-empty-directories": _remove_empty_directories, + "remove-glob": _remove_glob, + "remove-tree": _remove_tree, + "subprocess": _process, + "touch": _touch + } diff --git a/rtemsspec/tests/spec-packagebuild/qdp/output/run-actions.yml b/rtemsspec/tests/spec-packagebuild/qdp/output/run-actions.yml new file mode 100644 index 00000000..b5dd5ddb --- /dev/null +++ b/rtemsspec/tests/spec-packagebuild/qdp/output/run-actions.yml @@ -0,0 +1,13 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2023 embedded brains GmbH & Co. KG +copyrights-by-license: {} +directory: ${../variant:/prefix-directory} +directory-state-type: generic +enabled-by: true +files: [] +hash: null +links: [] +patterns: [] +qdp-type: directory-state +type: qdp diff --git a/rtemsspec/tests/spec-packagebuild/qdp/package-build.yml b/rtemsspec/tests/spec-packagebuild/qdp/package-build.yml index 4e72be8b..1d7a18c8 100644 --- a/rtemsspec/tests/spec-packagebuild/qdp/package-build.yml +++ b/rtemsspec/tests/spec-packagebuild/qdp/package-build.yml @@ -9,6 +9,8 @@ links: uid: steps/b - role: build-step uid: steps/c +- role: build-step + uid: steps/run-actions - role: build-step uid: steps/archive qdp-type: package-build diff --git a/rtemsspec/tests/spec-packagebuild/qdp/steps/run-actions.yml b/rtemsspec/tests/spec-packagebuild/qdp/steps/run-actions.yml new file mode 100644 index 00000000..505acbdd --- /dev/null +++ b/rtemsspec/tests/spec-packagebuild/qdp/steps/run-actions.yml @@ -0,0 +1,282 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +actions: +- action: mkdir + enabled-by: true + exist-ok: false + parents: true + path: ${../variant:/build-directory}/some/more/dirs +- action: touch + enabled-by: true + exist-ok: false + path: ${../variant:/build-directory}/some/more/dirs/file +- action: touch + enabled-by: false + exist-ok: false + path: ${../variant:/build-directory}/some/more/dirs/file +- action: touch + enabled-by: true + exist-ok: true + path: ${../variant:/build-directory}/some/more/dirs/file +- action: remove + enabled-by: true + missing-ok: false + path: ${../variant:/build-directory}/some/more/dirs/file +- action: remove + enabled-by: true + missing-ok: true + path: ${../variant:/build-directory}/some/more/dirs/file +- action: remove + enabled-by: true + missing-ok: false + path: ${../variant:/build-directory}/some/more/dirs +- action: remove + enabled-by: true + missing-ok: true + path: ${../variant:/build-directory}/some/more/dirs +- action: mkdir + enabled-by: true + exist-ok: false + parents: false + path: ${../variant:/build-directory}/some/more/dirs +- action: touch + enabled-by: true + exist-ok: false + path: ${../variant:/build-directory}/some/more/dirs/file +- action: remove-empty-directories + enabled-by: true + path: ${../variant:/build-directory}/some +- action: remove + enabled-by: true + missing-ok: false + path: ${../variant:/build-directory}/some/more/dirs/file +- action: remove-empty-directories + enabled-by: true + path: ${../variant:/build-directory}/some +- action: mkdir + enabled-by: true + exist-ok: false + parents: true + path: ${../variant:/build-directory}/some/more/dirs +- action: touch + enabled-by: true + exist-ok: false + path: ${../variant:/build-directory}/some/more/dirs/file +- action: remove-tree + enabled-by: true + missing-ok: true + path: ${../variant:/build-directory}/some/more +- action: remove-tree + enabled-by: true + missing-ok: true + path: ${../variant:/build-directory}/some/more +- action: remove-tree + enabled-by: true + missing-ok: false + path: ${../variant:/build-directory}/some +- action: mkdir + enabled-by: true + exist-ok: false + parents: true + path: ${../variant:/build-directory}/some/more/dirs +- action: touch + enabled-by: true + exist-ok: false + path: ${../variant:/build-directory}/some/more/dirs/file +- action: remove-glob + enabled-by: true + remove-tree: false + path: ${../variant:/build-directory}/some/more/dirs + patterns: + - foobar +- action: remove-glob + enabled-by: true + remove-tree: false + path: ${../variant:/build-directory}/some/more/dirs + patterns: + - file +- action: touch + enabled-by: true + exist-ok: false + path: ${../variant:/build-directory}/some/more/dirs/file +- action: remove-glob + enabled-by: true + remove-tree: true + path: ${../variant:/build-directory}/some + patterns: + - more +- action: remove-glob + enabled-by: true + remove-tree: false + path: ${../variant:/build-directory} + patterns: + - some +- action: directory-state-clear + enabled-by: true + output-name: destination +- action: directory-state-clear + enabled-by: true + output-name: disabled +- action: directory-state-add-tarfile-members + enabled-by: true + extract: true + output-name: destination + prefix-path: ${../variant:/deployment-directory} + search-path: ${../variant:/prefix-directory} + pattern: archive.tar.xz +- action: directory-state-clear + enabled-by: true + output-name: destination +- action: mkdir + enabled-by: true + exist-ok: false + parents: true + path: ${../variant:/build-directory}/some/more/dirs +- action: touch + enabled-by: true + exist-ok: false + path: ${../variant:/build-directory}/some/more/dirs/file +- action: directory-state-add-files + enabled-by: true + output-name: destination + path: ${../variant:/prefix-directory} + pattern: archive.tar.xz +- action: directory-state-add-tree + enabled-by: true + excludes: [] + output-name: destination + prefix: null + root: ${../variant:/build-directory}/some/more +- action: mkdir + enabled-by: true + exist-ok: false + parents: true + path: ${../output/run-actions:/directory}/dirs +- action: touch + enabled-by: true + exist-ok: false + path: ${../output/run-actions:/directory}/dirs/file +- action: directory-state-copy-tree + enabled-by: true + excludes: [] + output-name: destination + prefix: "u" + root: ${../variant:/build-directory}/some/more +- action: directory-state-move-tree + enabled-by: true + excludes: [] + output-name: destination + prefix: "v" + root: ${../output/run-actions:/directory}/u/dirs +- action: touch + enabled-by: true + exist-ok: false + path: ${../output/run-actions:/directory}/u/dirs/file +- action: create-ini-file + enabled-by: true + output-name: destination + sections: + - enabled-by: true + key-value-pairs: + - enabled-by: true + key: KA + value: VA + - enabled-by: false + key: KB + value: VB + name: AA + - enabled-by: false + key-value-pairs: [] + name: SB + target: null +- action: create-ini-file + enabled-by: true + output-name: destination + sections: [] + target: foo.ini +- action: copy-and-substitute + enabled-by: true + input-name: source + output-name: destination + source: null + target: null +- action: copy-and-substitute + enabled-by: true + input-name: source + output-name: destination + source: dir/subdir/c.txt + target: null +- action: copy-and-substitute + enabled-by: true + input-name: source + output-name: destination + source: null + target: some/other +- action: copy-and-substitute + enabled-by: true + input-name: source + output-name: destination + source: dir/subdir/c.txt + target: some/other/file.txt +- action: subprocess + command: + - git + - foobar + enabled-by: true + env: [] + expected-return-code: null + working-directory: ${../variant:/build-directory} +- action: subprocess + command: + - git + - status + enabled-by: true + env: + - action: clear + name: PATH + value: null + - action: set + name: FOOBAR + value: foo + - action: path-append + name: FOOBAR + value: bar + - action: path-prepend + name: FOOBAR + value: ${.:/host-processor-count} + - action: unset + name: FOOBAR + value: null + expected-return-code: null + working-directory: ${../variant:/build-directory} +- action: subprocess + command: + - git + - status + enabled-by: true + env: [] + expected-return-code: 0 + working-directory: ${../variant:/build-directory} +build-step-type: run-actions +copyrights: +- Copyright (C) 2023 embedded brains GmbH & Co. KG +description: Description. +enabled-by: run-actions +links: +- hash: null + name: variant + role: input + uid: ../variant +- hash: null + name: source + role: input + uid: ../source/a +- name: destination + role: output + uid: ../output/run-actions +- name: disabled + role: output + uid: ../output/b +params: {} +qdp-type: build-step +type: qdp + diff --git a/rtemsspec/tests/test_packagebuild.py b/rtemsspec/tests/test_packagebuild.py index 436c6f29..fc4ae327 100644 --- a/rtemsspec/tests/test_packagebuild.py +++ b/rtemsspec/tests/test_packagebuild.py @@ -101,6 +101,8 @@ def test_packagebuild(caplog, tmpdir): director.clear() variant = director["/qdp/variant"] prefix_dir = Path(variant["prefix-directory"]) + status = run_command(["git", "init"], str(prefix_dir)) + assert status == 0 director.build_package(None, None) log = get_and_clear_log(caplog) @@ -199,3 +201,15 @@ def test_packagebuild(caplog, tmpdir): "dir/subdir/c.txt\t663049a20dfea6b8da28b2eb90eddd10ccf28ef2519563310b9bde25b7268444014c48c4384ee5c5a54e7830e45fcd87df7910a7fda77b68c2efdd75f8de25e8", "dir/subdir/d.txt\t48fb10b15f3d44a09dc82d02b06581e0c0c69478c9fd2cf8f9093659019a1687baecdbb38c9e72b12169dc4148690f87467f9154f5931c5df665c6496cbfd5f5" ] + + # Test RunActions + variant["enabled"] = ["run-actions"] + director.build_package(None, None) + log = get_and_clear_log(caplog) + assert f"/qdp/steps/run-actions: make directory: {tmp_dir}/pkg/build/some/more/dirs" in log + assert f"/qdp/steps/run-actions: remove empty directory: {tmp_dir}/pkg/build/some/more/dirs" in log + assert f"/qdp/steps/run-actions: remove empty directory: {tmp_dir}/pkg/build/some/more" in log + assert f"/qdp/steps/run-actions: remove empty directory: {tmp_dir}/pkg/build/some" in log + assert f"/qdp/steps/run-actions: remove directory tree: {tmp_dir}/pkg/build/some" in log + assert f"/qdp/steps/run-actions: run in '{tmp_dir}/pkg/build': 'git' 'foobar'" in log + assert f"/qdp/steps/run-actions: run in '{tmp_dir}/pkg/build': 'git' 'status'" in log diff --git a/rtemsspec/util.py b/rtemsspec/util.py index 2e491244..a1f46372 100644 --- a/rtemsspec/util.py +++ b/rtemsspec/util.py @@ -1,7 +1,7 @@ # SPDX-License-Identifier: BSD-2-Clause """ This module provides utility functions. """ -# Copyright (C) 2020, 2021 embedded brains GmbH & Co. KG +# Copyright (C) 2020, 2023 embedded brains GmbH & Co. KG # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -33,9 +33,11 @@ import os from pathlib import Path import shutil import subprocess -from typing import Any, List, Optional, Union +from typing import Any, List, Optional, Set, Union import yaml +from rtemsspec.items import ItemMapper + def base64_to_hex(data: str) -> str: """ Converts the data from base64 to hex. """ @@ -79,6 +81,42 @@ def copy_files(src_dir: str, dst_dir: str, files: List[str], shutil.copy2(src_file, dst_file) +def copy_and_substitute(src_file: str, dst_file: str, mapper: ItemMapper, + log_context: str) -> None: + """ + Copies the file from the source to the destination path and performs a + variable substitution on the file content using the item mapper. + """ + logging.info("%s: read: %s", log_context, src_file) + with open(src_file, "r", encoding="utf-8") as src: + logging.info("%s: substitute using mapper of item %s", log_context, + mapper.item.uid) + content = mapper.substitute(src.read()) + logging.info("%s: write: %s", log_context, dst_file) + os.makedirs(os.path.dirname(dst_file), exist_ok=True) + with open(dst_file, "w+", encoding="utf-8") as dst: + dst.write(content) + + +def remove_empty_directories(scope: str, base: str) -> None: + """ + Recursively removes all empty subdirectories of base and base itself if it + gets empty. + + The scope is used for log messages. + """ + removed: Set[str] = set() + for root, subdirs, files in os.walk(base, topdown=False): + if files: + continue + if any(subdir for subdir in subdirs + if os.path.join(root, subdir) not in removed): + continue + logging.info("%s: remove empty directory: %s", scope, root) + os.rmdir(root) + removed.add(root) + + def load_config(config_filename: str) -> Any: """ Loads the configuration file with recursive includes. """ diff --git a/spec-qdp/spec/qdp-action-copy-and-substitute.yml b/spec-qdp/spec/qdp-action-copy-and-substitute.yml new file mode 100644 index 00000000..9b1d1527 --- /dev/null +++ b/spec-qdp/spec/qdp-action-copy-and-substitute.yml @@ -0,0 +1,42 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2023 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +- role: spec-refinement + spec-key: action + spec-value: copy-and-substitute + uid: qdp-action +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + input-name: + description: | + It shall be name of the input directory state. + spec-type: str + output-name: + description: | + It shall be name of the output directory state. + spec-type: str + source: + description: | + If the value is present, then it shall be the source file relative to + the base directory of the input directory state, otherwise the + source file is the first file of the input directory state. + spec-type: optional-str + target: + description: | + If the value is present, then it shall be the target file relative to + the base directory of the output directory state, otherwise the + target file is the first file of the output directory state. + spec-type: optional-str + description: | + This set of attributes specifies a copy and substitute action. + mandatory-attributes: all +spec-name: Copy and Substitute Action +spec-type: qdp-action-copy-and-substitute +type: spec diff --git a/spec-qdp/spec/qdp-action-create-ini-file.yml b/spec-qdp/spec/qdp-action-create-ini-file.yml new file mode 100644 index 00000000..269a22b8 --- /dev/null +++ b/spec-qdp/spec/qdp-action-create-ini-file.yml @@ -0,0 +1,35 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2023 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +- role: spec-refinement + spec-key: action + spec-value: create-ini-file + uid: qdp-action +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + output-name: + description: | + It shall be name of the output directory state. + spec-type: str + sections: + description: null + spec-type: qdp-ini-file-section-list + target: + description: | + If the value is present, then it shall be the target file relative to + the base directory of the output directory state, otherwise the + target file is the first file of the output directory state. + spec-type: optional-str + description: | + This set of attributes specifies a create INI file action. + mandatory-attributes: all +spec-name: Create INI File Action +spec-type: qdp-action-create-ini-file +type: spec diff --git a/spec-qdp/spec/qdp-action-directory-state-add-files.yml b/spec-qdp/spec/qdp-action-directory-state-add-files.yml new file mode 100644 index 00000000..ef6dd05d --- /dev/null +++ b/spec-qdp/spec/qdp-action-directory-state-add-files.yml @@ -0,0 +1,34 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2023 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +- role: spec-refinement + spec-key: action + spec-value: directory-state-add-files + uid: qdp-action +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + output-name: + description: | + It shall be name of the output directory state. + spec-type: str + pattern: + description: | + It shall be the pattern to match the files. + spec-type: str + path: + description: | + It shall be the path to start the search for files. + spec-type: str + description: | + This set of attributes specifies a directory state add files action. + mandatory-attributes: all +spec-name: Directory State Add Files Action +spec-type: qdp-action-directory-state-add-files +type: spec diff --git a/spec-qdp/spec/qdp-action-directory-state-add-tarfile-members.yml b/spec-qdp/spec/qdp-action-directory-state-add-tarfile-members.yml new file mode 100644 index 00000000..27b8b69d --- /dev/null +++ b/spec-qdp/spec/qdp-action-directory-state-add-tarfile-members.yml @@ -0,0 +1,43 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2023 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +- role: spec-refinement + spec-key: action + spec-value: directory-state-add-tarfile-members + uid: qdp-action +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + extract: + description: | + It shall be true, to extract the archive file. + spec-type: bool + output-name: + description: | + It shall be name of the output directory state. + spec-type: str + pattern: + description: | + It shall be the pattern to match the tarfiles. + spec-type: str + prefix-path: + description: | + It shall be prefix path for tarfile members. + spec-type: str + search-path: + description: | + It shall be the path to start the search for tarfiles. + spec-type: str + description: | + This set of attributes specifies a directory state add tarfile members + action. + mandatory-attributes: all +spec-name: Directory State Add Tarfile Members Action +spec-type: qdp-action-directory-state-add-tarfile-members +type: spec diff --git a/spec-qdp/spec/qdp-action-directory-state-add-tree.yml b/spec-qdp/spec/qdp-action-directory-state-add-tree.yml new file mode 100644 index 00000000..6a237d6c --- /dev/null +++ b/spec-qdp/spec/qdp-action-directory-state-add-tree.yml @@ -0,0 +1,49 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2023 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +- role: spec-refinement + spec-key: action + spec-value: directory-state-add-tree + uid: qdp-action +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + excludes: + description: | + It shall be a list of Python ``fnmatch`` patterns. If a file path + matches with the pattern, then the file is not added to the directory + state. The file paths are absolute paths relative to the base + directory of the directory state. For example, if the directory + state has a base of ``/base`` and a file to include has the path + ``/base/abc``, then the file path ``/abc`` is used to match with the + exclude patterns. + spec-type: list-str + output-name: + description: | + It shall be the name of the output directory state. + spec-type: str + root: + description: | + It shall be the root directory of the directory tree to add. + spec-type: str + prefix: + description: | + If the value is present, then it shall be the prefix path. + spec-type: optional-str + description: | + This set of attributes specifies a directory state add tree action. The + files of the directory tree starting at the root directory are added to + the file set of the directory state. The added file path is relative to + the root directory. The prefix is prepended to the file path for each + file before it is added to the directory state. The files are not copied + or moved. + mandatory-attributes: all +spec-name: Directory State Add Tree Action +spec-type: qdp-action-directory-state-add-tree +type: spec diff --git a/spec-qdp/spec/qdp-action-directory-state-clear.yml b/spec-qdp/spec/qdp-action-directory-state-clear.yml new file mode 100644 index 00000000..289e10cc --- /dev/null +++ b/spec-qdp/spec/qdp-action-directory-state-clear.yml @@ -0,0 +1,26 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2022 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +- role: spec-refinement + spec-key: action + spec-value: directory-state-clear + uid: qdp-action +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + output-name: + description: | + It shall be name of the output directory state. + spec-type: str + description: | + This set of attributes specifies a directory state clear action. + mandatory-attributes: all +spec-name: Directory State Clear Action +spec-type: qdp-action-directory-state-clear +type: spec diff --git a/spec-qdp/spec/qdp-action-directory-state-copy-tree.yml b/spec-qdp/spec/qdp-action-directory-state-copy-tree.yml new file mode 100644 index 00000000..b2876579 --- /dev/null +++ b/spec-qdp/spec/qdp-action-directory-state-copy-tree.yml @@ -0,0 +1,49 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2023 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +- role: spec-refinement + spec-key: action + spec-value: directory-state-copy-tree + uid: qdp-action +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + excludes: + description: | + It shall be a list of Python ``fnmatch`` patterns. If a file path + matches with the pattern, then the file is not added to the directory + state. The file paths are absolute paths relative to the base + directory of the directory state. For example, if the directory + state has a base of ``/base`` and a file to include has the path + ``/base/abc``, then the file path ``/abc`` is used to match with the + exclude patterns. + spec-type: list-str + output-name: + description: | + It shall be the name of the output directory state. + spec-type: str + root: + description: | + It shall be the root directory of the directory tree to add and copy. + spec-type: str + prefix: + description: | + If the value is present, then it shall be the prefix path. + spec-type: optional-str + description: | + This set of attributes specifies a directory state add and copy tree + action. The files of the directory tree starting at the root directory + are added to the file set of the directory state. The added file path is + relative to the root directory. The prefix is prepended to the file path + for each file before it is added to the directory state. The files are + copied. + mandatory-attributes: all +spec-name: Directory State Add and Copy Tree Action +spec-type: qdp-action-directory-state-copy-tree +type: spec diff --git a/spec-qdp/spec/qdp-action-directory-state-move-tree.yml b/spec-qdp/spec/qdp-action-directory-state-move-tree.yml new file mode 100644 index 00000000..250b6a78 --- /dev/null +++ b/spec-qdp/spec/qdp-action-directory-state-move-tree.yml @@ -0,0 +1,49 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2023 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +- role: spec-refinement + spec-key: action + spec-value: directory-state-move-tree + uid: qdp-action +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + excludes: + description: | + It shall be a list of Python ``fnmatch`` patterns. If a file path + matches with the pattern, then the file is not added to the directory + state. The file paths are absolute paths relative to the base + directory of the directory state. For example, if the directory + state has a base of ``/base`` and a file to include has the path + ``/base/abc``, then the file path ``/abc`` is used to match with the + exclude patterns. + spec-type: list-str + output-name: + description: | + It shall be the name of the output directory state. + spec-type: str + root: + description: | + It shall be the root directory of the directory tree to add and move. + spec-type: str + prefix: + description: | + If the value is present, then it shall be the prefix path. + spec-type: optional-str + description: | + This set of attributes specifies a directory state add and move tree + action. The files of the directory tree starting at the root directory + are added to the file set of the directory state. The added file path is + relative to the root directory. The prefix is prepended to the file path + for each file before it is added to the directory state. The files are + moved. + mandatory-attributes: all +spec-name: Directory State Add and Move Tree Action +spec-type: qdp-action-directory-state-move-tree +type: spec diff --git a/spec-qdp/spec/qdp-action-list.yml b/spec-qdp/spec/qdp-action-list.yml new file mode 100644 index 00000000..95398756 --- /dev/null +++ b/spec-qdp/spec/qdp-action-list.yml @@ -0,0 +1,16 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2022 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +spec-description: null +spec-example: null +spec-info: + list: + description: null + spec-type: qdp-action +spec-name: Action List +spec-type: qdp-action-list +type: spec diff --git a/spec-qdp/spec/qdp-action-mkdir.yml b/spec-qdp/spec/qdp-action-mkdir.yml new file mode 100644 index 00000000..624b9985 --- /dev/null +++ b/spec-qdp/spec/qdp-action-mkdir.yml @@ -0,0 +1,35 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2022 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +- role: spec-refinement + spec-key: action + spec-value: mkdir + uid: qdp-action +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + exist-ok: + description: | + It shall be true, if the directory may already exist, otherwise false. + spec-type: bool + parents: + description: | + It shall be true, if missing parent directories shall be created, + otherwise false. + spec-type: bool + path: + description: | + It shall be the path to the directory to make. + spec-type: str + description: | + This set of attributes specifies a make directory action. + mandatory-attributes: all +spec-name: Make Directory Action +spec-type: qdp-action-mkdir +type: spec diff --git a/spec-qdp/spec/qdp-action-remove-empty-directories.yml b/spec-qdp/spec/qdp-action-remove-empty-directories.yml new file mode 100644 index 00000000..dd6afa6f --- /dev/null +++ b/spec-qdp/spec/qdp-action-remove-empty-directories.yml @@ -0,0 +1,28 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2022 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +- role: spec-refinement + spec-key: action + spec-value: remove-empty-directories + uid: qdp-action +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + path: + description: | + It shall be the path to the base directory of the removal action. + spec-type: str + description: | + This set of attributes specifies a removal of empty directories action. + The action recursively removes all empty subdirectories of the base + directory and the base directory itself if it gets empty. + mandatory-attributes: all +spec-name: Remove Empty Directories Action +spec-type: qdp-action-remove-empty-directories +type: spec diff --git a/spec-qdp/spec/qdp-action-remove-glob.yml b/spec-qdp/spec/qdp-action-remove-glob.yml new file mode 100644 index 00000000..b1ba517c --- /dev/null +++ b/spec-qdp/spec/qdp-action-remove-glob.yml @@ -0,0 +1,38 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2023 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +- role: spec-refinement + spec-key: action + spec-value: remove-glob + uid: qdp-action +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + path: + description: | + It shall be the path to start the search for files and directories to + remove. + spec-type: str + patterns: + description: | + It shall be the list of patterns to match the files and directories + to remove. + spec-type: list-str + remove-tree: + description: | + It shall be true, if matching directories shall be removed as a + directory tree, otherwise false. + spec-type: bool + description: | + This set of attributes specifies a pattern based removal of files and + directories action. + mandatory-attributes: all +spec-name: Remove Matching Files and Directories Action +spec-type: qdp-action-remove-glob +type: spec diff --git a/spec-qdp/spec/qdp-action-remove-tree.yml b/spec-qdp/spec/qdp-action-remove-tree.yml new file mode 100644 index 00000000..4a659e8a --- /dev/null +++ b/spec-qdp/spec/qdp-action-remove-tree.yml @@ -0,0 +1,30 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2022 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +- role: spec-refinement + spec-key: action + spec-value: remove-tree + uid: qdp-action +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + missing-ok: + description: | + It shall be true, if the directory may be missing, otherwise false. + spec-type: bool + path: + description: | + It shall be the path to the directory tree to remove. + spec-type: str + description: | + This set of attributes specifies a removal of a directory tree action. + mandatory-attributes: all +spec-name: Remove Directory Tree Action +spec-type: qdp-action-remove-tree +type: spec diff --git a/spec-qdp/spec/qdp-action-remove.yml b/spec-qdp/spec/qdp-action-remove.yml new file mode 100644 index 00000000..6722af9f --- /dev/null +++ b/spec-qdp/spec/qdp-action-remove.yml @@ -0,0 +1,31 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2023 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +- role: spec-refinement + spec-key: action + spec-value: remove + uid: qdp-action +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + missing-ok: + description: | + It shall be true, if the file or directory may be missing, otherwise + false. + spec-type: bool + path: + description: | + It shall be the path to the file or directory to remove. + spec-type: str + description: | + This set of attributes specifies a file or directory remove action. + mandatory-attributes: all +spec-name: Remove File or Directory Action +spec-type: qdp-action-remove +type: spec diff --git a/spec-qdp/spec/qdp-action-subprocess-env-list.yml b/spec-qdp/spec/qdp-action-subprocess-env-list.yml new file mode 100644 index 00000000..cfb3370e --- /dev/null +++ b/spec-qdp/spec/qdp-action-subprocess-env-list.yml @@ -0,0 +1,16 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2022 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +spec-description: null +spec-example: null +spec-info: + list: + description: null + spec-type: qdp-action-subprocess-env +spec-name: Action Subprocess Environment List +spec-type: qdp-action-subprocess-env-list +type: spec diff --git a/spec-qdp/spec/qdp-action-subprocess-env.yml b/spec-qdp/spec/qdp-action-subprocess-env.yml new file mode 100644 index 00000000..1e24c20c --- /dev/null +++ b/spec-qdp/spec/qdp-action-subprocess-env.yml @@ -0,0 +1,33 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2022 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + action: + description: | + It shall be the action execution environment modification action. + spec-type: str + name: + description: | + If the value is present, then it shall be the environment variable + name. + spec-type: optional-str + value: + description: | + If the value is present, then it shall be the environment variable + value. + spec-type: optional-str + description: | + This set of attributes specifies an action to alter the action execution + environment. + mandatory-attributes: all +spec-name: Subprocess Action Environment Action +spec-type: qdp-action-subprocess-env +type: spec diff --git a/spec-qdp/spec/qdp-action-subprocess.yml b/spec-qdp/spec/qdp-action-subprocess.yml new file mode 100644 index 00000000..3b19a570 --- /dev/null +++ b/spec-qdp/spec/qdp-action-subprocess.yml @@ -0,0 +1,42 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2022 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +- role: spec-refinement + spec-key: action + spec-value: subprocess + uid: qdp-action +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + command: + description: | + It shall be the command and argument list to run as a subprocess. A + variable substitution is performed on the list elements. For + example, you can use + ``$${/variant:/build-directory}/some/path/to/build/file`` or + ``$${/variant:/deployment-directory}/some/path/to/deployment/file``. + spec-type: list-str + env: + description: null + spec-type: qdp-action-subprocess-env-list + expected-return-code: + description: | + If the value is present, then it shall be the expected return code of + the command. + spec-type: optional-int + working-directory: + description: | + It shall be the working directory to run the command. + spec-type: str + description: | + This set of attributes specifies a subprocess action. + mandatory-attributes: all +spec-name: Subprocess Action +spec-type: qdp-action-subprocess +type: spec diff --git a/spec-qdp/spec/qdp-action-touch.yml b/spec-qdp/spec/qdp-action-touch.yml new file mode 100644 index 00000000..f6aa8fdf --- /dev/null +++ b/spec-qdp/spec/qdp-action-touch.yml @@ -0,0 +1,30 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2023 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +- role: spec-refinement + spec-key: action + spec-value: touch + uid: qdp-action +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + exist-ok: + description: | + It shall be true, if the file may already exist, otherwise false. + spec-type: bool + path: + description: | + It shall be the path to the file to touch. + spec-type: str + description: | + This set of attributes specifies a touch file action. + mandatory-attributes: all +spec-name: Touch File Action +spec-type: qdp-action-touch +type: spec diff --git a/spec-qdp/spec/qdp-action.yml b/spec-qdp/spec/qdp-action.yml new file mode 100644 index 00000000..52e5344a --- /dev/null +++ b/spec-qdp/spec/qdp-action.yml @@ -0,0 +1,26 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2022 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + action: + description: | + It shall be the action type. + spec-type: name + enabled-by: + description: | + It shall define the conditions under which the action is enabled. + spec-type: enabled-by + description: | + This set of attributes specifies a action. + mandatory-attributes: all +spec-name: Action +spec-type: qdp-action +type: spec diff --git a/spec-qdp/spec/qdp-ini-file-key-value-pair-list.yml b/spec-qdp/spec/qdp-ini-file-key-value-pair-list.yml new file mode 100644 index 00000000..34891e96 --- /dev/null +++ b/spec-qdp/spec/qdp-ini-file-key-value-pair-list.yml @@ -0,0 +1,16 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2023 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +spec-description: null +spec-example: null +spec-info: + list: + description: null + spec-type: qdp-ini-file-key-value-pair +spec-name: INI File Key Value Pair List +spec-type: qdp-ini-file-key-value-pair-list +type: spec diff --git a/spec-qdp/spec/qdp-ini-file-key-value-pair.yml b/spec-qdp/spec/qdp-ini-file-key-value-pair.yml new file mode 100644 index 00000000..8cf815a6 --- /dev/null +++ b/spec-qdp/spec/qdp-ini-file-key-value-pair.yml @@ -0,0 +1,31 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2023 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + enabled-by: + description: | + It shall define the conditions under which the key-value pair is + enabled. + spec-type: enabled-by + key: + description: | + It shall be the name of the key. + spec-type: str + value: + description: | + It shall be the value associated with the key. + spec-type: str + description: | + This set of attributes specifies an INI file key-value pair. + mandatory-attributes: all +spec-name: INI File Key-Value Pair +spec-type: qdp-ini-file-key-value-pair +type: spec diff --git a/spec-qdp/spec/qdp-ini-file-section-list.yml b/spec-qdp/spec/qdp-ini-file-section-list.yml new file mode 100644 index 00000000..422a6df2 --- /dev/null +++ b/spec-qdp/spec/qdp-ini-file-section-list.yml @@ -0,0 +1,16 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2023 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +spec-description: null +spec-example: null +spec-info: + list: + description: null + spec-type: qdp-ini-file-section +spec-name: INI File Section List +spec-type: qdp-ini-file-section-list +type: spec diff --git a/spec-qdp/spec/qdp-ini-file-section.yml b/spec-qdp/spec/qdp-ini-file-section.yml new file mode 100644 index 00000000..0772b6da --- /dev/null +++ b/spec-qdp/spec/qdp-ini-file-section.yml @@ -0,0 +1,29 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2023 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + enabled-by: + description: | + It shall define the conditions under which the section is enabled. + spec-type: enabled-by + key-value-pairs: + description: null + spec-type: qdp-ini-file-key-value-pair-list + name: + description: | + It shall be the name of the section. + spec-type: str + description: | + This set of attributes specifies an INI file section. + mandatory-attributes: all +spec-name: INI File Section +spec-type: qdp-ini-file-section +type: spec diff --git a/spec-qdp/spec/qdp-run-actions.yml b/spec-qdp/spec/qdp-run-actions.yml new file mode 100644 index 00000000..f72ae596 --- /dev/null +++ b/spec-qdp/spec/qdp-run-actions.yml @@ -0,0 +1,31 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +copyrights: +- Copyright (C) 2022 embedded brains GmbH & Co. KG +enabled-by: true +links: +- role: spec-member + uid: root +- role: spec-refinement + spec-key: build-step-type + spec-value: run-actions + uid: qdp-build-step +spec-description: null +spec-example: null +spec-info: + dict: + attributes: + actions: + description: | + It shall be the list of actions to run as a subprocess. + spec-type: qdp-action-list + params: + description: | + It shall be an optional set of parameters which may be used for + variable subsitution. + spec-type: any + description: | + This set of attributes specifies actions to run as a subprocess. + mandatory-attributes: all +spec-name: Run Actions Item Type +spec-type: qdp-run-actions +type: spec -- cgit v1.2.3