Skip to content

Commit d2d8f40

Browse files
ax3lfranzpoeschel
andauthored
Script: New Version (#1467)
* Script: New Version Adding a script to update all version notes programmatically for releases. Add maintainer docs. Co-authored-by: Franz Pöschel <[email protected]>
1 parent 88089bc commit d2d8f40

File tree

4 files changed

+188
-3
lines changed

4 files changed

+188
-3
lines changed

docs/source/index.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,4 +167,5 @@ Maintenance
167167
:maxdepth: 1
168168
:hidden:
169169

170-
maintenance/release
170+
maintenance/release_github
171+
maintenance/release_channels

docs/source/maintenance/release.rst renamed to docs/source/maintenance/release_channels.rst

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
.. _maintenance-release:
1+
.. _maintenance-release-channels:
22

33
Release Channels
44
================
55

6+
After tagging and releasing a new openPMD-api version on GitHub, we update package managers that ship openPMD-api.
7+
68
Spack
79
-----
810

@@ -15,7 +17,7 @@ Example workflow for a new release:
1517

1618
- https://github.com/spack/spack/pull/14018
1719

18-
Please ping `@ax3l <github.com/ax3l>`_ in your pull-request.
20+
Please ping `@ax3l <github.com/ax3l>`__ in your pull-request.
1921

2022

2123
Conda-Forge
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
.. _maintenance-release-github:
2+
3+
New Version on GitHub
4+
=====================
5+
6+
These are the steps we perform to create a new openPMD-api release.
7+
8+
Regular Release
9+
---------------
10+
11+
As a first step, we merge in all pull requests and resolve all issued that we have assigned to the release's "Milestone" on GitHub.
12+
For example, here are all `issues and pull requests <https://github.com/openPMD/openPMD-api/milestone/8>`__ on the version ``0.16.0`` release.
13+
14+
Then, we prepare a pull request that updates the ``CHANGELOG.rst`` and upgrade guide in ``NEWS.rst``, example PR: `Release notes: 0.16 <https://github.com/openPMD/openPMD-api/pull/1648>`__
15+
In the same PR, we bump up the version in CMake files and documentation using our ``new_version.py`` script.
16+
17+
Once the PR is merged, we:
18+
19+
#. Wait for the CI to finish: there will be one more auto-commit added to the ``dev`` branch, updating out ``.pyi`` stub files
20+
#. Pull the latest ``dev`` branch to our local machine
21+
#. Add a GPG-signed tag, e.g., ``git tag -s 0.16.0``: see old releases for the format of this tag, e.g., use ``git show 0.15.0``. The text is from the top of ``CHANGELOG.rst``.
22+
#. Upload the GPG-signed tag to mainline, e.g., ``git push -u mainline 0.16.0``
23+
#. Click `Draft a new release <https://github.com/openPMD/openPMD-api/releases>`__ on GitHub, select the newly created tag.
24+
Fill the text fields using the same format that you see for `earlier releases <https://github.com/openPMD/openPMD-api/releases>`__, again, based on the top of the text in ``CHANGELOG.rst``.
25+
Skip the DOI badge for this release step.
26+
#. If you don't have GPG properly set up for your git, then you can just do the last step, which then also creates a tag.
27+
Be sure to use the same version scheme for the tag, i.e., we do *not* prefix our tags with ``v`` or something of that kind!
28+
#. Go to `Rodare <https://doi.org/10.14278/rodare.27>`__ and wait for the release to arrive.
29+
If there are issues, contact Rodare/HZDR IT support and check under `Settings - Webhooks <https://github.com/openPMD/openPMD-api/settings/hooks>`__ if the release was delivered.
30+
#. Once the Rodare DOI is auto-created, click on the badge on the right hand side of the page, copy the Markdown code, and edit your `newly created release <https://github.com/openPMD/openPMD-api/releases>`__ text on GitHub to add the badge as you see in earlier releases.
31+
32+
That's it!
33+
34+
35+
Backport (Bugfix) Release
36+
-------------------------
37+
38+
For bugfix releases, we generally follow the same workflow as for regular releases.
39+
40+
The main difference is that we:
41+
42+
#. Start a new branch from the release we want to backport to.
43+
We name the branch ``release-<version>``, e.g., backports on the ``0.15.0`` release for a ``0.15.1`` release are named ``release-0.15.1``.
44+
#. We add pull requests (usually we ``git cherry-pick`` commits) to that branch until we have all fixes collected.
45+
Backport releases try to not add features and to not break APIs!
46+
#. Then, we follow the same workflow as above, but we tag on the ``release-<version>`` branch instead of the ``dev`` branch.
47+
#. Once we uploaded the new tag to mainline and created the GitHub release, we remove the ``release-<version>`` branch from our mainline repo.
48+
The new tag we added contains all history we need if we wanted to do a follow-up bugfix, e.g., a ``release-0.15.2`` branch based on the ``0.15.1`` release.
49+
50+
As general guidance, we usually only fix bugs on the *latest* regular release.
51+
Don't sweat it - if it is too hard to backport a fix, consider doing a timely new regular version release.
52+
53+
That's it!

new_version.py

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
#!/usr/bin/env python3
2+
#
3+
# Copyright 2021-2023 Axel Huebl
4+
#
5+
# This file is part of openPMD-api.
6+
#
7+
8+
# This file is a maintainer tool to bump the versions inside openPMD-api's
9+
# source directory at all places where necessary.
10+
#
11+
from pathlib import Path
12+
import re
13+
import sys
14+
15+
# Maintainer Inputs ###########################################################
16+
17+
print(
18+
"""Hi there, this is an openPMD maintainer tool to update the source
19+
code of openPMD-api to a new version.
20+
For it to work, you need write access on the source directory and
21+
you should be working in a clean git branch without ongoing
22+
rebase/merge/conflict resolves and without unstaged changes."""
23+
)
24+
25+
# check source dir
26+
# REPO_DIR = Path(__file__).parent.parent.parent.absolute()
27+
REPO_DIR = Path(__file__).parent.absolute()
28+
print(f"\nYour current source directory is: {REPO_DIR}")
29+
30+
REPLY = input("Are you sure you want to continue? [Y/n] ")
31+
print()
32+
if REPLY not in ["Y", "y", ""]:
33+
print("You did not confirm with 'y', aborting.")
34+
sys.exit(1)
35+
36+
MAJOR = input("MAJOR version? (e.g., 1) ")
37+
MINOR = input("MINOR version? (e.g., 0) ")
38+
PATCH = input("PATCH version? (e.g., 0) ")
39+
SUFFIX = input("SUFFIX? (e.g., dev) ")
40+
41+
VERSION_STR = f"{MAJOR}.{MINOR}.{PATCH}"
42+
VERSION_STR_SUFFIX = VERSION_STR + (f"-{SUFFIX}" if SUFFIX else "")
43+
44+
print()
45+
print(f"Your new version is: {VERSION_STR_SUFFIX}")
46+
47+
# Recover the old version from the Readme.
48+
# Do not use CMakeLists.txt as it might already contain the upcoming version
49+
# code.
50+
with open(str(REPO_DIR.joinpath("README.md")), encoding="utf-8") as f:
51+
for line in f:
52+
match = re.search(r"find_package.*openPMD *([^ ]*) *CONFIG\).*", line)
53+
if match:
54+
OLD_VERSION_STR = match.group(1)
55+
break
56+
57+
print(f"The old version is: {OLD_VERSION_STR}")
58+
print()
59+
60+
61+
REPLY = input("Is this information correct? Will now start updating! [y/N] ")
62+
print()
63+
if REPLY not in ["Y", "y", ""]:
64+
print("You did not confirm with 'y', aborting.")
65+
sys.exit(1)
66+
67+
68+
# Ask for new #################################################################
69+
70+
print("""We will now run a few sed commands on your source directory.\n""")
71+
72+
# Updates #####################################################################
73+
74+
# run_test.sh (used also for Azure Pipelines)
75+
cmakelists_path = str(REPO_DIR.joinpath("CMakeLists.txt"))
76+
with open(cmakelists_path, encoding="utf-8") as f:
77+
cmakelists_content = f.read()
78+
cmakelists_content = re.sub(
79+
r"^(project.*openPMD.*VERSION *)(.*)(\).*)$",
80+
r"\g<1>{}\g<3>".format(VERSION_STR),
81+
cmakelists_content,
82+
flags=re.MULTILINE,
83+
)
84+
85+
with open(cmakelists_path, "w", encoding="utf-8") as f:
86+
f.write(cmakelists_content)
87+
88+
89+
def generic_replace(filename):
90+
filename = str(REPO_DIR.joinpath(filename))
91+
with open(filename, encoding="utf-8") as f:
92+
content = f.read()
93+
content = re.sub(re.escape(OLD_VERSION_STR), VERSION_STR, content)
94+
95+
with open(filename, "w", encoding="utf-8") as f:
96+
f.write(content)
97+
98+
99+
for file in ["docs/source/dev/linking.rst", "README.md"]:
100+
generic_replace(file)
101+
102+
version_hpp_path = str(REPO_DIR.joinpath("include/openPMD/version.hpp"))
103+
with open(version_hpp_path, encoding="utf-8") as f:
104+
version_hpp_content = f.read()
105+
106+
def replace(key, value):
107+
global version_hpp_content
108+
version_hpp_content = re.sub(
109+
r"^(#define OPENPMDAPI_VERSION_{}) .*$".format(re.escape(key)),
110+
r"\1 {}".format(value),
111+
version_hpp_content,
112+
flags=re.MULTILINE,
113+
)
114+
115+
replace("MAJOR", MAJOR)
116+
replace("MINOR", MINOR)
117+
replace("PATCH", PATCH)
118+
replace("LABEL", '"{}"'.format(SUFFIX))
119+
120+
with open(version_hpp_path, "w", encoding="utf-8") as f:
121+
f.write(version_hpp_content)
122+
123+
# Epilogue ####################################################################
124+
125+
print(
126+
"""Done. Please check your source, e.g. via
127+
git diff
128+
now and commit the changes if no errors occurred."""
129+
)

0 commit comments

Comments
 (0)