ci(release): promote по умолчанию шлёт текущий HEAD (не последний тег)
Дефолт promote.sh — текущий HEAD чекаута; второй аргумент по-прежнему задаёт явный ref (ветка/тег/sha). Типичный путь: cut на dev → promote testnet → promote main, все три от того же HEAD. testnet/main остаются независимыми FF-указателями. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+23
-21
@@ -8,32 +8,34 @@ fast-forward-указатель** на выбранный релизный те
|
|||||||
**и при этом прод и тест можно катить разным темпом и на разные версии
|
**и при этом прод и тест можно катить разным темпом и на разные версии
|
||||||
одновременно**.
|
одновременно**.
|
||||||
|
|
||||||
## Как релизить
|
## Как релизить (типичный путь)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 1. Нарезать релиз на dev (бамп версии lerna + тег, БЕЗ деплоя)
|
# стоишь на dev
|
||||||
pnpm run cut # = scripts/cut-release.sh
|
pnpm run cut # бамп версии lerna + тег + push dev (деплой НЕ запускает)
|
||||||
|
pnpm run testnet # текущий HEAD (= свежий cut) → testnet (staging), деплой пошёл
|
||||||
# 2. Выкатить в окружения — НЕЗАВИСИМО, в любом порядке и темпе
|
pnpm run production # тот же HEAD → main (production), деплой пошёл
|
||||||
pnpm run testnet # последний тег → testnet (staging)
|
|
||||||
pnpm run production # последний тег → main (production)
|
|
||||||
|
|
||||||
# Точечно: конкретную версию в конкретный контур
|
|
||||||
scripts/promote.sh main v2026.6.16 # эту версию в прод
|
|
||||||
scripts/promote.sh main testnet # ровно то, что сейчас на testnet, в прод
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Рекомендуемая практика (не обязательная): сначала `promote.sh testnet`, проверить
|
`promote` по умолчанию шлёт **текущий HEAD** в указанный контур, поэтому после
|
||||||
на staging, затем `promote.sh main <та же версия>`. Это уже не топологический
|
`cut` оба промоута идут «оттуда же» (с dev). Контуры независимы — можно гнать
|
||||||
гард (как в старом паровозе), а ваш процесс — контуры независимы.
|
прод и тест разным темпом:
|
||||||
|
|
||||||
- `cut-release.sh` — строго на `dev`. Считает версию `vYYYY.M.D` (повторный релиз
|
```bash
|
||||||
того же дня → суффикс `-N`), вызывает `lerna version` (бамп всех package.json +
|
scripts/promote.sh main v2026.6.16 # конкретную версию (тег) в прод
|
||||||
lerna.json, коммит `chore(release): publish`, тег, push `dev`). **Деплой не
|
scripts/promote.sh main testnet # ровно то, что сейчас на testnet, в прод
|
||||||
запускает** — CI не слушает `dev`.
|
# на другой ветке: promote main → улетит HEAD этой ветки (FF-гард не пустит, если
|
||||||
- `promote.sh <testnet|main> [<версия|ref>]` — server-side **fast-forward** push
|
# main не её предок)
|
||||||
выбранного релизного тега на ветку окружения. `REF` по умолчанию — последний тег
|
```
|
||||||
на линии `origin/dev`. Рабочее дерево не трогается. Только вперёд (FF).
|
|
||||||
|
- `cut-release.sh` — строго на `dev`. Версия `vYYYY.M.D` (повторный релиз того же
|
||||||
|
дня → суффикс `-N`), `lerna version` (бамп всех package.json + lerna.json, коммит
|
||||||
|
`chore(release): publish`, тег, push `dev`). **Деплой не запускает** — CI не
|
||||||
|
слушает `dev`.
|
||||||
|
- `promote.sh <testnet|main> [<ref>]` — server-side **fast-forward** push: по
|
||||||
|
умолчанию `HEAD`, иначе указанный ветка/тег/sha. Рабочее дерево не трогается.
|
||||||
|
Только вперёд (FF). **Деплой стартует только если в улетающем коммите есть бамп
|
||||||
|
`lerna.json`, которого ещё нет в целевой ветке** — то есть нужен свежий `cut`.
|
||||||
|
|
||||||
## Что триггерит деплой
|
## Что триггерит деплой
|
||||||
|
|
||||||
|
|||||||
+20
-27
@@ -1,27 +1,25 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
# Независимый деплой по окружениям. testnet и main — НЕ паровоз: каждый из них
|
# Деплой в окружение. По умолчанию летит ТЕКУЩИЙ HEAD (твой чекаут) в указанную
|
||||||
# самостоятельный fast-forward-указатель на выбранный релизный тег dev. Можно
|
# ветку окружения. testnet и main независимы — каждый двигается своим темпом;
|
||||||
# катить в прод и в тест разным темпом и на разные версии одновременно —
|
# только вперёд по fast-forward (живут на линейной истории dev → нет диверджа и
|
||||||
# расхождений и конфликтов нет, потому что оба указателя живут на ЛИНЕЙНОЙ
|
# конфликтов).
|
||||||
# истории dev (двигаются только вперёд по FF).
|
|
||||||
#
|
#
|
||||||
# scripts/promote.sh testnet # последний релиз (тег) → testnet
|
# scripts/promote.sh testnet # текущий HEAD → testnet (staging)
|
||||||
# scripts/promote.sh main # последний релиз (тег) → main
|
# scripts/promote.sh main # текущий HEAD → main (production)
|
||||||
# scripts/promote.sh main v2026.6.16 # конкретную версию → main
|
# scripts/promote.sh main v2026.6.16 # конкретную версию (тег) → main
|
||||||
# scripts/promote.sh main testnet # ровно то, что сейчас на testnet → main
|
# scripts/promote.sh main testnet # ровно то, что сейчас на testnet → main
|
||||||
#
|
#
|
||||||
# REF по умолчанию — последний релизный тег, достижимый из origin/dev (его вешает
|
# Деплой (release.yaml) стартует, только если в улетающем коммите есть изменение
|
||||||
# scripts/cut-release.sh). Деплой стартует push'ем в ветку с изменением lerna.json
|
# lerna.json (релизный бамп от scripts/cut-release.sh), которого ещё нет в целевой
|
||||||
# (бамп-коммит входит в диапазон FF) — слушает .github/workflows/release.yaml.
|
# ветке. Без свежего cut ветка передвинется, но пересборки не будет.
|
||||||
#
|
#
|
||||||
# Только FF (без --force): сервер отвергнет non-fast-forward — это ГАРД, не баг
|
# Только FF (без --force): сервер отвергнет non-fast-forward — это ГАРД, не баг
|
||||||
# (в target попал прямой коммит, либо ты пытаешься откатить ветку назад).
|
# (цель не является предком ref). Откат на старую версию / редеплой без движения
|
||||||
# Откат на более старую версию или редеплой без движения ветки — через
|
# ветки — через workflow_dispatch в release.yaml (inputs: environment + ref).
|
||||||
# workflow_dispatch в release.yaml (inputs: environment + ref), НЕ через этот скрипт.
|
|
||||||
|
|
||||||
usage() { echo "Использование: $0 <testnet|main> [<версия|ref>]"; }
|
usage() { echo "Использование: $0 <testnet|main> [<ref: ветка|тег|sha, по умолчанию HEAD>]"; }
|
||||||
|
|
||||||
TARGET="$1"
|
TARGET="$1"
|
||||||
case "$TARGET" in
|
case "$TARGET" in
|
||||||
@@ -34,14 +32,9 @@ esac
|
|||||||
|
|
||||||
git fetch --tags --force origin
|
git fetch --tags --force origin
|
||||||
|
|
||||||
REF="$2"
|
# По умолчанию — текущий HEAD. Второй аргумент: ветка (testnet/main/dev), тег или sha.
|
||||||
if [ -z "$REF" ]; then
|
REF="${2:-HEAD}"
|
||||||
# Последний релизный тег на линии origin/dev (vYYYY.M.D[-N] от cut-release.sh).
|
if [ "$REF" != "HEAD" ] && git show-ref --verify --quiet "refs/remotes/origin/$REF"; then
|
||||||
REF="$(git describe --tags --abbrev=0 origin/dev)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# REF может быть именем ветки (testnet/main/dev), тегом или sha — разрешаем единообразно.
|
|
||||||
if git show-ref --verify --quiet "refs/remotes/origin/$REF"; then
|
|
||||||
SRC="origin/$REF"
|
SRC="origin/$REF"
|
||||||
else
|
else
|
||||||
SRC="$REF"
|
SRC="$REF"
|
||||||
@@ -51,10 +44,10 @@ REF_SHA="$(git rev-parse --verify "${SRC}^{commit}")"
|
|||||||
REF_VERSION="$(git show "${REF_SHA}:lerna.json" \
|
REF_VERSION="$(git show "${REF_SHA}:lerna.json" \
|
||||||
| sed -nE 's/.*"version"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/p' | head -1)"
|
| sed -nE 's/.*"version"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/p' | head -1)"
|
||||||
|
|
||||||
echo "Деплой: $REF (v${REF_VERSION}) → $TARGET"
|
echo "Деплой: $REF → $TARGET (версия из lerna.json: v${REF_VERSION}, коммит ${REF_SHA:0:9})"
|
||||||
|
|
||||||
# Server-side fast-forward: двигаем удалённый TARGET на REF. Рабочее дерево не трогаем
|
# Server-side fast-forward: двигаем удалённый TARGET на REF. Рабочее дерево не трогаем.
|
||||||
# (никаких checkout/merge). Без --force: сервер отвергнет, если это не fast-forward.
|
# Без --force: сервер отвергнет, если это не fast-forward.
|
||||||
git push origin "${REF_SHA}:refs/heads/${TARGET}"
|
git push origin "${REF_SHA}:refs/heads/${TARGET}"
|
||||||
|
|
||||||
if [ "$TARGET" = "main" ]; then
|
if [ "$TARGET" = "main" ]; then
|
||||||
@@ -65,4 +58,4 @@ fi
|
|||||||
|
|
||||||
echo
|
echo
|
||||||
echo "Готово. origin/$TARGET = $REF (v${REF_VERSION})."
|
echo "Готово. origin/$TARGET = $REF (v${REF_VERSION})."
|
||||||
echo "CI задеплоит: $ENV_LABEL."
|
echo "CI задеплоит: $ENV_LABEL (если в диапазоне есть релизный бамп lerna.json)."
|
||||||
|
|||||||
Reference in New Issue
Block a user