CI: New Release workflow updates and fixes

This commit is contained in:
Max K 2024-07-21 17:44:32 +02:00
parent 08db9fb8f1
commit dd9fe61d1a
4 changed files with 87 additions and 65 deletions

View File

@ -62,8 +62,8 @@ runs:
if: ${{ inputs.type == 'patch' }}
shell: bash
run: |
python3 ./tests/ci/create_release.py --set-progress-started --progress "update ChangeLog"
[ "$(git branch --show-current)" != "master" ] && echo "not on the master" && exit 1
git checkout master
python3 ./tests/ci/create_release.py --set-progress-started --progress "update changelog, docker version, security"
echo "List versions"
./utils/list-versions/list-versions.sh > ./utils/list-versions/version_date.tsv
echo "Update docker version"
@ -96,17 +96,13 @@ runs:
Update version_date.tsv and changelogs after ${{ env.RELEASE_TAG }}
### Changelog category (leave one):
- Not for changelog (changelog entry is not required)
- name: Reset changes if Dry-run
if: ${{ inputs.dry-run }}
- name: Complete previous steps and Restore git state
if: ${{ inputs.type == 'patch' }}
shell: bash
run: |
git reset --hard HEAD
- name: Checkout back to GITHUB_REF
shell: bash
run: |
git checkout "$GITHUB_REF_NAME"
# set current progress to OK
python3 ./tests/ci/create_release.py --set-progress-completed
git reset --hard HEAD
git checkout "$GITHUB_REF_NAME"
- name: Create GH Release
shell: bash
if: ${{ inputs.type == 'patch' }}
@ -146,24 +142,23 @@ runs:
if: ${{ inputs.type == 'patch' }}
shell: bash
run: |
python3 ./tests/ci/create_release.py --set-progress-started --progress "docker server release"
cd "./tests/ci"
python3 ./create_release.py --set-progress-started --progress "docker server release"
export CHECK_NAME="Docker server image"
python3 docker_server.py --release-type auto --version ${{ env.RELEASE_TAG }} --check-name "$CHECK_NAME" --sha ${{ env.COMMIT_SHA }} ${{ ! inputs.dry-run && '--push' || '' }}
python3 ./tests/ci/create_release.py --set-progress-completed
python3 ./create_release.py --set-progress-completed
- name: Docker clickhouse/clickhouse-keeper building
if: ${{ inputs.type == 'patch' }}
shell: bash
run: |
python3 ./tests/ci/create_release.py --set-progress-started --progress "docker keeper release"
cd "./tests/ci"
python3 ./create_release.py --set-progress-started --progress "docker keeper release"
export CHECK_NAME="Docker keeper image"
python3 docker_server.py --release-type auto --version ${{ env.RELEASE_TAG }} --check-name "$CHECK_NAME" --sha ${{ env.COMMIT_SHA }} ${{ ! inputs.dry-run && '--push' || '' }}
python3 ./tests/ci/create_release.py --set-progress-completed
- name: Set Release progress completed
python3 ./create_release.py --set-progress-completed
- name: Set current Release progress to Completed with OK
shell: bash
run: |
# If we here - set completed status, to post proper Slack OK or FAIL message in the next step
python3 ./tests/ci/create_release.py --set-progress-started --progress "completed"
python3 ./tests/ci/create_release.py --set-progress-completed
- name: Post Slack Message

View File

@ -43,7 +43,6 @@ class R2MountPoint:
self.bucket_name = self._PROD_BUCKET_NAME
self.aux_mount_options = ""
self.async_mount = False
if self.app == MountPointApp.S3FS:
self.cache_dir = "/home/ubuntu/s3fs_cache"
# self.aux_mount_options += "-o nomodtime " if self.NOMODTIME else "" not for s3fs
@ -57,7 +56,6 @@ class R2MountPoint:
self.mount_cmd = f"s3fs {self.bucket_name} {self.MOUNT_POINT} -o url={self.API_ENDPOINT} -o use_path_request_style -o umask=0000 -o nomultipart -o logfile={self.LOG_FILE} {self.aux_mount_options}"
elif self.app == MountPointApp.RCLONE:
# run rclone mount process asynchronously, otherwise subprocess.run(daemonized command) will not return
self.async_mount = True
self.cache_dir = "/home/ubuntu/rclone_cache"
self.aux_mount_options += "--no-modtime " if self.NOMODTIME else ""
self.aux_mount_options += "-v " if self.DEBUG else "" # -vv too verbose
@ -85,10 +83,12 @@ class R2MountPoint:
Shell.run(_UNMOUNT_CMD)
Shell.run(_MKDIR_CMD)
Shell.run(_MKDIR_FOR_CACHE)
# didn't manage to use simple run() and not block or fail
Shell.run_as_daemon(self.mount_cmd)
if self.async_mount:
time.sleep(3)
if self.app == MountPointApp.S3FS:
Shell.run(self.mount_cmd, check=True)
else:
# didn't manage to use simple run() and without blocking or failure
Shell.run_as_daemon(self.mount_cmd)
time.sleep(3)
Shell.run(_TEST_MOUNT_CMD, check=True)
@classmethod
@ -107,6 +107,7 @@ class DebianArtifactory:
_PROD_REPO_URL = "https://packages.clickhouse.com/deb"
def __init__(self, release_info: ReleaseInfo, dry_run: bool):
self.release_info = release_info
self.codename = release_info.codename
self.version = release_info.version
if dry_run:
@ -154,9 +155,8 @@ class DebianArtifactory:
print("Running test command:")
print(f" {cmd}")
Shell.run(cmd, check=True)
release_info = ReleaseInfo.from_file()
release_info.debian_command = debian_command
release_info.dump()
self.release_info.debian_command = debian_command
self.release_info.dump()
def _copy_if_not_exists(src: Path, dst: Path) -> Path:
@ -177,6 +177,7 @@ class RpmArtifactory:
_SIGN_KEY = "885E2BDCF96B0B45ABF058453E4AD4719DDE9A38"
def __init__(self, release_info: ReleaseInfo, dry_run: bool):
self.release_info = release_info
self.codename = release_info.codename
self.version = release_info.version
if dry_run:
@ -230,9 +231,8 @@ class RpmArtifactory:
print("Running test command:")
print(f" {cmd}")
Shell.run(cmd, check=True)
release_info = ReleaseInfo.from_file()
release_info.rpm_command = rpm_command
release_info.dump()
self.release_info.rpm_command = rpm_command
self.release_info.dump()
class TgzArtifactory:
@ -240,6 +240,7 @@ class TgzArtifactory:
_PROD_REPO_URL = "https://packages.clickhouse.com/tgz"
def __init__(self, release_info: ReleaseInfo, dry_run: bool):
self.release_info = release_info
self.codename = release_info.codename
self.version = release_info.version
if dry_run:
@ -290,9 +291,8 @@ class TgzArtifactory:
expected_checksum == actual_checksum
), f"[{actual_checksum} != {expected_checksum}]"
Shell.run("rm /tmp/tmp.tgz*")
release_info = ReleaseInfo.from_file()
release_info.tgz_command = cmd
release_info.dump()
self.release_info.tgz_command = cmd
self.release_info.dump()
def parse_args() -> argparse.Namespace:
@ -340,9 +340,7 @@ def parse_args() -> argparse.Namespace:
if __name__ == "__main__":
args = parse_args()
assert args.dry_run
release_info = ReleaseInfo.from_file()
"""
Use S3FS. RCLONE has some errors with r2 remote which I didn't figure out how to resolve:
ERROR : IO error: NotImplemented: versionId not implemented
@ -350,26 +348,38 @@ if __name__ == "__main__":
"""
mp = R2MountPoint(MountPointApp.S3FS, dry_run=args.dry_run)
if args.export_debian:
with ReleaseContextManager(release_progress=ReleaseProgress.EXPORT_DEB) as _:
with ReleaseContextManager(
release_progress=ReleaseProgress.EXPORT_DEB
) as release_info:
mp.init()
DebianArtifactory(release_info, dry_run=args.dry_run).export_packages()
mp.teardown()
if args.export_rpm:
with ReleaseContextManager(release_progress=ReleaseProgress.EXPORT_RPM) as _:
with ReleaseContextManager(
release_progress=ReleaseProgress.EXPORT_RPM
) as release_info:
mp.init()
RpmArtifactory(release_info, dry_run=args.dry_run).export_packages()
mp.teardown()
if args.export_tgz:
with ReleaseContextManager(release_progress=ReleaseProgress.EXPORT_TGZ) as _:
with ReleaseContextManager(
release_progress=ReleaseProgress.EXPORT_TGZ
) as release_info:
mp.init()
TgzArtifactory(release_info, dry_run=args.dry_run).export_packages()
mp.teardown()
if args.test_debian:
with ReleaseContextManager(release_progress=ReleaseProgress.TEST_DEB) as _:
with ReleaseContextManager(
release_progress=ReleaseProgress.TEST_DEB
) as release_info:
DebianArtifactory(release_info, dry_run=args.dry_run).test_packages()
if args.test_tgz:
with ReleaseContextManager(release_progress=ReleaseProgress.TEST_TGZ) as _:
with ReleaseContextManager(
release_progress=ReleaseProgress.TEST_TGZ
) as release_info:
TgzArtifactory(release_info, dry_run=args.dry_run).test_packages()
if args.test_rpm:
with ReleaseContextManager(release_progress=ReleaseProgress.TEST_RPM) as _:
with ReleaseContextManager(
release_progress=ReleaseProgress.TEST_RPM
) as release_info:
RpmArtifactory(release_info, dry_run=args.dry_run).test_packages()

View File

@ -182,10 +182,11 @@ class Shell:
check=False,
)
if result.returncode == 0:
print(f"stdout: {result.stdout.strip()}")
res = result.stdout
else:
print(
f"ERROR: stdout {result.stdout.strip()}, stderr {result.stderr.strip()}"
f"ERROR: stdout: {result.stdout.strip()}, stderr: {result.stderr.strip()}"
)
if check:
assert result.returncode == 0

View File

@ -43,6 +43,7 @@ class ReleaseProgress:
TEST_TGZ = "test TGZ packages"
TEST_RPM = "test RPM packages"
TEST_DEB = "test DEB packages"
COMPLETED = "completed"
class ReleaseProgressDescription:
@ -108,6 +109,12 @@ class ReleaseInfo:
release_progress: str = ""
progress_description: str = ""
def is_patch(self):
return self.release_branch != "master"
def is_new_release_branch(self):
return self.release_branch == "master"
@staticmethod
def from_file() -> "ReleaseInfo":
with open(RELEASE_INFO_FILE, "r", encoding="utf-8") as json_file:
@ -126,12 +133,12 @@ class ReleaseInfo:
release_tag = None
previous_release_tag = None
previous_release_sha = None
codename = None
codename = ""
assert release_type in ("patch", "new")
if release_type == "new":
# check commit_ref is right and on a right branch
Shell.run(
f"git merge-base --is-ancestor origin/{commit_ref} origin/master",
f"git merge-base --is-ancestor {commit_ref} origin/master",
check=True,
)
with checkout(commit_ref):
@ -146,9 +153,6 @@ class ReleaseInfo:
git.latest_tag == expected_prev_tag
), f"BUG: latest tag [{git.latest_tag}], expected [{expected_prev_tag}]"
release_tag = version.describe
codename = (
VersionType.STABLE
) # dummy value (artifactory won't be updated for new release)
previous_release_tag = expected_prev_tag
previous_release_sha = Shell.run_strict(
f"git rev-parse {previous_release_tag}"
@ -205,7 +209,7 @@ class ReleaseInfo:
and commit_sha
and release_tag
and version
and codename in ("lts", "stable")
and (codename in ("lts", "stable") or release_type == "new")
)
self.release_branch = release_branch
@ -320,24 +324,27 @@ class ReleaseInfo:
Shell.run(
f"{GIT_PREFIX} checkout '{CMAKE_PATH}' '{CONTRIBUTORS_PATH}'"
)
self.version_bump_pr = GHActions.get_pr_url_by_branch(
repo=GITHUB_REPOSITORY, branch=branch_upd_version_contributors
)
self.version_bump_pr = "dry-run"
else:
self.version_bump_pr = GHActions.get_pr_url_by_branch(
repo=GITHUB_REPOSITORY, branch=branch_upd_version_contributors
)
def update_release_info(self, dry_run: bool) -> "ReleaseInfo":
branch = f"auto/{release_info.release_tag}"
if not dry_run:
url = GHActions.get_pr_url_by_branch(repo=GITHUB_REPOSITORY, branch=branch)
else:
url = "dry-run"
print(f"ChangeLog PR url [{url}]")
self.changelog_pr = url
print(f"Release url [{url}]")
self.release_url = (
f"https://github.com/{GITHUB_REPOSITORY}/releases/tag/{self.release_tag}"
)
self.docker_command = f"docker run --rm clickhouse/clickhouse:{self.release_branch} clickhouse --version"
if self.release_branch != "master":
branch = f"auto/{release_info.release_tag}"
if not dry_run:
url = GHActions.get_pr_url_by_branch(
repo=GITHUB_REPOSITORY, branch=branch
)
else:
url = "dry-run"
print(f"ChangeLog PR url [{url}]")
self.changelog_pr = url
print(f"Release url [{url}]")
self.release_url = f"https://github.com/{GITHUB_REPOSITORY}/releases/tag/{self.release_tag}"
if self.release_progress == ReleaseProgress.COMPLETED:
self.docker_command = f"docker run --rm clickhouse/clickhouse:{self.version} clickhouse --version"
self.dump()
return self
@ -712,13 +719,22 @@ if __name__ == "__main__":
if args.post_status:
release_info = ReleaseInfo.from_file()
release_info.update_release_info(dry_run=args.dry_run)
if release_info.debian_command:
if release_info.is_new_release_branch():
title = "New release branch"
else:
title = "New release"
if (
release_info.progress_description == ReleaseProgressDescription.OK
and release_info.release_progress == ReleaseProgress.COMPLETED
):
title = "Completed: " + title
CIBuddy(dry_run=args.dry_run).post_done(
f"New release issued", dataclasses.asdict(release_info)
title, dataclasses.asdict(release_info)
)
else:
title = "Failed: " + title
CIBuddy(dry_run=args.dry_run).post_critical(
f"Failed to issue new release", dataclasses.asdict(release_info)
title, dataclasses.asdict(release_info)
)
if args.set_progress_started: