CI: Enable autorelease by schedule

This commit is contained in:
Max Kainov 2024-12-17 14:52:02 +01:00
parent 92a504fb6a
commit a65468da06
4 changed files with 72 additions and 30 deletions

View File

@ -7,8 +7,8 @@ concurrency:
group: autoreleases
on:
# schedule:
# - cron: '0 9 * * *'
schedule:
- cron: '45 11 * * 2,4'
workflow_dispatch:
inputs:
dry-run:
@ -52,7 +52,7 @@ jobs:
echo 'EOF'
} >> "$GITHUB_OUTPUT"
if [[ "${{ github.event_name }}" == "schedule" ]]; then
echo "DRY_RUN=true" >> "$GITHUB_OUTPUT"
echo "DRY_RUN=false" >> "$GITHUB_OUTPUT"
else
echo "DRY_RUN=${{ github.event.inputs.dry-run }}" >> "$GITHUB_OUTPUT"
fi

View File

@ -44,7 +44,7 @@ def parse_args():
return parser.parse_args(), parser
MAX_NUMBER_OF_COMMITS_TO_CONSIDER_FOR_RELEASE = 5
MAX_NUMBER_OF_COMMITS_TO_CONSIDER_FOR_RELEASE = 8
AUTORELEASE_INFO_FILE = "/tmp/autorelease_info.json"
AUTORELEASE_MATRIX_PARAMS = "/tmp/autorelease_params.json"
@ -58,6 +58,7 @@ class ReleaseParams:
commit_sha: str
commits_to_branch_head: int
latest: bool
description: str = ""
def to_dict(self):
return dataclasses.asdict(self)
@ -96,6 +97,16 @@ def _prepare(token):
os.environ["GH_TOKEN"] = token
Shell.check("gh auth status")
# Check all previous version bump prs were merged
open_version_change_prs = Shell.get_output(
'gh pr list --state open --search "Update version_date.tsv" --json number,title'
)
if open_version_change_prs != "[]":
CIBuddy(dry_run=False).post_critical(
"Found not merged version bump PRs", body=open_version_change_prs
)
raise RuntimeError()
gh = GitHub(token)
prs = gh.get_release_pulls(GITHUB_REPOSITORY)
prs.sort(key=lambda x: x.head.ref)
@ -131,6 +142,7 @@ def _prepare(token):
commit_ci_status = ""
commits_to_branch_head = 0
description = ""
for idx, commit in enumerate(
commits_to_check[:MAX_NUMBER_OF_COMMITS_TO_CONSIDER_FOR_RELEASE]
):
@ -145,34 +157,14 @@ def _prepare(token):
commits_to_branch_head += 1
continue
# TODO: switch to check if CI is entirely green
statuses = [
CI.GH.get_commit_status_by_name(
token=token,
commit_sha=commit,
# handle old name for old releases
status_name=(CI.JobNames.BUILD_CHECK, "ClickHouse build check"),
),
CI.GH.get_commit_status_by_name(
token=token,
commit_sha=commit,
# handle old name for old releases
status_name=CI.JobNames.STATELESS_TEST_RELEASE,
),
CI.GH.get_commit_status_by_name(
token=token,
commit_sha=commit,
# handle old name for old releases
status_name=CI.JobNames.STATEFUL_TEST_RELEASE,
),
]
commit_sha = commit
if any(status == SUCCESS for status in statuses):
failed_jobs = CI.GH.get_failed_statuses(token=token, commit_sha=commit_sha)
if not failed_jobs:
commit_ci_status = SUCCESS
break
print(f"CI status [{statuses}] - skip")
commits_to_branch_head += 1
else:
# add failed jobs from most recent ready commit to the release info description to post it in alert
description = f"Failed jobs: {failed_jobs}"
break
ready = False
if commit_ci_status == SUCCESS and commit_sha:
@ -192,6 +184,7 @@ def _prepare(token):
num_patches=commit_num,
commits_to_branch_head=commits_to_branch_head,
latest=False,
description=description if not ready else "",
)
)

View File

@ -160,6 +160,54 @@ class GH:
return ""
@staticmethod
def get_failed_statuses(token: str, commit_sha: str) -> Optional[List]:
assert len(token) == 40
assert len(commit_sha) == 40
assert Utils.is_hex(commit_sha)
assert not Utils.is_hex(token)
status_dict = {} # type: Dict[str, Dict]
url = f"https://api.github.com/repos/{Envs.GITHUB_REPOSITORY}/commits/{commit_sha}/statuses"
headers = {
"Authorization": f"token {token}",
"Accept": "application/vnd.github.v3+json",
}
while url:
response = requests.get(url, headers=headers, timeout=5)
if response.status_code == 200:
statuses = response.json()
for status in statuses:
context = status["context"]
updated_at = status["updated_at"]
state = status["state"]
# Update if context is new or timestamp is newer
if (
context not in status_dict
or status_dict[context]["updated_at"] < updated_at
):
status_dict[context] = {
"state": state,
"updated_at": updated_at,
}
else:
print("ERROR: Failed to get CI statuses")
return None
# Check if there is a next page
url = response.links.get("next", {}).get("url", "")
# Collect failed statuses
failed_statuses = [
context
for context, data in status_dict.items()
if data["state"] not in (GH.ActionStatuses.SUCCESS,)
]
return failed_statuses
@staticmethod
def check_wf_completed(token: str, commit_sha: str) -> bool:
headers = {

View File

@ -80,6 +80,7 @@ class ClickHouseVersion:
self._tweak = 1
else:
self._major += 1
self._minor = 1
self._revision += 1
self._patch = 1
self._tweak = 1