Диспатч уходит после того, как ссылка ветки доехала

`workflow_dispatch` в API принимает только ref: SHA туда передать нельзя, имя
ветки резолвится на стороне GitHub в момент запуска. Конвейер перед этим сам
переписывает ветку ребейзом — и 12.09 на #536 диспатч, отправленный через три
секунды после force-push, встал на ДОпушевый SHA. Гейт искал прогон строго на
SHA материала, не нашёл и вернул задачу автору со словами «материал сменился».
Чинить было нечего: дерево задачи не менялось ни на байт, материал сдвинул сам
конвейер.

Две меры, у каждой своя роль.

Шаг ребейза не заканчивается, пока REST не отдаст новую вершину — именно REST,
потому что через него же идёт диспатч. Минута ожидания, после чего отказ, а не
молчание: диспатч на устаревший SHA стоит трёх минут гейта и потерянного
захода.

Гейт, не дождавшись прогона на материале и увидев на ветке диспатч на другом
SHA, сначала пробует запустить ещё раз. Своя гонка этим закрывается, чужой
коммит переживает и вторую попытку, а формулировка отказа больше не называет
сменой материала то, что ею не является.

Issue: #539
User-Visible: no
This commit is contained in:
Codex
2026-09-12 13:54:03 +03:00
parent 1ef35883e0
commit ccfd2565a7
5 changed files with 119 additions and 5 deletions
+21
View File
@@ -347,6 +347,8 @@ jobs:
if: needs.guard.outputs.stage == 'code' && steps.branch.outputs.name != ''
env:
TOKEN: ${{ secrets.HP_PROCESS_TOKEN }}
# #539: тем же токеном спрашивается REST — через него идёт и диспатч.
GH_TOKEN: ${{ secrets.HP_PROCESS_TOKEN }}
BRANCH: ${{ steps.branch.outputs.name }}
# rebase, в отличие от commit, не принимает -c user.*: он запускает
# свои процессы и требует личность в окружении, иначе падает с
@@ -389,6 +391,25 @@ jobs:
echo "::error::ветка $BRANCH изменилась во время ребейза — прогон прерван, чтобы не потерять коммит автора"
exit 1
fi
# #539: ссылка на стороне GitHub доезжает не мгновенно, а гейт ниже
# просит `workflow_dispatch` ПО ИМЕНИ ВЕТКИ — SHA туда передать
# нельзя. 12.09 на #536 диспатч, отправленный через три секунды после
# этого push, встал на ДОпушевый SHA: гейт не нашёл прогона на
# материале и вернул задачу автору, которому чинить было нечего.
# Поэтому шаг не заканчивается, пока REST не отдаст новую вершину —
# именно REST, потому что через него же идёт и сам диспатч.
after=$(git rev-parse HEAD)
settled=false
for _ in $(seq 1 30); do
seen=$(gh api "repos/${{ github.repository }}/git/ref/heads/$BRANCH" \
--jq .object.sha 2>/dev/null || true)
if [ "$seen" = "$after" ]; then settled=true; break; fi
sleep 2
done
if [ "$settled" != "true" ]; then
echo "::error::ссылка $BRANCH за минуту не стала указывать на $after — диспатч встал бы на устаревший SHA"
exit 1
fi
# Локальная ссылка обновляется тоже: шаг слияния берёт origin/$BRANCH,
# и без этого он ребейзил бы заново уже приведённое.
git fetch -q origin "+refs/heads/$BRANCH:refs/remotes/origin/$BRANCH"