Skip to content

Latest commit

 

History

History
138 lines (102 loc) · 9.18 KB

CONTRIBUTING.md

File metadata and controls

138 lines (102 loc) · 9.18 KB

🔨 Contributing to Euro-Calliope

Thank you for considering to contribute to Euro-Calliope. In the following we show you around in our software workshop to make your contribution as easy as possible.

1) Report

If you have found a bug in Euro-Calliope or you want to propose a new feature, please feel free to do so using our issue tracker.

2) Change

We welcome changes that you provide as a pull request.

If you consider doing that, you need to know two things: our code guidelines and our branching model. Our code guidelines are implemented through automatic linting (code analysis) and formatting. For both, we employ the tool Ruff. It is open-source and available as a plug-in to many IDEs. All you need is to install the plug-in for your IDE and then you should see linting problems and you will be able to format the code automatically based on our guidelines. If you want more, you can use a Git pre-commit-hook but that step is optional.

Next, let's talk about our branching model -- that is, which branches exist and what meaning they have. Do not worry, it is easy. Our branching model is a simplified version of git-flow. We are giving you a summary here that is likely sufficient for you. If you want more information, read the blog entry introducing git-flow.

We have two central and long-lived branches: main and develop. The main branch always points to the latest stable version: the latest release. The develop branch always points to the most recent development version. It is ahead of main and while we aim at keeping it clean and functional, it is less thoroughly tested and less mature than its older sibling.

Your change is developed on a feature branch (preferably in your own fork of the repository) that branches off of develop and will eventually be merged back into develop. To keep up-to-date with this branch on your fork, you can pull in changes periodically: git pull upstream develop.

In 99.9% of the cases, that's all you need to know.

In rare instances in which you need a hotfix, release, or long-lived feature branch, git-flow will provide you the flexibility you need. If you do not know what all this means, you do not need this flexibility.

ℹ️ By contributing to Euro-Calliope, e.g. through opening a pull request, you declare that your contributions are your own original work and that you have the right to license them, and you agree that your contributions are licensed according to the repository's license.

3) Test

There are two types of tests: those that run on our continuous integration software (CI), and those that cannot. The tests that are executed on and by the CI are unit tests of the functions in the scripts (./scripts/) and in the library code (./lib/), and tests of the configuration schema and the documentation. All CI tests are GitHub workflows and accordingly you can find them in ./.github/workflows/.

In addition, we have integration tests that test the models generated by Snakemake. As the generation is resource-intense, we cannot run them on CI at this point (see feature request). These tests are also fully automated and run each time the entire workflow is run, but you need to run the workflow on your local machine or your own cluster.

The following subsections show you how to run the tests and how to write your own.

Run the workflow tests

Tests of models with continental and national resolution run automatically when you run the entire workflow. To run the tests of models with regional resolution too, do the following:

snakemake # builds all models and runs continental and national tests
snakemake all_tests # builds all models and runs continental, national, and regional tests

Run the minimal workflow tests

As a developer, you may want to run the entire workflow often to spot errors early. For that, you can use a minimal test configuration that takes less time to run than the default configuration.

snakemake --configfile="config/minimal.yaml" all_tests

Make sure to run this in a clean working directory. Do not use the working directory in which you are using your normal configuration, or run snakemake clean first.

Run tests of library code and scripts

Library code and scripts are tested automatically by our CI. You still may want to run these tests locally while developing. Here's how. First, create a test environment using mamba or conda:

mamba env create -f requirements-test.yaml --no-default-packages # or replace mamba with conda
conda activate test-eurocalliope

Then run the test suite with py.test:

py.test

Write tests yourself

All test code is in ./tests/ and all GitHub workflow definitions are in ./.github/workflows/. The test folder comprises tests of code in scripts (./tests/scripts/), tests of library code (./tests/lib/), and tests of the model and other workflow artefacts (./tests/model/). Script and library code tests are based on plain Pytest and therefore, if you are familiar with Pytest, they should be self-explanatory to you. If you are unfamiliar with Pytest, we advise you to go and check out their documentation first.

Model tests are based on Pytest, too, but they require a custom Plugin and test runner through which we hook tests into the Snakemake workflow. This requires explanation.

The main reason for the custom mechanism is that we need a way to inject workflow artefacts (mainly Snakemake inputs) into the test suite. We do this through a custom Pytest plugin that lives within a script executed by Snakemake (./tests/model/test_runner.py) and takes Snakemake inputs and provides them as Pytest fixtures. Because fixtures are available to all tests, all tests can access Snakemake inputs in this way, no matter where tests are defined. This specific Pytest plugin cannot be used from the command line and therefore requires our own test runner, but this test runner is very simple: it is a small function in the same script (./tests/model/test_runner) that calls Pytest normally but includes the plugin into the call.

If you are intending to add a test that uses existing Snakemake inputs, you can use the existing fixtures in ./tests/model/test_runner.py. If you need new Snakemake inputs, add them to the Snakemake rule and create a new fixture providing these inputs. Take the existing fixtures as a starting point.

4) Release

Whenever you want to publish a new release of Euro-Calliope, you need to perform several manual steps. Be aware that you can publish a release only if you are a maintainer of the GitHub repository and if you have edit access to the two Zenodo archives.

  1. Branch off of develop into a release-vX.Y.Z branch and apply the following changes:
    1. Bump version to vX.Y.Z in the following places:
    2. Verify consistent versions of Snakemake.
    3. Verify consistent versions of Calliope.
    4. Update the changelog and add the release date.
    5. Update the release date in ./CITATION.cff.
    6. (If necessary) Update ./LICENSE.md.
    7. (If necessary) Update docs/img/spatial-scope-and-resolutions.png by running snakemake -s rules/doc.smk docs/img/spatial-scope-and-resolutions.png. Inspect the result visually. Check it in if it changed; check out the old version if it did not change. The figure will change when the spatial scope or resolution has changed.
  2. Build the pre-builts and test everything using the all_tests rule. Make sure you start with a clean workflow folder: delete ./build and ./data/automatic should they exist.
  3. Commit, open a pull request onto develop, and merge the release branch into both develop and main after successful review.
  4. Add a vX.Y.Z release tag to main, push it, and add a release on GitHub.
  5. Bump version on develop in the same places as in point 1.
  6. Upload the pre-builts to their home on Zenodo and make sure all metadata is correct.