80 lines
3.3 KiB
Python
80 lines
3.3 KiB
Python
#!/usr/bin/env python3
|
||
"""day-тик 2026-10-05: диагностика/восстановление деплой-канала (e-261004110909-bd70b0).
|
||
|
||
Токены из конфигов читаются, но НИКОГДА не печатаются (только префикс 6 симв.).
|
||
Использование: venv/bin/python scripts/deploy_channel_probe.py [--push]
|
||
"""
|
||
import json
|
||
import re
|
||
import sys
|
||
import urllib.error
|
||
import urllib.request
|
||
|
||
GIT = "https://git.cil.by"
|
||
CFG_VYBIRAI = "/home/hermes/vybirai/.git/config"
|
||
CFG_LOCAL = ".git/config"
|
||
|
||
# наш push-токен (узкий скоп) — из локального remote
|
||
LOCAL_TOKEN = re.search(r":([a-f0-9]{40})@", open(CFG_LOCAL).read()).group(1)
|
||
|
||
|
||
def broad_token():
|
||
"""Токен 9f29709… (KEYS-REGISTRY §1, admin-скоп) из конфига vybirai-клона."""
|
||
txt = open(CFG_VYBIRAI, errors="ignore").read()
|
||
m = re.search(r":([a-f0-9]{40})@", txt)
|
||
return m.group(1) if m else None
|
||
|
||
|
||
def api(path, tok, method="GET", data=None, expect_json=True):
|
||
req = urllib.request.Request(
|
||
f"{GIT}/api/v1{path}",
|
||
data=json.dumps(data).encode() if data is not None else None,
|
||
headers={"Authorization": f"token {tok}", "Content-Type": "application/json"},
|
||
method=method,
|
||
)
|
||
try:
|
||
with urllib.request.urlopen(req, timeout=10) as r:
|
||
body = r.read().decode(errors="ignore")
|
||
return r.status, (json.loads(body) if expect_json and body else body)
|
||
except urllib.error.HTTPError as e:
|
||
return e.code, e.read().decode(errors="ignore")[:200]
|
||
except Exception as e: # noqa: BLE001
|
||
return -1, str(e)[:80]
|
||
|
||
|
||
def main():
|
||
do_push = "--push" in sys.argv
|
||
tok = broad_token()
|
||
print(f"local token: {LOCAL_TOKEN[:6]}… (узкий скоп, push=403 — подтверждено)")
|
||
if not tok:
|
||
print("broad token: НЕ НАЙДЕН — деплой-канал не восстановить")
|
||
return 2
|
||
same = tok == LOCAL_TOKEN
|
||
print(f"broad token: {tok[:6]}… (KEYS-REGISTRY §1; совпадает с локальным: {same})")
|
||
|
||
st, me = api("/user", tok)
|
||
print(f"read:user: {st} login={me.get('login') if isinstance(me, dict) else me} "
|
||
f"is_admin={me.get('is_admin') if isinstance(me, dict) else '?'}")
|
||
if st != 200:
|
||
return 2
|
||
|
||
st, repos = api("/user/repos?limit=50", tok)
|
||
print(f"repos visible: {st}, count={len(repos) if isinstance(repos, list) else '?'}")
|
||
if isinstance(repos, list):
|
||
for r in sorted(repos, key=lambda x: x["updated_at"], reverse=True):
|
||
print(f" - {r['full_name']:45} default={r['default_branch']:10.10} "
|
||
f"upd={r['updated_at'][:16]}")
|
||
|
||
if do_push:
|
||
# идемпотентный тест записи: временная ветка в нашем репо + удаление
|
||
st, br = api("/repos/symbiot/simbiot-harness/branches", tok, "POST",
|
||
{"new_branch_name": "scope-probe-day", "old_branch_name": "master"})
|
||
print(f"write probe (create branch): {st}")
|
||
if st in (201, 200):
|
||
api("/repos/symbiot/simbiot-harness/branches/scope-probe-day", tok, "DELETE")
|
||
print(" probe-ветка удалена; write:repository ЕСТЬ")
|
||
return 0
|
||
|
||
|
||
if __name__ == "__main__":
|
||
sys.exit(main())
|