Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ci: Automate GitHub Release Status Update Based on ZetaChain Governance Proposals #2192

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 135 additions & 0 deletions .github/actions/release-status-checker/check_and_update.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import requests
import time
import logging
import os
from github import Github
from datetime import datetime, timezone, timedelta
import sys

# Setup logger
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
logger.addHandler(ch)

STATUS_ENDPOINT = os.environ["STATUS_ENDPOINT"]
PROPOSALS_ENDPOINT = os.environ["PROPOSAL_ENDPOINT"]


def get_current_block_height():
response = requests.get(STATUS_ENDPOINT)
response.raise_for_status()
data = response.json()
return int(data['result']['sync_info']['latest_block_height'])


def get_proposals():
response = requests.get(PROPOSALS_ENDPOINT)
response.raise_for_status()
data = response.json()
return [proposal['id'] for proposal in data['proposals']]


def get_proposal_details(proposal_id):
url = f"{PROPOSALS_ENDPOINT}/{proposal_id}"
response = requests.get(url)
response.raise_for_status()
data = response.json()
return data


def is_older_than_one_week(submit_time_str):
submit_time_str = submit_time_str.split('.')[0] + 'Z'
submit_time = datetime.strptime(submit_time_str, '%Y-%m-%dT%H:%M:%S%z')
current_time = datetime.now(timezone.utc)
return current_time - submit_time > timedelta(weeks=1)


def monitor_block_height(proposal_height):
max_checks = int(os.environ["MAX_WAIT_FOR_PROCESSING_BLOCKS_CHECK"])
checks = 0
while checks < max_checks:
current_height = get_current_block_height()
if current_height >= proposal_height:
for _ in range(50):
prev_height = current_height
time.sleep(3)
current_height = get_current_block_height()
if current_height > prev_height:
logger.info("Block height is moving. Network is processing blocks.")
return True
logger.warning("Network is not processing blocks.")
return False
checks += 1
time.sleep(3)
logger.warning("Max wait time reached. Proposal height not reached.")
return False


def update_github_release(proposal_title):
github_token = os.environ["GITHUB_TOKEN"]
g = Github(github_token)
repo = g.get_repo("zeta-chain/node")
releases = repo.get_releases()
for release in releases:
if release.title == proposal_title and release.prerelease:
release.update_release(release.title, release.body, draft=False, prerelease=False)
logger.info(f"Updated GitHub release '{proposal_title}' from pre-release to release.")
return
logger.warning(f"No matching GitHub pre-release found for title '{proposal_title}'.")


def main():
current_block_height = get_current_block_height()
logger.info(f"Current Block Height: {current_block_height}")
proposals_retrieved = get_proposals()
proposals = {}

for proposal_id in proposals_retrieved:
proposal_details = get_proposal_details(proposal_id)

submit_time_str = proposal_details["proposal"]["submit_time"]
if is_older_than_one_week(submit_time_str):
logger.info(f"Proposal {proposal_id} is older than one week. Skipping.")
continue

for message in proposal_details["proposal"]["messages"]:
if "content" not in message:
continue
proposal_type = message["content"]["@type"]
logger.info(f"id: {proposal_id}, proposal type: {proposal_type}")
if "plan" not in message["content"]:
continue
if proposal_details["proposal"]["status"] != "PROPOSAL_STATUS_PASSED":
logger.info(f'Proposal did not pass: {proposal_details["proposal"]["status"]}')
continue
if 'SoftwareUpgradeProposal' in str(proposal_type) or 'MsgSoftwareUpgrade' in str(proposal_type):
proposals[proposal_id] = {
"proposal_height": int(message["content"]["plan"]["height"]),
"proposal_title": message["content"]["title"]
}
break
if len(proposals) <= 0:
logger.info("No proposals found within the timeframe.")
sys.exit(0)
for proposal_id, proposal_data in proposals.items():
if current_block_height >= proposal_data["proposal_height"]:
logger.info(f"Proposal {proposal_id} height {proposal_data['proposal_height']} has been reached.")
update_github_release(proposal_data["proposal_title"])
else:
logger.info(
f"Waiting for proposal {proposal_id} height {proposal_data['proposal_height']} to be reached. Current height: {current_block_height}")
if monitor_block_height(proposal_data['proposal_height']):
logger.info(
f"Proposal {proposal_id} height {proposal_data['proposal_height']} has been reached and network is processing blocks.")
update_github_release(proposal_data["proposal_title"])
else:
logger.warning(
f"Failed to reach proposal {proposal_id} height {proposal_data['proposal_height']} or network is not processing blocks.")


if __name__ == "__main__":
main()
33 changes: 33 additions & 0 deletions .github/workflows/release-status-changer.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: "RELEASE:STATUS:UPDATER"

on:
schedule:
- cron: "*/10 * * * *"
workflow_dispatch:

jobs:
run-script:
runs-on: ubuntu-latest

steps:
- name: Checkout Repository
uses: actions/checkout@v2

- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.x'

- name: Install Dependencies
run: |
python -m pip install --upgrade pip
pip install requests PyGithub

- name: Execute Status Check
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
STATUS_ENDPOINT: "https://zetachain-mainnet.g.allthatnode.com/archive/tendermint/status"
PROPOSAL_ENDPOINT: "https://zetachain-mainnet.g.allthatnode.com/archive/rest/cosmos/gov/v1/proposals"
MAX_WAIT_FOR_PROCESSING_BLOCKS_CHECK: "500"
run: |
python .github/actions/release-status-checker/check_and_update.py
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
* [2119](https://github.com/zeta-chain/node/pull/2119) - Updated the release pipeline to only run on hotfix/ and release/ branches. Added option to only run pre-checks and not cut release as well. Switched approval steps to use environments.
* [2189](https://github.com/zeta-chain/node/pull/2189) - Updated the docker tag when a release trigger runs to be the github event for the release name which should be the version. Removed mac specific build as the arm build should handle that.
* [2191](https://github.com/zeta-chain/node/pull/2191) - Fixed conditional logic for the docker build step for non release builds to not overwrite the github tag.
* [2192](https://github.com/zeta-chain/node/pull/2192) - Added release status checker and updater pipeline that will update release statuses when they go live on network.
## v16.0.0

### Breaking Changes
Expand Down
Loading