support executing the farm with obfarm

This commit is contained in:
Niyuhang2 2023-11-13 16:35:27 +08:00
parent 5867d28716
commit aae61258c3
4 changed files with 243 additions and 0 deletions

9
.github/obfarm/Dockerfile vendored Normal file
View File

@ -0,0 +1,9 @@
# Container image that runs your code
FROM python:3.6
RUN pip3 install requests -i https://mirrors.aliyun.com/pypi/simple/
# Copies your code file from your action repository to the filesystem path `/` of the container
COPY obfarm.py /obfarm.py
# Code file to execute when the docker container starts up (`entrypoint.sh`)
ENTRYPOINT ["python3", "-u", "/obfarm.py"]

26
.github/obfarm/action.yaml vendored Normal file
View File

@ -0,0 +1,26 @@
# action.yml
name: 'call OB Farm to run task'
description: ''
inputs:
pipeline_id:
description: 'pipeline_id'
required: true
project:
description: 'project'
required: true
timeout:
description: 'timeout'
required: false
default: '3600'
outputs:
success:
description: 'the status for the task'
runs:
using: 'docker'
image: 'Dockerfile'
args:
- ${{ inputs.pipeline_id }}
- ${{ inputs.project }}
- ${{ inputs.timeout }}

188
.github/obfarm/obfarm.py vendored Normal file
View File

@ -0,0 +1,188 @@
# -*- coding: utf-8 -*-
import copy
import os
import sys
import traceback
import time
import json
import requests
from enum import Enum
from http import HTTPStatus
OUTPUT = {}
RESULT_FILE_KEY = "farm/ob_results/"
TASK_QUEUE_FILE_KEY = "farm/ob_jobs/{}.json"
def _range(start, last):
def to_str(pos):
if pos is None:
return ''
else:
return str(pos)
return to_str(start) + '-' + to_str(last)
def _make_range_string(range):
if range is None:
return ''
start = range[0]
last = range[1]
if start is None and last is None:
return ''
return 'bytes=' + _range(start, last)
class OssProxy:
def __init__(self, endpoint=""):
self.endpoint = endpoint
def get_object(self, key, _range=None):
url = "{}/{}".format(self.endpoint, key)
headers = {}
if _range is not None:
_range = (_range, None)
headers.update({"range": _make_range_string(_range)})
res = requests.get(url, headers=headers)
if res.status_code < 400:
result = res.content.decode()
return result
return ""
def get_object_meta(self, key):
url = "{}/{}".format(self.endpoint, key)
headers = {}
res = requests.head(url, headers=headers)
return res.headers
def exists_object(self, key):
...
class GithubProxy:
def __init__(self, host="api.github.com"):
self.host = host
def get_job_by_id(self, project, pipeline_id):
url = "https://{}/repos/{}/actions/runs/{}".format(
self.host, project, pipeline_id
)
try:
res = requests.get(
url, headers={
"Accept": "application/vnd.github+json"
}
)
status_code = res.status_code
if status_code == HTTPStatus.NOT_FOUND:
return {}
return res.json()
except:
traceback.print_exc()
return {}
class TaskStatusEnum(Enum):
submitting = 0
pending = 1
running = 2
stopping = 3
success = 4
fail = -1
kill = -2
timeout = -3
submit_task_fail = -4
def request(method, url, params=None, payload=None, timeout=10, data=None, without_check_status=False):
params = params or {}
try:
response = requests.request(
method,
url,
params=params,
json=payload,
data=data,
timeout=timeout
)
if not without_check_status and response.status_code >= 300:
try:
msg = response.json()["msg"]
except:
msg = response.text
print("[ERROR] MSG:{}".format(msg))
exit(1)
return response
except Exception:
import traceback
traceback.print_exc()
print("Please contact the management personnel for assistance !")
if not without_check_status:
exit(1)
def monitor_tasks(oss_proxy: OssProxy, github_pipeline_id, timeout):
end_time = time.time() + int(timeout)
end_task = False
while time.time() <= end_time:
if end_task is True:
pass
task_data = get_task_res(oss_proxy, github_pipeline_id)
if task_data:
end_task = True
time.sleep(1)
if task_data is not None:
task_status = int(task_data["status"])
if task_status <= TaskStatusEnum.fail.value:
print(TaskStatusEnum._value2member_map_[task_status])
print("there is the output url: {}".format(
"https://ce-farm.oceanbase-dev.com/farm2/ci/?id={}".format(task_data["task_id"])))
return False
elif task_status >= TaskStatusEnum.success.value:
print(TaskStatusEnum._value2member_map_[task_status])
print("there is the output url: {}".format(
"https://ce-farm.oceanbase-dev.com/farm2/ci/?id={}".format(task_data["task_id"])))
return True
time.sleep(5)
else:
...
def get_task_res(oss_proxy: OssProxy, github_pipeline_id):
try:
result_key = RESULT_FILE_KEY + "{}.json".format(github_pipeline_id)
origin_task_data = oss_proxy.get_object(result_key)
return json.loads(origin_task_data)
except:
return
def main(pipeline_id, project, timeout):
print("create a new task")
print("working....")
oss_proxy = OssProxy("https://obfarm-ce.oss-cn-hongkong.aliyuncs.com")
github_proxy = GithubProxy()
job_info = github_proxy.get_job_by_id(project, pipeline_id)
attempt_number = job_info["run_attempt"]
run_pipeline_id = "{}-{}".format(pipeline_id, attempt_number)
result = monitor_tasks(oss_proxy, run_pipeline_id, timeout)
if not result:
exit(1)
if __name__ == "__main__":
print(sys.argv)
if len(sys.argv) < 4:
print("Missing relevant parameters !")
OUTPUT.update({"success": -1})
sys.exit(1)
main(sys.argv[1], sys.argv[2], sys.argv[3])

20
.github/workflows/farm.yml vendored Normal file
View File

@ -0,0 +1,20 @@
name: Farm
on:
pull_request:
branches: [ master,develop ]
jobs:
farm:
name: Farm
runs-on: ubuntu-latest
steps:
- name: Checkout workspace
uses: actions/checkout@v3
- name: action by obfarm
uses: ./.github/obfarm/
id: farm
with:
pipeline_id: ${{ github.run_id }}
project: ${{ github.repository }}