fix: temporarily disable production deployment for all events
CI / test (pull_request) Successful in 9m11s
CI / Fingerprint diagnostics (production deployment temporarily disabled) (pull_request) Has been skipped

This commit is contained in:
codex committed 2026-10-05 18:35:19 +03:00
1 parent b8a27758b6
commit f39b5dd512
6 files changed
+39 -17

No files matched your search

+6 -6
View File
@@ -8,7 +8,7 @@ on:
workflow_dispatch:
inputs:
diagnostic_only:
description: 'Print deployment key fingerprint without contacting VPS'
description: 'Print key fingerprint; production deployment is temporarily disabled'
type: boolean
default: true
@@ -32,14 +32,15 @@ jobs:
- run: sh -n infra/install-postgres-backup-cron.sh
deploy:
if: (github.event_name == 'push' && github.ref == 'refs/heads/main') || github.event_name == 'workflow_dispatch'
# Production deployment is disabled until separate Workers deployment access is installed.
name: Fingerprint diagnostics (production deployment temporarily disabled)
if: github.event_name == 'workflow_dispatch' && github.event.inputs.diagnostic_only == 'true'
needs: test
runs-on: ubuntu-latest
concurrency:
group: production-deploy
cancel-in-progress: false
env:
DIAGNOSTIC_ONLY: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.diagnostic_only != 'false' }}
PROD_PATH: /srv/miem_workers
RELEASE_NAME: miem-workers-release-${{ github.run_id }}.tar
steps:
@@ -63,7 +64,6 @@ jobs:
PROD_SSH_KEY: ${{ secrets.PROD_SSH_KEY }}
PROD_KNOWN_HOSTS: ${{ secrets.PROD_KNOWN_HOSTS }}
- name: Deployment key fingerprint
if: env.DIAGNOSTIC_ONLY == 'true'
shell: bash
run: |
set +x
@@ -71,7 +71,7 @@ jobs:
trap 'rm -f "$RUNNER_TEMP/deploy_key" "$RUNNER_TEMP/known_hosts"' EXIT
ssh-keygen -y -P '' -f "$RUNNER_TEMP/deploy_key" | ssh-keygen -lf - -E sha256 | awk '{print $2}'
- name: Upload release
if: env.DIAGNOSTIC_ONLY != 'true'
if: ${{ false }}
shell: bash
run: |
set -euo pipefail
@@ -84,7 +84,7 @@ jobs:
PROD_HOST: ${{ secrets.PROD_HOST }}
PROD_USER: ${{ secrets.PROD_USER }}
- name: Deploy and verify
if: env.DIAGNOSTIC_ONLY != 'true'
if: ${{ false }}
shell: bash
run: |
set -euo pipefail
+3 -3
View File
@@ -128,9 +128,9 @@ docker compose exec postgres pg_dump -U miem miem_workers > backup.sql
docker compose down
```
Production deploy выполняется job `deploy` workflow `CI` после успешного `test` на push в `main` или вручную. Для него нужны Actions secrets `PROD_HOST`, `PROD_USER`, `PROD_SSH_KEY` и `PROD_KNOWN_HOSTS`; `.env` и ключи в репозиторий не добавляются. PostgreSQL backup выполняется на VPS раз в неделю user cron deploy-пользователя через `infra/postgres-backup.sh`: `pg_dumpall` сохраняет весь кластер в `~/backups/postgres/postgres-latest.sql`. Новый dump сначала создаётся во временный файл и заменяет старый только после успешного завершения; предыдущие dump-файлы `miem_workers` удаляются после успешного создания нового. Одновременно выполняется только один production deploy.
Production deployment временно отключён до установки отдельного deployment-доступа Workers. Workflow `CI` запускает тесты на push в `main` и pull_request в `main`; шаги Upload release и Deploy and verify безусловно отключены для всех событий и значений input. Стандартные имена deployment secrets: `PROD_HOST`, `PROD_USER`, `PROD_SSH_KEY`, `PROD_KNOWN_HOSTS`; `.env` и ключи в репозиторий не добавляются. PostgreSQL backup выполняется на VPS раз в неделю user cron deploy-пользователя через `infra/postgres-backup.sh`: `pg_dumpall` сохраняет весь кластер в `~/backups/postgres/postgres-latest.sql`. Новый dump сначала создаётся во временный файл и заменяет старый только после успешного завершения; предыдущие dump-файлы `miem_workers` удаляются после успешного создания нового. Эта правка не меняет существующий backup cron.
Ручной запуск `CI` по умолчанию использует `diagnostic_only=true`: выводит только SHA256 fingerprint ключа `PROD_SSH_KEY` и пропускает Upload release и Deploy and verify, без подключения к VPS. Публичный ключ передаётся через pipe, не сохраняется в файл или artifacts; shell tracing отключён. Для штатного deployment при ручном запуске нужно явно выбрать `diagnostic_only=false`. Deployment при push в `main` сохраняется.
Ручной запуск с `diagnostic_only=true` (по умолчанию) выводит только SHA256 fingerprint ключа `PROD_SSH_KEY`, без подключения к VPS. Публичный ключ передаётся через pipe, не сохраняется в файл или artifacts; shell tracing отключён. При `diagnostic_only=false` диагностический job пропускается: это значение также не разрешает deployment. Возврат production deployment требует отдельной reviewed правки после установки нового доступа.
## Проверки
@@ -143,7 +143,7 @@ node --check app/static/admin.js
Тесты с данными используют временную SQLite; отдельные API smoke-тесты запускают приложение с его текущей конфигурацией. Браузерная проверка: `pip install playwright`, `python -m playwright install chromium`, затем `python tests/browser_admin.py`. Она проверяет реальный рендеринг страниц, клавиатуру, диалог, фильтры и восстановление прогресса после ошибки. Скриншоты сохраняются во временную папку; путь выводится в конце.
Версия сервиса: `0.10.5`. Админка всегда показывает версии backend и frontend в footer.
Версия сервиса: `0.10.6`. Админка всегда показывает версии backend и frontend в footer.
## Разовый импорт публикаций
+3 -3
View File
@@ -1,3 +1,3 @@
APP_VERSION = "0.10.5"
FRONTEND_VERSION = "0.10.5"
BACKEND_VERSION = "0.10.5"
APP_VERSION = "0.10.6"
FRONTEND_VERSION = "0.10.6"
BACKEND_VERSION = "0.10.6"
+1 -1
View File
@@ -1,6 +1,6 @@
[project]
name = "miem-workers"
version = "0.10.5"
version = "0.10.6"
description = "MIEM employees parser, admin API, and web admin"
requires-python = ">=3.11"
dependencies = [
+1 -1
View File
@@ -18,7 +18,7 @@ def test_health_returns_versions():
response = TestClient(app).get("/api/health")
assert response.status_code == 200
assert response.json()["backend_version"] == "0.10.5"
assert response.json()["backend_version"] == "0.10.6"
def test_api_employees_and_stats_require_admin_session():
+25 -3
View File
@@ -1,5 +1,6 @@
import os
from pathlib import Path
import re
import subprocess
import textwrap
@@ -41,8 +42,29 @@ def test_fingerprint_output_and_cleanup(tmp_path, keygen_exit):
assert not (tmp_path / "known_hosts").exists()
def test_both_vps_steps_are_guarded():
assert "github.event.inputs.diagnostic_only != 'false'" in WORKFLOW
@pytest.mark.parametrize("event", ["push", "pull_request", "workflow_dispatch"])
@pytest.mark.parametrize("diagnostic_only", ["true", "false", ""])
def test_launch_conditions(event, diagnostic_only):
job = WORKFLOW.split("\n deploy:\n", 1)[1]
condition = re.search(r"^ if: (.+)$", job, re.MULTILINE).group(1)
terms = re.findall(r"(github\.[a-z_.]+) == '([^']*)'", condition)
assert condition == " && ".join(f"{name} == '{value}'" for name, value in terms)
context = {"github.event_name": event,
"github.event.inputs.diagnostic_only": diagnostic_only}
runs = all(context[name] == value for name, value in terms)
assert runs == (event == "workflow_dispatch" and diagnostic_only == "true")
def test_both_vps_steps_are_unconditionally_disabled():
for name in ("Upload release", "Deploy and verify"):
step = WORKFLOW.split(f" - name: {name}\n", 1)[1]
assert step.startswith(" if: env.DIAGNOSTIC_ONLY != 'true'\n")
assert step.startswith(" if: ${{ false }}\n")
def test_push_and_pull_request_keep_tests():
triggers = WORKFLOW.split("\njobs:\n", 1)[0]
for event in ("push", "pull_request"):
assert f" {event}:\n branches: [main]\n" in triggers
test_job = WORKFLOW.split("\n test:\n", 1)[1].split("\n deploy:\n", 1)[0]
assert " if:" not in test_job
assert "python -m pytest -q" in test_job