fix(pipeline): make deploy-staging gate conditional on self-hosting repo (ORCH-35)
This commit is contained in:
@@ -441,6 +441,26 @@ def check_deploy_status(repo: str, work_item_id: str, branch: str | None = None)
|
||||
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Self-hosting detection: staging-infra (localhost:8501) exists ONLY for the
|
||||
# orchestrator repo itself (self-hosting). Other repos have no staging instance
|
||||
# and their deployer prompts know nothing about it -- the gate must be a no-op
|
||||
# for them. The repo value is the plain gitea repo name (ProjectConfig.repo),
|
||||
# matching what _run_qg/advance_stage pass in. See ORCH-35 / PR #31.
|
||||
# ---------------------------------------------------------------------------
|
||||
SELF_HOSTING_REPO = "orchestrator"
|
||||
|
||||
|
||||
def is_self_hosting_repo(repo: str) -> bool:
|
||||
"""Return True iff repo is the self-hosted orchestrator (has staging infra).
|
||||
|
||||
Comparison is case-insensitive and strips whitespace for safety, but in
|
||||
practice repo comes from the gitea webhook payload .repository.name which
|
||||
is always lowercase (confirmed via projects.py registry entry).
|
||||
"""
|
||||
return (repo or "").strip().lower() == SELF_HOSTING_REPO.lower()
|
||||
|
||||
|
||||
def _parse_staging_status(content: str) -> tuple[bool, str]:
|
||||
"""Parse a 15-staging-log.md body and map its `staging_status:` frontmatter to a
|
||||
quality-gate verdict. Reads ONLY the machine-readable YAML field, never prose.
|
||||
@@ -505,16 +525,26 @@ def check_staging_status(repo: str, work_item_id: str, branch: str | None = None
|
||||
Gate the deploy-staging -> deploy transition on the deployer's machine-readable
|
||||
verdict in 15-staging-log.md frontmatter (staging_status: SUCCESS|FAILED).
|
||||
|
||||
Mirrors check_deploy_status (БАГ 8): reads ONLY the machine-readable YAML field,
|
||||
never the body prose. The deployer runs the staging test suite against localhost:8501
|
||||
and writes the verdict into 15-staging-log.md.
|
||||
ORCH-35 conditional gate (Variant A):
|
||||
- Non-self-hosting repos (anything other than "orchestrator") have no staging
|
||||
instance and no deployer knowledge of it -> gate is an immediate pass.
|
||||
- Self-hosting repo ("orchestrator") -> real check: reads ONLY the machine-
|
||||
readable staging_status: field from YAML frontmatter, never body prose.
|
||||
|
||||
Lookup order: worktree -> origin/main -> not found.
|
||||
Mirrors check_deploy_status (БАГ 8) for the self-hosting path.
|
||||
|
||||
Lookup order (self-hosting only): worktree -> origin/main -> not found.
|
||||
|
||||
Returns:
|
||||
(True, ...) -> staging_status: SUCCESS
|
||||
(True, "Staging gate N/A for <repo>") -> non-self-hosting repo (instant pass)
|
||||
(True, ...) -> staging_status: SUCCESS (self-hosting path)
|
||||
(False, ...) -> staging_status: FAILED, missing field, or no frontmatter
|
||||
"""
|
||||
# Variant A: non-self-hosting repos have no staging infra -- skip entirely.
|
||||
if not is_self_hosting_repo(repo):
|
||||
return True, f"Staging gate N/A for {repo}"
|
||||
|
||||
# Self-hosting (orchestrator) path: real verdict check.
|
||||
repo_path = _repo_path(repo, branch)
|
||||
log_path = os.path.join(repo_path, f"docs/work-items/{work_item_id}/15-staging-log.md")
|
||||
|
||||
@@ -526,7 +556,7 @@ def check_staging_status(repo: str, work_item_id: str, branch: str | None = None
|
||||
return False, f"Error reading staging log: {e}"
|
||||
return _parse_staging_status(content)
|
||||
|
||||
# Not in the feature worktree — the deployer may have merged it into main.
|
||||
# Not in the feature worktree -- the deployer may have merged it into main.
|
||||
main_content = _staging_log_from_main(repo, work_item_id)
|
||||
if main_content is not None:
|
||||
return _parse_staging_status(main_content)
|
||||
|
||||
Reference in New Issue
Block a user