From 68d041022d0ccd4fa05eb9edb4b34b0597103461 Mon Sep 17 00:00:00 2001 From: bot-backend Date: Thu, 20 Aug 2026 08:44:10 +0000 Subject: [PATCH] =?UTF-8?q?fix(ci):=20=D0=BE=D0=B6=D0=B8=D0=B4=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=B4=D0=BE=D0=BA=D0=B5=D1=80-=D0=BB=D0=BE?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=BB=D1=8F=D0=B5?= =?UTF-8?q?=D1=82=20=D1=81=D0=BB=D0=B5=D0=B4=20=D0=B2=20=D0=BB=D0=BE=D0=B3?= =?UTF-8?q?=D0=B5=20(#2950)=20(#2958)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .forgejo/workflows/deploy-tradein.yml | 19 +++++++++++++---- .forgejo/workflows/deploy.yml | 19 +++++++++++++---- .../ops/test_2950_deploy_concurrency_group.py | 21 +++++++++++++++++++ 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/.forgejo/workflows/deploy-tradein.yml b/.forgejo/workflows/deploy-tradein.yml index e15d8290..76d332bf 100644 --- a/.forgejo/workflows/deploy-tradein.yml +++ b/.forgejo/workflows/deploy-tradein.yml @@ -655,10 +655,21 @@ jobs: # прикрывать, что и требуется. Ожидание ограничено: не дождались за # 900с — падаем с внятным сообщением, а не молча ждём вечно. exec 9>/var/lock/gendesign-docker-deploy.lock - if ! flock -w 900 9; then - echo "ERROR: не дождался лока докер-деплоя за 900с." - echo " Кто держит: ssh на хост, затем fuser -v /var/lock/gendesign-docker-deploy.lock" - exit 1 + # Сначала неблокирующая попытка — чтобы ОЖИДАНИЕ оставляло след в логе. + # Без этого работающий лок ненаблюдаем: flock при успехе молчит, и отличить + # «второй деплой дождался первого» от «они просто разошлись по времени» + # нельзя — а именно это и есть критерий приёмки #2950. + if flock -n 9; then + echo "→ докер-лок свободен, взят сразу" + else + echo "→ докер-лок занят соседним деплоем, жду (до 900с)…" + lock_wait_started=$(date +%s) + if ! flock -w 900 9; then + echo "ERROR: не дождался лока докер-деплоя за 900с." + echo " Кто держит: ssh на хост, затем fuser -v /var/lock/gendesign-docker-deploy.lock" + exit 1 + fi + echo "→ докер-лок получен через $(( $(date +%s) - lock_wait_started ))с ожидания" fi cd /opt/gendesign diff --git a/.forgejo/workflows/deploy.yml b/.forgejo/workflows/deploy.yml index 92bb367b..fa30a939 100644 --- a/.forgejo/workflows/deploy.yml +++ b/.forgejo/workflows/deploy.yml @@ -501,10 +501,21 @@ jobs: # прикрывать, что и требуется. Ожидание ограничено: не дождались за # 900с — падаем с внятным сообщением, а не молча ждём вечно. exec 9>/var/lock/gendesign-docker-deploy.lock - if ! flock -w 900 9; then - echo "ERROR: не дождался лока докер-деплоя за 900с." - echo " Кто держит: ssh на хост, затем fuser -v /var/lock/gendesign-docker-deploy.lock" - exit 1 + # Сначала неблокирующая попытка — чтобы ОЖИДАНИЕ оставляло след в логе. + # Без этого работающий лок ненаблюдаем: flock при успехе молчит, и отличить + # «второй деплой дождался первого» от «они просто разошлись по времени» + # нельзя — а именно это и есть критерий приёмки #2950. + if flock -n 9; then + echo "→ докер-лок свободен, взят сразу" + else + echo "→ докер-лок занят соседним деплоем, жду (до 900с)…" + lock_wait_started=$(date +%s) + if ! flock -w 900 9; then + echo "ERROR: не дождался лока докер-деплоя за 900с." + echo " Кто держит: ssh на хост, затем fuser -v /var/lock/gendesign-docker-deploy.lock" + exit 1 + fi + echo "→ докер-лок получен через $(( $(date +%s) - lock_wait_started ))с ожидания" fi cd /opt/gendesign diff --git a/backend/tests/ops/test_2950_deploy_concurrency_group.py b/backend/tests/ops/test_2950_deploy_concurrency_group.py index d72c64f3..b8fa59b2 100644 --- a/backend/tests/ops/test_2950_deploy_concurrency_group.py +++ b/backend/tests/ops/test_2950_deploy_concurrency_group.py @@ -69,6 +69,27 @@ def test_prod_deploy_takes_the_host_lock(name: str) -> None: ) +@pytest.mark.parametrize("name", PROD_DEPLOYS) +def test_lock_wait_leaves_a_trace(name: str) -> None: + """Ожидание лока видно в логе — иначе работающий лок ненаблюдаем. + + `flock` при успехе молчит. Если брать лок сразу блокирующим вызовом, отличить + «второй деплой дождался первого» от «они просто разошлись по времени» нельзя — + а это и есть критерий приёмки #2950. Поэтому сначала неблокирующая попытка, и + при занятом локе в лог уходит и факт ожидания, и его длительность. + """ + script = _deploy_script(name) + assert "flock -n" in script, ( + f"{name}: лок берётся сразу блокирующим вызовом — ожидание не попадёт в лог, " + "и проверить, что взаимное исключение сработало, будет нечем" + ) + assert "жду" in script, f"{name}: нет строки об ожидании лока" + assert "с ожидания" in script, ( + f"{name}: не печатается длительность ожидания — без неё непонятно, " + "ждал деплой две секунды или четверть часа" + ) + + @pytest.mark.parametrize("name", PROD_DEPLOYS) def test_lock_wait_is_bounded_and_loud(name: str) -> None: """Ожидание ограничено и провал слышен: молча ждать вечно — не вариант."""