Contributing ============ .. note:: **Abstract** This document describes the development process of {kiwi} and how you can be part of it. This description applies to version |version|. .. toctree:: :maxdepth: 1 contributing/kiwi_from_python contributing/kiwi_plugin_architecture contributing/scripts_testing contributing/schema_extensions.rst The Basics ---------- The core appliance builder is developed in Python and follows the test- driven development rules. If you want to implement a bigger feature, consider opening an issue on GitHub first to discuss the changes. Or, join the discussion in the `#kiwi` channel on `Matrix `_. Fork the upstream repository ---------------------------- 1. On GitHub, navigate to: https://github.com/OSInside/kiwi. 2. In the top-right corner of the page, click :command:`Fork`. Create a local clone of the forked repository --------------------------------------------- .. code:: shell-session $ git clone https://github.com/YOUR-USERNAME/kiwi $ git remote add upstream https://github.com/OSInside/kiwi.git Install Required Operating System Packages ------------------------------------------ {kiwi} requires additional packages at runtime that are not provided by `pip`. Those will be pulled in by installing the following package: * kiwi-systemdeps The package is provided on the Open Build Service in the `Virtualization:Appliances:Builder `__ project. For manual inspection of the packages that are pulled in from the above `kiwi-systemdeps` package, please refer to the `package/python-kiwi-spec-template` spec file from the checked- out Git repository. Create a Python Virtual Development Environment ----------------------------------------------- The following commands initialize and activate a development environment for Python 3: .. code:: shell-session $ poetry install The command above automatically creates the application script called :command:`kiwi-ng`, which allows you to run {kiwi} from the Python sources inside the virtual environment using Poetry: .. code:: shell-session $ poetry run kiwi-ng --help Running the Unit Tests ---------------------- Before submitting your changes via a pull request, ensure that all tests pass and that the code has the required test coverage via the command: .. code:: shell-session $ make check $ make test Create a Branch for each Feature or Bugfix ------------------------------------------ Code changes should be done in an extra Git branch. This allows for creating GitHub pull requests in a clean way. See also: `Collaborating with issues and pull requests `_. .. code:: shell-session $ git checkout -b my-topic-branch Make and commit your changes. .. note:: You can make multiple commits, which is generally useful to give your changes a clear structure and to allow us to better review your work. .. note:: Your work is important and must be signed to ensure the integrity of the repository and the code. Thus, we recommend setting up a signing key as documented in :ref:`Signing_Git_Patches`. .. code:: shell-session $ git commit -S -a Once everything is done, push your local branch to your forked repository and create a pull request into the upstream repository. .. code:: shell-session $ git push origin my-topic-branch Thank you much for contributing to {kiwi}. Your time and work effort are very much appreciated! AI policy --------- {kiwi} accepts contributions created using gen-AI tools. Contributions using AI tools need to be clearly labeled with the tool used set as co-author. If the tool used offers a selection of models set the model as co-author. Ultimately the submitter, a human, is still responsible for the quality of the code. It is expected that code contributions are self reviewed prior to creating a pull request. The co-author is set using the `Co-authored-by:` trailer in the commit comment, for example `Co-authored-by: qwen2.5-coder` Coding Style ------------ {kiwi} follows the general PEP8 guidelines with the following exceptions: - We do not use free functions at all. Even utility functions must be part of a class but should be either prefixed with the `@classmethod` or `@staticmethod` decorators (whichever is more appropriate). - Do not set module and class-level variables; put these into the class's `__init__` method. Documentation ~~~~~~~~~~~~~ {kiwi} uses `Sphinx `_ for the API, user documentation, and man pages. .. code:: shell-session $ make docs API documentation is created from type hints. Even though python is not a strong typed language we value if all parameters and return values uses proper type hints. .. code:: python class Example: """ **Example class** This class has a single responsibility and provides... """ def __init__(self, names: List[str], set_names: bool = False): """ Initialize instance of Example with a list of some example names. If param_w_default is set to True the instance is initialized with an empty name list """ self.some_names = names if set_names else [] def is_retired(self, age: int = 0) -> bool: """ A method that implements... """ return len(age) > 70 Try to stick to the following guidelines when documenting source code: - Classes should be documented directly in their main docstring and not in `__init__`. - Document function parameters unless their name makes it clear - Only public methods should be documented; private methods don't have to be, unless they are complex and it is not easy to grasp what they do (which should be avoided anyway). Please also document any user-facing changes that you are implementing (e.g., adding a new build type) in the user documentation, which can be found in `doc/source`. Additional Information ---------------------- The following sections provide further information about the repository integrity, version, package, and documentation management. .. _Signing_Git_Patches: Signing Git Patches ~~~~~~~~~~~~~~~~~~~ To ensure the integrity of the repository and the codebase, patches sent for inclusion should be signed with a GPG key. To prepare Git to sign commits, follow these instructions: #. Create a key suitable for signing (it is not recommended to use existing keys to not mix it with your email environment): .. code:: shell-session $ gpg2 --expert --full-gen-key #. Either choose an RSA key for signing (option `(4)`) or an ECC key for signing (option `(10)`). For an RSA key, choose a key size of 4096 bits, and for an ECC key, choose Curve 25519 (option `(1)`). Enter a reasonable validity period (we recommend 2 to 5 years). Complete the key generation by entering your name and email address. #. Add the key ID to your git configuration by running the following :command:`git config` commands: .. code:: shell-session $ git config --local user.signingkey $YOUR_SIGN_KEY_ID $ git config --local commit.gpgSign true Omitting the `--local` flag will make these settings global for all repositories (they will be added to :file:`~/.gitconfig`). You can find your signkey's ID via: .. code:: shell-session $ gpg2 --list-keys --keyid-format long $YOUR_EMAIL pub rsa4096/AABBCCDDEEFF0011 2019-04-26 [S] [expires: 2021-04-16] AAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBB uid [ultimate] YOU <$YOUR_EMAIL> The key's ID in this case would be `AABBCCDDEEFF0011`. Note that your sign key will have only a `[S]` after the creation date, not a `[SC]` (then you are looking at your ordinary GPG key that can also encrypt). Bumping the Version ~~~~~~~~~~~~~~~~~~~ The {kiwi} project follows the `Semantic Versioning `_ scheme. We use the :command:`bumpversion` tool for consistent versioning. Follow these instructions to bump the major, minor, or patch part of the {kiwi} version. Ensure that your repository is clean (i.e., no modified and unknown files exist) before running :command:`bumpversion`. * For backward-compatible bug fixes: .. code:: shell-session $ bumpversion patch * For additional functionality in a backward-compatible manner. When changed, the patch level is reset to zero: .. code:: shell-session $ bumpversion minor * For incompatible API changes. When changed, the patch and minor levels are reset to zero: .. code:: shell-session $ bumpversion major Creating an RPM Package ~~~~~~~~~~~~~~~~~~~~~~~ We provide a template for an RPM spec file in :file:`package/python-kiwi-spec-template` alongside a `rpmlint` configuration file and an automatically updated :file:`python-kiwi.changes`. To create the necessary files to build an RPM package via `rpmbuild`, run: .. code:: shell-session $ make build The sources are collected in the :file:`dist/` directory. These can be directly built with :command:`rpmbuild`, :command:`fedpkg`, or submitted to the Open Build Service using :command:`osc`.