OBSOLETE расширен ключами base_jql и board_id: ensure_defaults убирает их при каждом открытии, миграция v7 -> v8 тоже. settings_version не растёт. PUT /settings для этих ключей по-прежнему отвечает 422 с пояснением. Тест миграции v3 обновлён: после миграции ключей в настройках нет (проекты уже созданы из них). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
5dc96dd43c
commit
fd13770427
@ -24,9 +24,9 @@ DEFAULTS = {
|
|||||||
"closed_statuses": ["Готово", "Снято"], # статусы Jira закрытых задач: список и доска приложения (hide-closed)
|
"closed_statuses": ["Готово", "Снято"], # статусы Jira закрытых задач: список и доска приложения (hide-closed)
|
||||||
}
|
}
|
||||||
|
|
||||||
# Ключи прежних версий (fact-status-removal): их удаляет миграция v8 и каждый ensure_defaults — процесс со старым кодом
|
# Ключи прежних версий (fact-status-removal; base_jql и board_id — v3, #129): их удаляет миграция v8 и каждый ensure_defaults — процесс со старым кодом
|
||||||
# (MCP-сессия до reconnect) вставил бы их снова своими умолчаниями
|
# (MCP-сессия до reconnect) вставил бы их снова своими умолчаниями
|
||||||
OBSOLETE = ("status_labels", "transitions_map")
|
OBSOLETE = ("status_labels", "transitions_map", "base_jql", "board_id")
|
||||||
|
|
||||||
# Что получает агент от модуля (без токенов и служебных ключей хаба); settings_version добавляет ядро
|
# Что получает агент от модуля (без токенов и служебных ключей хаба); settings_version добавляет ядро
|
||||||
AGENT_KEYS = ["project_key", "issue_types", "epic_name_field_id", "field_ids", "epic_link",
|
AGENT_KEYS = ["project_key", "issue_types", "epic_name_field_id", "field_ids", "epic_link",
|
||||||
|
|||||||
@ -299,8 +299,7 @@ def test_migrates_v3_creates_awpca(tmp_path):
|
|||||||
assert {k: v for k, v in api.project_rows(conn)[0].items() if not k.startswith(("wiki_", "jira_"))} | {
|
assert {k: v for k, v in api.project_rows(conn)[0].items() if not k.startswith(("wiki_", "jira_"))} | {
|
||||||
"created_at": None, "issues_count": None} == {
|
"created_at": None, "issues_count": None} == {
|
||||||
"label": "AWPCA", "name": "АРМ КА", "board_id": 4216, "board_type": None, "created_at": None, "issues_count": None}
|
"label": "AWPCA", "name": "АРМ КА", "board_id": 4216, "board_type": None, "created_at": None, "issues_count": None}
|
||||||
assert settings.get(conn, "base_jql") == "project = AURORA AND labels = AWPCA" # ключи на месте
|
assert settings.get(conn, "base_jql") is None and settings.get(conn, "board_id") is None # ключи v3 убраны (#129)
|
||||||
assert settings.get(conn, "board_id") == 4216
|
|
||||||
assert conn.execute("SELECT query FROM sync_run").fetchone()["query"] == new
|
assert conn.execute("SELECT query FROM sync_run").fetchone()["query"] == new
|
||||||
jqls = {r["status"]: json.loads(r["params"]).get("jql") for r in conn.execute("SELECT status, params FROM command WHERE type = 'refresh'")}
|
jqls = {r["status"]: json.loads(r["params"]).get("jql") for r in conn.execute("SELECT status, params FROM command WHERE type = 'refresh'")}
|
||||||
assert jqls["done"] == "project = AURORA AND labels = AWPCA" # завершённые не трогаем
|
assert jqls["done"] == "project = AURORA AND labels = AWPCA" # завершённые не трогаем
|
||||||
|
|||||||
@ -138,3 +138,48 @@ def test_sprint_types_pacing(conn):
|
|||||||
assert jira_settings.pacing(conn)["ensure_rank"] == 30
|
assert jira_settings.pacing(conn)["ensure_rank"] == 30
|
||||||
settings.validate("pacing", {"ensure_rank": 10})
|
settings.validate("pacing", {"ensure_rank": 10})
|
||||||
assert queue.estimate(conn, ["ensure_sprint_meta", "ensure_sprint_state", "ensure_rank"]) == 90
|
assert queue.estimate(conn, ["ensure_sprint_meta", "ensure_sprint_state", "ensure_rank"]) == 90
|
||||||
|
|
||||||
|
|
||||||
|
def test_v3_keys_removed_on_open(conn):
|
||||||
|
v0 = settings.get(conn, "settings_version")
|
||||||
|
conn.execute("INSERT OR REPLACE INTO setting(key, value) VALUES ('board_id', '4216'), ('base_jql', '\"project = AURORA\"')")
|
||||||
|
settings.ensure_defaults(conn)
|
||||||
|
stored = {r["key"] for r in conn.execute("SELECT key FROM setting")}
|
||||||
|
assert {"board_id", "base_jql"}.isdisjoint(stored)
|
||||||
|
assert settings.get(conn, "settings_version") == v0 # версия настроек не растёт
|
||||||
|
with pytest.raises(ValueError, match="доска Jira — свойство проекта"):
|
||||||
|
settings.validate("board_id", 4216)
|
||||||
|
with pytest.raises(ValueError, match="собирается из проектов"):
|
||||||
|
settings.validate("base_jql", "project = AURORA")
|
||||||
|
|
||||||
|
|
||||||
|
def test_v3_keys_removed_on_hub_start_api(tmp_path):
|
||||||
|
import threading
|
||||||
|
|
||||||
|
from sdlc_hub.core import api, db
|
||||||
|
from sdlc_hub.core.client import HubClient, HubError
|
||||||
|
path = tmp_path / "hub.sqlite"
|
||||||
|
c = db.connect(path)
|
||||||
|
settings.ensure_defaults(c)
|
||||||
|
c.execute("INSERT OR REPLACE INTO setting(key, value) VALUES ('board_id', '4216'), ('base_jql', '\"project = AURORA\"')")
|
||||||
|
c.commit()
|
||||||
|
c.close()
|
||||||
|
h = api.Hub(path, backups_dir=tmp_path / "backups")
|
||||||
|
conn = h.conn()
|
||||||
|
token = settings.tokens(conn)["client"]
|
||||||
|
conn.close()
|
||||||
|
srv = api.make_server(h, "127.0.0.1", 0)
|
||||||
|
th = threading.Thread(target=srv.serve_forever, daemon=True)
|
||||||
|
th.start()
|
||||||
|
try:
|
||||||
|
client = HubClient(f"http://127.0.0.1:{srv.server_port}", token)
|
||||||
|
got = client.get("/settings")
|
||||||
|
assert "board_id" not in got and got["base_jql"] != "project = AURORA" # base_jql вычисляется (без проектов — None)
|
||||||
|
for key in ("board_id", "base_jql"):
|
||||||
|
with pytest.raises(HubError) as e:
|
||||||
|
client.put("/settings", {key: 1})
|
||||||
|
assert e.value.status == 422 and e.value.detail
|
||||||
|
finally:
|
||||||
|
srv.shutdown()
|
||||||
|
srv.server_close()
|
||||||
|
th.join(5)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user