diff --git a/.circleci/continue_config.yml b/.circleci/continue_config.yml index b274e73878..223367058a 100644 --- a/.circleci/continue_config.yml +++ b/.circleci/continue_config.yml @@ -105,17 +105,6 @@ jobs: - run: name: Maybe merge main into develop or raise a PR command: ./tools/circleci/github_scripts/merge.sh . "main" "develop" "${GITHUB_TAGGING_TOKEN}" - - run: - name: Maybe trigger the release workflow - command: | - KEDRO_VERSION=$(./tools/circleci/github_scripts/kedro_version.py ./kedro) - if ./tools/circleci/check-no-version-pypi.sh "${KEDRO_VERSION}" - then - echo "Starting the release of Kedro ${KEDRO_VERSION}!" - ./tools/circleci/circle-release.sh github/kedro-org/kedro - else - echo "Kedro version ${KEDRO_VERSION} already exists on PyPI, skipping..." - fi merge_pr_to_develop: docker: @@ -128,41 +117,6 @@ jobs: name: Maybe merge an automatic PR into develop command: ./tools/circleci/github_scripts/attempt_merge_pr.sh "merge-main-to-develop" "develop" "${GITHUB_TAGGING_TOKEN}" - publish_kedro: - executor: - name: docker - python_version: "3.11" - steps: - - setup - - add_ssh_keys - - run: - name: Check Kedro version - command: | - KEDRO_VERSION=$(./tools/circleci/github_scripts/kedro_version.py ./kedro) - if ./tools/circleci/check-no-version-pypi.sh "${KEDRO_VERSION}" - then - echo "export KEDRO_VERSION=\"${KEDRO_VERSION}\"" >> $BASH_ENV - else - echo "Error: Kedro version ${KEDRO_VERSION} already exists on PyPI" - exit 1 - fi - - run: - name: Tag and publish release on Github - command: ./tools/circleci/github_scripts/release.sh kedro-org kedro ${GITHUB_TAGGING_TOKEN} ${KEDRO_VERSION} - - run: - name: Publish to PyPI - command: | - make package - python -m pip install twine -U - python -m twine upload --repository-url ${TWINE_REPOSITORY_URL} dist/* - - run: - name: Trigger Read The Docs build - command: | - ./tools/circleci/rtd-build.sh ${RTD_TOKEN} stable - # give some time for GitHub release to propagate - # otherwise RTD fails to build a new tag - sleep 120 - ./tools/circleci/rtd-build.sh ${RTD_TOKEN} ${KEDRO_VERSION} # Trigger kedro-viz build to ensure tests in that project pass viz_build: @@ -208,12 +162,3 @@ workflows: filters: branches: only: main - - kedro_release: - when: - and: - - <> - - not: <> - - not: <> - jobs: - - publish_kedro diff --git a/.github/workflows/check-release.yml b/.github/workflows/check-release.yml new file mode 100644 index 0000000000..726f80990b --- /dev/null +++ b/.github/workflows/check-release.yml @@ -0,0 +1,76 @@ +name: Check Kedro version and build-publish + +on: + push: + branches: + - main + +jobs: + check-version: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v3 + with: + python-version: '3.11' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install requests + - name: Check version + run: python tools/github_actions/github_actions_release.py + - name: Set outputs + id: version_check + run: | + echo "new_release=${{ env.NEW_RELEASE }}" >> $GITHUB_OUTPUT + echo "kedro_version=${{ env.KEDRO_VERSION }}" >> $GITHUB_OUTPUT + outputs: + new_release: ${{ steps.version_check.outputs.new_release }} + kedro_version: ${{ steps.version_check.outputs.kedro_version }} + + test-kedro: + needs: check-version + if: ${{ needs.check-version.outputs.new_release == 'true' }} + uses: ./.github/workflows/all-checks.yml + + build-publish: + needs: [check-version, test-kedro] + if: | + always() && + !contains(needs.*.result, 'failure') && + !contains(needs.*.result, 'cancelled') && + needs.check-version.outputs.new_release == 'true' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up Python + uses: actions/setup-python@v3 + with: + python-version: '3.11' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install build + - name: Build package + run: make package + - name: Extract release notes from RELEASE.md + id: extract + run: | + python tools/github_actions/extract_release_notes.py \ + "RELEASE.md" \ + "Release ${{needs.check-version.outputs.kedro_version}}" + - name: Create GitHub Release + uses: softprops/action-gh-release@v1 + with: + tag_name: ${{needs.check-version.outputs.kedro_version}} + name: ${{needs.check-version.outputs.kedro_version}} + body_path: release_body.txt + draft: false + prerelease: false + token: ${{ secrets.GH_TAGGING_TOKEN }} + - name: Publish distribution to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + packages-dir: dist + password: ${{ secrets.KEDRO_PYPI_TOKEN }} diff --git a/tools/circleci/check-no-version-pypi.sh b/tools/circleci/check-no-version-pypi.sh deleted file mode 100755 index 2579b33169..0000000000 --- a/tools/circleci/check-no-version-pypi.sh +++ /dev/null @@ -1,10 +0,0 @@ -KEDRO_VERSION=$1 - -PYPI_ENDPOINT="https://pypi.org/pypi/kedro/${KEDRO_VERSION}/json/" - -STATUS_CODE=$(curl --location --silent \ ---output /dev/null \ ---write-out "%{http_code}\n" \ -"${PYPI_ENDPOINT}") - -[ "${STATUS_CODE}" == "404" ] diff --git a/tools/circleci/circle-release.sh b/tools/circleci/circle-release.sh deleted file mode 100755 index ae655ffffb..0000000000 --- a/tools/circleci/circle-release.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env bash - -# Exit script if you try to use an uninitialized variable. -set -o nounset - -# Exit script if a statement returns a non-true return value. -set -o errexit - -PROJECT_SLUG=$1 -CIRCLE_ENDPOINT="https://circleci.com/api/v2/project/${PROJECT_SLUG}/pipeline" - -PAYLOAD=$(cat <<-END -{ - "branch": "${CIRCLE_BRANCH}", - "parameters": {"release_kedro": true} -} -END -) - -curl -X POST \ - --silent --show-error --fail --retry 3 \ - --output /dev/null \ - --header "Content-Type: application/json" \ - --header "Circle-Token: ${CIRCLE_RELEASE_TOKEN}" \ - --data "${PAYLOAD}" \ - "${CIRCLE_ENDPOINT}" diff --git a/tools/circleci/github_scripts/kedro_version.py b/tools/circleci/github_scripts/kedro_version.py deleted file mode 100755 index 7fade68941..0000000000 --- a/tools/circleci/github_scripts/kedro_version.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python3 -""" -Get version of Kedro -""" - -import os.path -import re -import sys -from pathlib import Path - -VERSION_MATCHSTR = r'\s*__version__\s*=\s*"(\d+\.\d+\.\d+)"' - - -def get_kedro_version(init_file_path): - match_obj = re.search(VERSION_MATCHSTR, Path(init_file_path).read_text()) - return match_obj.group(1) - - -def main(argv): - kedro_path = argv[1] - init_file_path = os.path.join(kedro_path, "__init__.py") - print(get_kedro_version(init_file_path)) - - -if __name__ == "__main__": - main(sys.argv) diff --git a/tools/circleci/github_scripts/release.sh b/tools/circleci/github_scripts/release.sh deleted file mode 100755 index 2b49880e64..0000000000 --- a/tools/circleci/github_scripts/release.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env bash - -set -eu - -GITHUB_USER=$1 -GITHUB_REPO=$2 -GITHUB_TAGGING_TOKEN=$3 -VERSION=$4 - -GITHUB_ENDPOINT="https://api.github.com/repos/${GITHUB_USER}/${GITHUB_REPO}/releases" - -PAYLOAD=$(cat <<-END -{ - "tag_name": "${VERSION}", - "target_commitish": "main", - "name": "${VERSION}", - "body": "Release ${VERSION}", - "draft": false, - "prerelease": false -} -END -) - -STATUS=$(curl -X POST \ - --output /dev/null --location --silent --write-out "%{http_code}\n" --retry 3 \ - --header "Authorization: token ${GITHUB_TAGGING_TOKEN}" \ - --header "Content-Type: application/json" \ - --data "${PAYLOAD}" \ - "${GITHUB_ENDPOINT}") - -[ "${STATUS}" == "201" ] || [ "${STATUS}" == "422" ] diff --git a/tools/github_actions/extract_release_notes.py b/tools/github_actions/extract_release_notes.py new file mode 100644 index 0000000000..a0ddc1c57f --- /dev/null +++ b/tools/github_actions/extract_release_notes.py @@ -0,0 +1,40 @@ +import sys + +ARGUMENT_COUNT = 3 + +def extract_section(filename, heading): + with open(filename) as file: + lines = file.readlines() + + start_line, end_line = None, None + + for i, line in enumerate(lines): + if line.startswith('# '): + current_heading = line.strip('#').replace(':', '').strip() + if current_heading == heading: + start_line = i + elif start_line is not None: + end_line = i + break + + if start_line is not None: + if end_line is None: + end_line = len(lines) + section_lines = lines[start_line + 1:end_line] + section = ''.join(section_lines).strip() + return section + else: + return None + + +if __name__ == '__main__': + if len(sys.argv) != ARGUMENT_COUNT: + raise Exception("Usage: python extract_release_notes.py ") + + filename = sys.argv[1] + heading = sys.argv[2] + section = extract_section(filename, heading) + if not section: + raise Exception(f"Section not found under the {heading} heading") + with open("release_body.txt", "w") as text_file: + text_file.write(section) diff --git a/tools/github_actions/github_actions_release.py b/tools/github_actions/github_actions_release.py new file mode 100755 index 0000000000..50bd076d7e --- /dev/null +++ b/tools/github_actions/github_actions_release.py @@ -0,0 +1,43 @@ +import os +import re +import sys +from pathlib import Path + +import requests + +VERSION_MATCHSTR = r'\s*__version__\s*=\s*"(\d+\.\d+\.\d+)"' +INIT_FILE_PATH = "kedro/__init__.py" +HTTP_STATUS_NOT_FOUND = 404 + +def get_package_version(): + init_file_path = Path(INIT_FILE_PATH) + match_obj = re.search(VERSION_MATCHSTR, init_file_path.read_text()) + if match_obj: + return match_obj.group(1) + + +def check_no_version_pypi(kedro_version): + pypi_endpoint = f"https://pypi.org/pypi/kedro/{kedro_version}/json/" + print(f"Check if Kedro {kedro_version} is on PyPI") + response = requests.get(pypi_endpoint, timeout=10) + if response.status_code == HTTP_STATUS_NOT_FOUND: + print(f"Starting the release of Kedro {kedro_version}") + return True + else: + print(f"Skipped: Kedro {kedro_version} already exists on PyPI") + return False + + +if __name__ == "__main__": + kedro_version = get_package_version() + new_release = check_no_version_pypi(kedro_version) + + env_file = os.getenv('GITHUB_ENV') + if env_file is not None: + with open(env_file, "a") as file: + file.write(f"NEW_RELEASE={'true' if new_release else 'false'}\n") + if new_release: + file.write(f"KEDRO_VERSION={kedro_version}\n") + else: + print("Error: GITHUB_ENV environment variable is not set.") + sys.exit()