Contributor’s guide

First of all, if you’re reading this, thanks for thinking about contributing! This project is maintained by us Arm folks, but we welcome contributions from anyone.

How to submit a merge request

Submitting a merge request requires forking the LISA repository in a similar fashion to the typical GitHub workflow:

  1. Create a GitLab account on https://gitlab.arm.com/tooling/lisa/. You can use an existing GitHub login if you want.

  2. Fork the repository. This requires the fork permission on the account, which can be obtained by following: https://gitlab.arm.com/documentation/contributions

  3. Push your branch to your fork (this might require setting up your SSH public key in your profile just like on GitHub).

  4. Open the merge request. ⚠️ If your fork is a private fork, GitLab will default to opening a merge request against your own fork, and no-one will ever know of your contribution. When opening the MR, there is a “Change branches” link next to “From XXX into main”. Click this link and select “tooling/lisa” in the “Target branch” project drop down. ⚠️

How to reach us

If you’re hitting an error/bug and need help, it’s best to raise an issue on GitLab.

Coding style

As a rule of thumb, the code you write should follow the PEP-8.

We strongly recommend using a code checker such as pylint, as it tracks unused imports/variables, informs you when you can simplify a statement using Python features, and overall just helps you write better code. However, we don’t enforce any linter in merged code.

Documentation

Docstring documentation should follow the ReST/Sphinx style. Classes, class attributes and public methods must be documented. If deemed necessary, private methods can be documented as well.

All in all, it should look like this:

def foo(a, b):
    """
    A one liner description

    :param a: A description for param a
    :type a: int

    :param b: A description for param b
    :type b: str

    Whatever extra description you might over as many lines as you need
    (but be reasonable)
    """
    pass

Note

LISA does not use type annotations as they have only been introduced recently and would currently conflict with exekall use (that is a solvable problem but has not been worked on yet). Parameters types must therefore be documented using the :type the_param: the_type in the function docstring.

References to classes should be made using :class:`path.to.TheClass`, same goes for methods (:meth:`...`) and functions (:func:`...`).

Examples on how to use the API can sometimes be useful. They should be introduced by **Example**:: and located:

  • In the module docstring if they involve multiple classes or functions from the module.

  • In the class docstring if they involve multiple methods of the class.

  • In the method/function otherwise.

Commits

As for the shape of the commit, nothing out of the ordinary: just follow the good old 50/72 rule (it’s okay if you bite off a few extra chars).

The header should highlight the impacted files/classes. The ‘lisa’ prefix can be omitted - for instance, if you’re modifying the lisa/wlgen/rta.py file, we’d expect a header of the shape lisa.wlgen.rta: ....

It should also contain a FIX, FEATURE or BREAKING CHANGE tag that will be used to generate the changelog, such as:

lisa.foo.bar: Fix some foobar

FIX

This fix fixes fixable fixtures by affixing an postfix operator.

When in doubt, have a look at the git log.

Subtrees

are available as subtrees under $repo/external.

Updating the subtrees

If you got a Pull Request merged in e.g. devlib and want to use some of the features you introduced in LISA, you’ll need to update the subtrees. There is a handy LISA shell command available for that: lisa-update-subtrees.

This will update every subtree in the repository with the right incantation, and the result can be pushed straight away to LISA as a Pull Request (or included in a broader Pull Request).

Submitting your subtree changes

Our changes to subtrees are often developped conjointly with LISA, so we write our modifications directly in the subtrees. You can commit these changes in the LISA repository, then shape those modifications into a git history ready to be pushed using git subtree split. Assuming you want to split a devlib change and have a devlib remote set up in your repository, you’d have to issue the following:

# Ensure refs are up to date
git fetch devlib
# Do the split
git subtree split --prefix=external/devlib -b my-devlib-feature

This will give you a my-devlib-feature branch ready to be pushed. To make things easier, we recommend setting up a remote to your devlib fork:

git remote add devlib-me git@github.com:me/devlib.git

You can then push this branch to your devlib fork like so:

git push -u devlib-me my-devlib-feature

Validating your changes

To ensure everything behaves as expected at all times, LISA comes with some self-tests in tests/ folder, which is a mix of unit and behavioural tests.

From the root of LISA, you can run those tests like so:

python3 -m pytest
# You can also target specific test modules
python3 -m pytest tests/test_test_bundle.py
# Or even specific test classes
python3 -m pytest tests/test_test_bundle.py::BundleCheck
# Or even specific test method
python3 -m pytest tests/test_test_bundle.py::BundleCheck::test_init

Writing self-tests

You should strive to validate as much of your code as possible through self-tests. It’s a nice way to showcase that your code works, and also how it works. On top of that, it makes sure that later changes won’t break it.

It’s possible to write tests that require a live target - see create_local_target(). However, as these tests are meant to be run by Github Actions as part of our pull-request validation, they have to be designed to work on a target with limited privilege.

API

Utilities

tests.utils.create_local_target()[source]
Returns:

A localhost lisa.target.Target instance

class tests.utils.StorageTestCase(methodName='runTest')[source]

Bases: TestCase

A base class for tests that also provides a directory

Create an instance of the class that will use the named test method when executed. Raises a ValueError if the instance does not have a method with the specified name.

setup_method(method)[source]
teardown_method(method)[source]

Updating binary tools

LISA comes with a number of prebuilt static binaries in lisa/_assets/binaries. They are all built according to recipes in tools/recipes/, and can be re-built and installed using e.g.: lisa-build-asset trace-cmd --native-build. See lisa-build-asset --help for more options.