From 39f29cc89761e98293bb91664ba4c81880b7b691 Mon Sep 17 00:00:00 2001 From: Storozhenko Evgeny Date: Sat, 19 Sep 2026 18:51:08 +0000 Subject: [PATCH] =?UTF-8?q?ci:=20workflow=20=D0=B4=D0=B5=D0=BF=D0=BB=D0=BE?= =?UTF-8?q?=D1=8F=20dedinit.ru=20=D1=87=D0=B5=D1=80=D0=B5=D0=B7=20SFTP=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B8=20=D0=BF=D1=83=D1=88=D0=B5=20=D0=B2=20main?= =?UTF-8?q?=20(Gitea=20Actions)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitea/workflows/deploy.yml | 26 +++++ .../auto-deploy-dedinit-actions/design.md | 104 ++++++++++++++++++ .../auto-deploy-dedinit-actions/proposal.md | 39 +++++++ .../specs/dedinit-deploy/spec.md | 74 +++++++++++++ .../auto-deploy-dedinit-actions/tasks.md | 16 +++ 5 files changed, 259 insertions(+) create mode 100644 .gitea/workflows/deploy.yml create mode 100644 openspec/changes/auto-deploy-dedinit-actions/design.md create mode 100644 openspec/changes/auto-deploy-dedinit-actions/proposal.md create mode 100644 openspec/changes/auto-deploy-dedinit-actions/specs/dedinit-deploy/spec.md create mode 100644 openspec/changes/auto-deploy-dedinit-actions/tasks.md diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml new file mode 100644 index 0000000..6b4531b --- /dev/null +++ b/.gitea/workflows/deploy.yml @@ -0,0 +1,26 @@ +name: deploy-dedinit + +on: + push: + branches: + - main + workflow_dispatch: + +jobs: + deploy: + name: Build & SFTP Deploy + runs-on: ubuntu-24.04 + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install dependencies + run: | + apt-get update -qq + apt-get install -y -qq make python3 python3-venv python3-pip hugo + + - name: Deploy via SFTP + env: + SSHPASS: ${{ secrets.SSHPASS }} + run: | + make deploy \ No newline at end of file diff --git a/openspec/changes/auto-deploy-dedinit-actions/design.md b/openspec/changes/auto-deploy-dedinit-actions/design.md new file mode 100644 index 0000000..82225a8 --- /dev/null +++ b/openspec/changes/auto-deploy-dedinit-actions/design.md @@ -0,0 +1,104 @@ +# Design: Автодеплой dedinit.ru через Gitea Actions + +## Архитектура + +``` +[пользователь/агент] + │ git push (main) в gitverse.ru (источник истины) + ▼ +[gitverse.ru] kpa39l/dedinit.ru + │ крон-скрипт: git fetch gitverse && git push gitea (каждые ~10 мин) + ▼ +[gitea.nixg.ru] estorozhenko/dedinit.ru ← НЕ mirror, Actions включены + │ push в main → Gitea Actions + ▼ +[bigbox-runner] (gitea-act-runner v3.3.1, label docker27-bash) + │ job-контейнер docker27-bash: checkout → make build → tools/deploy_sftp.py + ▼ +[kpa39l.myjino.ru:2222:/dedinit.ru/] (SFTP-only, пароль из secrets.SSHPASS) +``` + +## Шаги + +### 1. Снять mirror-статус у Gitea-репозитория + +Раньше репо было pull-mirror (интервал 8ч) с gitverse.ru. На mirror-репо Gitea +отключает Actions. Снимаем: + +```bash +curl -X PATCH "https://gitea.nixg.ru/api/v1/repos/estorozhenko/dedinit.ru" \ + -H "Authorization: token $GITEA_NIXG_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"mirror": false}' +``` + +Проверка: `GET /repos/estorozhenko/dedinit.ru` → `"mirror":false`, `"has_actions":true`. + +### 2. Синхронизация gitverse → gitea крон-скриптом + +Создать `/opt/gitea.nixg.ru/sync-dedinit.sh`: + +```bash +#!/usr/bin/env bash +set -euo pipefail +cd /opt/dedinit.ru +git fetch gitverse main || git fetch origin main # gitverse = источник истины +# аккуратно: приносим refs/heads/main gitverse → gitea +git push gitea main:main +``` + +(детали remote gitea — см. ниже) + cron на bigbox каждые 10 минут. + +### 3. Workflow `.gitea/workflows/deploy.yml` + +```yaml +name: deploy +on: + push: + branches: [main] +jobs: + deploy: + runs-on: [ubuntu-24.04] # label раннера bigbox-runner + steps: + - uses: actions/checkout@v4 + - name: install hugo + run: | + curl -sL https://api.github.com/repos/gohugoio/hugo/releases/latest \ + | grep -oE 'browser_download_url.*_extended.*linux-amd64.tar.gz' | head -1 + # распаковать hugo в /usr/local/bin + - name: build + run: make build + - name: deploy + env: + SSHPASS: ${{ secrets.SSHPASS }} + run: make deploy +``` + +### 4. Секрет в Gitea + +```bash +curl -X PUT "https://gitea.nixg.ru/api/v1/repos/estorozhenko/dedinit.ru/actions/secrets/SSHPASS" \ + -H "Authorization: token $GITEA_NIXG_TOKEN" \ + -d '{"value": "-Zp4ep747t25"}' +``` + +## Файлы + +- `.gitea/workflows/deploy.yml` — новый +- `tools/deploy_sftp.py`, `Makefile` — переиспользуются без изменений +- `/opt/gitea.nixg.ru/sync-dedinit.sh` (+ cron) — новый +- Для SSH-доступа к gitea: remote `gitea` = `git@gitverse` нет; проверю, есть ли SSH/HTTPS-доступ к gitea.nixg.ru, или поднимем родной remote через https+token. + +## Команды верификации + +- `curl -s https://gitea.nixg.ru/api/v1/repos/estorozhenko/dedinit.ru | grep '"has_actions"'` → true +- `openspec validate auto-deploy-dedinit-actions` → valid +- После пуша: `curl -s https://gitea.nixg.ru/api/v1/repos/estorozhenko/dedinit.ru/actions/runs | ...` → run существует +- `curl -s -o /dev/null -w '%{http_code}' https://dedinit.ru/` → 200 + +## Rollback + +1. Вернуть mirror: `PATCH /repos/estorozhenko/dedinit.ru` → `{"mirror": true}` +2. Убрать workflow: `git rm .gitea/workflows/deploy.yml` + push +3. Удалить секрет: `DELETE /repos/estorozhenko/dedinit.ru/actions/secrets/SSHPASS` +4. Остановить крон-скрипт синхронизации \ No newline at end of file diff --git a/openspec/changes/auto-deploy-dedinit-actions/proposal.md b/openspec/changes/auto-deploy-dedinit-actions/proposal.md new file mode 100644 index 0000000..a2908d7 --- /dev/null +++ b/openspec/changes/auto-deploy-dedinit-actions/proposal.md @@ -0,0 +1,39 @@ +# Proposal: Автодеплой dedinit.ru через Gitea Actions при пуше в master + +## Проблема + +Сейчас деплой dedinit.ru на Jino (SFTP) выполняется вручную: `make build && export SSHPASS=... && make deploy`. +Это требует присутствия человека, не даёт истории деплоев и не срабатывает при пуше со стороны +пользователя (он коммитит сам, но деплой забывает). + +## Что предлагается + +1. Подключить Gitea Actions: на каждый push в ветку `master` репозитория + `estorozhenko/dedinit.ru` (bigbox, gitea.nixg.ru) запускать workflow: + - checkout репозитория + - сборка Hugo: `make build` (hugo --minify) + - загрузка `public/` на Jino SFTP через существующий `tools/deploy_sftp.py` +2. Для этого: + - **снять mirror-статус** у `estorozhenko/dedinit.ru` в Gitea (на зеркале Actions не работают — штатное ограничение Gitea) + - синхронизацию gitverse → gitea перенести в крон-скрипт `git fetch + git push` (вместо mirror-интервала 8ч) + - деплой-секрет SFTP (пароль Jino) завести в Gitea Actions secrets + - раннер уже стоит и работает (bigbox-runner, v3.3.1, label `docker27-bash`) + +## Затронутые сервисы и файлы + +- `estorozhenko/dedinit.ru` (gitea.nixg.ru) — снятие mirror, включение Actions +- `/opt/dedinit.ru/.gitea/workflows/deploy.yml` — новый workflow +- `/opt/dedinit.ru/Makefile`, `tools/deploy_sftp.py` — без изменений (переиспользуются) +- `~/.ssh/config` / ssh-ключи — не нужны (деплой через пароль, как сейчас) +- Крон на bigbox: синхронизация gitverse→gitea (замена mirror-интервала) + +## План отката + +- Вернуть mirror-статус репозитория в Gitea (API `PATCH /repos/{owner}/{repo}` → `mirror:true`) +- Удалить `.gitea/workflows/deploy.yml` из репозитория (или отключить в настройках Actions) +- Удалить secrets SFTP из Gitea (пароль не скомпрометирован — он и так лежит в docs/) + +## Прочие решения + +- Ветка по умолчанию в репо — `main`, но задание «при пуше в master» — оформим триггер на `main` + (репо уже на main; в Gitea триггер по branch-шаблону). Уточним у пользователя, если нужен именно `master`. \ No newline at end of file diff --git a/openspec/changes/auto-deploy-dedinit-actions/specs/dedinit-deploy/spec.md b/openspec/changes/auto-deploy-dedinit-actions/specs/dedinit-deploy/spec.md new file mode 100644 index 0000000..456f236 --- /dev/null +++ b/openspec/changes/auto-deploy-dedinit-actions/specs/dedinit-deploy/spec.md @@ -0,0 +1,74 @@ +# dedinit-deploy Specification (delta) + +## ADDED Requirements + +### Requirement: Автоматический деплой при пуше в основную ветку + +Система SHALL запускать workflow деплоя при каждом push в основную ветку +(`main`) репозитория `estorozhenko/dedinit.ru` на gitea.nixg.ru. + +#### Scenario: Пуш в main запускает деплой + +- **GIVEN** репозиторий `estorozhenko/dedinit.ru` имеет Actions и раннер `bigbox-runner` online +- **WHEN** пользователь пушит коммит в ветку `main` +- **THEN** Gitea создаёт workflow-run вида `hugo build + sftp deploy`, который завершается + успехом, а `https://dedinit.ru/` обновляется без ручных действий + +#### Scenario: Ветка не-main не деплоит + +- **GIVEN** push в любую другую ветку +- **WHEN** workflow запускается +- **THEN** deploy-шаг пропускается (условие `if: github.ref == 'refs/heads/main'`) + +### Requirement: Деплой через SFTP Jino средствами репозитория + +Система SHALL выполнять сборку `hugo --minify` и зеркалирование `public/` на +`kpa39l.myjino.ru:2222:/dedinit.ru/` через существующий +`tools/deploy_sftp.py` (SFTP-only, пароль из env `SSHPASS`). + +#### Scenario: Успешный деплой + +- **GIVEN** раннер может запускать job-контейнеры (docker27-bash) +- **WHEN** workflow выполняется +- **THEN** в логе видно `hugo --minify` (build), затем `deploy_sftp.py`, + завершившийся `Done.` без ошибок + +#### Scenario: Пароль из Gitea secrets + +- **GIVEN** секрет `SSHPASS` задан в настройках репозитория Gitea +- **WHEN** deploy-шаг стартует +- **THEN** пароль берётся из переменной окружения, а не из файла `docs/DEPLOY_INSTRUCTIONS.md` + +### Requirement: Репозиторий не является mirror-репозиторием + +Система SHALL иметь репозиторий `estorozhenko/dedinit.ru` в Gitea без статуса +mirror (`mirror:false`, `has_actions:true`), иначе Gitea не выполняет Actions. + +#### Scenario: Снятие mirror-статуса + +- **GIVEN** `PATCH /api/v1/repos/estorozhenko/dedinit.ru` с `{"mirror": false}` +- **WHEN** запрос успешен +- **THEN** `GET /repos/estorozhenko/dedinit.ru` возвращает `"mirror":false`, `"has_actions":true` + +### Requirement: Синхронизация gitverse → gitea без mirror-интервала + +Система SHALL продолжать получать изменения из gitverse.ru (источника истины) +в gitea.nixg.ru, но не через встроенный mirror-интервал, а через крон-скрипт +`git fetch origin && git push` (чтобы репозиторий не был зеркалом). + +#### Scenario: Крон синхронизирует + +- **GIVEN** крон-джоб на bigbox, запускающий скрипт синхронизации +- **WHEN** в gitverse появился новый коммит в main +- **THEN** скрипт приносит его в gitea `estorozhenko/dedinit.ru`, и (при пуше в gitea) Actions деплоят + +### Requirement: Секрет деплоя не светится + +Система SHALL хранить пароль SFTP Jino только в Gitea Actions secrets +(переменная `SSHPASS`), не в git-истории и не в логах workflow. + +#### Scenario: Секрет маскируется + +- **GIVEN** workflow использует `${{ secrets.SSHPASS }}` +- **WHEN** runner печатает лог +- **THEN** Gitea/runner маскирует секрет в выводе (не появляется открытым текстом) \ No newline at end of file diff --git a/openspec/changes/auto-deploy-dedinit-actions/tasks.md b/openspec/changes/auto-deploy-dedinit-actions/tasks.md new file mode 100644 index 0000000..20bdb99 --- /dev/null +++ b/openspec/changes/auto-deploy-dedinit-actions/tasks.md @@ -0,0 +1,16 @@ +# Tasks: Автодеплой dedinit.ru через Gitea Actions + +- [ ] Снять mirror-статус с `estorozhenko/dedinit.ru` в Gitea (PATCH → mirror:false) + - Проверка: `curl -s https://gitea.nixg.ru/api/v1/repos/estorozhenko/dedinit.ru | grep '"has_actions"'` → true +- [ ] Настроить remote `gitea` в `/opt/dedinit.ru` (git@/https с доступом на push) + - Проверка: `git remote -v | grep gitea` +- [ ] Создать `.gitea/workflows/deploy.yml` (checkout → hugo build → sftp deploy) + - Проверка: `ls .gitea/workflows/deploy.yml` +- [ ] Завести секрет `SSHPASS` в Gitea Actions secrets репозитория + - Проверка: `curl .../actions/secrets/SSHPASS` → 200 +- [ ] Создать `sync-dedinit.sh` + cron (gitverse → gitea каждые 10 мин) + - Проверка: запуск скрипта вручную приносит коммит, `git log` показывает его в gitea +- [ ] Пуш в gitverse (или gitea), дождаться workflow-run + - Проверка: API `actions/runs` показывает run, `https://dedinit.ru/` → 200, содержимое обновлено +- [ ] `openspec validate auto-deploy-dedinit-actions` → valid +- [ ] `openspec archive auto-deploy-dedinit-actions --yes` → изменения смержены в specs \ No newline at end of file