Contributing#

Contributions are welcome, and they are greatly appreciated! Every little bit helps, and credit will always be given.

You can contribute in many ways:

Types of Contributions#

Report Bugs#

Report bugs at fury-gl/fury#issues.

If you are reporting a bug, please include:

  • Any details about your local setup that might be helpful in troubleshooting.

  • Detailed steps to reproduce the bug.

Fix Bugs#

Look through the GitHub issues for bugs. Anything tagged with “bug” is open to whoever wants to implement it.

Implement Features#

Look through the GitHub issues for features. Anything tagged with “feature” is open to whoever wants to implement it.

Write Documentation#

FURY could always use more documentation, whether as part of the official FURY docs, in docstrings, or even on the web in blog posts, articles, and such. FURY uses Sphinx to generate documentation. Please follow the numpy coding style and PEP8 for docstring documentation.

Submit Feedback#

The best way to send feedback is to file an issue at fury-gl/fury#issues.

If you are proposing a feature:

  • Explain in detail how it would work.

  • Keep the scope as narrow as possible, to make it easier to implement.

  • Remember that this is a volunteer-driven project, and that contributions are welcome :)

Get Started!#

Ready to contribute? Here’s how to set up FURY for local development.

We recommend the open-source Miniforge installers for Conda. If Conda is already installed, use your existing installation.

Run the development commands below from the repository root inside the fury-dev environment once it is activated.

  1. Fork the FURY repo on GitHub.

  2. Clone your fork locally:

    $ git clone https://github.com/your_name_here/fury.git
    $ cd fury
    
  3. Add a tracking branch which can always have the last version of FURY:

    $ git remote add fury-gl https://github.com/fury-gl/fury.git
    $ git fetch fury-gl
    $ git branch fury-gl-master --track fury-gl/master
    $ git checkout fury-gl-master
    $ git pull
    
  4. Create a branch from the last dev version of your tracking branch for local development:

    $ git checkout -b name-of-your-bugfix-or-feature
    
  5. Create and activate a Conda environment, then install FURY in editable mode:

    $ conda create --name fury-dev --override-channels --channel conda-forge python=3.12 pip
    $ conda activate fury-dev
    $ pip install -e .
    

    These examples use Python 3.12; other supported versions are listed in the Pull Request Guidelines below. If fury-dev already exists, use it only if compatible or choose another name. Do not install into base.

  6. Now you can make your changes locally:

    $ git add .
    $ git commit -m "Your detailed description of your changes."
    $ git push origin name-of-your-bugfix-or-feature
    
  7. Install the required packages for running the unittests and linting:

    $ pip install -r requirements/optional.txt
    $ pip install -r requirements/test.txt
    $ pip install -r requirements/style.txt
    
  8. Set up pre-commit hooks for automatic code formatting:

    $ pre-commit install
    

    This will ensure that your code is automatically formatted according to the project’s style guidelines before you push your changes.

  9. When you’re done making changes, check that your changes pass ruff and pytest:

    $ ruff check fury
    $ pytest fury
    
  10. Submit a pull request through the GitHub website.

Pull Request Guidelines#

Before you submit a pull request, check that it meets these guidelines:

  1. The pull request should include tests.

  2. If the pull request adds functionality, the docs should be updated. Put your new functionality into a function with a docstring, and add the feature to the list in README.md.

  3. FURY requires Python 3.12 or newer. Python 3.12, 3.13, and 3.14 are supported stable versions, tested in blocking Linux, macOS, and Windows CI. Python 3.12 support will be removed in an upcoming FURY release. Check fury-gl/fury and make sure that tests pass for every Python version in the matrix.

Publishing Releases#

Checklist before Releasing#

  • Review the open list of FURY issues. Check whether there are outstanding issues that can be closed, and whether there are any issues that should delay the release. Label them !

  • Check whether there are no builds failing on GitHub Actions.

  • Check the examples and tutorial - we really need an automated check here.

  • Run tools/prepare_release.py from the <fury root> directory:

    $ python tools/prepare_release.py
    

    This script walks you through the rest of the release preparation interactively and will prompt you when it needs input:

    • It asks for the release series (e.g. 0.x, 1.x, 2.x) and finds the latest tag in that series.

    • It pauses so you can review and update the .mailmap file for any duplicate authors, then prints git shortlog -nse <last-tag>..HEAD so you can double check that every contributor is recognized.

    • It updates the AUTHORS file with any new authors from git log.

    • It checks (and updates if needed) the copyright year range in LICENSE.

    • It asks for the new version number, then generates the release notes by running docs/source/ext/github_tools.py for you, creating docs/source/release_notes/releasev<version>.rst. It will pause for you to manually fill in the “Quick overview” section of that file.

    • It updates release-history.rst to include the newly generated release notes file.

    • It creates a release announcement blog post stub under docs/source/posts/<year>/, prompting you for the author id and name.

    • It asks you to confirm that deprecated functions/modules have been checked before continuing.

    • It runs the test suite (pytest -svv --doctest-modules fury) and builds the documentation (make -C docs html). It then runs the platform’s serve target, opening a browser at http://localhost:8000. Review the generated docs, then press Ctrl+C in the terminal to stop the preview and answer the confirmation prompt. On Windows, confirm batch termination if prompted. Answering no to the documentation confirmation repeats the tests, build, and preview until you confirm the docs look correct.

  • Before tagging, commit .github/workflows/release.yml, tools/github_release.py, and the prepared docs/source/release_notes/releasev<version>.rst. Verify its Release notes v<version> title, nonempty Quick Overview, and previous tag in the GitHub stats line. Both tags must exist when the workflow runs.

  • Install the development dependencies (including bundled Pandoc) and preview a prepared release locally:

    pip install -e ".[dev]"
    python tools/github_release.py --tag v2.0.0 --preview --output-file RELEASE_PREVIEW.md
    

    Inspect the Markdown in your editor, including links and formatting. This works offline without authentication or release creation. Omit --preview to generate only the introduction used by the workflow.

    Add --previous-tag v0.12.0 to override the recorded baseline. This changes the comparison link and printed metadata, not the prepared PR list or source notes. GitHub adds final PR author mentions and New Contributors during publication; the local preview uses prepared PRs and contributor names.

    Use explicitly labelled :doc: links in the overview; replace other Sphinx roles with ordinary RST links or inline literals. The helper prefers system Pandoc over the bundled copy; the workflow installs its own.

  • The release should now be ready.

Doing the release#

  • Update release-history.rst in the documentation if you have not done so already. You may also highlight any additions, improvements, and bug fixes.

  • Type git status and check that you are on the master branch with no uncommitted code.

  • Now it’s time for the source release. Mark the release with an empty commit, just to leave a marker. It makes it easier to find the release when skimming through the git history:

    git commit --allow-empty -m "REL: vX.Y.Z"
    
  • Tag the commit:

    git tag -am 'Second public release' vX.Y.Z  # Don't forget the leading v
    

    This will create a tag named vX.Y.Z. The -a flag (strongly recommended) opens up a text editor where you should enter a brief description of the release.

  • Verify that the __version__ attribute is correctly updated:

    import fury
    fury.__version__  # should be 'X.Y.Z'
    

    Incidentally, once you resume development and add the first commit after this tag, __version__ will take on a value like X.Y.Z+1.g58ad5f7, where +1 means “1 commit past version X.Y.Z” and 58ad5f7 is the first 7 characters of the hash of the current commit. The letter g stands for “git”. This is all managed automatically by versioneer and in accordance with the specification in PEP 440.

  • Push the new commit and the tag to the upstream fury-gl/fury repository (the following assumes origin points there):

    git push origin master
    git push origin vX.Y.Z
    

    The Release workflow publishes a GitHub release immediately, not a draft. It runs only for upstream tag pushes; pushing a tag to a fork does not publish an upstream release. Supported tags are vMAJOR.MINOR.PATCH with optional aN, bN, or rcN suffixes. Suffixed versions are marked as prereleases and are not selected as latest.

    The release title is the tag. Its body contains the curated Quick Overview, a link to the full tagged release notes, and GitHub-generated What's Changed entries comparing against the notes’ recorded previous tag. The workflow uploads no assets and does not publish to PyPI or deploy the website; the package publication steps below remain separate.

    Check the Actions run and the published release. Missing or malformed notes, missing tags, conversion failures, and API/permission errors fail the run. Infrastructure failures before publication can be retried. An existing release is never overwritten: rerunning after successful publication fails with a conflict and leaves it unchanged. Do not move a published tag to fix release preparation.

  • Register for a PyPI account and Install twine, a tool for uploading packages to PyPI:

    python3 -m pip install --upgrade twine
    
  • Remove any extraneous files:

    git clean -dfx
    

    If you happen to have any important files in your project directory that are not committed to git, move them first; this will delete them!

  • Publish a release on PyPI:

    python -m build
    twine upload dist/*
    
  • Check how everything looks on pypi - the description, the packages. If necessary delete the release and try again if it doesn’t look right.

  • Set up maintenance / development branches

    If this is a full release you need to set up two branches, one for further substantial development (often called ‘trunk’) and another for maintenance releases.

    • Branch to maintenance:

      git co -b maint/X.Y.Z
      

      Push with something like git push upstream-rw maint/0.6.x --set-upstream

    • Start next development series:

      git co main-master
      

      Next merge the maintenance branch with the “ours” strategy. This just labels the maintenance branch info.py edits as seen but discarded, so we can merge from maintenance in future without getting spurious merge conflicts:

      git merge -s ours maint/0.6.x
      

      Push with something like git push upstream-rw main-master:master

    If this is just a maintenance release from maint/0.6.x or similar, just tag and set the version number to - say - 0.6.2.dev.

  • Push the tag with git push upstream-rw 0.6.0

Other stuff that needs doing for the release#

  • Checkout the tagged release, build the html docs and upload them to the github pages website:

    make upload
    
  • Announce to the mailing lists. With fear and trembling.