Skip to content

Commit

Permalink
Update release scripts for 0.5.0 release (#5)
Browse files Browse the repository at this point in the history
* udpade find_contributtors script to better handle multiple repository configuration

* move GH_TOKEN related exception to `get_github`

* improve adding additional repos to find contributors without citation

* add warning about additional_notes

* add option to add pr from docs

* Add header and highlights paragraphs

* don't use full repo specifier

* Merge main, docs, and first time contributors

* Allow using header snippet

* uncomment main repo crawling

* Fix typo in commit link f-string

* Remove warning and add date

* Update highlights section

* Run black

* Use ruff-fmt instead of black

* fix format and ignore E501

---------

Co-authored-by: Juan Nunez-Iglesias <[email protected]>
  • Loading branch information
Czaki and jni authored Jul 23, 2024
1 parent 49143c4 commit 3ca65b6
Show file tree
Hide file tree
Showing 16 changed files with 497 additions and 323 deletions.
9 changes: 2 additions & 7 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,10 @@ repos:
- id: end-of-file-fixer
exclude: patch_dir
- id: check-yaml
- repo: https://github.com/psf/black-pre-commit-mirror
rev: 23.10.1
hooks:
- id: black
pass_filenames: true
exclude: _vendor|vendored|examples
- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.1.3
rev: v0.4.8
hooks:
- id: ruff
exclude: _vendor|vendored
args: [--output-format, github]
- id: ruff-format
42 changes: 26 additions & 16 deletions add_login_to_citation_cff.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
This is a script for adding logins to the existing CITATION.cff file.
This simplifies future updating of this file. It creates a backup file with .bck suffix/
"""

from __future__ import annotations

import argparse
Expand All @@ -23,7 +24,7 @@
)

LOCAL_DIR = Path(__file__).parent
DEFAULT_CORRECTION_FILE = LOCAL_DIR / "name_corrections.yaml"
DEFAULT_CORRECTION_FILE = LOCAL_DIR / 'name_corrections.yaml'


def get_name(user, correction_dict):
Expand All @@ -36,10 +37,12 @@ def get_name(user, correction_dict):

def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("path", help="The path to the citation file to sort", type=Path)
parser.add_argument(
"--correction-file",
help="The file with the corrections",
'path', help='The path to the citation file to sort', type=Path
)
parser.add_argument(
'--correction-file',
help='The file with the corrections',
default=DEFAULT_CORRECTION_FILE,
type=existing_file,
)
Expand All @@ -51,7 +54,7 @@ def main():
def add_logins(cff_path: Path, correction_file: Path | None = None) -> None:
setup_cache()

with cff_path.open(encoding="utf8") as f:
with cff_path.open(encoding='utf8') as f:
data = safe_load(f)

contributors_iterable = get_repo().get_contributors()
Expand All @@ -62,30 +65,37 @@ def add_logins(cff_path: Path, correction_file: Path | None = None) -> None:

contributors = {
get_name(user, correction_dict): user
for user in tqdm(contributors_iterable, total=contributors_iterable.totalCount)
for user in tqdm(
contributors_iterable, total=contributors_iterable.totalCount
)
if get_name(user, correction_dict) is not None
}

for user in get_repo().get_contributors():
if get_name(user, correction_dict) is None and user.login not in BOT_LIST:
print(f"Could not find {user.login}", file=sys.stderr)
if (
get_name(user, correction_dict) is None
and user.login not in BOT_LIST
):
print(f'Could not find {user.login}', file=sys.stderr)

# assert len(contributors) == contributors_iterable.totalCount

for i, author in enumerate(data["authors"]):
if "alias" in author:
for i, author in enumerate(data['authors']):
if 'alias' in author:
continue
name = unidecode(f'{author["given-names"]} {author["family-names"]}'.lower())
name = unidecode(
f'{author["given-names"]} {author["family-names"]}'.lower()
)
if name in contributors:
author["alias"] = contributors[name].login
author['alias'] = contributors[name].login
else:
print(f"Could not find {name}", file=sys.stderr)
print(f'Could not find {name}', file=sys.stderr)

shutil.copy(str(cff_path), f"{cff_path}.bck")
shutil.copy(str(cff_path), f'{cff_path}.bck')

with cff_path.open("w", encoding="utf8") as f:
with cff_path.open('w', encoding='utf8') as f:
safe_dump(data, f, sort_keys=False, allow_unicode=True)


if __name__ == "__main__":
if __name__ == '__main__':
main()
10 changes: 10 additions & 0 deletions additional_notes/0.5.0/header.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
*Thursday, Jul 11, 2024*

We're happy to announce the release of napari 0.5.0!
napari is a fast, interactive, multi-dimensional image viewer for Python.
It's designed for exploring, annotating, and analyzing multi-dimensional
images. It's built on Qt (for the GUI), VisPy (for performant GPU-based
rendering), and the scientific Python stack (NumPy, SciPy, and friends).

For more information, examples, and documentation, please visit our website:
https://napari.org/
49 changes: 49 additions & 0 deletions additional_notes/0.5.0/highlights.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
napari 0.5.0 is the beginning of an architectural overhaul of napari. The
architecture improvements, which are still ongoing, enable more responsive
asynchronous loading when slicing layers or panning and zooming in multiscale
2D layers ([#5816](https://github.com/napari/napari/pull/5816)). There's
several performance improvements, too, including faster points layer creation
and updates ([#6727](https://github.com/napari/napari/pull/6727)).

Other architectural changes, refactoring napari on top of
[app-model](https://app-model.readthedocs.io/en/latest/), have enabled us to
(finally 😅) implement [NAP-6](nap-6-contributable-menus), which allows
plugins to organize their commands in defined menus in the napari menubar
and application. Please read [NAP-6](nap-6-contributable-menus) for all the
juicy details, including how to request more menus if the existing ones don't
meet your needs. 📋 ([#7011](https://github.com/napari/napari/pull/7011))

Another important development for plugins is that we have added fields for
axis names and physical units in layers
([#6979](https://github.com/napari/napari/pull/6979)). If you implement a
reader plugin, you can now specify the names of the axes in the data that you
are reading in, and the physical units of the scale and other transformations.
Currently, napari is *not* using this information, but we will in upcoming
versions, so plugins should start providing this information if they have it.

There's plenty of new features, too, including a polygon drawing tool when
painting labels ([#5806](https://github.com/napari/napari/pull/5806)),
pinch-to-zoom ([#5859](https://github.com/napari/napari/pull/5859)), better
ways to show/hide individual layers when exploring your data
([#5574](https://github.com/napari/napari/pull/5574))
([#5618](https://github.com/napari/napari/pull/5618)), creating a layer from
an image or URL in your clipboard
([#6532](https://github.com/napari/napari/pull/6532)),
a new way to export figure-quality renderings from the canvas
([#6730](https://github.com/napari/napari/pull/6730)) (2D-only for now),
and the ability to copy and paste spatial metadata (scale, translate, etc)
between layers ([#6864](https://github.com/napari/napari/pull/6864)).

You'll also note a new little button on layer controls, including images:

```{image} ../images/transform-icon.svg
:alt: transform layer icon
:width: 100px
:align: center
```

This little button allows you to resize and rotate layers, enabling manual
alignment ([#6794](https://github.com/napari/napari/pull/6794))!

All in all, this release has over 20 new features and over 100 bug fixes and
improvements. Please see below for the full list of changes since 0.4.19.
62 changes: 37 additions & 25 deletions cherry_pick_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"""
This is script to cherry-pick commits base on PR labels
"""

from __future__ import annotations

import argparse
Expand All @@ -28,32 +29,38 @@

def main():
parser = argparse.ArgumentParser()
parser.add_argument("base_branch", help="The base branch.")
parser.add_argument("milestone", help="The milestone to list")
parser.add_argument('base_branch', help='The base branch.')
parser.add_argument('milestone', help='The milestone to list')
parser.add_argument(
'--first-commits',
help='file with list of first commits to cherry pick',
)
parser.add_argument(
"--first-commits", help="file with list of first commits to cherry pick"
'--stop-after', help='Stop after this PR', default=0, type=int
)
parser.add_argument("--stop-after", help="Stop after this PR", default=0, type=int)
parser.add_argument(
"--git-main-branch",
help="The git main branch",
default=os.environ.get("GIT_RELEASE_MAIN_BRANCH", "main"),
'--git-main-branch',
help='The git main branch',
default=os.environ.get('GIT_RELEASE_MAIN_BRANCH', 'main'),
)

parser.add_argument(
"--working-dir", help="path to repository", default=LOCAL_DIR, type=Path
'--working-dir',
help='path to repository',
default=LOCAL_DIR,
type=Path,
)
parser.add_argument(
"--skip-commits",
nargs="+",
help="list of commits to skip as they are already cherry-picked",
'--skip-commits',
nargs='+',
help='list of commits to skip as they are already cherry-picked',
type=int,
)

argcomplete.autocomplete(parser)
args = parser.parse_args()

target_branch = f"v{args.milestone}x"
target_branch = f'v{args.milestone}x'

if args.first_commits is not None:
with open(args.first_commits) as f:
Expand All @@ -74,18 +81,23 @@ def main():


def prepare_repo(
working_dir: Path, target_branch: str, base_branch: str, main_branch: str = "main"
working_dir: Path,
target_branch: str,
base_branch: str,
main_branch: str = 'main',
) -> Repo:
if not working_dir.exists():
repo = Repo.clone_from(f"git@{GH}:{GH_USER}/{GH_REPO}.git", working_dir)
repo = Repo.clone_from(
f'git@{GH}:{GH_USER}/{GH_REPO}.git', working_dir
)
else:
repo = Repo(LOCAL_DIR / REPO_DIR_NAME)

if target_branch not in repo.branches:
repo.git.checkout(base_branch)
repo.git.checkout("HEAD", b=target_branch)
repo.git.checkout('HEAD', b=target_branch)
else:
repo.git.reset("--hard", "HEAD")
repo.git.reset('--hard', 'HEAD')
repo.git.checkout(main_branch)
repo.git.pull()
repo.git.checkout(target_branch)
Expand All @@ -101,7 +113,7 @@ def perform_cherry_pick(
first_commits: set,
stop_after: int | None,
base_branch: str,
main_branch: str = "main",
main_branch: str = 'main',
skip_commits: list[int] = None,
):
"""
Expand Down Expand Up @@ -141,13 +153,13 @@ def perform_cherry_pick(
setup_cache()

milestone = get_milestone(milestone_str)
patch_dir_path = working_dir / "patch_dir" / milestone.title
patch_dir_path = working_dir / 'patch_dir' / milestone.title
patch_dir_path.mkdir(parents=True, exist_ok=True)

# with short_cache(60):
pr_targeted_for_release = [
x
for x in iter_pull_request(f"milestone:{milestone.title} is:merged")
for x in iter_pull_request(f'milestone:{milestone.title} is:merged')
if x.milestone == milestone
]

Expand Down Expand Up @@ -187,20 +199,20 @@ def perform_cherry_pick(
# commit = repo.commit(pr_commits_dict[pull.number])
# print("hash", pr_commits_dict[pull.number])
# break
patch_file = patch_dir_path / f"{pull.number}.patch"
patch_file = patch_dir_path / f'{pull.number}.patch'
if patch_file.exists():
print(f"Apply patch {patch_file}")
print(f'Apply patch {patch_file}')
repo.git.am(str(patch_file))
continue
try:
repo.git.cherry_pick(pr_commits_dict[pull.number])
except GitCommandError:
print(pull, pr_commits_dict[pull.number])
repo.git.mergetool()
repo.git.cherry_pick("--continue")
with open(patch_file, "w") as f:
f.write(repo.git.format_patch("HEAD~1", "--stdout"))
repo.git.cherry_pick('--continue')
with open(patch_file, 'w') as f:
f.write(repo.git.format_patch('HEAD~1', '--stdout'))


if __name__ == "__main__":
if __name__ == '__main__':
main()
Loading

0 comments on commit 3ca65b6

Please sign in to comment.