Skip to content

ci: последовательные публикации в один ref — гонка перезаписи тега :dev - #7

Open
fUS1ONd wants to merge 1 commit into
devfrom
fix/publish-tag-race
Open

ci: последовательные публикации в один ref — гонка перезаписи тега :dev#7
fUS1ONd wants to merge 1 commit into
devfrom
fix/publish-tag-race

Conversation

@fUS1ONd

@fUS1ONd fUS1ONd commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Проблема — не теоретическая, поймана на живом выкате

Мерж PR #6 и PR #5 подряд запустил две публикации. Мультиарх-сборка идёт минутами, и время выполнения у прогонов разное, поэтому прогон более раннего коммита финишировал позже и затёр тег :dev своим образом:

Прогон Коммит Что внутри Финиш
PR #5 b6c040e ссылки в футере 23:24:49
PR #6 f1b1032 только CI 23:26:05 ← затёр тег

Проверено по метке в самом опубликованном образе:

$ docker inspect ghcr.io/lecturelog/lecturelog-web:dev \
    --format '{{index .Config.Labels "org.opencontainers.image.revision"}}'
f1b1032a220643548c6e54a8e52f94b224cf31ae     # ожидалось b6c040e

То есть :dev указывал на сборку без изменений из последнего мержа. Выкат на прод отдал бы старый код, причём молча: docker compose pull отработал бы успешно, healthcheck был бы зелёный, а изменений на сайте не было бы. Такой баг ищут в коде, которого нет.

Пришлось перезапускать публикацию из dev HEAD руками.

Решение

concurrency на уровне workflow — публикации в один и тот же ref идут строго последовательно.

cancel-in-progress: false намеренно. Прерванная на середине публикация оставила бы тег в неопределённом состоянии (часть манифеста запушена, часть нет). Лучше дождаться предыдущей и опубликовать поверх: тогда последним всегда оказывается образ последнего коммита — а это ровно то свойство, которое здесь и нарушилось.

Границы

Не решает случай, когда публикация вообще падает — тогда :dev остаётся на предыдущем коммите, и это правильное поведение. Речь только про порядок успешных публикаций.

Тег latest и версионные теги v* живут в другом ref и в эту гонку не попадают, но группа publish-${{ github.ref }} покрывает и их.

Проверено

  • actionlint — без замечаний
  • Гейт на этом PR (ci.yml уже в dev, так что PR проверяется автоматически)
  • Логика подтверждена фактическими метками образов и временами финиша выше

Два мержа подряд давали гонку: прогон более раннего коммита заканчивался
позже (мультиарх-сборка идёт минутами, время выполнения не одинаково) и
затирал :dev своим образом, откатывая тег на старый код.

Это не теория — произошло при мерже PR #6 и #5. Прогон PR #5 (с ссылками
в футере) финишировал в 23:24:49, прогон PR #6 в 23:26:05, и метка
org.opencontainers.image.revision в опубликованном :dev показывала
f1b1032 вместо b6c040e. Выкат на прод отдал бы код без изменений из PR #5.

cancel-in-progress намеренно false: прерванная публикация оставила бы тег
в неопределённом состоянии. Лучше дождаться предыдущей и опубликовать
поверх — тогда последним всегда оказывается образ последнего коммита.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant