From 1db19bc405ecfc95920b148c65e7d70b33e5dda6 Mon Sep 17 00:00:00 2001 From: Asad Hasan Date: Tue, 27 Aug 2024 10:53:14 +0100 Subject: [PATCH] ENG-1235: Push release tags automatically on `rasa-sdk` (#1139) * ENG-1235: Create and push release tags automatically * ENG-1235: Fixed tag-done message * ENG-1235: Added more info to module docstring, about release tagging * ENG-1235: Increased docstring info * ENG-1235: Updated readme/docs accordingly * ENG-1235: Address PR feedback, to not generate changelog on Dev versions either --- .github/workflows/tag-release.yml | 71 +++++++++++++++++++ Makefile | 3 + README.md | 10 +-- scripts/release.py | 112 ++++++++++++++++++++++++------ 4 files changed, 164 insertions(+), 32 deletions(-) create mode 100644 .github/workflows/tag-release.yml diff --git a/.github/workflows/tag-release.yml b/.github/workflows/tag-release.yml new file mode 100644 index 000000000..5394b73d5 --- /dev/null +++ b/.github/workflows/tag-release.yml @@ -0,0 +1,71 @@ +name: Tag Release Version +on: + pull_request: + branches: + - main + - '[0-9]+.[0-9]+.x' + types: [closed] + +env: + COMMIT_EMAIL: sara-tagger@users.noreply.github.com + DEFAULT_PYTHON_VERSION: "3.10" + +jobs: + if_merged_tag_release: + name: Tag Release Version + if: startsWith(github.head_ref, 'prepare-release-') && github.event.pull_request.merged == true + runs-on: ubuntu-22.04 + steps: + - name: Checkout git repository 🕝 + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4 + with: + token: ${{ secrets.RELEASE_TAGGER_PAT }} + + - name: Set up Python ${{ env.DEFAULT_PYTHON_VERSION }} 🐍 + uses: actions/setup-python@0a5c61591373683505ea898e09a3ea4f39ef2b9c # v5.0.0 + with: + python-version: ${{ env.DEFAULT_PYTHON_VERSION }} + + - name: Read Poetry Version 🔢 + run: | + echo "POETRY_VERSION=$(scripts/poetry-version.sh)" >> $GITHUB_ENV + shell: bash + + - name: Install poetry 🦄 + uses: Gr1N/setup-poetry@15821dc8a61bc630db542ae4baf6a7c19a994844 # v8 + with: + poetry-version: ${{ env.POETRY_VERSION }} + + - name: Load Poetry Cached Libraries ⬇ + id: cache-poetry + uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0 + with: + path: .venv + key: ${{ runner.os }}-poetry-${{ env.POETRY_VERSION }}-${{ env.DEFAULT_PYTHON_VERSION }}-${{ hashFiles('**/poetry.lock') }}-${{ secrets.POETRY_CACHE_VERSION }} + restore-keys: ${{ runner.os }}-poetry-${{ env.DEFAULT_PYTHON_VERSION }} + + - name: Clear Poetry cache + if: steps.cache-poetry.outputs.cache-hit == 'true' && contains(github.event.pull_request.labels.*.name, 'tools:clear-poetry-cache-unit-tests') + run: rm -r .venv + + - name: Create virtual environment + if: steps.cache-poetry.outputs.cache-hit != 'true' || contains(github.event.pull_request.labels.*.name, 'tools:clear-poetry-cache-unit-tests') + run: python -m venv create .venv + + - name: Set up virtual environment + run: poetry config virtualenvs.in-project true + + - name: Install Dependencies 📦 + # Poetry intermittently fails to install dependency if it is not PEP 517 compliant + # This is a workaround for that issue + run: | + sudo apt-get -y install libpq-dev + make install-full + + - name: Configure git + run: | + git config --global user.email ${{ env.COMMIT_EMAIL }} + git config --global user.name "Github Actions" + + - name: Tag Release + run: make tag-release diff --git a/Makefile b/Makefile index cd36690b2..0adad188b 100644 --- a/Makefile +++ b/Makefile @@ -104,6 +104,9 @@ cleanup-generated-changelog: ## cleanup the generated changelog release: ## start the release process poetry run python scripts/release.py +tag-release: ## Tag a release. + poetry run python scripts/release.py --tag + generate-grpc: ## generate grpc code poetry run python -m grpc_tools.protoc \ -Irasa_sdk/grpc_py=./proto \ diff --git a/README.md b/README.md index 004b45f3e..a33ad68cc 100644 --- a/README.md +++ b/README.md @@ -129,15 +129,7 @@ by GitHub Actions. 2. If this is a minor / major release: Make sure all fixes from currently supported minor versions have been merged from their respective release branches (e.g. 3.3.x) back into main. 3. Run `make release` 4. Create a PR against main or the release branch (e.g. `1.2.x`) -5. Once your PR is merged, pull the release branch locally. -6. Create a tag for a new release (this SHOULD always happen on `main` or release branches), e.g. using - ```bash - git tag 1.2.0 -m "next release" - git push origin 1.2.0 - ``` - GitHub Actions will build this tag and push a package to - [pypi](https://pypi.python.org/pypi/rasa-sdk). -6. **If this is a minor release**, a new release branch should be created +5. **If this is a minor release**, a new release branch should be created pointing to the same commit as the tag to allow for future patch releases, e.g. ```bash diff --git a/scripts/release.py b/scripts/release.py index 6e7010cfe..65869a23c 100644 --- a/scripts/release.py +++ b/scripts/release.py @@ -3,7 +3,12 @@ - creates a new changelog section in CHANGELOG.mdx based on all collected changes - increases the version number - pushes the new branch to GitHub + +When run with `--tag`: +- tags the current commit with the version number found in the version module +- and pushes the tag to GitHub. """ + import argparse import os import re @@ -32,12 +37,15 @@ def create_argument_parser() -> argparse.ArgumentParser: """Parse all the command line arguments for the release script.""" - parser = argparse.ArgumentParser(description="prepare the next library release") + parser = argparse.ArgumentParser( + description="Prepare or tag the next library release" + ) parser.add_argument( "--next_version", type=str, help="Either next version number or 'major', 'minor', 'micro', 'alpha', 'rc'", ) + parser.add_argument("--tag", help="Tag the next release", action="store_true") return parser @@ -284,39 +292,97 @@ def print_done_message_same_branch(version: Version) -> None: ) -def main(args: argparse.Namespace) -> None: - """Start a release preparation.""" +def tag_commit(tag: Text) -> None: + """Tags a git commit.""" + print(f"Applying tag '{tag}' to commit.") + check_call(["git", "tag", tag, "-m", "next release"]) + + +def push_tag(tag: Text) -> None: + """Pushes a tag to the remote.""" + print(f"Pushing tag '{tag}' to origin.") + check_call(["git", "push", "origin", tag, "--tags"]) + +def print_tag_release_done_message(version: Version) -> None: + """Print final information for the user about the tagged commit.""" + print() + print( + f"\033[94m All done - tag for version {version} " + "was added and pushed to the remote \033[0m" + ) + + +def tag_release() -> None: + """Tag the current commit with the current version.""" print( - "The release script will increase the version number, " - "create a changelog and create a release branch. Let's go!" + """ + The release tag script will tag the current commit with the current version. + + This should be done on the applicable *.x branch after running + `make release` and merging the prepared release branch. + """ ) + branch = git_current_branch() + version = Version(get_current_version()) + + if ( + not version.is_alpha + and not version.is_beta + and not git_current_branch_is_main_or_release() + ): + print( + f""" + You are currently on branch {branch}. + You should only apply release tags to release branches (e.g. 1.x) or main. + """ + ) + sys.exit(1) ensure_clean_git() - version = next_version(args) - confirm_version(version) + tag = str(version) + tag_commit(tag) + push_tag(tag) + + print_tag_release_done_message(version) - write_version_file(version) - write_version_to_pyproject(version) - if not version.pre: - # never update changelog on a prerelease version - generate_changelog(version) +def main(args: argparse.Namespace) -> None: + """Start a release preparation, or tag release.""" - # alpha workflow on feature branch when a version bump is required - if version.is_alpha and not git_current_branch_is_main_or_release(): - create_commit(version) - push_changes() + if not args.tag: + print( + "The release script will increase the version number, " + "create a changelog and create a release branch. Let's go!" + ) - print_done_message_same_branch(version) - else: - base = git_current_branch() - branch = create_release_branch(version) + ensure_clean_git() + version = next_version(args) + confirm_version(version) - create_commit(version) - push_changes() + write_version_file(version) + write_version_to_pyproject(version) - print_done_message(branch, base, version) + if not version.pre and not version.dev: + # never update changelog on a prerelease or Dev version + generate_changelog(version) + + # alpha workflow on feature branch when a version bump is required + if version.is_alpha and not git_current_branch_is_main_or_release(): + create_commit(version) + push_changes() + + print_done_message_same_branch(version) + else: + base = git_current_branch() + branch = create_release_branch(version) + + create_commit(version) + push_changes() + + print_done_message(branch, base, version) + else: + tag_release() if __name__ == "__main__":