Allow release only from ready commits

This commit is contained in:
Mikhail f. Shiryaev 2022-11-07 21:30:41 +01:00
parent 64e6a00f94
commit c12c1cdf9b
No known key found for this signature in database
GPG Key ID: 4B02ED204C7D93F4

View File

@ -1,5 +1,14 @@
#!/usr/bin/env python
"""
script to create releases for ClickHouse
The `gh` CLI prefered over the PyGithub to have an easy way to rollback bad
release in command line by simple execution giving rollback commands
On another hand, PyGithub is used for convenient getting commit's status from API
"""
from contextlib import contextmanager
from typing import List, Optional
@ -8,6 +17,8 @@ import logging
import subprocess
from git_helper import commit, release_branch
from github_helper import GitHub
from mark_release_ready import RELEASE_READY_STATUS
from version_helper import (
FILE_WITH_VERSION_PATH,
GENERATED_CONTRIBUTORS,
@ -67,12 +78,12 @@ class Release:
self._release_branch = ""
self._rollback_stack = [] # type: List[str]
def run(self, cmd: str, cwd: Optional[str] = None) -> str:
def run(self, cmd: str, cwd: Optional[str] = None, **kwargs) -> str:
cwd_text = ""
if cwd:
cwd_text = f" (CWD='{cwd}')"
logging.info("Running command%s:\n %s", cwd_text, cmd)
return self._git.run(cmd, cwd)
return self._git.run(cmd, cwd, **kwargs)
def set_release_branch(self):
# Fetch release commit in case it does not exist locally
@ -94,6 +105,38 @@ class Release:
return VersionType.LTS
return VersionType.STABLE
def check_commit_release_ready(self):
# First, get the auth token from gh cli
auth_status = self.run(
"gh auth status -t", stderr=subprocess.STDOUT
).splitlines()
token = ""
for line in auth_status:
if "✓ Token:" in line:
token = line.split()[-1]
if not token:
logging.error("Can not extract token from `gh auth`")
raise subprocess.SubprocessError("Can not extract token from `gh auth`")
gh = GitHub(token, per_page=100)
repo = gh.get_repo(str(self.repo))
# Statuses are ordered by descending updated_at, so the first necessary
# status in the list is the most recent
statuses = repo.get_commit(self.release_commit).get_statuses()
for status in statuses:
if status.context == RELEASE_READY_STATUS:
if status.state == "success":
return
raise Exception(
f"the status {RELEASE_READY_STATUS} is {status.state}, not success"
)
raise Exception(
f"the status {RELEASE_READY_STATUS} "
f"is not found for commit {self.release_commit}"
)
def check_prerequisites(self):
"""
Check tooling installed in the system, `git` is checked by Git() init
@ -108,6 +151,8 @@ class Release:
)
raise
self.check_commit_release_ready()
def do(self, check_dirty: bool, check_branch: bool, with_release_branch: bool):
self.check_prerequisites()