Skip to content

Commit

Permalink
Add interactive prepare_release.py (#224)
Browse files Browse the repository at this point in the history
* add prepare_release.py

* update CONTRIBUTING.md with prepare_release.py workflow

* a few small changes
  • Loading branch information
ianbulovic authored Dec 21, 2024
1 parent 638abe7 commit d64d2c1
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 9 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Unreleased

## 0.7.1 (Nov 2024)

* Update release build instructions to fix versioning issue.

## 0.7.0 (Nov 2024)
Expand Down
25 changes: 16 additions & 9 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,23 +164,30 @@ the Semantic Versioning guidelines. The key points are as follows:
> API changes and backwards compatible feature adds fall under the MINOR
> version, and the API is not considered stable.
Add a new heading to [`CHANGELOG.md`](CHANGELOG.md) with the new version number
and the release date, absorbing all the unreleased changes. The "Unreleased"
section should be left empty.
#### 2. Creating a PR for the release

Create a locked version of the uv lock file with:
```SETUPTOOLS_SCM_PRETEND_VERSION=<desired version number> uv lock``` and push the updated lockfile to main.
When the codebase is ready for release, run `python scripts/prepare_release.py <new version number>`.
This will walk you through the last few changes that need to be made before release,
including updating the changelog and setting the setuptools_scm fallback version,
and will also update the lockfile and your venv with the new package version.

#### 2. Creating a release with GitHub
> [!WARNING]
> `prepare_release.py` requires uv to update the lockfile.
> It will not work if uv is not installed on your machine.
Once you're done, commit your changes and open a PR on `main` with a title like "Release 0.7.0".
Make sure the CI passes, then you can merge and continue to step 3.

#### 3. Creating a release with GitHub

Go to the [releases](https://github.com/Machine-Learning-for-Medical-Language/cnlp_transformers/releases)
page, and click "Draft a new release". Create a new tag with the new version
number (e.g., `v0.7.0`), and set the release title to be the same as the tag.
number preceded by a `v` (e.g. `v0.7.0`), and set the release title to be the same as the tag.
Click "Generate release notes" to automatically generate release notes from the
commit history. You can edit these release notes as necessary. When you're ready,
click "Publish release".

#### 3. Setting up your PyPI API key
#### 4. Setting up your PyPI API key

1. Log into your PyPI account

Expand All @@ -195,7 +202,7 @@ click "Publish release".
password = <the token value, including the `pypi-` prefix>
```

#### 4. Building and uploading to PyPI
#### 5. Building and uploading to PyPI

1. Checkout the commit for the new version; this will usually
be the latest commit in `main`.
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Homepage = "https://github.com/Machine-Learning-for-Medical-Language/cnlp_transf
"Bug Tracker" = "https://github.com/Machine-Learning-for-Medical-Language/cnlp_transformers/issues"

[tool.setuptools_scm]
fallback_version = "0.7.1"

[tool.setuptools.packages.find]
where = ["src"]
Expand Down
70 changes: 70 additions & 0 deletions scripts/prepare_release.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import os
import re
import subprocess
import sys

import tomllib


def validate_version_str(version_str: str):
match = re.fullmatch(r"v?(\d+)\.(\d+)\.(\d+)", version_str)
if match is None:
print(f"'{version_str}' is not a valid version string; must be 'X.Y.Z'.")
exit(1)
return ".".join(match.groups())


def get_fallback_version():
with open("pyproject.toml", "rb") as pyproject_file:
pyproject = tomllib.load(pyproject_file)

return pyproject["tool"]["setuptools_scm"]["fallback_version"]


def prepare_release_interactive(version: str):
version = validate_version_str(version)
print(f"Preparing to release {version}\n")

# Update changelog
print(
"Update the changelog:\n",
f" In CHANGELOG.md, move everything in 'Unreleased' to a new header for {version}.",
" Also feel free to add in any missing notable features included in this release.",
sep="\n",
)
input(" Press enter to continue.")
print()

# Update setuptools_scm fallback version
if get_fallback_version() != version:
print("Update the setuptools_scm fallback version:\n")
while (current := get_fallback_version()) != version:
print(
f' In pyproject.toml, under [tool.setuptools_scm], change fallback_version to "{version}" (currently "{current}")',
)
input(" Press enter to continue.")
print()

# Update lockfile
print(
"Updating lockfile and venv with `uv sync --reinstall-package cnlp_transformers`..."
)
subprocess.run(
["uv", "sync", "--reinstall-package", "cnlp_transformers"],
env=os.environ.copy() | {"SETUPTOOLS_SCM_PRETEND_VERSION": version},
)
print(
f'Done! Before committing your changes, make sure `cnlpt --version` outputs "{version}".'
)


if __name__ == "__main__":
if len(sys.argv) < 2:
print(
"Error: please provide a version for the release (e.g., `python prepare_release.py 1.2.3`)`"
)
exit(1)
elif len(sys.argv) > 2:
print("Error: too many arguments")
exit(1)
prepare_release_interactive(sys.argv[1])

0 comments on commit d64d2c1

Please sign in to comment.