mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-19 16:20:50 +00:00
add buddy, move release into action.yml
try callable wf fix add ci buddy
This commit is contained in:
parent
e3b2fbf7ec
commit
3de472cedc
165
.github/actions/release/action.yml
vendored
Normal file
165
.github/actions/release/action.yml
vendored
Normal file
@ -0,0 +1,165 @@
|
||||
name: Release
|
||||
|
||||
description: Makes patch releases and creates new release branch
|
||||
|
||||
inputs:
|
||||
ref:
|
||||
description: 'Git reference (branch or commit sha) from which to create the release'
|
||||
required: true
|
||||
type: string
|
||||
type:
|
||||
description: 'The type of release: "new" for a new release or "patch" for a patch release'
|
||||
required: true
|
||||
type: choice
|
||||
options:
|
||||
- patch
|
||||
- new
|
||||
dry-run:
|
||||
description: 'Dry run'
|
||||
required: false
|
||||
default: true
|
||||
type: boolean
|
||||
token:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Prepare Release Info
|
||||
shell: bash
|
||||
run: |
|
||||
python3 ./tests/ci/create_release.py --prepare-release-info \
|
||||
--ref ${{ inputs.ref }} --release-type ${{ inputs.type }} \
|
||||
${{ inputs.dry-run && '--dry-run' || '' }}
|
||||
echo "::group::Release Info"
|
||||
python3 -m json.tool /tmp/release_info.json
|
||||
echo "::endgroup::"
|
||||
release_tag=$(jq -r '.release_tag' /tmp/release_info.json)
|
||||
commit_sha=$(jq -r '.commit_sha' /tmp/release_info.json)
|
||||
echo "Release Tag: $release_tag"
|
||||
echo "RELEASE_TAG=$release_tag" >> "$GITHUB_ENV"
|
||||
echo "COMMIT_SHA=$commit_sha" >> "$GITHUB_ENV"
|
||||
- name: Download All Release Artifacts
|
||||
if: ${{ inputs.type == 'patch' }}
|
||||
shell: bash
|
||||
run: |
|
||||
python3 ./tests/ci/create_release.py --download-packages ${{ inputs.dry-run && '--dry-run' || '' }}
|
||||
- name: Push Git Tag for the Release
|
||||
shell: bash
|
||||
run: |
|
||||
python3 ./tests/ci/create_release.py --push-release-tag ${{ inputs.dry-run && '--dry-run' || '' }}
|
||||
- name: Push New Release Branch
|
||||
if: ${{ inputs.type == 'new' }}
|
||||
shell: bash
|
||||
run: |
|
||||
python3 ./tests/ci/create_release.py --push-new-release-branch ${{ inputs.dry-run && '--dry-run' || '' }}
|
||||
- name: Bump CH Version and Update Contributors' List
|
||||
shell: bash
|
||||
run: |
|
||||
python3 ./tests/ci/create_release.py --create-bump-version-pr ${{ inputs.dry-run && '--dry-run' || '' }}
|
||||
- name: Checkout master
|
||||
shell: bash
|
||||
run: |
|
||||
git checkout master
|
||||
- name: Bump Docker versions, Changelog, Security
|
||||
if: ${{ inputs.type == 'patch' }}
|
||||
shell: bash
|
||||
run: |
|
||||
[ "$(git branch --show-current)" != "master" ] && echo "not on the master" && exit 1
|
||||
echo "List versions"
|
||||
./utils/list-versions/list-versions.sh > ./utils/list-versions/version_date.tsv
|
||||
echo "Update docker version"
|
||||
./utils/list-versions/update-docker-version.sh
|
||||
echo "Generate ChangeLog"
|
||||
export CI=1
|
||||
docker run -u "${UID}:${GID}" -e PYTHONUNBUFFERED=1 -e CI=1 --network=host \
|
||||
--volume=".:/ClickHouse" clickhouse/style-test \
|
||||
/ClickHouse/tests/ci/changelog.py -v --debug-helpers \
|
||||
--gh-user-or-token=${{ inputs.token }} --jobs=5 \
|
||||
--output="/ClickHouse/docs/changelogs/${{ env.RELEASE_TAG }}.md" ${{ env.RELEASE_TAG }}
|
||||
git add ./docs/changelogs/${{ env.RELEASE_TAG }}.md
|
||||
echo "Generate Security"
|
||||
python3 ./utils/security-generator/generate_security.py > SECURITY.md
|
||||
git diff HEAD
|
||||
- name: Create ChangeLog PR
|
||||
if: ${{ inputs.type == 'patch' && ! inputs.dry-run }}
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
with:
|
||||
author: "robot-clickhouse <robot-clickhouse@users.noreply.github.com>"
|
||||
token: ${{ inputs.token }}
|
||||
committer: "robot-clickhouse <robot-clickhouse@users.noreply.github.com>"
|
||||
commit-message: Update version_date.tsv and changelogs after ${{ env.RELEASE_TAG }}
|
||||
branch: auto/${{ env.RELEASE_TAG }}
|
||||
assignees: ${{ github.event.sender.login }} # assign the PR to the tag pusher
|
||||
delete-branch: true
|
||||
title: Update version_date.tsv and changelog after ${{ env.RELEASE_TAG }}
|
||||
labels: do not test
|
||||
body: |
|
||||
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 }}
|
||||
shell: bash
|
||||
run: |
|
||||
git reset --hard HEAD
|
||||
- name: Checkout back to GITHUB_REF
|
||||
shell: bash
|
||||
run: |
|
||||
git checkout "$GITHUB_REF_NAME"
|
||||
- name: Create GH Release
|
||||
shell: bash
|
||||
if: ${{ inputs.type == 'patch' }}
|
||||
run: |
|
||||
python3 ./tests/ci/create_release.py --create-gh-release \
|
||||
${{ inputs.dry-run && '--dry-run' || '' }}
|
||||
- name: Export TGZ Packages
|
||||
if: ${{ inputs.type == 'patch' }}
|
||||
shell: bash
|
||||
run: |
|
||||
python3 ./tests/ci/artifactory.py --export-tgz ${{ inputs.dry-run && '--dry-run' || '' }}
|
||||
- name: Test TGZ Packages
|
||||
if: ${{ inputs.type == 'patch' }}
|
||||
shell: bash
|
||||
run: |
|
||||
python3 ./tests/ci/artifactory.py --test-tgz ${{ inputs.dry-run && '--dry-run' || '' }}
|
||||
- name: Export RPM Packages
|
||||
if: ${{ inputs.type == 'patch' }}
|
||||
shell: bash
|
||||
run: |
|
||||
python3 ./tests/ci/artifactory.py --export-rpm ${{ inputs.dry-run && '--dry-run' || '' }}
|
||||
- name: Test RPM Packages
|
||||
if: ${{ inputs.type == 'patch' }}
|
||||
shell: bash
|
||||
run: |
|
||||
python3 ./tests/ci/artifactory.py --test-rpm ${{ inputs.dry-run && '--dry-run' || '' }}
|
||||
- name: Export Debian Packages
|
||||
if: ${{ inputs.type == 'patch' }}
|
||||
shell: bash
|
||||
run: |
|
||||
python3 ./tests/ci/artifactory.py --export-debian ${{ inputs.dry-run && '--dry-run' || '' }}
|
||||
- name: Test Debian Packages
|
||||
if: ${{ inputs.type == 'patch' }}
|
||||
shell: bash
|
||||
run: |
|
||||
python3 ./tests/ci/artifactory.py --test-debian ${{ inputs.dry-run && '--dry-run' || '' }}
|
||||
- name: Docker clickhouse/clickhouse-server building
|
||||
if: ${{ inputs.type == 'patch' }}
|
||||
shell: bash
|
||||
run: |
|
||||
cd "./tests/ci"
|
||||
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' || '' }}
|
||||
- name: Docker clickhouse/clickhouse-keeper building
|
||||
if: ${{ inputs.type == 'patch' }}
|
||||
shell: bash
|
||||
run: |
|
||||
cd "./tests/ci"
|
||||
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' || '' }}
|
||||
- name: Post Slack Message
|
||||
if: ${{ !cancelled() }}
|
||||
shell: bash
|
||||
run: |
|
||||
python3 ./tests/ci/create_release.py --post-status ${{ inputs.dry-run && '--dry-run' || '' }}
|
55
.github/workflows/auto_release.yml
vendored
55
.github/workflows/auto_release.yml
vendored
@ -2,6 +2,7 @@ name: AutoRelease
|
||||
|
||||
env:
|
||||
PYTHONUNBUFFERED: 1
|
||||
DRY_RUN: true
|
||||
|
||||
concurrency:
|
||||
group: release
|
||||
@ -9,6 +10,12 @@ on: # yamllint disable-line rule:truthy
|
||||
# schedule:
|
||||
# - cron: '0 10-16 * * 1-5'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
dry-run:
|
||||
description: 'Dry run'
|
||||
required: false
|
||||
default: true
|
||||
type: boolean
|
||||
|
||||
jobs:
|
||||
AutoRelease:
|
||||
@ -31,7 +38,7 @@ jobs:
|
||||
- name: Auto Release Prepare
|
||||
run: |
|
||||
cd "$GITHUB_WORKSPACE/tests/ci"
|
||||
python3 auto_release.py
|
||||
python3 auto_release.py --prepare
|
||||
echo "::group::Auto Release Info"
|
||||
python3 -m json.tool /tmp/autorelease_info.json
|
||||
echo "::endgroup::"
|
||||
@ -40,14 +47,50 @@ jobs:
|
||||
cat /tmp/autorelease_info.json
|
||||
echo 'EOF'
|
||||
} >> "$GITHUB_ENV"
|
||||
- name: Post Release Branch statuses
|
||||
run: |
|
||||
cd "$GITHUB_WORKSPACE/tests/ci"
|
||||
python3 auto_release.py --post-status
|
||||
- name: Release ${{ fromJson(env.AUTO_RELEASE_PARAMS).releases[0].release_branch }}
|
||||
if: ${{ fromJson(env.AUTO_RELEASE_PARAMS).releases[0] }}
|
||||
uses: ./.github/workflows/create_release.yml
|
||||
if: ${{ fromJson(env.AUTO_RELEASE_PARAMS).releases[0] && fromJson(env.AUTO_RELEASE_PARAMS).releases[0].ready }}
|
||||
uses: ./.github/actions/release
|
||||
with:
|
||||
type: patch
|
||||
ref: ${{ fromJson(env.AUTO_RELEASE_PARAMS).releases[0].commit_sha }}
|
||||
dry-run: true
|
||||
autorelease: true
|
||||
type: patch
|
||||
dry-run: ${{ inputs.dry-run }}
|
||||
token: ${{secrets.ROBOT_CLICKHOUSE_COMMIT_TOKEN}}
|
||||
- name: Release ${{ fromJson(env.AUTO_RELEASE_PARAMS).releases[1].release_branch }}
|
||||
if: ${{ fromJson(env.AUTO_RELEASE_PARAMS).releases[0] && fromJson(env.AUTO_RELEASE_PARAMS).releases[1].ready }}
|
||||
uses: ./.github/actions/release
|
||||
with:
|
||||
ref: ${{ fromJson(env.AUTO_RELEASE_PARAMS).releases[1].commit_sha }}
|
||||
type: patch
|
||||
dry-run: ${{ inputs.dry-run }}
|
||||
token: ${{secrets.ROBOT_CLICKHOUSE_COMMIT_TOKEN}}
|
||||
- name: Release ${{ fromJson(env.AUTO_RELEASE_PARAMS).releases[2].release_branch }}
|
||||
if: ${{ fromJson(env.AUTO_RELEASE_PARAMS).releases[2] && fromJson(env.AUTO_RELEASE_PARAMS).releases[2].ready }}
|
||||
uses: ./.github/actions/release
|
||||
with:
|
||||
ref: ${{ fromJson(env.AUTO_RELEASE_PARAMS).releases[2].commit_sha }}
|
||||
type: patch
|
||||
dry-run: ${{ inputs.dry-run }}
|
||||
token: ${{secrets.ROBOT_CLICKHOUSE_COMMIT_TOKEN}}
|
||||
- name: Release ${{ fromJson(env.AUTO_RELEASE_PARAMS).releases[3].release_branch }}
|
||||
if: ${{ fromJson(env.AUTO_RELEASE_PARAMS).releases[3] && fromJson(env.AUTO_RELEASE_PARAMS).releases[3].ready }}
|
||||
uses: ./.github/actions/release
|
||||
with:
|
||||
ref: ${{ fromJson(env.AUTO_RELEASE_PARAMS).releases[3].commit_sha }}
|
||||
type: patch
|
||||
dry-run: ${{ inputs.dry-run }}
|
||||
token: ${{secrets.ROBOT_CLICKHOUSE_COMMIT_TOKEN}}
|
||||
- name: Release ${{ fromJson(env.AUTO_RELEASE_PARAMS).releases[4].release_branch }}
|
||||
if: ${{ fromJson(env.AUTO_RELEASE_PARAMS).releases[4] && fromJson(env.AUTO_RELEASE_PARAMS).releases[4].ready }}
|
||||
uses: ./.github/actions/release
|
||||
with:
|
||||
ref: ${{ fromJson(env.AUTO_RELEASE_PARAMS).releases[4].commit_sha }}
|
||||
type: patch
|
||||
dry-run: ${{ inputs.dry-run }}
|
||||
token: ${{secrets.ROBOT_CLICKHOUSE_COMMIT_TOKEN}}
|
||||
- name: Post Slack Message
|
||||
if: ${{ !cancelled() }}
|
||||
run: |
|
||||
|
140
.github/workflows/create_release.yml
vendored
140
.github/workflows/create_release.yml
vendored
@ -3,7 +3,7 @@ name: CreateRelease
|
||||
concurrency:
|
||||
group: release
|
||||
|
||||
'on':
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref:
|
||||
@ -22,10 +22,6 @@ concurrency:
|
||||
required: false
|
||||
default: true
|
||||
type: boolean
|
||||
autorelease:
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
jobs:
|
||||
CreateRelease:
|
||||
@ -36,138 +32,16 @@ jobs:
|
||||
- name: DebugInfo
|
||||
if: ${{ ! inputs.autorelease }}
|
||||
uses: hmarr/debug-action@f7318c783045ac39ed9bb497e22ce835fdafbfe6
|
||||
- name: Set envs
|
||||
if: ${{ ! inputs.autorelease }}
|
||||
# https://docs.github.com/en/actions/learn-github-actions/workflow-commands-for-github-actions#multiline-strings
|
||||
run: |
|
||||
cat >> "$GITHUB_ENV" << 'EOF'
|
||||
ROBOT_CLICKHOUSE_SSH_KEY<<RCSK
|
||||
${{secrets.ROBOT_CLICKHOUSE_SSH_KEY}}
|
||||
RCSK
|
||||
RELEASE_INFO_FILE=${{ runner.temp }}/release_info.json
|
||||
EOF
|
||||
- name: Check out repository code
|
||||
if: ${{ ! inputs.autorelease }}
|
||||
uses: ClickHouse/checkout@v1
|
||||
with:
|
||||
token: ${{secrets.ROBOT_CLICKHOUSE_COMMIT_TOKEN}}
|
||||
fetch-depth: 0
|
||||
- name: Prepare Release Info
|
||||
run: |
|
||||
python3 ./tests/ci/create_release.py --prepare-release-info \
|
||||
--ref ${{ inputs.ref }} --release-type ${{ inputs.type }} \
|
||||
--outfile ${{ env.RELEASE_INFO_FILE }} ${{ inputs.dry-run && '--dry-run' || '' }}
|
||||
echo "::group::Release Info"
|
||||
python3 -m json.tool "$RELEASE_INFO_FILE"
|
||||
echo "::endgroup::"
|
||||
release_tag=$(jq -r '.release_tag' "$RELEASE_INFO_FILE")
|
||||
commit_sha=$(jq -r '.commit_sha' "$RELEASE_INFO_FILE")
|
||||
echo "Release Tag: $release_tag"
|
||||
echo "RELEASE_TAG=$release_tag" >> "$GITHUB_ENV"
|
||||
echo "COMMIT_SHA=$commit_sha" >> "$GITHUB_ENV"
|
||||
- name: Download All Release Artifacts
|
||||
if: ${{ inputs.type == 'patch' }}
|
||||
run: |
|
||||
python3 ./tests/ci/create_release.py --infile "$RELEASE_INFO_FILE" --download-packages ${{ inputs.dry-run && '--dry-run' || '' }}
|
||||
- name: Push Git Tag for the Release
|
||||
run: |
|
||||
python3 ./tests/ci/create_release.py --push-release-tag --infile "$RELEASE_INFO_FILE" ${{ inputs.dry-run && '--dry-run' || '' }}
|
||||
- name: Push New Release Branch
|
||||
if: ${{ inputs.type == 'new' }}
|
||||
run: |
|
||||
python3 ./tests/ci/create_release.py --push-new-release-branch --infile "$RELEASE_INFO_FILE" ${{ inputs.dry-run && '--dry-run' || '' }}
|
||||
- name: Bump CH Version and Update Contributors' List
|
||||
run: |
|
||||
python3 ./tests/ci/create_release.py --create-bump-version-pr --infile "$RELEASE_INFO_FILE" ${{ inputs.dry-run && '--dry-run' || '' }}
|
||||
- name: Checkout master
|
||||
run: |
|
||||
git checkout master
|
||||
- name: Bump Docker versions, Changelog, Security
|
||||
if: ${{ inputs.type == 'patch' }}
|
||||
run: |
|
||||
[ "$(git branch --show-current)" != "master" ] && echo "not on the master" && exit 1
|
||||
echo "List versions"
|
||||
./utils/list-versions/list-versions.sh > ./utils/list-versions/version_date.tsv
|
||||
echo "Update docker version"
|
||||
./utils/list-versions/update-docker-version.sh
|
||||
echo "Generate ChangeLog"
|
||||
export CI=1
|
||||
docker run -u "${UID}:${GID}" -e PYTHONUNBUFFERED=1 -e CI=1 --network=host \
|
||||
--volume=".:/ClickHouse" clickhouse/style-test \
|
||||
/ClickHouse/tests/ci/changelog.py -v --debug-helpers \
|
||||
--gh-user-or-token="$GH_TOKEN" --jobs=5 \
|
||||
--output="/ClickHouse/docs/changelogs/${{ env.RELEASE_TAG }}.md" ${{ env.RELEASE_TAG }}
|
||||
git add ./docs/changelogs/${{ env.RELEASE_TAG }}.md
|
||||
echo "Generate Security"
|
||||
python3 ./utils/security-generator/generate_security.py > SECURITY.md
|
||||
git diff HEAD
|
||||
- name: Create ChangeLog PR
|
||||
if: ${{ inputs.type == 'patch' && ! inputs.dry-run }}
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
- name: Call Release Action
|
||||
uses: ./.github/actions/release
|
||||
with:
|
||||
author: "robot-clickhouse <robot-clickhouse@users.noreply.github.com>"
|
||||
token: ${{ secrets.ROBOT_CLICKHOUSE_COMMIT_TOKEN }}
|
||||
committer: "robot-clickhouse <robot-clickhouse@users.noreply.github.com>"
|
||||
commit-message: Update version_date.tsv and changelogs after ${{ env.RELEASE_TAG }}
|
||||
branch: auto/${{ env.RELEASE_TAG }}
|
||||
assignees: ${{ github.event.sender.login }} # assign the PR to the tag pusher
|
||||
delete-branch: true
|
||||
title: Update version_date.tsv and changelog after ${{ env.RELEASE_TAG }}
|
||||
labels: do not test
|
||||
body: |
|
||||
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 }}
|
||||
run: |
|
||||
git reset --hard HEAD
|
||||
- name: Checkout back to GITHUB_REF
|
||||
run: |
|
||||
git checkout "$GITHUB_REF_NAME"
|
||||
- name: Create GH Release
|
||||
if: ${{ inputs.type == 'patch' }}
|
||||
run: |
|
||||
python3 ./tests/ci/create_release.py --create-gh-release \
|
||||
--infile ${{ env.RELEASE_INFO_FILE }} ${{ inputs.dry-run && '--dry-run' || '' }}
|
||||
|
||||
- name: Export TGZ Packages
|
||||
if: ${{ inputs.type == 'patch' }}
|
||||
run: |
|
||||
python3 ./tests/ci/artifactory.py --export-tgz --infile ${{ env.RELEASE_INFO_FILE }} ${{ inputs.dry-run && '--dry-run' || '' }}
|
||||
- name: Test TGZ Packages
|
||||
if: ${{ inputs.type == 'patch' }}
|
||||
run: |
|
||||
python3 ./tests/ci/artifactory.py --test-tgz --infile ${{ env.RELEASE_INFO_FILE }} ${{ inputs.dry-run && '--dry-run' || '' }}
|
||||
- name: Export RPM Packages
|
||||
if: ${{ inputs.type == 'patch' }}
|
||||
run: |
|
||||
python3 ./tests/ci/artifactory.py --export-rpm --infile ${{ env.RELEASE_INFO_FILE }} ${{ inputs.dry-run && '--dry-run' || '' }}
|
||||
- name: Test RPM Packages
|
||||
if: ${{ inputs.type == 'patch' }}
|
||||
run: |
|
||||
python3 ./tests/ci/artifactory.py --test-rpm --infile ${{ env.RELEASE_INFO_FILE }} ${{ inputs.dry-run && '--dry-run' || '' }}
|
||||
- name: Export Debian Packages
|
||||
if: ${{ inputs.type == 'patch' }}
|
||||
run: |
|
||||
python3 ./tests/ci/artifactory.py --export-debian --infile ${{ env.RELEASE_INFO_FILE }} ${{ inputs.dry-run && '--dry-run' || '' }}
|
||||
- name: Test Debian Packages
|
||||
if: ${{ inputs.type == 'patch' }}
|
||||
run: |
|
||||
python3 ./tests/ci/artifactory.py --test-debian --infile ${{ env.RELEASE_INFO_FILE }} ${{ inputs.dry-run && '--dry-run' || '' }}
|
||||
- name: Docker clickhouse/clickhouse-server building
|
||||
if: ${{ inputs.type == 'patch' }}
|
||||
run: |
|
||||
cd "./tests/ci"
|
||||
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' || '' }}
|
||||
- name: Docker clickhouse/clickhouse-keeper building
|
||||
if: ${{ inputs.type == 'patch' }}
|
||||
run: |
|
||||
cd "./tests/ci"
|
||||
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' || '' }}
|
||||
- name: Post Slack Message
|
||||
if: ${{ !cancelled() }}
|
||||
run: |
|
||||
echo Slack Message
|
||||
ref: ${{ inputs.ref }}
|
||||
type: inputs.type
|
||||
dry-run: ${{ inputs.dry-run }}
|
||||
token: ${{secrets.ROBOT_CLICKHOUSE_COMMIT_TOKEN}}
|
||||
|
@ -4,7 +4,7 @@ from pathlib import Path
|
||||
from typing import Optional
|
||||
from shutil import copy2
|
||||
from create_release import PackageDownloader, ReleaseInfo, ShellRunner
|
||||
from ci_utils import WithIter
|
||||
from ci_utils import WithIter, Shell
|
||||
|
||||
|
||||
class MountPointApp(metaclass=WithIter):
|
||||
@ -141,12 +141,16 @@ class DebianArtifactory:
|
||||
ShellRunner.run("sync")
|
||||
|
||||
def test_packages(self):
|
||||
ShellRunner.run("docker pull ubuntu:latest")
|
||||
Shell.run("docker pull ubuntu:latest")
|
||||
print(f"Test packages installation, version [{self.version}]")
|
||||
cmd = f"docker run --rm ubuntu:latest bash -c \"apt update -y; apt install -y sudo gnupg ca-certificates; apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 8919F6BD2B48D754; echo 'deb {self.repo_url} stable main' | tee /etc/apt/sources.list.d/clickhouse.list; apt update -y; apt-get install -y clickhouse-client={self.version}\""
|
||||
debian_command = f"echo 'deb {self.repo_url} stable main' | tee /etc/apt/sources.list.d/clickhouse.list; apt update -y; apt-get install -y clickhouse-common-static={self.version} clickhouse-client={self.version}"
|
||||
cmd = f'docker run --rm ubuntu:latest bash -c "apt update -y; apt install -y sudo gnupg ca-certificates; apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 8919F6BD2B48D754; {debian_command}"'
|
||||
print("Running test command:")
|
||||
print(f" {cmd}")
|
||||
ShellRunner.run(cmd)
|
||||
Shell.run(cmd, check=True)
|
||||
release_info = ReleaseInfo.from_file()
|
||||
release_info.debian_command = debian_command
|
||||
release_info.dump()
|
||||
|
||||
|
||||
def _copy_if_not_exists(src: Path, dst: Path) -> Path:
|
||||
@ -210,15 +214,19 @@ class RpmArtifactory:
|
||||
pub_key_path.write_text(ShellRunner.run(update_public_key)[1])
|
||||
if codename == RepoCodenames.LTS:
|
||||
self.export_packages(RepoCodenames.STABLE)
|
||||
ShellRunner.run("sync")
|
||||
Shell.run("sync")
|
||||
|
||||
def test_packages(self):
|
||||
ShellRunner.run("docker pull fedora:latest")
|
||||
Shell.run("docker pull fedora:latest")
|
||||
print(f"Test package installation, version [{self.version}]")
|
||||
cmd = f'docker run --rm fedora:latest /bin/bash -c "dnf -y install dnf-plugins-core && dnf config-manager --add-repo={self.repo_url} && dnf makecache && dnf -y install clickhouse-client-{self.version}-1"'
|
||||
rpm_command = f"dnf config-manager --add-repo={self.repo_url} && dnf makecache && dnf -y install clickhouse-client-{self.version}-1"
|
||||
cmd = f'docker run --rm fedora:latest /bin/bash -c "dnf -y install dnf-plugins-core && dnf config-manager --add-repo={self.repo_url} && {rpm_command}"'
|
||||
print("Running test command:")
|
||||
print(f" {cmd}")
|
||||
ShellRunner.run(cmd)
|
||||
Shell.run(cmd, check=True)
|
||||
release_info = ReleaseInfo.from_file()
|
||||
release_info.rpm_command = rpm_command
|
||||
release_info.dump()
|
||||
|
||||
|
||||
class TgzArtifactory:
|
||||
@ -280,12 +288,6 @@ def parse_args() -> argparse.Namespace:
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
description="Adds release packages to the repository",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--infile",
|
||||
type=str,
|
||||
required=True,
|
||||
help="input file with release info",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--export-debian",
|
||||
action="store_true",
|
||||
@ -328,7 +330,7 @@ if __name__ == "__main__":
|
||||
args = parse_args()
|
||||
assert args.dry_run
|
||||
|
||||
release_info = ReleaseInfo.from_file(args.infile)
|
||||
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
|
||||
|
@ -1,20 +1,17 @@
|
||||
import argparse
|
||||
import dataclasses
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
from typing import List
|
||||
|
||||
from get_robot_token import get_best_robot_token
|
||||
from github_helper import GitHub
|
||||
from ssh import SSHKey
|
||||
from ci_utils import Shell
|
||||
from env_helper import GITHUB_REPOSITORY
|
||||
from report import SUCCESS
|
||||
|
||||
LOGGER_NAME = __name__
|
||||
HELPER_LOGGERS = ["github_helper", LOGGER_NAME]
|
||||
logger = logging.getLogger(LOGGER_NAME)
|
||||
from ci_buddy import CIBuddy
|
||||
from ci_config import CI
|
||||
|
||||
|
||||
def parse_args():
|
||||
@ -23,8 +20,17 @@ def parse_args():
|
||||
"branches and do a release in case for green builds."
|
||||
)
|
||||
parser.add_argument("--token", help="GitHub token, if not set, used from smm")
|
||||
|
||||
return parser.parse_args()
|
||||
parser.add_argument(
|
||||
"--post-status",
|
||||
action="store_true",
|
||||
help="Post release branch statuses",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--prepare",
|
||||
action="store_true",
|
||||
help="Prepare autorelease info",
|
||||
)
|
||||
return parser.parse_args(), parser
|
||||
|
||||
|
||||
MAX_NUMBER_OF_COMMITS_TO_CONSIDER_FOR_RELEASE = 5
|
||||
@ -33,8 +39,16 @@ AUTORELEASE_INFO_FILE = "/tmp/autorelease_info.json"
|
||||
|
||||
@dataclasses.dataclass
|
||||
class ReleaseParams:
|
||||
ready: bool
|
||||
ci_status: str
|
||||
num_patches: int
|
||||
release_branch: str
|
||||
commit_sha: str
|
||||
commits_to_branch_head: int
|
||||
latest: bool
|
||||
|
||||
def to_dict(self):
|
||||
return dataclasses.asdict(self)
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
@ -49,83 +63,128 @@ class AutoReleaseInfo:
|
||||
with open(AUTORELEASE_INFO_FILE, "w", encoding="utf-8") as f:
|
||||
print(json.dumps(dataclasses.asdict(self), indent=2), file=f)
|
||||
|
||||
@staticmethod
|
||||
def from_file() -> "AutoReleaseInfo":
|
||||
with open(AUTORELEASE_INFO_FILE, "r", encoding="utf-8") as json_file:
|
||||
res = json.load(json_file)
|
||||
releases = [ReleaseParams(**release) for release in res["releases"]]
|
||||
return AutoReleaseInfo(releases=releases)
|
||||
|
||||
def main():
|
||||
args = parse_args()
|
||||
|
||||
token = args.token or get_best_robot_token()
|
||||
def _prepare(token):
|
||||
assert len(token) > 10
|
||||
os.environ["GH_TOKEN"] = token
|
||||
(Shell.run("gh auth status", check=True))
|
||||
Shell.run("gh auth status", check=True)
|
||||
|
||||
gh = GitHub(token)
|
||||
prs = gh.get_release_pulls(GITHUB_REPOSITORY)
|
||||
prs.sort(key=lambda x: x.head.ref)
|
||||
branch_names = [pr.head.ref for pr in prs]
|
||||
|
||||
print(f"Found release branches [{branch_names}]")
|
||||
repo = gh.get_repo(GITHUB_REPOSITORY)
|
||||
|
||||
repo = gh.get_repo(GITHUB_REPOSITORY)
|
||||
autoRelease_info = AutoReleaseInfo(releases=[])
|
||||
|
||||
for pr in prs:
|
||||
print(f"Checking PR [{pr.head.ref}]")
|
||||
print(f"\nChecking PR [{pr.head.ref}]")
|
||||
|
||||
refs = list(repo.get_git_matching_refs(f"tags/v{pr.head.ref}"))
|
||||
refs.sort(key=lambda ref: ref.ref)
|
||||
assert refs
|
||||
|
||||
refs.sort(key=lambda ref: ref.ref)
|
||||
latest_release_tag_ref = refs[-1]
|
||||
latest_release_tag = repo.get_git_tag(latest_release_tag_ref.object.sha)
|
||||
commit_num = int(
|
||||
Shell.run(
|
||||
f"git rev-list --count {latest_release_tag.tag}..origin/{pr.head.ref}",
|
||||
check=True,
|
||||
)
|
||||
)
|
||||
print(
|
||||
f"Previous release is [{latest_release_tag}] was [{commit_num}] commits before, date [{latest_release_tag.tagger.date}]"
|
||||
)
|
||||
commit_reverse_index = 0
|
||||
commit_found = False
|
||||
commit_checked = False
|
||||
commit_sha = ""
|
||||
while (
|
||||
commit_reverse_index < commit_num - 1
|
||||
and commit_reverse_index < MAX_NUMBER_OF_COMMITS_TO_CONSIDER_FOR_RELEASE
|
||||
):
|
||||
commit_checked = True
|
||||
commit_sha = Shell.run(
|
||||
f"git rev-list --max-count=1 --skip={commit_reverse_index} origin/{pr.head.ref}",
|
||||
check=True,
|
||||
)
|
||||
print(
|
||||
f"Check if commit [{commit_sha}] [{pr.head.ref}~{commit_reverse_index}] is ready for release"
|
||||
)
|
||||
commit_reverse_index += 1
|
||||
|
||||
cmd = f"gh api -H 'Accept: application/vnd.github.v3+json' /repos/{GITHUB_REPOSITORY}/commits/{commit_sha}/status"
|
||||
ci_status_json = Shell.run(cmd, check=True)
|
||||
ci_status = json.loads(ci_status_json)["state"]
|
||||
if ci_status == SUCCESS:
|
||||
commit_found = True
|
||||
break
|
||||
if commit_found:
|
||||
commits = Shell.run(
|
||||
f"git rev-list --first-parent {latest_release_tag.tag}..origin/{pr.head.ref}",
|
||||
check=True,
|
||||
).split("\n")
|
||||
commit_num = len(commits)
|
||||
print(
|
||||
f"Previous release [{latest_release_tag.tag}] was [{commit_num}] commits ago, date [{latest_release_tag.tagger.date}]"
|
||||
)
|
||||
|
||||
commits_to_check = commits[:-1] # Exclude the version bump commit
|
||||
commit_sha = ""
|
||||
commit_ci_status = ""
|
||||
commits_to_branch_head = 0
|
||||
|
||||
for idx, commit in enumerate(
|
||||
commits_to_check[:MAX_NUMBER_OF_COMMITS_TO_CONSIDER_FOR_RELEASE]
|
||||
):
|
||||
print(
|
||||
f"Check commit [{commit}] [{pr.head.ref}~{idx+1}] as release candidate"
|
||||
)
|
||||
commit_num -= 1
|
||||
|
||||
is_completed = CI.GHActions.check_wf_completed(
|
||||
token=token, commit_sha=commit
|
||||
)
|
||||
if not is_completed:
|
||||
print(f"CI is in progress for [{commit}] - check previous commit")
|
||||
commits_to_branch_head += 1
|
||||
continue
|
||||
|
||||
commit_ci_status = CI.GHActions.get_commit_status_by_name(
|
||||
token=token,
|
||||
commit_sha=commit,
|
||||
status_name=(CI.JobNames.BUILD_CHECK, "ClickHouse build check"),
|
||||
)
|
||||
commit_sha = commit
|
||||
if commit_ci_status == SUCCESS:
|
||||
break
|
||||
else:
|
||||
print(f"CI status [{commit_ci_status}] - skip")
|
||||
commits_to_branch_head += 1
|
||||
|
||||
ready = commit_ci_status == SUCCESS and commit_sha
|
||||
if ready:
|
||||
print(
|
||||
f"Add release ready info for commit [{commit_sha}] and release branch [{pr.head.ref}]"
|
||||
)
|
||||
autoRelease_info.add_release(
|
||||
ReleaseParams(release_branch=pr.head.ref, commit_sha=commit_sha)
|
||||
)
|
||||
else:
|
||||
print(f"WARNING: No good commits found for release branch [{pr.head.ref}]")
|
||||
if commit_checked:
|
||||
print(
|
||||
f"ERROR: CI is failed. check CI status for branch [{pr.head.ref}]"
|
||||
)
|
||||
print(f"WARNING: No ready commits found for release branch [{pr.head.ref}]")
|
||||
|
||||
autoRelease_info.add_release(
|
||||
ReleaseParams(
|
||||
release_branch=pr.head.ref,
|
||||
commit_sha=commit_sha,
|
||||
ready=ready,
|
||||
ci_status=commit_ci_status,
|
||||
num_patches=commit_num,
|
||||
commits_to_branch_head=commits_to_branch_head,
|
||||
latest=False,
|
||||
)
|
||||
)
|
||||
|
||||
if autoRelease_info.releases:
|
||||
autoRelease_info.releases[-1].latest = True
|
||||
|
||||
autoRelease_info.dump()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if os.getenv("ROBOT_CLICKHOUSE_SSH_KEY", ""):
|
||||
with SSHKey("ROBOT_CLICKHOUSE_SSH_KEY"):
|
||||
main()
|
||||
def main():
|
||||
args, parser = parse_args()
|
||||
|
||||
if args.post_status:
|
||||
info = AutoReleaseInfo.from_file()
|
||||
for release_info in info.releases:
|
||||
if release_info.ready:
|
||||
CIBuddy(dry_run=False).post_info(
|
||||
title=f"Auto Release Status for {release_info.release_branch}",
|
||||
body=release_info.to_dict(),
|
||||
)
|
||||
else:
|
||||
CIBuddy(dry_run=False).post_warning(
|
||||
title=f"Auto Release Status for {release_info.release_branch}",
|
||||
body=release_info.to_dict(),
|
||||
)
|
||||
elif args.prepare:
|
||||
_prepare(token=args.token or get_best_robot_token())
|
||||
else:
|
||||
main()
|
||||
parser.print_help()
|
||||
sys.exit(2)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
@ -1295,7 +1295,7 @@ def main() -> int:
|
||||
error_description = f"Out Of Memory, exit_code {job_report.exit_code}"
|
||||
else:
|
||||
error_description = f"Unknown, exit_code {job_report.exit_code}"
|
||||
CIBuddy().post_error(
|
||||
CIBuddy().post_job_error(
|
||||
error_description + f" after {int(job_report.duration)}s",
|
||||
job_name=_get_ext_check_name(args.job_name),
|
||||
)
|
||||
|
@ -1,5 +1,6 @@
|
||||
import json
|
||||
import os
|
||||
from typing import Union, Dict
|
||||
|
||||
import boto3
|
||||
import requests
|
||||
@ -60,7 +61,55 @@ class CIBuddy:
|
||||
except Exception as e:
|
||||
print(f"ERROR: Failed to post message, ex {e}")
|
||||
|
||||
def post_error(self, error_description, job_name="", with_instance_info=True):
|
||||
def _post_formatted(
|
||||
self, title, body: Union[Dict, str], with_wf_link: bool
|
||||
) -> None:
|
||||
message = title
|
||||
if isinstance(body, dict):
|
||||
for name, value in body.items():
|
||||
if "commit_sha" in name:
|
||||
value = (
|
||||
f"<https://github.com/{self.repo}/commit/{value}|{value[:8]}>"
|
||||
)
|
||||
message += f" *{name}*: {value}\n"
|
||||
else:
|
||||
message += body + "\n"
|
||||
run_id = os.getenv("GITHUB_RUN_ID", "")
|
||||
if with_wf_link and run_id:
|
||||
message += f" *workflow*: <https://github.com/{self.repo}/actions/runs/{run_id}|{run_id}>\n"
|
||||
self.post(message)
|
||||
|
||||
def post_info(
|
||||
self, title, body: Union[Dict, str], with_wf_link: bool = True
|
||||
) -> None:
|
||||
title_extended = f":white_circle: *{title}*\n\n"
|
||||
self._post_formatted(title_extended, body, with_wf_link)
|
||||
|
||||
def post_done(
|
||||
self, title, body: Union[Dict, str], with_wf_link: bool = True
|
||||
) -> None:
|
||||
title_extended = f":white_check_mark: *{title}*\n\n"
|
||||
self._post_formatted(title_extended, body, with_wf_link)
|
||||
|
||||
def post_warning(
|
||||
self, title, body: Union[Dict, str], with_wf_link: bool = True
|
||||
) -> None:
|
||||
title_extended = f":warning: *{title}*\n\n"
|
||||
self._post_formatted(title_extended, body, with_wf_link)
|
||||
|
||||
def post_critical(
|
||||
self, title, body: Union[Dict, str], with_wf_link: bool = True
|
||||
) -> None:
|
||||
title_extended = f":black_circle: *{title}*\n\n"
|
||||
self._post_formatted(title_extended, body, with_wf_link)
|
||||
|
||||
def post_job_error(
|
||||
self,
|
||||
error_description,
|
||||
job_name="",
|
||||
with_instance_info=True,
|
||||
with_wf_link: bool = True,
|
||||
):
|
||||
instance_id, instance_type = "unknown", "unknown"
|
||||
if with_instance_info:
|
||||
instance_id = Shell.run("ec2metadata --instance-id") or instance_id
|
||||
@ -82,10 +131,13 @@ class CIBuddy:
|
||||
message += line_pr_
|
||||
else:
|
||||
message += line_br_
|
||||
run_id = os.getenv("GITHUB_RUN_ID", "")
|
||||
if with_wf_link and run_id:
|
||||
message += f" *workflow*: <https://github.com/{self.repo}/actions/runs/{run_id}|{run_id}>\n"
|
||||
self.post(message)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# test
|
||||
buddy = CIBuddy(dry_run=True)
|
||||
buddy.post_error("TEst")
|
||||
buddy.post_job_error("TEst")
|
||||
|
@ -32,6 +32,9 @@ class CI:
|
||||
from ci_definitions import MQ_JOBS as MQ_JOBS
|
||||
from ci_definitions import WorkflowStages as WorkflowStages
|
||||
from ci_definitions import Runners as Runners
|
||||
from ci_utils import Envs as Envs
|
||||
from ci_utils import Utils as Utils
|
||||
from ci_utils import GHActions as GHActions
|
||||
from ci_definitions import Labels as Labels
|
||||
from ci_definitions import TRUSTED_CONTRIBUTORS as TRUSTED_CONTRIBUTORS
|
||||
from ci_utils import CATEGORY_TO_LABEL as CATEGORY_TO_LABEL
|
||||
|
@ -1,9 +1,16 @@
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import time
|
||||
from contextlib import contextmanager
|
||||
from pathlib import Path
|
||||
from typing import Any, Iterator, List, Union, Optional, Tuple
|
||||
from typing import Any, Iterator, List, Union, Optional, Sequence
|
||||
|
||||
import requests
|
||||
|
||||
|
||||
class Envs:
|
||||
GITHUB_REPOSITORY = os.getenv("GITHUB_REPOSITORY", "ClickHouse/ClickHouse")
|
||||
|
||||
|
||||
LABEL_CATEGORIES = {
|
||||
@ -80,6 +87,62 @@ class GHActions:
|
||||
print(line)
|
||||
print("::endgroup::")
|
||||
|
||||
@staticmethod
|
||||
def get_commit_status_by_name(
|
||||
token: str, commit_sha: str, status_name: Union[str, Sequence]
|
||||
) -> Optional[str]:
|
||||
assert len(token) == 40
|
||||
assert len(commit_sha) == 40
|
||||
assert is_hex(commit_sha)
|
||||
assert not is_hex(token)
|
||||
url = f"https://api.github.com/repos/{Envs.GITHUB_REPOSITORY}/commits/{commit_sha}/statuses?per_page={200}"
|
||||
headers = {
|
||||
"Authorization": f"token {token}",
|
||||
"Accept": "application/vnd.github.v3+json",
|
||||
}
|
||||
response = requests.get(url, headers=headers, timeout=5)
|
||||
|
||||
if isinstance(status_name, str):
|
||||
status_name = (status_name,)
|
||||
if response.status_code == 200:
|
||||
assert "next" not in response.links, "Response truncated"
|
||||
statuses = response.json()
|
||||
for status in statuses:
|
||||
if status["context"] in status_name:
|
||||
return status["state"]
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def check_wf_completed(token: str, commit_sha: str) -> bool:
|
||||
headers = {
|
||||
"Authorization": f"token {token}",
|
||||
"Accept": "application/vnd.github.v3+json",
|
||||
}
|
||||
url = f"https://api.github.com/repos/{Envs.GITHUB_REPOSITORY}/commits/{commit_sha}/check-runs?per_page={100}"
|
||||
|
||||
for i in range(3):
|
||||
try:
|
||||
response = requests.get(url, headers=headers, timeout=5)
|
||||
response.raise_for_status()
|
||||
# assert "next" not in response.links, "Response truncated"
|
||||
|
||||
data = response.json()
|
||||
assert data["check_runs"], "?"
|
||||
|
||||
for check in data["check_runs"]:
|
||||
if check["status"] != "completed":
|
||||
print(
|
||||
f" Check workflow status: Check not completed [{check['name']}]"
|
||||
)
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"ERROR: exception {e}")
|
||||
time.sleep(1)
|
||||
|
||||
return False
|
||||
|
||||
|
||||
class Shell:
|
||||
@classmethod
|
||||
@ -108,15 +171,18 @@ class Shell:
|
||||
)
|
||||
if result.returncode == 0:
|
||||
res = result.stdout
|
||||
elif check:
|
||||
print(f"ERROR: stdout {result.stdout}, stderr {result.stderr}")
|
||||
assert result.returncode == 0
|
||||
else:
|
||||
print(
|
||||
f"ERROR: stdout {result.stdout.strip()}, stderr {result.stderr.strip()}"
|
||||
)
|
||||
if check:
|
||||
assert result.returncode == 0
|
||||
return res.strip()
|
||||
|
||||
@classmethod
|
||||
def check(cls, command):
|
||||
result = subprocess.run(
|
||||
command + " 2>&1",
|
||||
command,
|
||||
shell=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
|
@ -14,6 +14,7 @@ from ssh import SSHAgent
|
||||
from env_helper import GITHUB_REPOSITORY, S3_BUILDS_BUCKET
|
||||
from s3_helper import S3Helper
|
||||
from ci_utils import Shell
|
||||
from ci_buddy import CIBuddy
|
||||
from version_helper import (
|
||||
FILE_WITH_VERSION_PATH,
|
||||
GENERATED_CONTRIBUTORS,
|
||||
@ -27,6 +28,7 @@ from ci_config import CI
|
||||
|
||||
CMAKE_PATH = get_abs_path(FILE_WITH_VERSION_PATH)
|
||||
CONTRIBUTORS_PATH = get_abs_path(GENERATED_CONTRIBUTORS)
|
||||
RELEASE_INFO_FILE = "/tmp/release_info.json"
|
||||
|
||||
|
||||
class ShellRunner:
|
||||
@ -67,17 +69,25 @@ class ReleaseInfo:
|
||||
codename: str
|
||||
previous_release_tag: str
|
||||
previous_release_sha: str
|
||||
changelog_pr: str = ""
|
||||
version_bump_pr: str = ""
|
||||
release_url: str = ""
|
||||
debian_command: str = ""
|
||||
rpm_command: str = ""
|
||||
|
||||
@staticmethod
|
||||
def from_file(file_path: str) -> "ReleaseInfo":
|
||||
with open(file_path, "r", encoding="utf-8") as json_file:
|
||||
def from_file() -> "ReleaseInfo":
|
||||
with open(RELEASE_INFO_FILE, "r", encoding="utf-8") as json_file:
|
||||
res = json.load(json_file)
|
||||
return ReleaseInfo(**res)
|
||||
|
||||
def dump(self):
|
||||
print(f"Dump release info into [{RELEASE_INFO_FILE}]")
|
||||
with open(RELEASE_INFO_FILE, "w", encoding="utf-8") as f:
|
||||
print(json.dumps(dataclasses.asdict(self), indent=2), file=f)
|
||||
|
||||
@staticmethod
|
||||
def prepare(commit_ref: str, release_type: str, outfile: str) -> None:
|
||||
Path(outfile).parent.mkdir(parents=True, exist_ok=True)
|
||||
Path(outfile).unlink(missing_ok=True)
|
||||
def prepare(commit_ref: str, release_type: str) -> None:
|
||||
version = None
|
||||
release_branch = None
|
||||
release_tag = None
|
||||
@ -91,7 +101,7 @@ class ReleaseInfo:
|
||||
f"git merge-base --is-ancestor origin/{commit_ref} origin/master"
|
||||
)
|
||||
with checkout(commit_ref):
|
||||
_, commit_sha = ShellRunner.run(f"git rev-parse {commit_ref}")
|
||||
commit_sha = Shell.run(f"git rev-parse {commit_ref}", check=True)
|
||||
# Git() must be inside "with checkout" contextmanager
|
||||
git = Git()
|
||||
version = get_version_from_repo(git=git)
|
||||
@ -112,7 +122,7 @@ class ReleaseInfo:
|
||||
assert previous_release_sha
|
||||
if release_type == "patch":
|
||||
with checkout(commit_ref):
|
||||
_, commit_sha = ShellRunner.run(f"git rev-parse {commit_ref}")
|
||||
commit_sha = Shell.run(f"git rev-parse {commit_ref}", check=True)
|
||||
# Git() must be inside "with checkout" contextmanager
|
||||
git = Git()
|
||||
version = get_version_from_repo(git=git)
|
||||
@ -171,8 +181,7 @@ class ReleaseInfo:
|
||||
previous_release_tag=previous_release_tag,
|
||||
previous_release_sha=previous_release_sha,
|
||||
)
|
||||
with open(outfile, "w", encoding="utf-8") as f:
|
||||
print(json.dumps(dataclasses.asdict(res), indent=2), file=f)
|
||||
res.dump()
|
||||
|
||||
def push_release_tag(self, dry_run: bool) -> None:
|
||||
if dry_run:
|
||||
@ -276,21 +285,38 @@ class ReleaseInfo:
|
||||
f"{GIT_PREFIX} checkout '{CMAKE_PATH}' '{CONTRIBUTORS_PATH}'"
|
||||
)
|
||||
|
||||
def update_release_info(self, dry_run: bool) -> None:
|
||||
branch = f"auto/{release_info.release_tag}"
|
||||
if not dry_run:
|
||||
get_url_cmd = f"gh pr list --repo {GITHUB_REPOSITORY} --head {branch} --json url --jq '.[0].url'"
|
||||
url = Shell.run(get_url_cmd)
|
||||
if url:
|
||||
print(f"Update release info with Changelog PR link [{url}]")
|
||||
else:
|
||||
print(f"WARNING: Changelog PR not found, branch [{branch}]")
|
||||
else:
|
||||
url = "dry-run"
|
||||
|
||||
self.changelog_pr = url
|
||||
self.dump()
|
||||
|
||||
def create_gh_release(self, packages_files: List[str], dry_run: bool) -> None:
|
||||
repo = os.getenv("GITHUB_REPOSITORY")
|
||||
assert repo
|
||||
cmds = []
|
||||
cmds.append(
|
||||
cmds = [
|
||||
f"gh release create --repo {repo} --title 'Release {self.release_tag}' {self.release_tag}"
|
||||
)
|
||||
]
|
||||
for file in packages_files:
|
||||
cmds.append(f"gh release upload {self.release_tag} {file}")
|
||||
if not dry_run:
|
||||
for cmd in cmds:
|
||||
ShellRunner.run(cmd)
|
||||
Shell.run(cmd, check=True)
|
||||
self.release_url = f"https://github.com/{GITHUB_REPOSITORY}/releases/tag/{self.release_tag}"
|
||||
else:
|
||||
print("Dry-run, would run commands:")
|
||||
print("\n * ".join(cmds))
|
||||
self.release_url = f"dry-run"
|
||||
self.dump()
|
||||
|
||||
|
||||
class RepoTypes:
|
||||
@ -508,6 +534,11 @@ def parse_args() -> argparse.Namespace:
|
||||
action="store_true",
|
||||
help="Create GH Release object and attach all packages",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--post-status",
|
||||
action="store_true",
|
||||
help="Post release status into Slack",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--ref",
|
||||
type=str,
|
||||
@ -525,18 +556,6 @@ def parse_args() -> argparse.Namespace:
|
||||
action="store_true",
|
||||
help="do not make any actual changes in the repo, just show what will be done",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--outfile",
|
||||
default="",
|
||||
type=str,
|
||||
help="output file to write json result to, if not set - stdout",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--infile",
|
||||
default="",
|
||||
type=str,
|
||||
help="input file with release info",
|
||||
)
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
@ -547,7 +566,7 @@ def checkout(ref: str) -> Iterator[None]:
|
||||
rollback_cmd = f"{GIT_PREFIX} checkout {orig_ref}"
|
||||
assert orig_ref
|
||||
if ref not in (orig_ref,):
|
||||
ShellRunner.run(f"{GIT_PREFIX} checkout {ref}")
|
||||
Shell.run(f"{GIT_PREFIX} checkout {ref}")
|
||||
try:
|
||||
yield
|
||||
except (Exception, KeyboardInterrupt) as e:
|
||||
@ -587,27 +606,21 @@ if __name__ == "__main__":
|
||||
|
||||
if args.prepare_release_info:
|
||||
assert (
|
||||
args.ref and args.release_type and args.outfile
|
||||
), "--ref, --release-type and --outfile must be provided with --prepare-release-info"
|
||||
ReleaseInfo.prepare(
|
||||
commit_ref=args.ref, release_type=args.release_type, outfile=args.outfile
|
||||
)
|
||||
args.ref and args.release_type
|
||||
), "--ref and --release-type must be provided with --prepare-release-info"
|
||||
ReleaseInfo.prepare(commit_ref=args.ref, release_type=args.release_type)
|
||||
if args.push_release_tag:
|
||||
assert args.infile, "--infile <release info file path> must be provided"
|
||||
release_info = ReleaseInfo.from_file(args.infile)
|
||||
release_info = ReleaseInfo.from_file()
|
||||
release_info.push_release_tag(dry_run=args.dry_run)
|
||||
if args.push_new_release_branch:
|
||||
assert args.infile, "--infile <release info file path> must be provided"
|
||||
release_info = ReleaseInfo.from_file(args.infile)
|
||||
release_info = ReleaseInfo.from_file()
|
||||
release_info.push_new_release_branch(dry_run=args.dry_run)
|
||||
if args.create_bump_version_pr:
|
||||
# TODO: store link to PR in release info
|
||||
assert args.infile, "--infile <release info file path> must be provided"
|
||||
release_info = ReleaseInfo.from_file(args.infile)
|
||||
release_info = ReleaseInfo.from_file()
|
||||
release_info.update_version_and_contributors_list(dry_run=args.dry_run)
|
||||
if args.download_packages:
|
||||
assert args.infile, "--infile <release info file path> must be provided"
|
||||
release_info = ReleaseInfo.from_file(args.infile)
|
||||
release_info = ReleaseInfo.from_file()
|
||||
p = PackageDownloader(
|
||||
release=release_info.release_branch,
|
||||
commit_sha=release_info.commit_sha,
|
||||
@ -615,14 +628,23 @@ if __name__ == "__main__":
|
||||
)
|
||||
p.run()
|
||||
if args.create_gh_release:
|
||||
assert args.infile, "--infile <release info file path> must be provided"
|
||||
release_info = ReleaseInfo.from_file(args.infile)
|
||||
release_info = ReleaseInfo.from_file()
|
||||
p = PackageDownloader(
|
||||
release=release_info.release_branch,
|
||||
commit_sha=release_info.commit_sha,
|
||||
version=release_info.version,
|
||||
)
|
||||
release_info.create_gh_release(p.get_all_packages_files(), args.dry_run)
|
||||
if args.post_status:
|
||||
release_info = ReleaseInfo.from_file()
|
||||
release_info.update_release_info(dry_run=args.dry_run)
|
||||
if release_info.debian_command:
|
||||
CIBuddy(dry_run=args.dry_run).post_done(
|
||||
f"New release issued", dataclasses.asdict(release_info)
|
||||
)
|
||||
else:
|
||||
CIBuddy(dry_run=args.dry_run).post_critical(
|
||||
f"Failed to issue new release", dataclasses.asdict(release_info)
|
||||
)
|
||||
|
||||
# tear down ssh
|
||||
if _ssh_agent and _key_pub:
|
||||
|
@ -296,13 +296,16 @@ class PRInfo:
|
||||
else:
|
||||
if "schedule" in github_event:
|
||||
self.event_type = EventType.SCHEDULE
|
||||
else:
|
||||
elif "inputs" in github_event:
|
||||
# assume this is a dispatch
|
||||
self.event_type = EventType.DISPATCH
|
||||
logging.warning(
|
||||
"event.json does not match pull_request or push:\n%s",
|
||||
json.dumps(github_event, sort_keys=True, indent=4),
|
||||
)
|
||||
print("PR Info:")
|
||||
print(self)
|
||||
else:
|
||||
logging.warning(
|
||||
"event.json does not match pull_request or push:\n%s",
|
||||
json.dumps(github_event, sort_keys=True, indent=4),
|
||||
)
|
||||
self.sha = os.getenv(
|
||||
"GITHUB_SHA", "0000000000000000000000000000000000000000"
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user