-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
186 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
# This workflow is triggered when a PR is merged whose source branch's name starts with "release" and whose target branch is "main". | ||
# It checks for the current package version (in pyproject.toml) and the latest tag on GitHub. | ||
# If package version is more recent, it builds the project, uploads to PYPI, creates a Tag and makes a release on GitHub. | ||
# Secrets PYPI_USERNAME and PYPI_PASSWORD are required! | ||
|
||
name: Check and release | ||
on: | ||
pull_request: | ||
branches: [main] | ||
types: [closed] | ||
|
||
jobs: | ||
build: | ||
defaults: | ||
run: | ||
shell: bash | ||
working-directory: ./python | ||
|
||
if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release') | ||
runs-on: ubuntu-latest | ||
steps: | ||
|
||
- name: Checkout Repo | ||
uses: actions/checkout@v3 | ||
|
||
- name: Setup Python | ||
uses: actions/setup-python@v4 | ||
with: | ||
python-version: '3.11' | ||
|
||
- name: Install Poetry | ||
run: | | ||
export POETRY_HOME=/opt/poetry | ||
python3 -m venv $POETRY_HOME | ||
$POETRY_HOME/bin/pip install poetry==1.4.0 | ||
$POETRY_HOME/bin/poetry --version | ||
- name: Run release script | ||
env: | ||
PYPI_USERNAME: __token__ | ||
PYPI_PASSWORD: ${{secrets.FETCHBOT_PYPI_TOKEN}} | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
GH_TOKEN: ${{ github.token }} | ||
run: | | ||
pip install tomli packaging poetry | ||
git config --global user.email "ci-bot@fetch.ai" | ||
git config --global user.name "CI BOT" | ||
python3 ./scripts/do_release.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
"""Release automation script.""" | ||
|
||
import os | ||
import subprocess | ||
import sys | ||
from pathlib import Path | ||
|
||
import tomli | ||
from packaging.version import Version | ||
|
||
|
||
ROOT = Path(__file__).parent.parent | ||
|
||
|
||
class EnvCredentials: | ||
"""Credentials from env variables.""" | ||
|
||
@property | ||
def pypi_username(self) -> str: | ||
"""Get PYPI username.""" | ||
return os.environ.get("PYPI_USERNAME") or "" | ||
|
||
@property | ||
def pypi_password(self) -> str: | ||
"""Get PYPI password.""" | ||
return os.environ.get("PYPI_PASSWORD") or "" | ||
|
||
|
||
def get_the_latest_release_version() -> Version: | ||
"""Get release version from gihtub tags.""" | ||
text = subprocess.check_output("git ls-remote --tags origin", shell=True, text=True) | ||
tags = [i.split("\t")[1].strip() for i in text.splitlines()] | ||
tags = [i for i in tags if i.startswith("refs/tags/v") and not i.endswith("^{}")] | ||
versions = [i.replace("refs/tags/v", "") for i in tags] | ||
return Version(versions[-1]) | ||
|
||
|
||
def get_current_version() -> Version: | ||
"""Get current code version.""" | ||
text = (ROOT / "pyproject.toml").read_text() | ||
version = tomli.loads(text)["tool"]["poetry"]["version"] | ||
return Version(version) | ||
|
||
|
||
def do_we_need_to_release() -> bool: | ||
"""Check is code version is newer than on github.""" | ||
current_version = get_current_version() | ||
released_version = get_the_latest_release_version() | ||
return current_version > released_version | ||
|
||
|
||
def make_tag(current_version: Version) -> None: | ||
"""Make git tag.""" | ||
subprocess.check_call( | ||
f"git tag v{current_version} -m 'Release {current_version}'", shell=True | ||
) | ||
|
||
|
||
def push_tag(current_version) -> None: | ||
"""Push tag to github.""" | ||
subprocess.check_call(f"git push origin v{current_version}", shell=True) | ||
|
||
|
||
def make_release(current_version: Version) -> None: | ||
"""Make release on Github.""" | ||
subprocess.check_call( | ||
f"""gh release create v{current_version} --title "v{current_version}" | ||
--generate-notes""", | ||
shell=True, | ||
) | ||
|
||
|
||
def build_packages(): | ||
"""Build packages.""" | ||
subprocess.check_call("poetry build", shell=True) | ||
|
||
|
||
class ReleaseTool: | ||
"""Release helper tool.""" | ||
|
||
def __init__(self, credentials: EnvCredentials) -> None: | ||
"""Init release tool instance.""" | ||
self._credentials = credentials | ||
|
||
def upload_packages(self): | ||
"""Upload packages to PYPI.""" | ||
result = subprocess.run( | ||
f"poetry publish --skip-existing --username {self._credentials.pypi_username} " | ||
f"--password {self._credentials.pypi_password} --verbose", | ||
check=True, | ||
shell=True, | ||
stdout=sys.stdout, | ||
stderr=sys.stderr, | ||
) | ||
if result.returncode != 0: | ||
raise RuntimeError("Upload pacakges failed!") | ||
|
||
def main(self): | ||
"""Run release process.""" | ||
current_version = get_current_version() | ||
latest_release_version = get_the_latest_release_version() | ||
|
||
print("Current version:", current_version) | ||
print("Latest release version:", latest_release_version) | ||
|
||
if current_version > latest_release_version: | ||
print("Current version is newer. Good to go.") | ||
else: | ||
print("Current version is not newer. Exiting.") | ||
return | ||
|
||
print("\nBuilding packages") | ||
build_packages() | ||
print("Packages built") | ||
|
||
print("\nUpload packages") | ||
self.upload_packages() | ||
print("Packages uploaded") | ||
|
||
print("\nMake tag") | ||
make_tag(current_version) | ||
print("Tag made") | ||
|
||
print("\nPush tag") | ||
push_tag(current_version) | ||
print("Tag pushed") | ||
|
||
print("\nMake release") | ||
make_release(current_version) | ||
print("Release made." "") | ||
|
||
print("\nDONE") | ||
|
||
|
||
if __name__ == "__main__": | ||
creds = EnvCredentials() | ||
ReleaseTool(creds).main() |