# Релизы и версионирование CDN Manager CDNManager использует [Conventional Commits](https://www.conventionalcommits.org/) и [semantic-release](https://semantic-release.gitbook.io/) для полностью автоматических релизов на Gitea (`git.shx.one`). Ручное повышение версии в коде не требуется. Заголовок после `тип(scope):` — **на русском** (см. `.cursor/rules/commit-messages-ru.mdc`). Analyzer смотрит только префикс `feat` / `fix` / … ## Как определяется версия | Тип коммита | Bump | |-------------|------| | `feat` | minor (1.0.0 → 1.1.0) | | `fix`, `perf`, `ci`, `refactor` | patch (1.5.1 → 1.5.2) | | `feat!`, `fix!` или `BREAKING CHANGE:` в теле | major (1.0.0 → 2.0.0) | | `docs`, `chore`, `test` | без релиза | **Scope:** один идентификатор **без запятых** (`web`, `api`, `ci`). Заголовок `refactor(a, b): …` **не парсится** semantic-release → релиз не создаётся (commitlint на PR это тоже отклонит). `refactor` — patch без новых функций: перестройка кода/UI при том же поведении для пользователя. Первый релиз при отсутствии git-тегов — **1.0.0**, если есть releasable-коммиты. ## CI-пайплайн (push в main) ```text push/merge в main → workflow CD: quality (web, api) → job publish: → semantic-release: git tag vX.Y.Z на текущий commit (без доп. commit) → Gitea Release + CHANGELOG.md как attachment → зеркало base-образов в cdnmanager-buildcache:base-* → docker buildx bake с VERSION=X.Y.Z (pull=false, named builder cfdm) → образы: latest, vX.Y.Z, X.Y.Z, sha-*, короткий SHA → job update-wiki (параллельно publish): docs/Home.md → wiki ``` Pull request: workflow **CI** — quality gates + commitlint; релиз и образы **не** публикуются. Workflows: [.gitea/workflows/ci.yaml](../.gitea/workflows/ci.yaml), [.gitea/workflows/cd.yaml](../.gitea/workflows/cd.yaml), reusable [.gitea/workflows/quality.yaml](../.gitea/workflows/quality.yaml). Конфиг semantic-release: [.releaserc.json](../.releaserc.json) — без `@semantic-release/git` (CHANGELOG не коммитится в репозиторий). ## Секреты Gitea Один PAT — **`ACTIONS_PAT`** (Settings → Actions → Secrets). | Право PAT | Зачем | |-----------|--------| | push tags | git tag `vX.Y.Z` на commit merge | | releases | Gitea Release + notes | | packages (Container Registry) | push образов | Fallback для **git tag**: `gitea.token`, если PAT недоступен. Push образов в Container Registry — **только `ACTIONS_PAT`** (у job token Gitea нет права packages). Wiki: секрет **`ACTIONS_PAT`** (fallback `GITEA_TOKEN`) для clone/push `*.wiki.git` на `https://git.shx.one` (не внутренний `GITEA_INSTANCE_URL` раннера). Токен передаётся в URL (`oauth2:`): Gitea на неаутентифицированный wiki push отвечает 404, а не 401. ## Источник правды для версии Semver из git-тега пробрасывается в образ как `APP_VERSION` / `GIT_SHA` / `BUILD_TIME` при bake (`deploy/docker/cfdm/Dockerfile`). ## Scope и semantic-release Парсер conventional-commits **не понимает запятые в scope**. Правило: **один scope** (`web`, `api`, `ci`, `docker`). На push в `main` job **publish** запускает `scripts/commit/verify-release-commits.mjs` — в логе будут предупреждения о непарсящихся коммитах. Если релиз «не создался», а CI зелёный: смотрите лог **Detect new release** / **Verify releasable** — часто `No releasable commits`. Причины: 1. Subject не Conventional Commits (`Update CDN Manager: …`, `Init Commit`) — parser не видит `type`. 2. Только `docs` / `chore` / `test` с прошлого тега — намеренный no-op. 3. Scope с запятыми: `refactor(a, b): …` — type не парсится. Исправление: новый коммит с корректным заголовком (например `fix(web): …` или `feat(fleet): …`) и push в `main`. Локально husky `commit-msg` + commitlint; шаблон [`.gitmessage`](../.gitmessage). ## Перезапуск упавшего job publish semantic-release пишет `.release-version` только в `successCmd` при **новом** релизе. Если тег `vX.Y.Z` уже создан, а `docker buildx bake` упал, повторный run того же SHA делает semantic-release no-op (файла нет). Job **publish** тогда берёт версию из git-тега на `HEAD` и публикует образы. Перезапускать нужно **весь job publish**, не отдельный шаг bake: checkout + semantic-release + detect + bake идут подряд. ## CHANGELOG Release notes — в Gitea Release; файл `CHANGELOG.md` генерируется в CI и прикрепляется как asset, **не** попадает в git history. ## Проверка после релиза 1. Один run workflow **CD** на push в main: job **publish** зелёный. 2. Gitea: тег `vX.Y.Z` на том же commit, что и merge; Release с notes. 3. Container Registry: `cfdm:vX.Y.Z`, `cfdm:X.Y.Z`, `cfdm:latest` и алиас `cdn-manager` с теми же тегами. 4. `curl http://localhost:8080/health` → `"status":"ok"`. ## Первый релиз (bootstrap) Merge в `main` с `feat(release): …` → **v1.0.0** в том же CI run.