Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 442413581d |
Executable
+336
@@ -0,0 +1,336 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
CI Trace 上报脚本 - 用于 Gitea Actions workflow 中上报 Trace 数据到 AgentLoop
|
||||
|
||||
在 CI workflow 的每个 job 中调用:
|
||||
- 开始时:python3 .gitea/scripts/ci_trace_report.py --status running
|
||||
- 结束时:python3 .gitea/scripts/ci_trace_report.py --status ok --start-time $CI_TRACE_START_TIME
|
||||
|
||||
环境变量(Gitea Actions 内置):
|
||||
GITEA_REPOSITORY / GITHUB_REPOSITORY - 仓库名 (owner/repo)
|
||||
GITEA_WORKFLOW / GITHUB_WORKFLOW - workflow 名称
|
||||
GITEA_JOB / GITHUB_JOB - job ID
|
||||
GITEA_SHA / GITHUB_SHA - commit SHA
|
||||
GITEA_REF_NAME / GITHUB_REF_NAME - 分支名
|
||||
GITEA_RUN_ID / GITHUB_RUN_ID - run ID
|
||||
GITEA_ACTOR / GITHUB_ACTOR - 触发者
|
||||
GITEA_EVENT_NAME / GITHUB_EVENT_NAME - 事件类型
|
||||
PR_NUMBER / GITEA_PR_NUMBER - PR 号(如果是 PR 触发)
|
||||
|
||||
AgentLoop 配置(通过 Secrets 注入):
|
||||
AGENTLOOP_LICENSE_KEY - LicenseKey(必填)
|
||||
AGENTLOOP_ENDPOINT - Trace 上报地址(可选,有默认值)
|
||||
AGENTLOOP_PROJECT - SLS Project 名(可选)
|
||||
AGENTLOOP_WORKSPACE - CMS Workspace 名(可选)
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import time
|
||||
import uuid
|
||||
import argparse
|
||||
import urllib.request
|
||||
import urllib.error
|
||||
|
||||
|
||||
# ========== 默认配置 ==========
|
||||
DEFAULT_ENDPOINT = "https://proj-xtrace-495e81719a1fd9a2c5fd671eefafbe-cn-hangzhou.cn-hangzhou.log.aliyuncs.com/apm/trace/opentelemetry/v1/traces"
|
||||
DEFAULT_PROJECT = "proj-xtrace-495e81719a1fd9a2c5fd671eefafbe-cn-hangzhou"
|
||||
DEFAULT_WORKSPACE = "agentloop-13b8d6efb7fde6e9b193eb982ade68e2"
|
||||
|
||||
|
||||
# ========== OTLP Protobuf 手动编码 ==========
|
||||
|
||||
def _encode_varint(value):
|
||||
result = bytearray()
|
||||
while value > 0x7F:
|
||||
result.append((value & 0x7F) | 0x80)
|
||||
value >>= 7
|
||||
result.append(value & 0x7F)
|
||||
return bytes(result)
|
||||
|
||||
def _encode_tag(field_number, wire_type):
|
||||
return _encode_varint((field_number << 3) | wire_type)
|
||||
|
||||
def _encode_string_field(field_number, value):
|
||||
value_bytes = value.encode('utf-8')
|
||||
return _encode_tag(field_number, 2) + _encode_varint(len(value_bytes)) + value_bytes
|
||||
|
||||
def _encode_bytes_field(field_number, value_bytes):
|
||||
return _encode_tag(field_number, 2) + _encode_varint(len(value_bytes)) + value_bytes
|
||||
|
||||
def _encode_int_field(field_number, value):
|
||||
return _encode_tag(field_number, 0) + _encode_varint(value & 0xFFFFFFFFFFFFFFFF)
|
||||
|
||||
def _encode_message_field(field_number, message_bytes):
|
||||
return _encode_tag(field_number, 2) + _encode_varint(len(message_bytes)) + message_bytes
|
||||
|
||||
def _encode_key_value(key, value_str):
|
||||
any_value = _encode_string_field(1, value_str)
|
||||
return _encode_string_field(1, key) + _encode_message_field(2, any_value)
|
||||
|
||||
def _encode_status(status_code, status_msg=""):
|
||||
data = _encode_int_field(1, status_code)
|
||||
if status_msg:
|
||||
data += _encode_string_field(2, status_msg)
|
||||
return data
|
||||
|
||||
def _encode_span(trace_id_bytes, span_id_bytes, parent_span_id_bytes,
|
||||
name, start_time_unix_nano, end_time_unix_nano,
|
||||
span_kind, attributes, status_code, status_msg=""):
|
||||
data = b""
|
||||
data += _encode_bytes_field(1, trace_id_bytes)
|
||||
data += _encode_bytes_field(2, span_id_bytes)
|
||||
if parent_span_id_bytes:
|
||||
data += _encode_bytes_field(3, parent_span_id_bytes)
|
||||
data += _encode_string_field(4, name)
|
||||
data += _encode_int_field(5, span_kind)
|
||||
data += _encode_int_field(6, start_time_unix_nano)
|
||||
data += _encode_int_field(7, end_time_unix_nano)
|
||||
for key, value in attributes.items():
|
||||
kv = _encode_key_value(key, str(value))
|
||||
data += _encode_message_field(9, kv)
|
||||
status = _encode_status(status_code, status_msg)
|
||||
data += _encode_message_field(12, status)
|
||||
return data
|
||||
|
||||
def _encode_resource_spans(service_name, scope_spans_bytes):
|
||||
svc_kv = _encode_key_value("service.name", service_name)
|
||||
resource = _encode_message_field(1, svc_kv)
|
||||
data = _encode_message_field(1, resource)
|
||||
data += _encode_message_field(2, scope_spans_bytes)
|
||||
return data
|
||||
|
||||
def _encode_scope_spans(scope_name, spans_bytes_list):
|
||||
scope = _encode_string_field(1, scope_name)
|
||||
data = _encode_message_field(1, scope)
|
||||
for span_bytes in spans_bytes_list:
|
||||
data += _encode_message_field(2, span_bytes)
|
||||
return data
|
||||
|
||||
def _encode_traces_data(resource_spans_bytes_list):
|
||||
data = b""
|
||||
for rs_bytes in resource_spans_bytes_list:
|
||||
data += _encode_message_field(1, rs_bytes)
|
||||
return data
|
||||
|
||||
|
||||
# ========== 辅助函数 ==========
|
||||
|
||||
def _gen_trace_id():
|
||||
return uuid.uuid4().bytes
|
||||
|
||||
def _gen_span_id():
|
||||
return uuid.uuid4().bytes[:8]
|
||||
|
||||
def _env(name, default=""):
|
||||
"""获取环境变量,支持 GITEA_ 和 GITHUB_ 前缀"""
|
||||
val = os.getenv(name, "")
|
||||
if val:
|
||||
return val
|
||||
# 尝试另一种前缀
|
||||
if name.startswith("GITEA_"):
|
||||
alt = "GITHUB_" + name[6:]
|
||||
return os.getenv(alt, default)
|
||||
if name.startswith("GITHUB_"):
|
||||
alt = "GITEA_" + name[7:]
|
||||
return os.getenv(alt, default)
|
||||
return default
|
||||
|
||||
|
||||
def _get_pr_number():
|
||||
"""从环境变量或事件文件中获取 PR 号"""
|
||||
# 直接从环境变量
|
||||
pr = os.getenv("PR_NUMBER", "") or os.getenv("GITEA_PR_NUMBER", "")
|
||||
if pr:
|
||||
return pr
|
||||
|
||||
# 从 GITHUB_EVENT_PATH 读取
|
||||
event_path = os.getenv("GITHUB_EVENT_PATH", "") or os.getenv("GITEA_EVENT_PATH", "")
|
||||
if event_path and os.path.isfile(event_path):
|
||||
try:
|
||||
with open(event_path, "r") as f:
|
||||
event = json.load(f)
|
||||
if "pull_request" in event and "number" in event["pull_request"]:
|
||||
return str(event["pull_request"]["number"])
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return ""
|
||||
|
||||
|
||||
def _get_ci_attributes():
|
||||
"""从 CI 环境变量中收集属性"""
|
||||
attrs = {
|
||||
"ci.repo": _env("GITEA_REPOSITORY") or _env("GITHUB_REPOSITORY") or "unknown",
|
||||
"ci.workflow": _env("GITEA_WORKFLOW") or _env("GITHUB_WORKFLOW") or "unknown",
|
||||
"ci.job": _env("GITEA_JOB") or _env("GITHUB_JOB") or "unknown",
|
||||
"ci.commit_sha": _env("GITEA_SHA") or _env("GITHUB_SHA") or "unknown",
|
||||
"ci.branch": _env("GITEA_REF_NAME") or _env("GITHUB_REF_NAME") or "unknown",
|
||||
"ci.run_id": _env("GITEA_RUN_ID") or _env("GITHUB_RUN_ID") or "unknown",
|
||||
"ci.actor": _env("GITEA_ACTOR") or _env("GITHUB_ACTOR") or "unknown",
|
||||
"ci.event": _env("GITEA_EVENT_NAME") or _env("GITHUB_EVENT_NAME") or "unknown",
|
||||
}
|
||||
pr = _get_pr_number()
|
||||
if pr:
|
||||
attrs["ci.pr_number"] = pr
|
||||
return attrs
|
||||
|
||||
|
||||
# ========== 核心上报逻辑 ==========
|
||||
|
||||
def build_trace(service_name, trace_name, status, duration_ms, attributes=None):
|
||||
"""构建一条完整的 Trace 数据,返回 protobuf bytes。"""
|
||||
trace_id = _gen_trace_id()
|
||||
end_time = int(time.time() * 1e9)
|
||||
start_time = end_time - int(duration_ms * 1e6)
|
||||
status_code = 1 if status in ("ok", "running") else 2
|
||||
status_msg = "" if status in ("ok", "running") else "Job failed"
|
||||
|
||||
main_attrs = {
|
||||
"agent.trace_name": trace_name,
|
||||
"agent.service": service_name,
|
||||
"ci.trace_status": status,
|
||||
}
|
||||
if attributes:
|
||||
main_attrs.update(attributes)
|
||||
|
||||
main_span = _encode_span(
|
||||
trace_id_bytes=trace_id,
|
||||
span_id_bytes=_gen_span_id(),
|
||||
parent_span_id_bytes=b"",
|
||||
name=trace_name,
|
||||
start_time_unix_nano=start_time,
|
||||
end_time_unix_nano=end_time,
|
||||
span_kind=1,
|
||||
attributes=main_attrs,
|
||||
status_code=status_code,
|
||||
status_msg=status_msg,
|
||||
)
|
||||
|
||||
scope_spans = _encode_scope_spans("ci-trace", [main_span])
|
||||
resource_spans = _encode_resource_spans(service_name, scope_spans)
|
||||
return _encode_traces_data([resource_spans])
|
||||
|
||||
|
||||
def report_ci_trace(service_name, trace_name, status="ok", duration_ms=1000,
|
||||
endpoint=None, license_key=None, project=None, workspace=None,
|
||||
extra_attributes=None):
|
||||
"""
|
||||
上报 CI Trace 数据。返回 (success: bool, message: str)
|
||||
永远不会抛出异常,失败也返回 False。
|
||||
"""
|
||||
try:
|
||||
endpoint = endpoint or os.getenv("AGENTLOOP_ENDPOINT", DEFAULT_ENDPOINT)
|
||||
license_key = license_key or os.getenv("AGENTLOOP_LICENSE_KEY", "")
|
||||
project = project or os.getenv("AGENTLOOP_PROJECT", DEFAULT_PROJECT)
|
||||
workspace = workspace or os.getenv("AGENTLOOP_WORKSPACE", DEFAULT_WORKSPACE)
|
||||
|
||||
if not license_key:
|
||||
return False, "[Trace] 跳过上报:未配置 AGENTLOOP_LICENSE_KEY"
|
||||
|
||||
# 收集 CI 属性
|
||||
attrs = _get_ci_attributes()
|
||||
if extra_attributes:
|
||||
attrs.update(extra_attributes)
|
||||
|
||||
payload = build_trace(
|
||||
service_name=service_name,
|
||||
trace_name=trace_name,
|
||||
status=status,
|
||||
duration_ms=duration_ms,
|
||||
attributes=attrs,
|
||||
)
|
||||
|
||||
headers = {
|
||||
"Content-Type": "application/x-protobuf",
|
||||
"x-arms-license-key": license_key,
|
||||
"x-arms-project": project,
|
||||
"x-cms-workspace": workspace,
|
||||
}
|
||||
|
||||
req = urllib.request.Request(endpoint, data=payload, headers=headers, method="POST")
|
||||
try:
|
||||
with urllib.request.urlopen(req, timeout=10) as resp:
|
||||
status_code = resp.status
|
||||
resp_body = resp.read().decode("utf-8", errors="replace")
|
||||
except urllib.error.HTTPError as e:
|
||||
status_code = e.code
|
||||
resp_body = e.read().decode("utf-8", errors="replace")
|
||||
|
||||
if status_code in (200, 202):
|
||||
return True, f"[Trace] ✓ 上报成功: {service_name} / {trace_name} ({status}, {duration_ms}ms)"
|
||||
else:
|
||||
return False, f"[Trace] ⚠ 上报失败: HTTP {status_code} - {resp_body[:200]}"
|
||||
except Exception as e:
|
||||
return False, f"[Trace] ⚠ 上报异常: {type(e).__name__}: {str(e)}"
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="CI AgentLoop Trace 上报")
|
||||
parser.add_argument("--service", dest="service_name",
|
||||
default=os.getenv("TRACE_SERVICE", ""),
|
||||
help="服务名称(也可通过 TRACE_SERVICE 环境变量设置)")
|
||||
parser.add_argument("--name", dest="trace_name",
|
||||
default=os.getenv("TRACE_NAME", ""),
|
||||
help="Trace 名称(也可通过 TRACE_NAME 环境变量设置)")
|
||||
parser.add_argument("--status", default=os.getenv("TRACE_STATUS", "ok"),
|
||||
choices=["ok", "error", "running"],
|
||||
help="状态: ok / error / running(默认 ok)")
|
||||
parser.add_argument("--start-time", dest="start_time",
|
||||
default=os.getenv("TRACE_START_TIME", ""),
|
||||
help="开始时间戳(秒),用于计算 duration;不填则用默认 1s")
|
||||
parser.add_argument("--duration-ms", dest="duration_ms", type=int, default=0,
|
||||
help="直接指定耗时(毫秒),优先级高于 --start-time")
|
||||
parser.add_argument("--attrs", default="",
|
||||
help="附加属性(JSON 字符串)")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# 必须参数检查
|
||||
if not args.service_name:
|
||||
print("[Trace] ⚠ 跳过上报:未指定 service(--service 或 TRACE_SERVICE)")
|
||||
sys.exit(0)
|
||||
|
||||
# 计算耗时
|
||||
duration_ms = args.duration_ms
|
||||
if duration_ms <= 0 and args.start_time:
|
||||
try:
|
||||
start_ts = float(args.start_time)
|
||||
duration_ms = int((time.time() - start_ts) * 1000)
|
||||
except (ValueError, TypeError):
|
||||
duration_ms = 1000
|
||||
if duration_ms <= 0:
|
||||
duration_ms = 1000 # 默认 1 秒
|
||||
|
||||
# 解析附加属性
|
||||
extra_attrs = {}
|
||||
if args.attrs:
|
||||
try:
|
||||
extra_attrs = json.loads(args.attrs)
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
|
||||
# 生成 trace_name:如果没指定,用 workflow+job
|
||||
trace_name = args.trace_name
|
||||
if not trace_name:
|
||||
wf = _env("GITEA_WORKFLOW") or _env("GITHUB_WORKFLOW") or "CI"
|
||||
job = _env("GITEA_JOB") or _env("GITHUB_JOB") or "job"
|
||||
trace_name = f"{wf} / {job}"
|
||||
|
||||
success, msg = report_ci_trace(
|
||||
service_name=args.service_name,
|
||||
trace_name=trace_name,
|
||||
status=args.status,
|
||||
duration_ms=duration_ms,
|
||||
extra_attributes=extra_attrs,
|
||||
)
|
||||
|
||||
print(msg)
|
||||
# 永远 exit 0,不影响 CI
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -17,6 +17,14 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
run: "set -eu\npython3 - <<'PY'\nimport io, os, tarfile, time, urllib.request, urllib.error\nurl = f\"{os.environ['GITHUB_API_URL']}/repos/{os.environ['GITHUB_REPOSITORY']}/archive/{os.environ['GITHUB_SHA']}.tar.gz\"\nrequest = urllib.request.Request(url, headers={\"Authorization\": f\"token {os.environ['GITHUB_TOKEN']}\"})\nlast_err = None\nfor attempt in range(5):\n try:\n with urllib.request.urlopen(request, timeout=120) as response:\n archive = response.read()\n break\n except urllib.error.HTTPError as e:\n last_err = e\n if e.code >= 500 and attempt < 4:\n wait = 2 ** attempt\n print(f\"Checkout HTTP {e.code}, retrying in {wait}s (attempt {attempt+1}/5)...\")\n time.sleep(wait)\n continue\n raise\n except Exception as e:\n last_err = e\n if attempt < 4:\n wait = 2 ** attempt\n print(f\"Checkout error: {e}, retrying in {wait}s (attempt {attempt+1}/5)...\")\n time.sleep(wait)\n continue\n raise\nelse:\n raise last_err\nwith tarfile.open(fileobj=io.BytesIO(archive), mode='r:gz') as tar:\n root_prefix = tar.getmembers()[0].name.split('/', 1)[0] + '/'\n for member in tar.getmembers():\n name = member.name\n if name == root_prefix[:-1]:\n continue\n if name.startswith(root_prefix):\n member.name = name[len(root_prefix):]\n if member.name:\n tar.extract(member, '.')\nPY\n"
|
||||
|
||||
- name: Record start time & report trace start
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\necho "CI_TRACE_START_TIME=$(date +%s)" >> $GITHUB_ENV\nTRACE_SERVICE="auto-approve" TRACE_NAME="自动批准 / Auto Approve on CI Green" python3 .gitea/scripts/ci_trace_report.py --status running\n\nexit 0\n"
|
||||
- name: Auto approve when CI passes
|
||||
shell: bash
|
||||
env:
|
||||
@@ -172,3 +180,12 @@ jobs:
|
||||
echo
|
||||
echo "⏰ 等待超时(20分钟),CI尚未全部完成"
|
||||
exit 0
|
||||
- name: Report trace end (always)
|
||||
if: always()
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\nif [ "${{ job.status }}" = "success" ]; then\n TRACE_STATUS="ok"\nelse\n TRACE_STATUS="error"\nfi\n\nTRACE_SERVICE="auto-approve" TRACE_NAME="自动批准 / Auto Approve on CI Green" TRACE_STATUS="$TRACE_STATUS" python3 .gitea/scripts/ci_trace_report.py --start-time "$CI_TRACE_START_TIME"\n\nexit 0\n"
|
||||
|
||||
@@ -17,6 +17,14 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
run: "set -eu\npython3 - <<'PY'\nimport io, os, tarfile, time, urllib.request, urllib.error\nurl = f\"{os.environ['GITHUB_API_URL']}/repos/{os.environ['GITHUB_REPOSITORY']}/archive/{os.environ['GITHUB_SHA']}.tar.gz\"\nrequest = urllib.request.Request(url, headers={\"Authorization\": f\"token {os.environ['GITHUB_TOKEN']}\"})\nlast_err = None\nfor attempt in range(5):\n try:\n with urllib.request.urlopen(request, timeout=120) as response:\n archive = response.read()\n break\n except urllib.error.HTTPError as e:\n last_err = e\n if e.code >= 500 and attempt < 4:\n wait = 2 ** attempt\n print(f\"Checkout HTTP {e.code}, retrying in {wait}s (attempt {attempt+1}/5)...\")\n time.sleep(wait)\n continue\n raise\n except Exception as e:\n last_err = e\n if attempt < 4:\n wait = 2 ** attempt\n print(f\"Checkout error: {e}, retrying in {wait}s (attempt {attempt+1}/5)...\")\n time.sleep(wait)\n continue\n raise\nelse:\n raise last_err\nwith tarfile.open(fileobj=io.BytesIO(archive), mode='r:gz') as tar:\n root_prefix = tar.getmembers()[0].name.split('/', 1)[0] + '/'\n for member in tar.getmembers():\n name = member.name\n if name == root_prefix[:-1]:\n continue\n if name.startswith(root_prefix):\n member.name = name[len(root_prefix):]\n if member.name:\n tar.extract(member, '.')\nPY\n"
|
||||
|
||||
- name: Record start time & report trace start
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\necho "CI_TRACE_START_TIME=$(date +%s)" >> $GITHUB_ENV\nTRACE_SERVICE="auto-merge" TRACE_NAME="自动合并 / Auto Merge on CI Green + Approved" python3 .gitea/scripts/ci_trace_report.py --status running\n\nexit 0\n"
|
||||
- name: Auto merge when CI passes and approved
|
||||
shell: bash
|
||||
env:
|
||||
@@ -172,3 +180,12 @@ jobs:
|
||||
echo
|
||||
echo "等待超时(30分钟)"
|
||||
exit 0
|
||||
- name: Report trace end (always)
|
||||
if: always()
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\nif [ "${{ job.status }}" = "success" ]; then\n TRACE_STATUS="ok"\nelse\n TRACE_STATUS="error"\nfi\n\nTRACE_SERVICE="auto-merge" TRACE_NAME="自动合并 / Auto Merge on CI Green + Approved" TRACE_STATUS="$TRACE_STATUS" python3 .gitea/scripts/ci_trace_report.py --start-time "$CI_TRACE_START_TIME"\n\nexit 0\n"
|
||||
|
||||
@@ -95,6 +95,14 @@ jobs:
|
||||
tar.extract(member, '.')
|
||||
INNERPY
|
||||
|
||||
- name: Record start time & report trace start
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\necho "CI_TRACE_START_TIME=$(date +%s)" >> $GITHUB_ENV\nTRACE_SERVICE="" TRACE_NAME="" python3 .gitea/scripts/ci_trace_report.py --status running\n\nexit 0\n"
|
||||
- name: Record job start time
|
||||
shell: sh
|
||||
run: 'set -eu
|
||||
@@ -144,6 +152,15 @@ jobs:
|
||||
NOTIFY_MODE=failure JOB_NAME="Build Staging ${{ matrix.service_display }} Image" python3 scripts/ci_notify.py
|
||||
|
||||
'
|
||||
- name: Report trace end (always)
|
||||
if: always()
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\nif [ "${{ job.status }}" = "success" ]; then\n TRACE_STATUS="ok"\nelse\n TRACE_STATUS="error"\nfi\n\nTRACE_SERVICE="" TRACE_NAME="" TRACE_STATUS="$TRACE_STATUS" python3 .gitea/scripts/ci_trace_report.py --start-time "$CI_TRACE_START_TIME"\n\nexit 0\n"
|
||||
deploy-staging:
|
||||
name: Deploy Staging (Watchtower auto-deploy)
|
||||
runs-on: runtime-builder
|
||||
@@ -200,6 +217,14 @@ jobs:
|
||||
tar.extract(member, '.')
|
||||
INNERPY
|
||||
|
||||
- name: Record start time & report trace start
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\necho "CI_TRACE_START_TIME=$(date +%s)" >> $GITHUB_ENV\nTRACE_SERVICE="" TRACE_NAME="" python3 .gitea/scripts/ci_trace_report.py --status running\n\nexit 0\n"
|
||||
- name: Record job start time
|
||||
shell: sh
|
||||
run: 'set -eu
|
||||
@@ -302,6 +327,15 @@ jobs:
|
||||
NOTIFY_MODE=failure JOB_NAME="Deploy Staging" python3 scripts/ci_notify.py
|
||||
|
||||
'
|
||||
- name: Report trace end (always)
|
||||
if: always()
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\nif [ "${{ job.status }}" = "success" ]; then\n TRACE_STATUS="ok"\nelse\n TRACE_STATUS="error"\nfi\n\nTRACE_SERVICE="" TRACE_NAME="" TRACE_STATUS="$TRACE_STATUS" python3 .gitea/scripts/ci_trace_report.py --start-time "$CI_TRACE_START_TIME"\n\nexit 0\n"
|
||||
staging-e2e:
|
||||
name: Staging E2E Tests
|
||||
runs-on: runtime-builder
|
||||
@@ -355,6 +389,14 @@ jobs:
|
||||
tar.extract(member, '.')
|
||||
PY
|
||||
|
||||
- name: Record start time & report trace start
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\necho "CI_TRACE_START_TIME=$(date +%s)" >> $GITHUB_ENV\nTRACE_SERVICE="" TRACE_NAME="" python3 .gitea/scripts/ci_trace_report.py --status running\n\nexit 0\n"
|
||||
- name: Record job start time
|
||||
shell: sh
|
||||
run: 'set -eu
|
||||
@@ -382,6 +424,15 @@ jobs:
|
||||
NOTIFY_MODE=failure JOB_NAME="Staging E2E Tests" python3 scripts/ci_notify.py
|
||||
|
||||
'
|
||||
- name: Report trace end (always)
|
||||
if: always()
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\nif [ "${{ job.status }}" = "success" ]; then\n TRACE_STATUS="ok"\nelse\n TRACE_STATUS="error"\nfi\n\nTRACE_SERVICE="" TRACE_NAME="" TRACE_STATUS="$TRACE_STATUS" python3 .gitea/scripts/ci_trace_report.py --start-time "$CI_TRACE_START_TIME"\n\nexit 0\n"
|
||||
staging-api-tests:
|
||||
name: Staging API Integration Tests
|
||||
runs-on: runtime-builder
|
||||
@@ -435,6 +486,14 @@ jobs:
|
||||
tar.extract(member, '.')
|
||||
PY
|
||||
|
||||
- name: Record start time & report trace start
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\necho "CI_TRACE_START_TIME=$(date +%s)" >> $GITHUB_ENV\nTRACE_SERVICE="" TRACE_NAME="" python3 .gitea/scripts/ci_trace_report.py --status running\n\nexit 0\n"
|
||||
- name: Record job start time
|
||||
shell: sh
|
||||
run: 'set -eu
|
||||
@@ -462,6 +521,15 @@ jobs:
|
||||
NOTIFY_MODE=failure JOB_NAME="Staging API Integration Tests" python3 scripts/ci_notify.py
|
||||
|
||||
'
|
||||
- name: Report trace end (always)
|
||||
if: always()
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\nif [ "${{ job.status }}" = "success" ]; then\n TRACE_STATUS="ok"\nelse\n TRACE_STATUS="error"\nfi\n\nTRACE_SERVICE="" TRACE_NAME="" TRACE_STATUS="$TRACE_STATUS" python3 .gitea/scripts/ci_trace_report.py --start-time "$CI_TRACE_START_TIME"\n\nexit 0\n"
|
||||
build-production:
|
||||
name: Build Production ${{ matrix.service_display }} Image
|
||||
runs-on: runtime-builder
|
||||
@@ -536,6 +604,14 @@ jobs:
|
||||
tar.extract(member, '.')
|
||||
INNERPY
|
||||
|
||||
- name: Record start time & report trace start
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\necho "CI_TRACE_START_TIME=$(date +%s)" >> $GITHUB_ENV\nTRACE_SERVICE="" TRACE_NAME="" python3 .gitea/scripts/ci_trace_report.py --status running\n\nexit 0\n"
|
||||
- name: Record job start time
|
||||
shell: sh
|
||||
run: 'set -eu
|
||||
@@ -586,6 +662,15 @@ jobs:
|
||||
NOTIFY_MODE=failure JOB_NAME="Build Production ${{ matrix.service_display }} Image" python3 scripts/ci_notify.py
|
||||
|
||||
'
|
||||
- name: Report trace end (always)
|
||||
if: always()
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\nif [ "${{ job.status }}" = "success" ]; then\n TRACE_STATUS="ok"\nelse\n TRACE_STATUS="error"\nfi\n\nTRACE_SERVICE="" TRACE_NAME="" TRACE_STATUS="$TRACE_STATUS" python3 .gitea/scripts/ci_trace_report.py --start-time "$CI_TRACE_START_TIME"\n\nexit 0\n"
|
||||
deploy-production:
|
||||
name: Deploy Production
|
||||
runs-on: runtime-builder
|
||||
@@ -642,6 +727,14 @@ jobs:
|
||||
tar.extract(member, '.')
|
||||
INNERPY
|
||||
|
||||
- name: Record start time & report trace start
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\necho "CI_TRACE_START_TIME=$(date +%s)" >> $GITHUB_ENV\nTRACE_SERVICE="" TRACE_NAME="" python3 .gitea/scripts/ci_trace_report.py --status running\n\nexit 0\n"
|
||||
- name: Record job start time
|
||||
shell: sh
|
||||
run: 'set -eu
|
||||
@@ -732,6 +825,15 @@ jobs:
|
||||
NOTIFY_MODE=failure JOB_NAME="Deploy Production" python3 scripts/ci_notify.py
|
||||
|
||||
'
|
||||
- name: Report trace end (always)
|
||||
if: always()
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\nif [ "${{ job.status }}" = "success" ]; then\n TRACE_STATUS="ok"\nelse\n TRACE_STATUS="error"\nfi\n\nTRACE_SERVICE="" TRACE_NAME="" TRACE_STATUS="$TRACE_STATUS" python3 .gitea/scripts/ci_trace_report.py --start-time "$CI_TRACE_START_TIME"\n\nexit 0\n"
|
||||
production-e2e:
|
||||
name: Production Browser E2E
|
||||
runs-on: runtime-builder
|
||||
@@ -745,6 +847,14 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
run: "set -eu\npython3 - <<'PY'\nimport io, os, tarfile, time, urllib.request, urllib.error\nurl = f\"{os.environ['GITHUB_API_URL']}/repos/{os.environ['GITHUB_REPOSITORY']}/archive/{os.environ['GITHUB_SHA']}.tar.gz\"\nrequest = urllib.request.Request(url, headers={\"Authorization\": f\"token {os.environ['GITHUB_TOKEN']}\"})\n# Retry up to 5 times with backoff for transient 5xx errors\nlast_err = None\nfor attempt in range(5):\n try:\n with urllib.request.urlopen(request, timeout=120) as response:\n archive = response.read()\n break\n except urllib.error.HTTPError as e:\n last_err = e\n if e.code >= 500 and attempt < 4:\n wait = 2 ** attempt\n print(f\"Checkout HTTP {e.code}, retrying in {wait}s (attempt {attempt+1}/5)...\")\n time.sleep(wait)\n continue\n raise\n except Exception as e:\n last_err = e\n if attempt < 4:\n wait = 2 ** attempt\n print(f\"'
|
||||
Checkout error: {e}, retrying in {wait}s (attempt {attempt+1}/5)...\")\n time.sleep(wait)\n continue\n raise\nelse:\n raise last_err\nwith tarfile.open(fileobj=io.BytesIO(archive), mode='r:gz') as tar:\n root_prefix = tar.getmembers()[0].name.split('/', 1)[0] + '/'\n for member in tar.getmembers():\n name = member.name\n if name == root_prefix[:-1]:\n continue\n if name.startswith(root_prefix):\n member.name = name[len(root_prefix):]\n if member.name:\n tar.extract(member, '.')\nPY\n"
|
||||
- name: Record start time & report trace start
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\necho "CI_TRACE_START_TIME=$(date +%s)" >> $GITHUB_ENV\nTRACE_SERVICE="" TRACE_NAME="" python3 .gitea/scripts/ci_trace_report.py --status running\n\nexit 0\n"
|
||||
- name: Record job start time
|
||||
shell: sh
|
||||
run: 'set -eu
|
||||
@@ -773,6 +883,15 @@ jobs:
|
||||
|
||||
'
|
||||
|
||||
- name: Report trace end (always)
|
||||
if: always()
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\nif [ "${{ job.status }}" = "success" ]; then\n TRACE_STATUS="ok"\nelse\n TRACE_STATUS="error"\nfi\n\nTRACE_SERVICE="" TRACE_NAME="" TRACE_STATUS="$TRACE_STATUS" python3 .gitea/scripts/ci_trace_report.py --start-time "$CI_TRACE_START_TIME"\n\nexit 0\n"
|
||||
acr-cleanup:
|
||||
name: ACR Image Cleanup
|
||||
runs-on: runtime-builder
|
||||
@@ -827,6 +946,14 @@ with tarfile.open(fileobj=io.BytesIO(archive), mode='r:gz') as tar:
|
||||
tar.extract(member, '.')
|
||||
INNERPY
|
||||
|
||||
- name: Record start time & report trace start
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\necho "CI_TRACE_START_TIME=$(date +%s)" >> $GITHUB_ENV\nTRACE_SERVICE="ci-build" TRACE_NAME="CI构建 / ACR Image Cleanup" python3 .gitea/scripts/ci_trace_report.py --status running\n\nexit 0\n"
|
||||
- name: Clean up old ACR images
|
||||
shell: sh
|
||||
env:
|
||||
@@ -845,3 +972,12 @@ INNERPY
|
||||
run: |
|
||||
set +e
|
||||
NOTIFY_MODE=failure JOB_NAME="ACR Image Cleanup" python3 scripts/ci_notify.py
|
||||
- name: Report trace end (always)
|
||||
if: always()
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\nif [ "${{ job.status }}" = "success" ]; then\n TRACE_STATUS="ok"\nelse\n TRACE_STATUS="error"\nfi\n\nTRACE_SERVICE="ci-build" TRACE_NAME="CI构建 / ACR Image Cleanup" TRACE_STATUS="$TRACE_STATUS" python3 .gitea/scripts/ci_trace_report.py --start-time "$CI_TRACE_START_TIME"\n\nexit 0\n"
|
||||
|
||||
+102
-1
@@ -35,6 +35,14 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
run: "set -eu\npython3 - <<'PY'\nimport io, os, tarfile, time, urllib.request, urllib.error\nurl = f\"{os.environ['GITHUB_API_URL']}/repos/{os.environ['GITHUB_REPOSITORY']}/archive/{os.environ['GITHUB_SHA']}.tar.gz\"\nrequest = urllib.request.Request(url, headers={\"Authorization\": f\"token {os.environ['GITHUB_TOKEN']}\"})\nlast_err = None\nfor attempt in range(5):\n try:\n with urllib.request.urlopen(request, timeout=120) as response:\n archive = response.read()\n break\n except urllib.error.HTTPError as e:\n last_err = e\n if e.code >= 500 and attempt < 4:\n wait = 2 ** attempt\n print(f\"Checkout HTTP {e.code}, retrying in {wait}s (attempt {attempt+1}/5)...\")\n time.sleep(wait)\n continue\n raise\n except Exception as e:\n last_err = e\n if attempt < 4:\n wait = 2 ** attempt\n print(f\"Checkout error: {e}, retrying in {wait}s (attempt {attempt+1}/5)...\")\n time.sleep(wait)\n continue\n raise\nelse:\n raise last_err\nwith tarfile.open(fileobj=io.BytesIO(archive), mode='r:gz') as tar:\n root_prefix = tar.getmembers()[0].name.split('/', 1)[0] + '/'\n for member in tar.getmembers():\n name = member.name\n if name == root_prefix[:-1]:\n continue\n if name.startswith(root_prefix):\n member.name = name[len(root_prefix):]\n if member.name:\n tar.extract(member, '.')\nPY\n"
|
||||
- name: Record start time & report trace start
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\necho "CI_TRACE_START_TIME=$(date +%s)" >> $GITHUB_ENV\nTRACE_SERVICE="" TRACE_NAME="" python3 .gitea/scripts/ci_trace_report.py --status running\n\nexit 0\n"
|
||||
- name: Check changed files
|
||||
id: check
|
||||
shell: bash
|
||||
@@ -63,6 +71,15 @@ jobs:
|
||||
echo "🔧 包含全栈变更,运行完整CI"
|
||||
fi
|
||||
|
||||
- name: Report trace end (always)
|
||||
if: always()
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\nif [ "${{ job.status }}" = "success" ]; then\n TRACE_STATUS="ok"\nelse\n TRACE_STATUS="error"\nfi\n\nTRACE_SERVICE="" TRACE_NAME="" TRACE_STATUS="$TRACE_STATUS" python3 .gitea/scripts/ci_trace_report.py --start-time "$CI_TRACE_START_TIME"\n\nexit 0\n"
|
||||
validate:
|
||||
needs: check-frontend-only
|
||||
if: always() && needs.check-frontend-only.outputs.skip_backend != 'true'
|
||||
@@ -81,6 +98,14 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
run: "set -eu\npython3 - <<'PY'\nimport io, os, tarfile, time, urllib.request, urllib.error\nurl = f\"{os.environ['GITHUB_API_URL']}/repos/{os.environ['GITHUB_REPOSITORY']}/archive/{os.environ['GITHUB_SHA']}.tar.gz\"\nrequest = urllib.request.Request(url, headers={\"Authorization\": f\"token {os.environ['GITHUB_TOKEN']}\"})\nlast_err = None\nfor attempt in range(5):\n try:\n with urllib.request.urlopen(request, timeout=120) as response:\n archive = response.read()\n break\n except urllib.error.HTTPError as e:\n last_err = e\n if e.code >= 500 and attempt < 4:\n wait = 2 ** attempt\n print(f\"Checkout HTTP {e.code}, retrying in {wait}s (attempt {attempt+1}/5)...\")\n time.sleep(wait)\n continue\n raise\n except Exception as e:\n last_err = e\n if attempt < 4:\n wait = 2 ** attempt\n print(f\"Checkout error: {e}, retrying in {wait}s (attempt {attempt+1}/5)...\"\
|
||||
)\n time.sleep(wait)\n continue\n raise\nelse:\n raise last_err\nwith tarfile.open(fileobj=io.BytesIO(archive), mode='r:gz') as tar:\n root_prefix = tar.getmembers()[0].name.split('/', 1)[0] + '/'\n for member in tar.getmembers():\n name = member.name\n if name == root_prefix[:-1]:\n continue\n if name.startswith(root_prefix):\n member.name = name[len(root_prefix):]\n if member.name:\n tar.extract(member, '.')\nPY\n"
|
||||
- name: Record start time & report trace start
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\necho "CI_TRACE_START_TIME=$(date +%s)" >> $GITHUB_ENV\nTRACE_SERVICE="" TRACE_NAME="" python3 .gitea/scripts/ci_trace_report.py --status running\n\nexit 0\n"
|
||||
- name: Record job start time
|
||||
shell: sh
|
||||
run: 'set -eu
|
||||
@@ -233,6 +258,15 @@ jobs:
|
||||
NOTIFY_MODE=failure JOB_NAME="Validate Code Quality And Tests" python3 scripts/ci_notify.py
|
||||
|
||||
'
|
||||
- name: Report trace end (always)
|
||||
if: always()
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\nif [ "${{ job.status }}" = "success" ]; then\n TRACE_STATUS="ok"\nelse\n TRACE_STATUS="error"\nfi\n\nTRACE_SERVICE="" TRACE_NAME="" TRACE_STATUS="$TRACE_STATUS" python3 .gitea/scripts/ci_trace_report.py --start-time "$CI_TRACE_START_TIME"\n\nexit 0\n"
|
||||
unit-tests:
|
||||
needs: check-frontend-only
|
||||
if: always() && needs.check-frontend-only.outputs.skip_backend != 'true'
|
||||
@@ -252,6 +286,14 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
run: "set -eu\npython3 - <<'PY'\nimport io, os, tarfile, time, urllib.request, urllib.error\nurl = f\"{os.environ['GITHUB_API_URL']}/repos/{os.environ['GITHUB_REPOSITORY']}/archive/{os.environ['GITHUB_SHA']}.tar.gz\"\nrequest = urllib.request.Request(url, headers={\"Authorization\": f\"token {os.environ['GITHUB_TOKEN']}\"})\nlast_err = None\nfor attempt in range(5):\n try:\n with urllib.request.urlopen(request, timeout=120) as response:\n archive = response.read()\n break\n except urllib.error.HTTPError as e:\n last_err = e\n if e.code >= 500 and attempt < 4:\n wait = 2 ** attempt\n print(f\"Checkout HTTP {e.code}, retrying in {wait}s (attempt {attempt+1}/5)...\")\n time.sleep(wait)\n continue\n raise\n except Exception as e:\n last_err = e\n if attempt < 4:\n wait = 2 ** attempt\n print(f\"Checkout error: {e}, retrying in {wait}s (attempt {attempt+1}/5)...\"\
|
||||
)\n time.sleep(wait)\n continue\n raise\nelse:\n raise last_err\nwith tarfile.open(fileobj=io.BytesIO(archive), mode='r:gz') as tar:\n root_prefix = tar.getmembers()[0].name.split('/', 1)[0] + '/'\n for member in tar.getmembers():\n name = member.name\n if name == root_prefix[:-1]:\n continue\n if name.startswith(root_prefix):\n member.name = name[len(root_prefix):]\n if member.name:\n tar.extract(member, '.')\nPY\n"
|
||||
- name: Record start time & report trace start
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\necho "CI_TRACE_START_TIME=$(date +%s)" >> $GITHUB_ENV\nTRACE_SERVICE="" TRACE_NAME="" python3 .gitea/scripts/ci_trace_report.py --status running\n\nexit 0\n"
|
||||
- name: Record job start time
|
||||
shell: sh
|
||||
run: 'set -eu
|
||||
@@ -425,6 +467,15 @@ jobs:
|
||||
NOTIFY_MODE=failure JOB_NAME="Unit Tests" python3 scripts/ci_notify.py
|
||||
|
||||
'
|
||||
- name: Report trace end (always)
|
||||
if: always()
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\nif [ "${{ job.status }}" = "success" ]; then\n TRACE_STATUS="ok"\nelse\n TRACE_STATUS="error"\nfi\n\nTRACE_SERVICE="" TRACE_NAME="" TRACE_STATUS="$TRACE_STATUS" python3 .gitea/scripts/ci_trace_report.py --start-time "$CI_TRACE_START_TIME"\n\nexit 0\n"
|
||||
integration-tests:
|
||||
name: Integration Tests
|
||||
runs-on: ci-l2
|
||||
@@ -447,6 +498,14 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
run: "set -eu\npython3 - <<'PY'\nimport io, os, tarfile, time, urllib.request, urllib.error\nurl = f\"{os.environ['GITHUB_API_URL']}/repos/{os.environ['GITHUB_REPOSITORY']}/archive/{os.environ['GITHUB_SHA']}.tar.gz\"\nrequest = urllib.request.Request(url, headers={\"Authorization\": f\"token {os.environ['GITHUB_TOKEN']}\"})\nlast_err = None\nfor attempt in range(5):\n try:\n with urllib.request.urlopen(request, timeout=120) as response:\n archive = response.read()\n break\n except urllib.error.HTTPError as e:\n last_err = e\n if e.code >= 500 and attempt < 4:\n wait = 2 ** attempt\n print(f\"Checkout HTTP {e.code}, retrying in {wait}s (attempt {attempt+1}/5)...\")\n time.sleep(wait)\n continue\n raise\n except Exception as e:\n last_err = e\n if attempt < 4:\n wait = 2 ** attempt\n print(f\"Checkout error: {e}, retrying in {wait}s (attempt {attempt+1}/5)...\"\
|
||||
)\n time.sleep(wait)\n continue\n raise\nelse:\n raise last_err\nwith tarfile.open(fileobj=io.BytesIO(archive), mode='r:gz') as tar:\n root_prefix = tar.getmembers()[0].name.split('/', 1)[0] + '/'\n for member in tar.getmembers():\n name = member.name\n if name == root_prefix[:-1]:\n continue\n if name.startswith(root_prefix):\n member.name = name[len(root_prefix):]\n if member.name:\n tar.extract(member, '.')\nPY\n"
|
||||
- name: Record start time & report trace start
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\necho "CI_TRACE_START_TIME=$(date +%s)" >> $GITHUB_ENV\nTRACE_SERVICE="" TRACE_NAME="" python3 .gitea/scripts/ci_trace_report.py --status running\n\nexit 0\n"
|
||||
- name: Record job start time
|
||||
shell: sh
|
||||
run: 'set -eu
|
||||
@@ -544,6 +603,15 @@ jobs:
|
||||
NOTIFY_MODE=failure JOB_NAME="Integration Tests" python3 scripts/ci_notify.py
|
||||
|
||||
'
|
||||
- name: Report trace end (always)
|
||||
if: always()
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\nif [ "${{ job.status }}" = "success" ]; then\n TRACE_STATUS="ok"\nelse\n TRACE_STATUS="error"\nfi\n\nTRACE_SERVICE="" TRACE_NAME="" TRACE_STATUS="$TRACE_STATUS" python3 .gitea/scripts/ci_trace_report.py --start-time "$CI_TRACE_START_TIME"\n\nexit 0\n"
|
||||
frontend-lint:
|
||||
name: Frontend Lint
|
||||
runs-on: ci-check
|
||||
@@ -555,6 +623,14 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
run: "set -eu\npython3 - <<'PY'\nimport io, os, tarfile, time, urllib.request, urllib.error\nurl = f\"{os.environ['GITHUB_API_URL']}/repos/{os.environ['GITHUB_REPOSITORY']}/archive/{os.environ['GITHUB_SHA']}.tar.gz\"\nrequest = urllib.request.Request(url, headers={\"Authorization\": f\"token {os.environ['GITHUB_TOKEN']}\"})\nlast_err = None\nfor attempt in range(5):\n try:\n with urllib.request.urlopen(request, timeout=120) as response:\n archive = response.read()\n break\n except urllib.error.HTTPError as e:\n last_err = e\n if e.code >= 500 and attempt < 4:\n wait = 2 ** attempt\n print(f\"Checkout HTTP {e.code}, retrying in {wait}s (attempt {attempt+1}/5)...\")\n time.sleep(wait)\n continue\n raise\n except Exception as e:\n last_err = e\n if attempt < 4:\n wait = 2 ** attempt\n print(f\"Checkout error: {e}, retrying in {wait}s (attempt {attempt+1}/5)...\"\
|
||||
)\n time.sleep(wait)\n continue\n raise\nelse:\n raise last_err\nwith tarfile.open(fileobj=io.BytesIO(archive), mode='r:gz') as tar:\n root_prefix = tar.getmembers()[0].name.split('/', 1)[0] + '/'\n for member in tar.getmembers():\n name = member.name\n if name == root_prefix[:-1]:\n continue\n if name.startswith(root_prefix):\n member.name = name[len(root_prefix):]\n if member.name:\n tar.extract(member, '.')\nPY\n"
|
||||
- name: Record start time & report trace start
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\necho "CI_TRACE_START_TIME=$(date +%s)" >> $GITHUB_ENV\nTRACE_SERVICE="" TRACE_NAME="" python3 .gitea/scripts/ci_trace_report.py --status running\n\nexit 0\n"
|
||||
- name: Record job start time
|
||||
shell: sh
|
||||
run: 'set -eu
|
||||
@@ -596,6 +672,15 @@ jobs:
|
||||
'
|
||||
|
||||
|
||||
- name: Report trace end (always)
|
||||
if: always()
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\nif [ "${{ job.status }}" = "success" ]; then\n TRACE_STATUS="ok"\nelse\n TRACE_STATUS="error"\nfi\n\nTRACE_SERVICE="" TRACE_NAME="" TRACE_STATUS="$TRACE_STATUS" python3 .gitea/scripts/ci_trace_report.py --start-time "$CI_TRACE_START_TIME"\n\nexit 0\n"
|
||||
frontend-unit-test:
|
||||
name: Frontend Unit Tests
|
||||
runs-on: ci-check
|
||||
@@ -608,6 +693,14 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
run: "set -eu\npython3 - <<'PY'\nimport io, os, tarfile, time, urllib.request, urllib.error\nurl = f\"{os.environ['GITHUB_API_URL']}/repos/{os.environ['GITHUB_REPOSITORY']}/archive/{os.environ['GITHUB_SHA']}.tar.gz\"\nrequest = urllib.request.Request(url, headers={\"Authorization\": f\"token {os.environ['GITHUB_TOKEN']}\"})\nlast_err = None\nfor attempt in range(5):\n try:\n with urllib.request.urlopen(request, timeout=120) as response:\n archive = response.read()\n break\n except urllib.error.HTTPError as e:\n last_err = e\n if e.code >= 500 and attempt < 4:\n wait = 2 ** attempt\n print(f\"Checkout HTTP {e.code}, retrying in {wait}s (attempt {attempt+1}/5)...\")\n time.sleep(wait)\n continue\n raise\n except Exception as e:\n last_err = e\n if attempt < 4:\n wait = 2 ** attempt\n print(f\"Checkout error: {e}, retrying in {wait}s (attempt {attempt+1}/5)...\")\n time.sleep(wait)\n continue\n raise\nelse:\n raise last_err\nwith tarfile.open(fileobj=io.BytesIO(archive), mode='r:gz') as tar:\n root_prefix = tar.getmembers()[0].name.split('/', 1)[0] + '/'\n for member in tar.getmembers():\n name = member.name\n if name == root_prefix[:-1]:\n continue\n if name.startswith(root_prefix):\n member.name = name[len(root_prefix):]\n if member.name:\n tar.extract(member, '.')\nPY\n"
|
||||
- name: Record start time & report trace start
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\necho "CI_TRACE_START_TIME=$(date +%s)" >> $GITHUB_ENV\nTRACE_SERVICE="" TRACE_NAME="" python3 .gitea/scripts/ci_trace_report.py --status running\n\nexit 0\n"
|
||||
- name: Record job start time
|
||||
shell: sh
|
||||
run: 'set -eu
|
||||
@@ -637,4 +730,12 @@ jobs:
|
||||
|
||||
NOTIFY_MODE=failure JOB_NAME="Frontend Unit Tests" python3 scripts/ci_notify.py
|
||||
|
||||
'
|
||||
' - name: Report trace end (always)
|
||||
if: always()
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\nif [ "${{ job.status }}" = "success" ]; then\n TRACE_STATUS="ok"\nelse\n TRACE_STATUS="error"\nfi\n\nTRACE_SERVICE="" TRACE_NAME="" TRACE_STATUS="$TRACE_STATUS" python3 .gitea/scripts/ci_trace_report.py --start-time "$CI_TRACE_START_TIME"\n\nexit 0\n"
|
||||
|
||||
@@ -22,6 +22,14 @@ jobs:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Record start time & report trace start
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\necho "CI_TRACE_START_TIME=$(date +%s)" >> $GITHUB_ENV\nTRACE_SERVICE="ci-trigger-monitor" TRACE_NAME="CI触发监控 / Monitor CI Trigger Reliability" python3 .gitea/scripts/ci_trace_report.py --status running\n\nexit 0\n"
|
||||
- name: Check CI trigger status for all open PRs
|
||||
env:
|
||||
GITEA_API_TOKEN: ${{ secrets.REVIEW_GITEA_TOKEN }}
|
||||
@@ -34,3 +42,12 @@ jobs:
|
||||
python3 scripts/ci_trigger_monitor.py
|
||||
# 监控脚本永远不fail,避免告警风暴
|
||||
exit 0
|
||||
- name: Report trace end (always)
|
||||
if: always()
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\nif [ "${{ job.status }}" = "success" ]; then\n TRACE_STATUS="ok"\nelse\n TRACE_STATUS="error"\nfi\n\nTRACE_SERVICE="ci-trigger-monitor" TRACE_NAME="CI触发监控 / Monitor CI Trigger Reliability" TRACE_STATUS="$TRACE_STATUS" python3 .gitea/scripts/ci_trace_report.py --start-time "$CI_TRACE_START_TIME"\n\nexit 0\n"
|
||||
|
||||
@@ -25,6 +25,14 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Record start time & report trace start
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\necho "CI_TRACE_START_TIME=$(date +%s)" >> $GITHUB_ENV\nTRACE_SERVICE="code-review" TRACE_NAME="AI代码审查 / AI Code Review" python3 .gitea/scripts/ci_trace_report.py --status running\n\nexit 0\n"
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python3 -m pip install --upgrade pip
|
||||
@@ -51,3 +59,12 @@ jobs:
|
||||
python3 scripts/ci_code_review.py
|
||||
# 审查脚本异常不影响 CI 通过
|
||||
continue-on-error: true
|
||||
- name: Report trace end (always)
|
||||
if: always()
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\nif [ "${{ job.status }}" = "success" ]; then\n TRACE_STATUS="ok"\nelse\n TRACE_STATUS="error"\nfi\n\nTRACE_SERVICE="code-review" TRACE_NAME="AI代码审查 / AI Code Review" TRACE_STATUS="$TRACE_STATUS" python3 .gitea/scripts/ci_trace_report.py --start-time "$CI_TRACE_START_TIME"\n\nexit 0\n"
|
||||
|
||||
@@ -64,6 +64,14 @@ jobs:
|
||||
tar.extract(member, '.')
|
||||
PY
|
||||
|
||||
- name: Record start time & report trace start
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\necho "CI_TRACE_START_TIME=$(date +%s)" >> $GITHUB_ENV\nTRACE_SERVICE="daily-check" TRACE_NAME="每日健康检查 / Production Smoke Test" python3 .gitea/scripts/ci_trace_report.py --status running\n\nexit 0\n"
|
||||
- name: Production health check & smoke test
|
||||
id: smoke
|
||||
shell: sh
|
||||
@@ -107,6 +115,15 @@ jobs:
|
||||
exit $SMOKE_EXIT
|
||||
|
||||
# ── 2. Staging API 集成测试 ─────────────────────────────────────────
|
||||
- name: Report trace end (always)
|
||||
if: always()
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\nif [ "${{ job.status }}" = "success" ]; then\n TRACE_STATUS="ok"\nelse\n TRACE_STATUS="error"\nfi\n\nTRACE_SERVICE="daily-check" TRACE_NAME="每日健康检查 / Production Smoke Test" TRACE_STATUS="$TRACE_STATUS" python3 .gitea/scripts/ci_trace_report.py --start-time "$CI_TRACE_START_TIME"\n\nexit 0\n"
|
||||
staging-api-tests:
|
||||
name: Staging API Integration Tests
|
||||
runs-on: saas
|
||||
@@ -161,6 +178,14 @@ jobs:
|
||||
tar.extract(member, '.')
|
||||
PY
|
||||
|
||||
- name: Record start time & report trace start
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\necho "CI_TRACE_START_TIME=$(date +%s)" >> $GITHUB_ENV\nTRACE_SERVICE="daily-check" TRACE_NAME="每日健康检查 / Staging API Integration Tests" python3 .gitea/scripts/ci_trace_report.py --status running\n\nexit 0\n"
|
||||
- name: Run API smoke test on staging
|
||||
id: smoke
|
||||
shell: sh
|
||||
@@ -244,6 +269,15 @@ jobs:
|
||||
fi
|
||||
|
||||
# ── 3. Staging 浏览器 E2E ──────────────────────────────────────────
|
||||
- name: Report trace end (always)
|
||||
if: always()
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\nif [ "${{ job.status }}" = "success" ]; then\n TRACE_STATUS="ok"\nelse\n TRACE_STATUS="error"\nfi\n\nTRACE_SERVICE="daily-check" TRACE_NAME="每日健康检查 / Staging API Integration Tests" TRACE_STATUS="$TRACE_STATUS" python3 .gitea/scripts/ci_trace_report.py --start-time "$CI_TRACE_START_TIME"\n\nexit 0\n"
|
||||
staging-e2e:
|
||||
name: Staging Browser E2E
|
||||
runs-on: saas
|
||||
@@ -298,6 +332,14 @@ jobs:
|
||||
tar.extract(member, '.')
|
||||
PY
|
||||
|
||||
- name: Record start time & report trace start
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\necho "CI_TRACE_START_TIME=$(date +%s)" >> $GITHUB_ENV\nTRACE_SERVICE="daily-check" TRACE_NAME="每日健康检查 / Staging Browser E2E" python3 .gitea/scripts/ci_trace_report.py --status running\n\nexit 0\n"
|
||||
- name: Run Playwright E2E on staging
|
||||
id: e2e
|
||||
shell: sh
|
||||
@@ -333,6 +375,15 @@ jobs:
|
||||
exit $EXIT_CODE
|
||||
|
||||
# ── 4. 性能基线巡检 ────────────────────────────────────────────────
|
||||
- name: Report trace end (always)
|
||||
if: always()
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\nif [ "${{ job.status }}" = "success" ]; then\n TRACE_STATUS="ok"\nelse\n TRACE_STATUS="error"\nfi\n\nTRACE_SERVICE="daily-check" TRACE_NAME="每日健康检查 / Staging Browser E2E" TRACE_STATUS="$TRACE_STATUS" python3 .gitea/scripts/ci_trace_report.py --start-time "$CI_TRACE_START_TIME"\n\nexit 0\n"
|
||||
performance-check:
|
||||
name: Performance Baseline Check
|
||||
runs-on: saas
|
||||
@@ -456,6 +507,14 @@ jobs:
|
||||
echo "耗时: ${ELAPSED}s"
|
||||
echo "======================================"
|
||||
|
||||
- name: Record start time & report trace start
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\necho "CI_TRACE_START_TIME=$(date +%s)" >> $GITHUB_ENV\nTRACE_SERVICE="daily-check" TRACE_NAME="每日健康检查 / Performance Baseline Check" python3 .gitea/scripts/ci_trace_report.py --status running\n\nexit 0\n"
|
||||
- name: Generate performance report
|
||||
id: report
|
||||
shell: sh
|
||||
@@ -581,6 +640,15 @@ jobs:
|
||||
fi
|
||||
|
||||
# ── 5. 每日巡检汇总报告 ────────────────────────────────────────────
|
||||
- name: Report trace end (always)
|
||||
if: always()
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\nif [ "${{ job.status }}" = "success" ]; then\n TRACE_STATUS="ok"\nelse\n TRACE_STATUS="error"\nfi\n\nTRACE_SERVICE="daily-check" TRACE_NAME="每日健康检查 / Performance Baseline Check" TRACE_STATUS="$TRACE_STATUS" python3 .gitea/scripts/ci_trace_report.py --start-time "$CI_TRACE_START_TIME"\n\nexit 0\n"
|
||||
daily-report:
|
||||
name: Daily Check Report
|
||||
runs-on: saas
|
||||
@@ -656,3 +724,20 @@ jobs:
|
||||
# 不 exit 1,因为我们用了 always(),保持 report job 成功,
|
||||
# 但其他失败的 job 已经让整体流水线标记为失败
|
||||
fi
|
||||
- name: Record start time & report trace start
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\necho "CI_TRACE_START_TIME=$(date +%s)" >> $GITHUB_ENV\nTRACE_SERVICE="daily-check" TRACE_NAME="每日健康检查 / Daily Check Report" python3 .gitea/scripts/ci_trace_report.py --status running\n\nexit 0\n"
|
||||
- name: Report trace end (always)
|
||||
if: always()
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\nif [ "${{ job.status }}" = "success" ]; then\n TRACE_STATUS="ok"\nelse\n TRACE_STATUS="error"\nfi\n\nTRACE_SERVICE="daily-check" TRACE_NAME="每日健康检查 / Daily Check Report" TRACE_STATUS="$TRACE_STATUS" python3 .gitea/scripts/ci_trace_report.py --start-time "$CI_TRACE_START_TIME"\n\nexit 0\n"
|
||||
|
||||
@@ -61,6 +61,14 @@ jobs:
|
||||
tar.extract(member, '.')
|
||||
PY
|
||||
|
||||
- name: Record start time & report trace start
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\necho "CI_TRACE_START_TIME=$(date +%s)" >> $GITHUB_ENV\nTRACE_SERVICE="" TRACE_NAME="" python3 .gitea/scripts/ci_trace_report.py --status running\n\nexit 0\n"
|
||||
- name: Extract PR number
|
||||
shell: sh
|
||||
run: |
|
||||
@@ -193,3 +201,12 @@ jobs:
|
||||
> /dev/null
|
||||
echo "Cleanup comment posted"
|
||||
|
||||
- name: Report trace end (always)
|
||||
if: always()
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\nif [ "${{ job.status }}" = "success" ]; then\n TRACE_STATUS="ok"\nelse\n TRACE_STATUS="error"\nfi\n\nTRACE_SERVICE="" TRACE_NAME="" TRACE_STATUS="$TRACE_STATUS" python3 .gitea/scripts/ci_trace_report.py --start-time "$CI_TRACE_START_TIME"\n\nexit 0\n"
|
||||
|
||||
@@ -72,6 +72,14 @@ jobs:
|
||||
tar.extract(member, '.')
|
||||
PY
|
||||
|
||||
- name: Record start time & report trace start
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\necho "CI_TRACE_START_TIME=$(date +%s)" >> $GITHUB_ENV\nTRACE_SERVICE="" TRACE_NAME="" python3 .gitea/scripts/ci_trace_report.py --status running\n\nexit 0\n"
|
||||
- name: Record job start time
|
||||
shell: sh
|
||||
run: |
|
||||
@@ -272,3 +280,12 @@ jobs:
|
||||
run: |
|
||||
set +e
|
||||
NOTIFY_MODE=failure JOB_NAME="Deploy Preview Environment" python3 scripts/ci_notify.py
|
||||
- name: Report trace end (always)
|
||||
if: always()
|
||||
shell: sh
|
||||
env:
|
||||
AGENTLOOP_ENDPOINT: ${ secrets.AGENTLOOP_ENDPOINT }
|
||||
AGENTLOOP_LICENSE_KEY: ${ secrets.AGENTLOOP_LICENSE_KEY }
|
||||
AGENTLOOP_PROJECT: ${ secrets.AGENTLOOP_PROJECT }
|
||||
AGENTLOOP_WORKSPACE: ${ secrets.AGENTLOOP_WORKSPACE }
|
||||
run: "set +e\n\nif [ "${{ job.status }}" = "success" ]; then\n TRACE_STATUS="ok"\nelse\n TRACE_STATUS="error"\nfi\n\nTRACE_SERVICE="" TRACE_NAME="" TRACE_STATUS="$TRACE_STATUS" python3 .gitea/scripts/ci_trace_report.py --start-time "$CI_TRACE_START_TIME"\n\nexit 0\n"
|
||||
|
||||
Reference in New Issue
Block a user