Files
EvoBGP/docs/releasing.md
T
DenozordecandCursor 8267141136
CI / changes (push) Successful in 5s
CI / commitlint (push) Skipped
CI / openapi (push) Successful in 38s
CI / web (push) Successful in 55s
CI / go (push) Successful in 1m4s
CI / bird2 (push) Successful in 17s
CI / release (push) Successful in 4m17s
ci(gitea): point registry and remotes at git.shx.one
Перевести CI, semantic-release, bake и compose с git.shts.su на git.shx.one.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-17 16:43:39 +07:00

102 lines
6.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Релизы и версионирование EvoBGP
EvoBGP использует [Conventional Commits](https://www.conventionalcommits.org/) и [semantic-release](https://semantic-release.gitbook.io/) для полностью автоматических релизов на Gitea (`git.shx.one`). Ручное повышение версии в коде не требуется.
## Как определяется версия
| Тип коммита | 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`, `httpapi`, `api`). Заголовок `refactor(a, b): …` **не парсится** semantic-release → релиз не создаётся (commitlint на PR это тоже отклонит). Подробнее — раздел «Scope и semantic-release» ниже.
`refactor` — patch без новых функций: перестройка кода/UI при том же поведении для пользователя. По semver на одном уровне с `fix`, но семантически «мельче» `feat` (не minor).
Отдельного суффикса `1.x.y.fix` в semver нет: «fix» в Conventional Commits означает **patch** (третья цифра). Для починки пайплайна без смены продукта — `fix(ci):` или `ci:` (оба дают patch после настройки `.releaserc.json`).
Первый релиз при отсутствии git-тегов — **1.0.0**, если есть releasable-коммиты.
**Как не перепутать `feat` и `fix`:** см. раздел «Выбор type: semver, а не «красивые слова»» в [.cursor/rules/conventional-commits.mdc](../.cursor/rules/conventional-commits.mdc). Кратко: `feat` — новая возможность (minor); `fix` — починка ожидаемого поведения (patch); follow-up баги после недавнего `feat` — всегда `fix`, даже если diff большой.
Подробные правила сообщений коммитов: [.cursor/rules/conventional-commits.mdc](../.cursor/rules/conventional-commits.mdc).
## CI-пайплайн (один push в main)
```text
push/merge в main
→ CI: openapi, web, go, bird2 (параллельно)
→ job release (в том же workflow, после quality gates):
→ semantic-release: git tag vX.Y.Z на текущий commit (без доп. commit)
→ Gitea Release + CHANGELOG.md как attachment
→ docker buildx bake с VERSION=X.Y.Z
→ образы: latest, vX.Y.Z, X.Y.Z, sha-*, короткий SHA
```
Pull request: только quality gates + commitlint; релиз и образы **не** публикуются.
Workflow: [.gitea/workflows/ci.yaml](../.gitea/workflows/ci.yaml) (job **release**).
Конфиг 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: **`gitea.token`** (нужны права на releases и packages).
## Источник правды для версии в runtime
Semver из git-тега пробрасывается в Go-бинарники через `-ldflags` при сборке Docker (`deploy/docker/gobinary/Dockerfile`). Пакет [`internal/version`](../internal/version/version.go):
- локально (`go run`) — `version: "dev"`
- в образе после релиза — совпадает с тегом (например `1.2.3`)
API: `GET /version`, `GET /v1/version` — поля `version`, `git_sha`, `build_time`.
Web UI показывает версию из API (footer sidebar, страница «Мониторинг»).
## Scope и semantic-release
Парсер [conventional-commits-parser](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-commits-parser) (его использует semantic-release) **не понимает запятые в scope**:
| Заголовок | Парсится | Релиз |
|-----------|----------|-------|
| `refactor(web): fix layout` | да, `refactor` | patch |
| `refactor(NetworkOverviewTab, NetworkSpeakersCard): fix layout` | **нет**, `type: null` | **нет** |
Правило: **один scope** из таблицы в [.cursor/rules/conventional-commits.mdc](../.cursor/rules/conventional-commits.mdc) (`web`, `httpapi`, `api`, …).
На push в `main` job **release** запускает `scripts/commit/verify-release-commits.mjs` — в логе будут предупреждения о непарсящихся коммитах.
Если релиз «не создался», а CI зелёный: смотрите лог release — часто `No releasable commits`. Исправление: новый коммит с корректным заголовком (например `refactor(web): …`).
## Перезапуск упавшего job release
semantic-release пишет `.release-version` только в `successCmd` при **новом** релизе. Если тег `vX.Y.Z` уже создан, а `docker buildx bake` упал, повторный run того же SHA делает semantic-release no-op (файла нет). Job **release** тогда берёт версию из git-тега на `HEAD` и публикует образы.
Перезапускать нужно **весь job release**, не отдельный шаг bake: checkout + semantic-release + detect + bake идут подряд.
## CHANGELOG
Release notes — в Gitea Release; файл `CHANGELOG.md` генерируется в CI и прикрепляется как asset, **не** попадает в git history.
## Проверка после релиза
1. Один run workflow **CI** на push в main: job **release** зелёный.
2. Gitea: тег `vX.Y.Z` на том же commit, что и merge; Release с notes.
3. Container Registry: `evobgp-api:vX.Y.Z`, `evobgp-api:X.Y.Z`, `evobgp-api:latest`.
4. `curl http://localhost:8080/version``"version":"X.Y.Z"`.
## Первый релиз (bootstrap)
Merge в `main` с `feat(release): ...`**v1.0.0** в том же CI run.