- _cherry_pick_onto_main replaces _rebase_and_push: creates fresh branch from origin/main, cherry-picks extraction commits, force-pushes - Eliminates ~23% merge failure rate from rebase race conditions - Agent branch protection: PIPELINE_OWNED_PREFIXES filter in SQL prevents auto-merge of agent-owned branches (theseus/*, rio/*, etc.) - Empty-commit handling: skips already-merged content gracefully - Entity conflict auto-resolution preserved for cherry-pick path - Post-pick evidence dedup runs as safety net (same as post-rebase) - Separate fetch calls for main and branch (fixes long branch name issue) Fixes: PRs #2141, #157, #2142, #2180 (agent branch orphaning) Fixes: ~23% merge failure rate (rebase race condition) Related: PRs #1751, #1752 (enrichment dedup shares root cause) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
104 lines
3.4 KiB
Python
104 lines
3.4 KiB
Python
"""Tests for merge stage — pipeline ownership gate.
|
|
|
|
Note: cherry-pick mechanism tested on VPS (requires git repos + aiohttp).
|
|
These tests verify the ownership filter logic and SQL query behavior.
|
|
"""
|
|
|
|
import asyncio
|
|
import sqlite3
|
|
import unittest.mock as mock
|
|
|
|
import pytest
|
|
|
|
|
|
# Can't import lib.merge directly (aiohttp not installed locally).
|
|
# Test the ownership prefixes and SQL logic directly.
|
|
|
|
PIPELINE_OWNED_PREFIXES = ("extract/", "ingestion/", "epimetheus/", "reweave/", "fix/")
|
|
|
|
|
|
class TestPipelineOwnedPrefixes:
|
|
"""Verify the pipeline ownership gate correctly filters branches."""
|
|
|
|
def test_extraction_branches_are_pipeline_owned(self):
|
|
branches = [
|
|
"extract/2026-03-31-some-source",
|
|
"ingestion/2026-03-31-batch",
|
|
"epimetheus/merge-gate",
|
|
"reweave/2026-03-31",
|
|
"fix/dedup-evidence",
|
|
]
|
|
for branch in branches:
|
|
assert any(
|
|
branch.startswith(pfx) for pfx in PIPELINE_OWNED_PREFIXES
|
|
), f"{branch} should be pipeline-owned"
|
|
|
|
def test_agent_branches_are_not_pipeline_owned(self):
|
|
branches = [
|
|
"theseus/research-ai-alignment",
|
|
"rio/market-analysis",
|
|
"astra/space-claims",
|
|
"vida/health-extraction",
|
|
"clay/entertainment-review",
|
|
"leo/entity-update",
|
|
]
|
|
for branch in branches:
|
|
assert not any(
|
|
branch.startswith(pfx) for pfx in PIPELINE_OWNED_PREFIXES
|
|
), f"{branch} should NOT be pipeline-owned"
|
|
|
|
def test_bare_prefix_without_slash_is_not_owned(self):
|
|
"""Prefixes must include slash to prevent partial matches."""
|
|
assert not any(
|
|
"extraction-test".startswith(pfx) for pfx in PIPELINE_OWNED_PREFIXES
|
|
)
|
|
|
|
|
|
class TestOwnershipSqlFilter:
|
|
"""Test the SQL LIKE-based filtering that _claim_next_pr uses."""
|
|
|
|
def test_sql_like_filter_matches_pipeline_branches(self):
|
|
conn = sqlite3.connect(":memory:")
|
|
conn.execute("CREATE TABLE branches (name TEXT)")
|
|
branches = [
|
|
"extract/2026-03-31-test",
|
|
"theseus/research",
|
|
"reweave/2026-03-31",
|
|
"rio/market",
|
|
"fix/dedup",
|
|
"astra/space",
|
|
"ingestion/batch-1",
|
|
]
|
|
for b in branches:
|
|
conn.execute("INSERT INTO branches VALUES (?)", (b,))
|
|
|
|
prefix_clauses = " OR ".join(
|
|
f"name LIKE '{pfx}%'" for pfx in PIPELINE_OWNED_PREFIXES
|
|
)
|
|
rows = conn.execute(
|
|
f"SELECT name FROM branches WHERE {prefix_clauses}"
|
|
).fetchall()
|
|
|
|
matched = {r[0] for r in rows}
|
|
assert matched == {
|
|
"extract/2026-03-31-test",
|
|
"reweave/2026-03-31",
|
|
"fix/dedup",
|
|
"ingestion/batch-1",
|
|
}
|
|
# Agent branches must NOT match
|
|
assert "theseus/research" not in matched
|
|
assert "rio/market" not in matched
|
|
assert "astra/space" not in matched
|
|
|
|
def test_empty_table_returns_nothing(self):
|
|
conn = sqlite3.connect(":memory:")
|
|
conn.execute("CREATE TABLE branches (name TEXT)")
|
|
|
|
prefix_clauses = " OR ".join(
|
|
f"name LIKE '{pfx}%'" for pfx in PIPELINE_OWNED_PREFIXES
|
|
)
|
|
rows = conn.execute(
|
|
f"SELECT name FROM branches WHERE {prefix_clauses}"
|
|
).fetchall()
|
|
assert rows == []
|