commit aca853438047dc5cea15b22efc99aa038b0e484e Author: estorozhenko Date: Sun Sep 6 13:51:17 2026 +0000 Initial commit: Hermes skill project-git-setup diff --git a/SKILL.md b/SKILL.md new file mode 100644 index 0000000..1321819 --- /dev/null +++ b/SKILL.md @@ -0,0 +1,142 @@ +--- +name: project-git-setup +title: "Git-инициализация нового проекта (gitverse.ru + gitea pull-mirror)" +description: "Use when setting up git for a new project." +version: 1.0.0 +author: hermes +license: MIT +--- + +# Git-инициализация нового проекта + +## When to Use + +Любой новый проект или перевод существующего каталога под git — сразу после +создания проекта (даже «пустого», с одним README). Схема: локальный git → +**приватный** репозиторий на gitverse.ru (истина) → **pull mirror** в gitea.nixg.ru +(локальная резервная копия, синхронизация каждые **12 часов** = 2 раза в сутки). + +## Триггеры + +- «новый проект», «заведи git», «инициализируй репозиторий» +- Создание проекта, который будет жить в `/opt/` (стандарт окружения — всё в /opt) + +## Шаг 0. Собрать факты + +- Имя репозитория: lowercase, дефисы (`tproxy-web`, `monitoring`, `openspec-lab`) +- Путь проекта (обычно `/opt/`) +- Стек: есть ли `Dockerfile` / `docker-compose.yml` / `compose.yaml`? Node/Python/Go? +- Существующий `.gitignore` (дополнить, не затирать) + +## Токены — только из настроек (НИКОГДА не искать по каталогам) + +Единый источник: **`/opt/hermes/.hermes/secrets/git-tokens.env`** (chmod 600). + +```bash +source /opt/hermes/.hermes/secrets/git-tokens.env +# → GITVERSE_LOGIN, GITVERSE_PAT, GITVERSE_API, GITEA_API, GITEA_TOKEN +``` + +Если файла нет — создать по образцу (значения брать из obsidian +`homelab/gitea.nixg.ru/Gitverse mirror token.md` ИЛИ из URL существующего mirror: +`docker exec gitea cat /data/git/repositories/estorozhenko/.git/config`), +затем записать в secrets и chmod 600. + +**Правила:** +- Токены в коде/README/коммитах не хранить. В `.gitignore` всех проектов — строка `secrets/`. +- Внутри скиллов и reference — только плейсхолдеры ``/${GITVERSE_PAT}, не значения. +- Новый токен создаётся один раз, кладётся в secrets файл, дальше только `source`. + +## Шаг 1. .gitignore + +Шаблон `templates/docker-gitignore.md` использовать если в проекте есть docker +(compose/Dockerfile — почти всегда в наших проектах). Для не-docker проектов — базовый +шаблон оттуда без docker-секции. Дополнить спецификой стека (секции Python/Node/Go в шаблоне). +**НИКОГДА не игнорить**: `docker-compose*.yml`, `Dockerfile*`, `README*`, `*.md`, `*.yml` конфиги, план/статус-файлы (PLAN.md, STATUS.md, TODO.md). + +## Шаг 2. Локальный git + +```bash +cd /opt/ +git init +git config user.name "estorozhenko" # если не задан глобально +git config user.email "estorozhenko@nixg.ru" +git add -A +git commit -m "Initial commit" +``` + +## Шаг 3. Создать ПРИВАТНЫЙ репозиторий на gitverse.ru + +```bash +source /opt/hermes/.hermes/secrets/git-tokens.env +# проверить логин (реальный аккаунт — kpa39l, НЕ estorozhenko!) +curl -s -H "Authorization: Bearer $GITVERSE_PAT" \ + -H "Accept: application/vnd.gitverse.object+json;version=1" \ + "$GITVERSE_API/user" +# создать репо: private:true ОБЯЗАТЕЛЬНО, auto_init:false (иначе push упадёт) +curl -s -X POST "$GITVERSE_API/user/repos" \ + -H "Authorization: Bearer $GITVERSE_PAT" \ + -H "Accept: application/vnd.gitverse.object+json;version=1" \ + -H "Content-Type: application/json" \ + -d "{\"name\":\"\",\"description\":\"<описание>\",\"private\":true,\"auto_init\":false}" +``` + +HTTP 201 = создан; 409 = уже существует. + +## Шаг 4. Push на gitverse + +```bash +git remote add origin "https://$GITVERSE_LOGIN:$GITVERSE_PAT@gitverse.ru/$GITVERSE_LOGIN/.git" +git push -u origin <текущая-ветка> +``` + +Ветку НЕ переименовывать без явной команды пользователя (в разных проектах уже master и main — сохранять как есть). + +## Шаг 5. Pull mirror в gitea (синхронизация 2 раза в сутки) + +```bash +source /opt/hermes/.hermes/secrets/git-tokens.env +# токен gitea уже в GITEA_TOKEN; при необходимости перевыпустить: +# docker exec -u 1000 gitea gitea admin user generate-access-token \ +# --username estorozhenko --token-name -mirror \ +# --scopes "read:repository,write:repository,read:user,write:user" --raw +# и обновить GITEA_TOKEN в secrets/git-tokens.env + +curl -X POST "$GITEA_API/repos/migrate" \ + -H "Authorization: token $GITEA_TOKEN" -H "Content-Type: application/json" \ + -d "{\"clone_addr\":\"https://oauth2:$GITVERSE_PAT@gitverse.ru/$GITVERSE_LOGIN/.git\", + \"repo_name\":\"\",\"repo_owner\":\"estorozhenko\",\"service\":\"git\", + \"mirror\":true,\"mirror_interval\":\"12h\"}" +``` + +HTTP 201 = mirror создан, интервал 12h = два раза в сутки. + +## Шаг 6. Проверка (обязательно) + +1. HEAD совпадает: + ```bash + source /opt/hermes/.hermes/secrets/git-tokens.env + git ls-remote "https://oauth2:$GITVERSE_PAT@gitverse.ru/$GITVERSE_LOGIN/.git" HEAD + docker exec gitea git --git-dir=/data/git/repositories/estorozhenko/.git rev-parse HEAD + ``` +2. Принудительная синхронизация: + ```bash + curl -X POST "$GITEA_API/repos/estorozhenko//mirror-sync" \ + -H "Authorization: token $GITEA_TOKEN" # → 200 + ``` + +После этого работать как обычно: `git commit` + `git push`; mirror подтянет изменения автоматически через ≤12ч. + +## Питфолы (проверено на практике) + +- **База gitverse API — `https://api.gitverse.ru`**, НЕ `gitverse.ru/api/v1/...` (тот путь отдаёт HTML Next.js SPA, не JSON). +- Gitea migrate **с ssh:// всегда 422** — только `https://oauth2:@gitverse.ru/...`. Настраивать SSH-протокол в MIGRATIONS_ALLOWED_PROTOCOLS бесполезно (известный баг, не листать заново). +- `auto_init: false` — иначе gitverse создаёт свой README, и первый push падает (non-fast-forward). +- `private: true` — требование пользователя, не забывать. +- `mirror_interval: "12h"` = два раза в сутки; "8h" не подходит по ТЗ. +- Токены не хранить в коде/README/коммитах — только в remote URL и переменных сессии. + +## Связанные навыки + +- `git-forge-management` — общие операции с gitverse/gitea, references `gitea-pull-mirror-gitverse.md`, `gitverse-api.md` +- `github-repo-management` — для GitHub (gh CLI) \ No newline at end of file diff --git a/templates/docker-gitignore.md b/templates/docker-gitignore.md new file mode 100644 index 0000000..1c16949 --- /dev/null +++ b/templates/docker-gitignore.md @@ -0,0 +1,97 @@ +# Шаблон .gitignore для проектов с Docker + +Секция docker — базовый минимум. Секции Python/Node/Go — добавить по стеку. +**НИКОГДА не игнорировать**: `docker-compose*.yml`, `compose*.yaml`, `Dockerfile*`, `README*`, `*.md`, `*.yml`/`*.yaml` (конфиги), `PLAN.md`, `STATUS.md`, `TODO.md`. + +## Docker (всегда, если есть compose/Dockerfile) + +``` +# --- Docker --- +*.pid +*.seed +*.sock +*.swp +.dockerignore-tmp +``` + +> НЕ игнорировать `docker-compose*.yml` — это источник истины деплоя, он в git. +> Пропускать `.env*` только если они содержат секреты; `.env.example` — в git. + +## Python (pip/venv/poetry) + +``` +# --- Python --- +__pycache__/ +*.py[cod] +*$py.class +*.egg-info/ +.eggs/ +build/ +dist/ +.venv/ +venv/ +env/ +.env +.pytest_cache/ +.mypy_cache/ +.ruff_cache/ +.coverage +htmlcov/ +.tox/ +.uv/ +.ipynb_checkpoints/ +``` + +## Node (npm/yarn/pnpm) + +``` +# --- Node --- +node_modules/ +npm-debug.log* +yarn-error.log* +pnpm-debug.log* +dist/ +build/ +coverage/ +.env.local +.env.*.local +.next/ +out/ +``` + +## Go + +``` +# --- Go --- +/bin/ +*.exe +*.test +*.out +coverage.out +``` + +## Универсальное (всегда) + +``` +# --- OS / редакторы --- +.DS_Store +Thumbs.db +*~ +.idea/ +.vscode/ +*.swp +*.swo + +# --- Логи / временное --- +*.log +logs/ +tmp/ +temp/ +``` + +## Правило проверки + +Перед `git add -A` проверить `git status` — в списке не должно быть секретов, +venv/node_modules, бинарников. Если `.env` реальный с секретами — решение по +включению/исключению явно согласовать с пользователем (по умолчанию: игнорить, +`.env.example` с заглушками фиксировать в git). \ No newline at end of file