diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 87fdbcdf0..8bd90ffa6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -131,6 +131,60 @@ begin contributing to to the project. 1. On GitHub, send a New pull request to the main repository's master branch. GitHub pull requests are the expected method of code collaboration on this project. +Release Process +--------------- +1. Pre-Release Steps + 1. Checkout the master branch and pull down the latest changes + ```bash + git checkout master + # Discard all local changes + git restore . + # Merge changes from upstream + git pull upstream master + ``` + 1. Build master to ensure it is in a good state and ready for release + ```bash + tox -e clean + tox + ``` + 1. Ensure no commits are made on ni/nimi-python/master until the release is complete + 1. Create and checkout a branch for release-related changes + 1. Update [CHANGELOG.md](./CHANGELOG.md) + * Delete empty (i.e. No changes) sub-sections under "Unreleased" section + * Change the "Unreleased" header to the version of the release + * Change [Unreleased] in TOC to the version of the release + * Commit to branch + 1. Update release versions + * `python3 tools/build_release.py --update --release` + * For each module, this will drop the .devN from our versions in config_addon.py and update the LATEST_RELEASE versions to match. + * Commit to branch + 1. Clean and build to update generated files with new version + * `python3 tools/build_release.py --build` + * Commit to branch + 1. Create a pull request + * It should contain all the changes made so far + * Get the pull request reviewed but DO NOT merge to master yet +1. Release Steps + 1. Wait until the pull request has been approved + 1. Upload the releases to PyPI + * `python3 tools/build_release.py --upload` + * You will need to type in your PyPI credentials + 1. Merge the pull request to origin/master + 1. Create a release on GitHub using the portion from the changelog for this release for the description + * Add the ZIP files under `generated/examples` for each module as a release artifact. +1. Post-Release Steps + 1. Create and checkout another branch for post-release changes + 1. Update the module versions + * `python3 tools/build_release.py --update` + * This will update the version to X.X.(N+1).dev0 + * Commit to branch + 1. Clean and build to update generated files with new version + * `python3 tools/build_release.py --build` + * Commit to branch + 1. Update changelog + * Copy Unreleased section from bottom of changelog to the top and add a link to it in the TOC + * Commit to branch + 1. Create a pull request containing post-release changes and get it merged Developer Certificate of Origin (DCO) ------------------------------------- diff --git a/tools/build_release.py b/tools/build_release.py index bca7ad8a7..ba2c5d90a 100644 --- a/tools/build_release.py +++ b/tools/build_release.py @@ -27,44 +27,8 @@ def main(): usage = """Release script Prereqs * Be able to build locally - * `pip install --upgrade twine tox` into whichever Python 2.7 you use to build - -Steps - * Build master to ensure it is in a good state and ready for release - * Ensure no commits are made on master until the release is complete - * Create and checkout a branch for release-related changes - * Update CHANGELOG.md - * Delete empty (i.e. No changes) sub-sections under "Unreleased" section - * Change the "Unreleased" header to the version of the release - * Change [Unreleased] in TOC to the version of the release - * Commit to branch - * Update contents of src//LATEST_RELEASE with the versions of each module being released by dropping the '.dev0' suffix. - * `python3 tools/build_release.py --update --release` - * This will update all the versions to remove any '.devN' - * Commit to branch - * `python3 tools/build_release.py --build` - * Clean and build to update generated files with new version - * Commit to branch - * Create a pull request - * It should contain all the changes made so far - * Get the pull request reviewed but DO NOT merge to master yet - * `python3 tools/build_release.py --upload` - * Upload to PyPI - you will need to type in your credentials - * Merge the pull request to origin/master - * Create a release on GitHub using the portion from the changelog for this release for the description - * Add the ZIP files under `generated/examples` for each module as a release artifact. - * Create and checkout another branch for post-release changes - * `python3 tools/build_release.py --update` - * This will update the version to X.X.(N+1).dev0 - * Commit to branch - * `python3 tools/build_release.py --build` - * Clean and Build to update generated files - * Commit to branch - * Update changelog - * Copy Unreleased section from bottom of changelog to the top and add a link to it in the TOC - * Commit to branch - * Create a pull request containing post-release changes and get it merged - + * `pip install --upgrade twine tox` into whichever Python you use to build +Steps: see "Release Process" section of CONTRIBUTING.md """ parser = argparse.ArgumentParser(description=usage, formatter_class=CustomFormatter) @@ -107,8 +71,8 @@ def main(): logging.info('Updating versions') for d in drivers_to_update: - logging.info(pp.pformat(python_cmd + ['tools/updateReleaseInfo.py', '--src-file', f'src/{d}/metadata/config_addon.py', ] + passthrough_params)) - check_call(python_cmd + ['tools/updateReleaseInfo.py', '--src-file', f'src/{d}/metadata/config_addon.py', ] + passthrough_params) + logging.info(pp.pformat(python_cmd + ['tools/updateReleaseInfo.py', '--src-folder', f'src/{d}', ] + passthrough_params)) + check_call(python_cmd + ['tools/updateReleaseInfo.py', '--src-folder', f'src/{d}', ] + passthrough_params) if args.build: logging.info('Clean and build') diff --git a/tools/updateReleaseInfo.py b/tools/updateReleaseInfo.py index 63c00558a..c5a4207f2 100644 --- a/tools/updateReleaseInfo.py +++ b/tools/updateReleaseInfo.py @@ -3,6 +3,7 @@ import argparse from configure_logging import configure_logging import logging +import os import pprint import re @@ -12,11 +13,11 @@ def main(): # Setup the required arguments for this script usage = """ -Update version when it is a dev version. I.e. X.Y.Z.devN to X.Y.Z.dev(N+1) +Update version in files. Example: X.Y.Z.devN to X.Y.Z """ parser = argparse.ArgumentParser(description=usage) file_group = parser.add_argument_group("Input and Output files") - file_group.add_argument("--src-file", action="store", required=True, help="Source file") + file_group.add_argument("--src-folder", action="store", required=True, help="Source folder") file_group.add_argument("--release", action="store_true", default=False, help="This is a release build, so only remove '.devN'. Error if not there") verbosity_group = parser.add_argument_group("Verbosity, Logging & Debugging") @@ -34,7 +35,8 @@ def main(): logging.info(pp.pformat(args)) - with open(args.src_file) as content_file: + metadata_file = os.path.join(args.src_folder, "metadata", "config_addon.py") + with open(metadata_file) as content_file: contents = content_file.read() module_dev_version_re = re.compile(r"'module_version': '(\d+\.\d+\.\d+)\.dev(\d+)'") @@ -43,6 +45,7 @@ def main(): if args.release: logging.info('Dev version found, updating {0}.dev{1} to {0}'.format(m.group(1), int(m.group(2)))) contents = module_dev_version_re.sub(f"'module_version': '{m.group(1)}'", contents) + new_version = m.group(1) else: logging.info('Dev version found, updating {0}.dev{1} to {0}.dev{2}'.format(m.group(1), int(m.group(2)), int(m.group(2)) + 1)) contents = module_dev_version_re.sub(f"'module_version': '{m.group(1)}.dev{int(m.group(2)) + 1}'", contents) @@ -54,9 +57,16 @@ def main(): contents = module_version_re.sub(f"'module_version': '{m.group(1)}{int(m.group(2)) + 1}.dev0'", contents) if not args.preview: - with open(args.src_file, 'w') as content_file: + with open(metadata_file, 'w') as content_file: content_file.write(contents) + if args.release and "nifake" not in args.src_folder: + latest_release_file = os.path.join(args.src_folder, "LATEST_RELEASE") + logging.info(f'Updating version in {latest_release_file} to {new_version}.') + if not args.preview: + with open(latest_release_file, 'w') as content_file: + content_file.write(f'{new_version}\n') + if __name__ == '__main__': main()