From 5b4704c3d5b1e04abb57d0bec6eb3a6e5d5a9261 Mon Sep 17 00:00:00 2001 From: Luca Marconato Date: Sat, 4 Jan 2025 00:43:56 +0100 Subject: [PATCH 1/2] improved release instructions and workflow --- .github/workflows/build.yaml | 24 --- .github/workflows/release.yaml | 20 +- CHANGELOG.md | 328 --------------------------------- docs/changelog.md | 5 +- docs/contributing.md | 84 +++++++-- docs/index.md | 1 - 6 files changed, 77 insertions(+), 385 deletions(-) delete mode 100644 .github/workflows/build.yaml delete mode 100644 CHANGELOG.md diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml deleted file mode 100644 index c6b6e6050..000000000 --- a/.github/workflows/build.yaml +++ /dev/null @@ -1,24 +0,0 @@ -name: Check Build - -on: - push: - branches: [main] - pull_request: - branches: [main] - -jobs: - package: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Set up Python 3.12 - uses: actions/setup-python@v4 - with: - python-version: "3.12" - cache: pip - - name: Install build dependencies - run: python -m pip install --upgrade pip wheel twine build - - name: Build package - run: python -m build - - name: Check package - run: twine check --strict dist/*.whl diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index ee38475ef..299ed867b 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -5,26 +5,26 @@ on: types: [published] jobs: - release: - # requires that you have put your twine API key in your - # github secrets (see readme for details) + package_and_release: runs-on: ubuntu-latest - if: contains(github.ref, 'tags') + if: startsWith(github.ref, 'refs/tags/v') steps: - - name: Checkout code - uses: actions/checkout@v3 - + - uses: actions/checkout@v3 - name: Set up Python 3.12 uses: actions/setup-python@v4 with: python-version: "3.12" - + cache: pip + - name: Install build dependencies + run: python -m pip install --upgrade pip wheel twine build + - name: Build package + run: python -m build + - name: Check package + run: twine check --strict dist/*.whl - name: Install hatch run: pip install hatch - - name: Build project for distribution run: hatch build - - name: Publish a Python distribution to PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index ecde18b30..000000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,328 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog][], -and this project adheres to [Semantic Versioning][]. - -[keep a changelog]: https://keepachangelog.com/en/1.0.0/ -[semantic versioning]: https://semver.org/spec/v2.0.0.html - -## Incoming release - -### Major - -- Added attributes at the SpatialData object level (`.attrs`) -- `rasterize_bins()` can now produce a labels element #811 @ArneDefauw - -### Minor - -- Added `asv` benchmark code #784 @berombau -- Validate tables while parsing #808 -- fix join non matching tables #813 - -### Fixed - -- Relaxed `fsspec` requirement #798 -- Fix for `to_polygons` when using processed instead of threads in Dask #756 @ArneDefauw -- Fix `transform_to_data_extent` converting labels to images #791 @aeisenbarth - -## [0.2.6] - 2024-11-26 - -### Added - -- Added `set_channel_names` method to `SpatialData` to change the channel names of an - image element in `SpatialData` #786 -- Added `write_channel_names` method to `SpatialData` to overwrite channel metadata on disk - without overwriting the image array itself. #786 - -### Changed - -- Argument `c_coords` is moved out of kwargs for the `ImageModel`s. #779 -- `get_channels` is marked for deprecation in `SpatialData` v0.3.0. Function is replaced - by `get_channel_names` #786 -- Updated dependency of `multiscale-spatial-image` #792 -- Adjust to new version of `xarray` with `DataTree` # 752 - -### Fixed - -- Updated deprecated default stages of `pre-commit` #771 -- Preserve points `feature_key` during queries #794 - -## [0.2.5] - 2024-11-06 - -### Fixed - -- Incompatibility issues due to newest release of `multiscale-spatial-image` #760 - -## [0.2.4] - 2024-11-06 - -### Major - -- Enable vectorization of `bounding_box_query` for all `SpatialData` elements. #699 - -### Minor - -- Added `shortest_path` parameter to `get_transformation_between_coordinate_systems` #714 -- Added `get_pyramid_levels()` utils API #719 -- Improved ergonomics of `concatenate()` when element names are non-unique #720 -- Improved performance of writing images with multiscales #577 - -## [0.2.3] - 2024-09-25 - -### Minor - -- Added `clip: bool = False` parameter to `polygon_query()` #670 -- Add `sort` parameter to `PointsModel.parse()` #672 - -### Fixed - -- Fix interpolation artifact multiscale computation for labels #697 - -## [0.2.2] - 2024-08-07 - -### Major - -- New disk format for shapes using `GeoParquet` (the change is backward compatible) #542 - -### Minor - -- Add `return_background` as argument to `get_centroids` and `get_element_instances` #621 -- Ability to save data using older disk formats #542 - -### Fixed - -- Circles validation now checks for inf or nan radii #653 -- Bug with table name in torch dataset #654 @LLehner - -## [0.2.1] - 2024-07-04 - -### Minor - -- Relaxing `spatial-image` package requirement #616 - -## [0.2.0] - 2024-07-03 - -### Changed - -- Using `DataArray` directly instead of the subclass `SpatialImage` (removed install constraint for the `spatial_image` package) #587 -- Using `DataTree` directly instead of the subclass `MultiscaleSpatialImage` (removed install constraint for the `multiscale_spatial_image` package) #587 -- Changed `element`parameter (deprecation in v0.3.0) of `transform_element_to_coordinate_system` to a string `element_name` #611 - -### Major - -- Added operation: `to_polygons()` @quentinblampey #560 -- Extended `rasterize()` to support all the data types @quentinblampey #566 -- Added operation: `rasterize_bins()` @quentinblampey #578 -- Added operation: `map_raster()` to apply functions block-wise to raster data @ArneDefauw #588 - -### Minor - -- Removed `pygeos` dependency @omsai #545 -- Channel coordinate annotations on images now persist through `rasterize()` @clwgg #544 -- Added `datasets` module -- Extended `get_values()` to `AnnData` tables #579 -- Added `get_element_instances()` (replaces `_get_unique_label_values_as_index()`) #582 -- Added `get_element_annotators()`, retrieving the tables that annotate a particular SpatialElement #595 - -### Fixed - -- Preserve channel names of multi-scale images in `transform` (#379) -- Fix `filter_by_coordinate_system` with SpatialData object having a table not annotating an element (#619) - -## [0.1.2] - 2024-03-30 - -### Minor - -- Made `get_channels()` public. -- Added utils `force_2d()` to force 3D shapes to 2D (this is a temporary solution until `.force_2d()` is available in `geopandas`). - -## [0.1.1] - 2024-03-28 - -### Added - -- Added method `update_annotated_regions_metadata() which updates the `region`value automatically from the`region_key` columns - -### Changed - -- Renamed `join_sdata_spatialelement_table` to `join_spatialelement_table`, and made it work also without `SpatialData` objects. - -## [0.1.0] - 2024-03-24 - -### Added - -#### Major - -- Implemented support in `SpatialData` for storing multiple tables. -- These tables can annotate a `SpatialElement` but now not necessarily so. -- Deprecated `.table` attribute in favor of `.tables` dict-like accessor. - -- Added join operations -- Added SQL like joins that can be executed by calling one public function `join_sdata_spatialelement_table`. The following joins are supported: `left`, `left_exclusive`, `right`, `right_exclusive` and `inner`. The function has an option to match rows. For `left` only matching `left` is supported and for `right` join only `right` matching of rows is supported. Not all joins are supported for `Labels` elements. -- Added function `match_element_to_table` which allows the user to perform a right join of `SpatialElement`(s) with a table with rows matching the row order in the table. - -- Incremental IO of data and metadata: -- Increased in-memory vs on-disk control: changes performed in-memory (e.g. adding a new image) are not automatically performed on-disk. -- Deprecated `add_image()`, `add_labels()`, `add_shapes()`, `add_points()` in favor of `.images`, `.labels`, `.shapes`, `.points` dict-like accessors. -- new methods `write_element()`, `write_transformations()`, `write_metadata()`, `remove_element_from_disk()` -- new methods `write_consolidated_metadata()` and `has_consolidated_metadata()` -- deprecated `save_transformations()` -- improved `__repr__()` with information on Zarr storage and Dask-backed files -- new utils `is_self_contained()`, `describe_elements_are_self_contained()` -- new utils `element_paths_in_memory()`, `element_paths_on_disk()` - -#### Minor - -- Multiple table helper functions -- Added public helper function `get_table_keys()` in `spatialdata.models` to retrieve annotation information of a given table. -- Added public helper function `check_target_region_column_symmetry()` in `spatialdata.models` to check whether annotation - metadata in `table.uns['spatialdata_attrs']` corresponds with respective columns in `table.obs`. -- Added function `validate_table_in_spatialdata()` in SpatialData to validate the annotation target of a table being present in the `SpatialData` object. -- Added method `get_annotated_regions()` in `SpatialData` to get the regions annotated by a given table. -- Added method `get_region_key_column()` in `SpatialData` to get the region_key column in table.obs. -- Added method `get_instance_key_column()` in `SpatialData` to get the instance_key column in table.obs. -- Added method `set_table_annotates_spatialelement()` in `SpatialData` to either set or change the annotation metadata of a table in a given `SpatialData` object. - Added `table_name` parameter to the `aggregate()` function to allow users to give a custom table name to table resulting from aggregation. -- Added `table_name` parameter to the `get_values()` function. - -- Utils -- Added `gen_spatial_elements()` generator in SpatialData to generate the `SpatialElements` in a given `SpatialData` object. -- Added `gen_elements` generator in `SpatialData` to generate elements of a `SpatialData` object including tables. -- added `SpatialData.subset()` API -- added `SpatialData.locate_element()` API -- added utils function: `get_centroids()` -- added utils function: `deepcopy()` -- added operation: `to_circles()` -- documented previously-added `get_channels()` to retrieve the channel names of a raster element indepently of it being single or multi-scale - -- Transformations-related - - - added utils function: `transform_to_data_extent()` - - added utils function: `are_extents_equal()` - - added utils function: `postpone_transformation()` - - added utils function: `remove_transformations_to_coordinate_system()` - -- added testing utilities: `assert_spatial_data_objects_are_identical()`, `assert_elements_are_identical()`, `assert_elements_dict_are_identical()` - -### Changed/fixed - -#### Major - -- refactored data loader for deep learning -- refactored `SpatialData.write()` to be more robust -- generalized spatial queries to any combination of 2D/3D data and 2D/3D query region #409 - -#### Minor - -- Changed the string representation of `SpatialData` to reflect the changes in regard to multiple tables and incremental IO. -- improved usability and robustness of `sdata.write()` when `overwrite=True` @aeisenbarth -- fixed warnings for categorical dtypes in tables in `TableModel` and `PointsModel` -- fixed wrong order of points after spatial queries - -## [0.0.14] - 2023-10-11 - -### Added - -#### Minor - -- new API: sdata.rename_coordinate_systems() - -#### Technical - -- decompose affine transformation into simpler transformations -- remove padding for blobs() - -#### Major - -- get_extent() function to compute bounding box of the data - -#### Minor - -- testing against pre-release packages - -### Fixed - -- Fixed bug with get_values(): ignoring background channel in labels - -## [0.0.13] - 2023-10-02 - -### Added - -- polygon_query() support for images #358 - -### Fixed - -- Fix missing c_coords argument in blobs multiscale #342 -- Replaced hardcoded string with instance_key #346 - -## [0.0.12] - 2023-06-24 - -### Added - -- Add multichannel blobs sample data (by @melonora) - -## [0.0.11] - 2023-06-21 - -### Improved - -- Aggregation APIs. - -## [0.0.10] - 2023-06-06 - -### Fixed - -- Fix blobs (#282) - -## [0.0.9] - 2023-05-23 - -### Updated - -- Update napari-spatialdata pin (#279) -- pin typing-extensions - -## [0.0.8] - 2023-05-22 - -### Merged - -- Merge pull request #271 from scverse/fix/aggregation - -## [0.0.7] - 2023-05-20 - -### Updated - -- Update readme - -## [0.0.6] - 2023-05-10 - -### Added - -- This release adds polygon spatial query. - -## [0.0.5] - 2023-05-05 - -### Fixed - -- fix tests badge (#242) - -## [0.0.4] - 2023-05-04 - -### Tested - -- This release tests distribution via pypi - -## [0.0.3] - 2023-05-02 - -### Added - -- This is an alpha release to test the release process. - -## [0.0.2] - 2023-05-02 - -### Added - -- make version dynamic - -## [0.0.1.dev1] - 2023-03-25 - -### Added - -- Dev version, not official release yet diff --git a/docs/changelog.md b/docs/changelog.md index d9e79ba64..feef5a161 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,3 +1,4 @@ -```{include} ../CHANGELOG.md +# Changelog -``` +Please refer directly to the [Releases](https://github.com/scverse/spatialdata/releases) section on GitHub, where you can find curated release notes for each release. +For developers, please consult the [contributing guide](https://github.com/scverse/spatialdata/blob/main/docs/contributing.md), which explains how to keep release notes are up-to-date at each release. diff --git a/docs/contributing.md b/docs/contributing.md index 6aef3bbf7..37f036c26 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -82,13 +82,17 @@ Before making a release, you need to update the version number. Please adhere to > > Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format. -We use [bump2version][] to automatically update the version number in all places and automatically create a git tag. -Run one of the following commands in the root of the repository +You can find the [labels for pre-release in this page](https://packaging.python.org/en/latest/discussions/versioning/#valid-version-numbers). + +You can either use [bump2version][] to automatically create a git tag with the updated version number, or manually create the tag yourself (locally or from the GitHub interface when making a release). +If you use `bump2version`, you can run one of the following commands in the root of the repository ```bash bump2version patch bump2version minor bump2version major +# if you want to create a pre-release +bump2version --new-version 1.2.0rc1 ``` Once you are done, run @@ -99,39 +103,79 @@ git push --tags to publish the created tag on GitHub. +It's important that the tag for a pre-release follows this naming convention as it will determine if the package is displayed as [pre-release or release](https://pypi.org/project/spatialdata/#history) in PyPI. + [bump2version]: https://github.com/c4urself/bump2version -### Building and publishing the package on PyPI +### Making a release on GitHub and publishing to PyPI -Python packages are not distributed as source code, but as _distributions_. The most common distribution format is the so-called _wheel_. To build a _wheel_, run +If you already tagged and pushed a commit as explained above and you want to create a release from that tag, you can go to the [Tags page on GitHub](https://github.com/scverse/spatialdata/tags), select the (latest) tag and press the "Create release from tag" button. Please name the release with the same string used for the tag (including the `v` prefix). -```bash -python -m build -``` +Alternatively you can go to the [Releases page on GitHub](https://github.com/scverse/spatialdata/releases) and press the "Draft a new release button". Now press "Choose a tag" and create a new tag. -This command creates a _source archive_ and a _wheel_, which are required for publishing your package to [PyPI][]. These files are created directly in the root of the repository. +Both approaches lead to the same page and view. From this, you need to specify if the release is a pre-release or if it should be set as the latest release (please use the checkboxes accordingly). -Before uploading them to [PyPI][] you can check that your _distribution_ is valid by running: +The last step is to fill the releases notes (explained in the next session), after this, you can press the "Publish release" button and the release will be available on GitHub. A [GitHub action](https://github.com/scverse/spatialdata/blob/main/.github/workflows/release.yaml) will automatically build the package and [upload it to PyPI](https://pypi.org/project/spatialdata/#history). The action may fail, so please check the [status badge of the action from the Readme](https://github.com/scverse/spatialdata/actions/workflows/release.yaml). -```bash -twine check dist/* +#### Writing release notes + +We recommend using the button "Generate release notes" to automatically collect all the information of the pull requests that are part of the release. +The release notes serve as a changelog for the user of the package so it's important to have them curated and well-organized. This is explained in depth below. + +Here is an example of automatically generated release notes for a previous release (v0.2.3): +``` +## What's Changed +* Add clip parameter to polygon_query; tests missing by @LucaMarconato in https://github.com/scverse/spatialdata/pull/670 +* Add sort parameter to points model by @LucaMarconato in https://github.com/scverse/spatialdata/pull/672 +* [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci in https://github.com/scverse/spatialdata/pull/673 +* Docs for datasets (blobs, raccoon) by @LucaMarconato in https://github.com/scverse/spatialdata/pull/674 +* Update issue templates by @LucaMarconato in https://github.com/scverse/spatialdata/pull/675 +* Minor fixes: `id()` -> `is`, inplace category subset `AnnData` relational query by @LucaMarconato in https://github.com/scverse/spatialdata/pull/681 +* Added ColorLike to _types.py by @timtreis in https://github.com/scverse/spatialdata/pull/689 +* [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci in https://github.com/scverse/spatialdata/pull/685 +* [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci in https://github.com/scverse/spatialdata/pull/690 +* [pre-commit.ci] pre-commit autoupdate by @pre-commit-ci in https://github.com/scverse/spatialdata/pull/698 +* Fix labels multiscales method by @aeisenbarth in https://github.com/scverse/spatialdata/pull/697 + + +**Full Changelog**: https://github.com/scverse/spatialdata/compare/v0.2.2...v0.2.3 ``` -and finally publishing it with: +The release notes above can be hard to read, but this is addressed by our [configuration file](https://github.com/scverse/spatialdata/blob/main/.github/release.yml). It organizes release notes by change type, inferred from GitHub labels, and ignores PRs from bots. We recommend opening the PRs included in the release and adding the appropriate labels. The automatic generation will then group PRs by [release labels](https://github.com/scverse/spatialdata/labels?q=release-) and list each PR on a separate line. Here is an example output: -```bash -twine upload dist/* ``` + + +## What's Changed +### Major +* Adding `attrs` at the `SpatialData` object level by @quentinblampey in https://github.com/scverse/spatialdata/pull/711 +### Minor +* Add asv benchmark code by @berombau in https://github.com/scverse/spatialdata/pull/784 +* relabel block by @ArneDefauw in https://github.com/scverse/spatialdata/pull/664 +* validate tables while parsing by @melonora in https://github.com/scverse/spatialdata/pull/808 +### Fixed +* relaxed fsspec version by @LucaMarconato in https://github.com/scverse/spatialdata/pull/798 +* fix for to_polygons when using processes instead of threads in dask by @ArneDefauw in https://github.com/scverse/spatialdata/pull/756 +* Fix `transform_to_data_extent` converting labels to images by @aeisenbarth in https://github.com/scverse/spatialdata/pull/791 +* fix join non matching table by @melonora in https://github.com/scverse/spatialdata/pull/813 + + +**Full Changelog**: https://github.com/scverse/spatialdata/compare/v0.2.6...v0.2.7 +``` + +Use informative titles for PRs, as these will serve as section titles in the release notes (rename the PRs if necessary). You can also manually edit the release notes before publishing them to improve readability. -Provide your username and password when requested and then go check out your package on [PyPI][]! +Some additional considerations +- Important! If a PR is large and its title isn't informative or requires multiple lines, **do not** add a release tag. Instead, in the first message of the PR discussion, please include a markdown section with a brief description of the intended release notes. This will allow the person making a release to manually add the PR content to the release notes during the release process. +- Please avoid redundancy and do not add the same release notes to consecutive pre-releases/releases/post-releases. +- When automatically generating the release notes, you can use the button "Previous tag: ..." to choose which PRs will be included in the release notes. +- Finally, you can see an example of a release in action in from Luca [this short video tutorial](https://www.loom.com/share/7097455bc0b9449fbe72d53fc778cbf9). -For more information, follow the [Python packaging tutorial][]. +### Publishing to conda-forge -It is possible to automate this with GitHub actions, see also [this feature request][pypi-feature-request] -in the cookiecutter-scverse template. +Shortly after you make a release in PyPI, a new PR will be automatically made in the conda-forge "feedstock repository" for the package (this has been previously setup). The PR will contain a checklist of which tasks should be done to be able to merge the PR. Once the PR is merged, the package will be available in the conda-forge channel. -[python packaging tutorial]: https://packaging.python.org/en/latest/tutorials/packaging-projects/#generating-distribution-archives -[pypi-feature-request]: https://github.com/scverse/cookiecutter-scverse/issues/88 +Practically, the changes that usually needs to be done are comparing the package requirements in `pyproject.toml` from your repository, with the packages and versions in the `meta.yaml` file in the conda-forge feedstock repository. If there are any differences, you should update the `meta.yaml` file accordingly. After that, the CI will run and if green the PR can be merged. ## Writing documentation diff --git a/docs/index.md b/docs/index.md index b27ce758b..4b22d673c 100644 --- a/docs/index.md +++ b/docs/index.md @@ -68,7 +68,6 @@ tutorials/notebooks/notebooks.md tutorials/notebooks/datasets/README.md design_doc.md contributing.md -changelog.md references.md ``` From c3c59ff1be14797d7bda48c0063b2cb8acb20692 Mon Sep 17 00:00:00 2001 From: Luca Marconato Date: Sat, 4 Jan 2025 00:52:08 +0100 Subject: [PATCH 2/2] readded changelog placeholder in docs --- docs/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/index.md b/docs/index.md index 4b22d673c..b27ce758b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -68,6 +68,7 @@ tutorials/notebooks/notebooks.md tutorials/notebooks/datasets/README.md design_doc.md contributing.md +changelog.md references.md ```