ci(lint): forbid literal skip-ci marker в commit messages
GitLab платформа skip'ает pipeline на любом commit'е чей subject или body содержит pattern с square brackets вокруг 'skip ci'. Trap: semantic-release включает release notes из всех commit'ов в release commit body — если хотя бы один commit имеет этот pattern в subject/body, release tag pipeline скипается → нет images → нет auto-PR. Реальный случай: v2.16.1 — commit fix(release): 'remove ... из semantic- release commit message' содержал паттерн дословно. Pipeline 6831 (v2.16.1 tag) skipped → пришлось trigger через API. Новый CI job 'commit-msg-lint' (stage: test): - Запускается на MR pipeline'ах и feature-branch push'ах - Скипает chore(release) commit'ы (semantic-release auto-bot) - Для каждого commit'а в range проверяет subject+body на square-bracket skip-ci pattern - Fails CI с ясной подсказкой (как переформулировать) при match RELEASE.md обновлён с разделом 'Skip-ci marker trap': примеры правильных формулировок (skip-ci marker, the directive, etc) и escape hatch (manual API trigger).
This commit is contained in:
+52
-5
@@ -88,18 +88,65 @@ BREAKING CHANGE: /api/v1/* paths больше не поддерживаются.
|
||||
## Skip release for specific commit
|
||||
|
||||
Если хочешь смержить `feat:` или `fix:` но **не** делать release сейчас —
|
||||
добавь `[skip ci]` в commit message ИЛИ используй non-release type
|
||||
(`chore:`, `docs:`, etc).
|
||||
используй non-release type (`chore:`, `docs:`, etc).
|
||||
|
||||
```
|
||||
chore(deps): bump axios 1.7 -> 1.8
|
||||
```
|
||||
|
||||
> ⚠ **НЕ используй `[skip ci]`** в commit message — см. раздел
|
||||
> «Skip-ci marker trap» ниже.
|
||||
|
||||
## Loop prevention
|
||||
|
||||
Release job создаёт commit `chore(release): vX.Y.Z [skip ci]`. `[skip ci]` —
|
||||
стандартный GitLab marker, новый pipeline не триггерится. Версия package.json
|
||||
+ CHANGELOG.md обновляются в этом коммите.
|
||||
Release job создаёт commit `chore(release): vX.Y.Z`. Loop prevention работает
|
||||
через releaseRules в `.releaserc.json` — chore-тип имеет `release: false` →
|
||||
semantic-release на release commit'е detect'ит «no releasable commits» →
|
||||
exit 0 → нет нового tag → нет loop'а.
|
||||
|
||||
> **Historical note:** до MR !154 (2026-05-12) сюда добавлялось `[skip ci]`.
|
||||
> Это работало для main pipeline'а, НО skip'ало и tag pipeline на том же SHA
|
||||
> → images с tag'ом `v*-*-*-<sha>` не собирались → `propose-prod-image-bump`
|
||||
> auto-PR не запускался → manual ручной MR в infra-repo. Удалено.
|
||||
|
||||
## ⚠ Skip-ci marker trap
|
||||
|
||||
GitLab pipeline pattern matcher honors `[skip ci]` в commit subject ИЛИ body —
|
||||
**где угодно в message'е**. semantic-release auto-генерирует release notes
|
||||
из subject+body всех commit'ов с момента последнего tag'а.
|
||||
|
||||
**Trap:** если хоть один commit body содержит литеральное `[skip ci]` (даже
|
||||
описывая фикс этого marker'а в комментариях/changelog), эта строка попадёт
|
||||
в release commit body → GitLab пропустит tag pipeline → нет images →
|
||||
manual escape через `glab api -X POST projects/367/pipeline?ref=vX.Y.Z`.
|
||||
|
||||
**Реальный случай:** v2.16.1 (2026-05-12). Commit `fix(release): remove
|
||||
[skip ci] из semantic-release commit message` — literal `[skip ci]` в
|
||||
subject. Release notes v2.16.1 содержали эту строку → tag pipeline 6831
|
||||
skipped. Pipeline пришлось trigger вручную.
|
||||
|
||||
**Защита:** CI job `commit-msg-lint` (см. `.gitlab-ci.yml`) fail'ит любой
|
||||
commit с substring `[skip ci]` в subject или body. Запускается на MR
|
||||
pipeline'ах и feature-branch push'ах.
|
||||
|
||||
**Если нужно упомянуть skip-ci в commit message:**
|
||||
|
||||
- ✅ `fix: remove skip-ci marker` (дефис вместо пробела)
|
||||
- ✅ `docs: explain GitLab pipeline skip syntax`
|
||||
- ✅ `chore: remove the skip-ci directive from .releaserc`
|
||||
- ❌ `fix: remove [skip ci]` (literal — fails lint)
|
||||
- ❌ `update [skip ci] policy` (literal — fails lint)
|
||||
|
||||
## Manually trigger skipped tag pipeline
|
||||
|
||||
Если tag pipeline всё-таки попал в trap (legacy commits до commit-msg-lint
|
||||
или CI bypass через --no-verify):
|
||||
|
||||
```bash
|
||||
GITLAB_HOST=git.nstart.cloud glab api -X POST "projects/367/pipeline?ref=vX.Y.Z"
|
||||
```
|
||||
|
||||
Создаёт новый pipeline на той же tag-ref. Escape hatch, не regular workflow.
|
||||
|
||||
## Branch policy
|
||||
|
||||
|
||||
Reference in New Issue
Block a user