feat(replication): расхардкод хоста + секреты нового хоста + smoke-runbook
Фундамент тиража 10-common (эпик ORCH-10): платформа разворачивается на
новой инфре без правки кода — только env/конфиг. Каждый дефолт = боевому
значению (пустой .env => поведение 1:1, kill-switch-природа, NFR-2);
STAGE_TRANSITIONS/QG_CHECKS/check_*/machine-verdict/схема БД не тронуты.
- config: agent_home_dir / agent_git_name / git_email_domain / staging_port
(ADR-001 D2/D4); код-блокеры A1-A4 закрыты: plane_sync ссылки из
gitea_public_url+gitea_owner, launcher - единый agent_git_env() (x2 места),
self_deploy/post_deploy - HOME+домен из Settings (имена системных акторов -
платформенные литералы)
- image_freshness: staging_port из конфига + fail-closed guard
staging_port == прод-порт -> отказ ДО ssh/build (инвариант ORCH-058 AC-9
стал исполняемым); REPO= передаётся хуку явно обоими инвокерами (D7)
- SELF_HOSTING_REPO - нормативная платформенная константа (D3, пин-тест)
- compose: полная ${VAR:-default}-интерполяция (реестр B, карта D6); группа
ORCH-040 uid/gid/HOME/маунты двигается согласованно (build.args APP_*);
group_add "МИНА 1" сохранён x3; оба app-сервиса с явным command:
- Dockerfile: ARG APP_UID/APP_GID/APP_USER/APP_HOME (CMD exec-form 8500
сознательно не тронут - D5); deploy-hook: REPO="${REPO:-...}" (D1 реестра)
- секреты: stdlib scripts/gen_secrets.py (token_hex(32); печать по умолчанию;
--write никогда не перезаписывает существующий .env молча, exit=2;
перезапись только --force); .env.example дополнен до полноты ключей старта
- доки: новый docs/operations/REPLICATION.md (карта env, чек-лист секретов,
smoke-процедура с PASS/FAIL, границы 10-common/Lite/Bundled), INFRA.md,
README, CLAUDE.md, CHANGELOG
- анти-регресс: tests/test_no_host_hardcodes.py (tokenize-сканер запрещённых
литералов, config-модули - структурное исключение, allowlist пуст,
негативная самопроверка) + test_host_config_keys / test_infra_parametrization
/ test_secrets_gen / test_replication_smoke; согласованные структурные
правки test_orch040_compose (судит резолв дефолтов) и
test_deploy_hook_rollback_sim (REPO через env-override = контракт D7)
Полный регресс: 1764 passed.
Refs: ORCH-101
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -51,6 +51,31 @@ def is_valid_model(name: str) -> bool:
|
||||
return False
|
||||
return bool(_MODEL_NAME_RE.match(name.strip()))
|
||||
|
||||
|
||||
def agent_git_env() -> dict:
|
||||
"""ORCH-101 (A2): subprocess env for agent runs and their git commit/push.
|
||||
|
||||
HOME and the git identity are read from Settings (ORCH_AGENT_HOME_DIR /
|
||||
ORCH_AGENT_GIT_NAME / ORCH_GIT_EMAIL_DOMAIN) instead of host hardcodes; the
|
||||
defaults equal the previous production literals (/home/slin,
|
||||
claude-bot@mva154.local), so an unset env is byte-for-byte the old
|
||||
behaviour (BR-5 zero-regression). Single source for BOTH launch sites (the
|
||||
agent Popen and the post-run git commit/push), so the two can never drift.
|
||||
HOME must stay consistent with the compose mounts of .claude/.ssh
|
||||
(ORCH-040 invariant — the same ORCH_AGENT_HOME_DIR interpolates the mount
|
||||
targets in docker-compose.yml).
|
||||
"""
|
||||
email = f"{settings.agent_git_name}@{settings.git_email_domain}"
|
||||
return {
|
||||
**os.environ,
|
||||
"HOME": settings.agent_home_dir,
|
||||
"GIT_AUTHOR_NAME": settings.agent_git_name,
|
||||
"GIT_AUTHOR_EMAIL": email,
|
||||
"GIT_COMMITTER_NAME": settings.agent_git_name,
|
||||
"GIT_COMMITTER_EMAIL": email,
|
||||
}
|
||||
|
||||
|
||||
# ORCH-061: action stages whose success is an ACTION (restart/retag), not a src
|
||||
# edit — so "no changes to commit" is EXPECTED there, not under-delivery (FR-3).
|
||||
_ACTION_STAGES = frozenset({"deploy-staging", "deploy"})
|
||||
@@ -589,14 +614,9 @@ class AgentLauncher:
|
||||
["bash", "-c", cmd],
|
||||
stdout=log_fh,
|
||||
stderr=subprocess.STDOUT,
|
||||
env={
|
||||
**os.environ,
|
||||
"HOME": "/home/slin",
|
||||
"GIT_AUTHOR_NAME": "claude-bot",
|
||||
"GIT_AUTHOR_EMAIL": "claude-bot@mva154.local",
|
||||
"GIT_COMMITTER_NAME": "claude-bot",
|
||||
"GIT_COMMITTER_EMAIL": "claude-bot@mva154.local",
|
||||
},
|
||||
# ORCH-101 (A2): HOME + git identity from Settings (defaults = the
|
||||
# previous hardcoded values), shared with the post-run git env.
|
||||
env=agent_git_env(),
|
||||
)
|
||||
|
||||
# Update DB with output path
|
||||
@@ -820,14 +840,8 @@ class AgentLauncher:
|
||||
# (ensure_worktree did the checkout), so no checkout is needed here.
|
||||
repo_path = get_worktree_path(repo, branch)
|
||||
try:
|
||||
git_env = {
|
||||
**os.environ,
|
||||
"HOME": "/home/slin",
|
||||
"GIT_AUTHOR_NAME": "claude-bot",
|
||||
"GIT_AUTHOR_EMAIL": "claude-bot@mva154.local",
|
||||
"GIT_COMMITTER_NAME": "claude-bot",
|
||||
"GIT_COMMITTER_EMAIL": "claude-bot@mva154.local",
|
||||
}
|
||||
# ORCH-101 (A2): same Settings-driven env as the agent Popen above.
|
||||
git_env = agent_git_env()
|
||||
result = subprocess.run(
|
||||
["git", "-C", repo_path, "status", "--porcelain"],
|
||||
capture_output=True, text=True, timeout=10, env=git_env
|
||||
|
||||
Reference in New Issue
Block a user