mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-01 20:29:00 +00:00
fix(process): publish steps tell a GitHub push refusal from a moved branch (#723)
Two steps publish a commit and treated every failed push as a moved branch: the release review job (release-review.yml) retried three times with "dev went ahead", and the review document step (_process.yml) rebased and pushed again. A refusal by GitHub itself - a token without the workflow right, a branch rule, a hook - cannot be cured by a retry or a rebase, and the step never said what GitHub answered. Both pushes now keep stderr and hand it to the #705 classifier through the same CLI the rebase guard uses (merge-candidate.mjs --push-refusal). Only a stale lease (rejected / fetch first / stale info) keeps the old retry or rebase. Any other outcome stops the step at once, without retries: the log gets the git answer and the step summary gets the reason and the git answer, both passed through redactSecrets (token, credential URL, Authorization). The review document step takes the classifier from dev, as the rebase guard does: a task branch behind dev may not carry it. The summary text is written by the new --summary option (refusalSummary), not by a multi-line string in run:, and both commit messages are now built line by line into a file instead of a heredoc (PROCESS.md §10.4 item 4). release-review.yml is dispatch-only and is not mirrored to main. PROCESS.md names the rule next to the rebase guard; the #638 trailer witness in test/release-review.test.mjs follows the line-by-line message. test/publish-push-refusal.test.mjs runs both steps as they are with real bash and real git in temporary repositories; only the push transport is replaced: a moved branch is a real neighbour push, a GitHub refusal is a recorded stderr carrying a token, a credential URL and an Authorization header. On the old steps 9 of its 11 tests fail. Issue: #723 User-Visible: no Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018qZfe7YS4rqEMKoVeS3GKd
This commit is contained in:
@@ -1597,14 +1597,17 @@ jobs:
|
||||
fi
|
||||
# Первый рубеж: что вообще проиндексировано.
|
||||
git diff --cached --name-only | node scripts/review-doc-guard.mjs
|
||||
# Сообщение коммита — построчно в файл, без heredoc в `run:` (#723).
|
||||
msg="$RUNNER_TEMP/review-doc-commit.txt"
|
||||
{
|
||||
echo "docs: review document for #$NUM"
|
||||
echo ""
|
||||
echo "Issue: #$NUM"
|
||||
echo "User-Visible: no"
|
||||
} > "$msg"
|
||||
git -c user.name="claude[bot]" \
|
||||
-c user.email="209825114+claude[bot]@users.noreply.github.com" \
|
||||
commit -q -F - <<EOF
|
||||
docs: review document for #$NUM
|
||||
|
||||
Issue: #$NUM
|
||||
User-Visible: no
|
||||
EOF
|
||||
commit -q -F "$msg"
|
||||
# Второй рубеж, и он главный: что пуш ДОБАВИТ в целевую ветку. Первый
|
||||
# судит намерение шага, этот — результат, а расходились они именно
|
||||
# тогда, когда база оказывалась не той.
|
||||
@@ -1612,8 +1615,26 @@ jobs:
|
||||
# Публикация в dev идёт из детачнутого состояния поверх ветки задачи
|
||||
# либо dev, поэтому push нужен с явным перебазированием при гонке:
|
||||
# dev мог уйти вперёд, пока шло ревью — оно длится до 45 минут.
|
||||
#
|
||||
# #723: гонкой считается только устаревший lease. Отказ разбирает код
|
||||
# слияния (merge-candidate.mjs --push-refusal, #705) — из dev, как у
|
||||
# стража ребейза: ветка, отставшая от dev, его может не нести. Отказ
|
||||
# GitHub (право на workflow, правило ветки, хук) ребейз не лечит:
|
||||
# шаг падает сразу, причина и ответ git без токена — в журнале и в
|
||||
# сводке шага; метка не меняется.
|
||||
tools="$RUNNER_TEMP/publish-tools"
|
||||
rm -rf "$tools" && mkdir -p "$tools"
|
||||
git fetch -q origin dev
|
||||
git archive origin/dev scripts | tar -x -C "$tools"
|
||||
push_err="$RUNNER_TEMP/review-doc-push.stderr"
|
||||
if ! git push -q "https://x-access-token:$TOKEN@github.com/${{ github.repository }}" \
|
||||
"HEAD:$target"; then
|
||||
"HEAD:$target" 2> "$push_err"; then
|
||||
kind=$(node "$tools/scripts/merge-candidate.mjs" --push-refusal="$push_err" --ref="$target" \
|
||||
--stage=review-doc --summary="$GITHUB_STEP_SUMMARY") || kind=unknown
|
||||
if [ "$kind" != "stale" ]; then
|
||||
echo "::error::push документа ревью в $target отклонён ($kind) — это не сдвиг $target, ребейз не поможет; причина и ответ git — выше и в сводке шага"
|
||||
exit 1
|
||||
fi
|
||||
git fetch -q origin "$target"
|
||||
if ! git -c user.name="claude[bot]" \
|
||||
-c user.email="209825114+claude[bot]@users.noreply.github.com" \
|
||||
@@ -1626,8 +1647,13 @@ jobs:
|
||||
# После ребейза набор путей другой — проверяется заново. Форс здесь
|
||||
# запрещён и не появляется: ветка двигается только вперёд.
|
||||
git diff --name-only "origin/$target...HEAD" | node scripts/review-doc-guard.mjs
|
||||
git push -q "https://x-access-token:$TOKEN@github.com/${{ github.repository }}" \
|
||||
"HEAD:$target"
|
||||
if ! git push -q "https://x-access-token:$TOKEN@github.com/${{ github.repository }}" \
|
||||
"HEAD:$target" 2> "$push_err"; then
|
||||
kind=$(node "$tools/scripts/merge-candidate.mjs" --push-refusal="$push_err" --ref="$target" \
|
||||
--stage=review-doc --summary="$GITHUB_STEP_SUMMARY") || kind=unknown
|
||||
echo "::error::документ ревью не опубликован в $target и после ребейза ($kind); причина и ответ git — выше"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
# Постусловие: до ветки дошёл именно ожидаемый файл. Коммит с
|
||||
# документом, названным не по формату, — тот же вердикт без
|
||||
|
||||
@@ -303,6 +303,9 @@ jobs:
|
||||
(cd "$dir" && sha256sum -c manifest.sha256)
|
||||
test "$DOC" = "$(node scripts/release-review.mjs doc --tag="$TAG")"
|
||||
counts=$(jq -r '"High \(.high) · Medium \(.medium) · Low \(.low)"' "$dir/result.json")
|
||||
# Сообщение коммита — построчно в файл, без heredoc в `run:` (#723).
|
||||
msg="$RUNNER_TEMP/release-review-commit.txt"
|
||||
push_err="$RUNNER_TEMP/release-review-push.stderr"
|
||||
for attempt in 1 2 3; do
|
||||
git fetch -q origin dev
|
||||
git reset -q --hard origin/dev
|
||||
@@ -318,24 +321,36 @@ jobs:
|
||||
node scripts/reviews-index.mjs --dir=docs/reviews --strict
|
||||
git add -- "$DOC" docs/reviews/INDEX.md
|
||||
git diff --cached --name-only | node scripts/review-doc-guard.mjs
|
||||
{
|
||||
echo "docs: release review for $TAG"
|
||||
echo ""
|
||||
echo "Независимое ревью линии перед стабильным релизом (PROCESS.md §11.5)."
|
||||
echo "Итог: $counts. Выпуск не блокирует; решение по находкам — за владельцем."
|
||||
echo ""
|
||||
echo "Issue: #638"
|
||||
echo "User-Visible: no"
|
||||
} > "$msg"
|
||||
git -c user.name="claude[bot]" \
|
||||
-c user.email="209825114+claude[bot]@users.noreply.github.com" \
|
||||
commit -q -F - <<MSG
|
||||
docs: release review for $TAG
|
||||
|
||||
Независимое ревью линии перед стабильным релизом (PROCESS.md §11.5).
|
||||
Итог: $counts. Выпуск не блокирует; решение по находкам — за владельцем.
|
||||
|
||||
Issue: #638
|
||||
User-Visible: no
|
||||
MSG
|
||||
commit -q -F "$msg"
|
||||
git diff --name-only "origin/dev...HEAD" | node scripts/review-doc-guard.mjs
|
||||
if git push -q "https://x-access-token:$TOKEN@github.com/${{ github.repository }}" HEAD:dev; then
|
||||
if git push -q "https://x-access-token:$TOKEN@github.com/${{ github.repository }}" HEAD:dev 2> "$push_err"; then
|
||||
echo "### Независимое ревью $TAG" >> "$GITHUB_STEP_SUMMARY"
|
||||
echo "Итог: $counts — \`$DOC\` в dev. Выпуск не блокируется." >> "$GITHUB_STEP_SUMMARY"
|
||||
echo "::notice::$DOC опубликован: $counts"
|
||||
exit 0
|
||||
fi
|
||||
# #723: сдвигом dev считается только устаревший lease — отказ
|
||||
# разбирает код слияния (merge-candidate.mjs --push-refusal, #705).
|
||||
# Отказ GitHub (право на workflow, правило ветки, хук) повтор не
|
||||
# лечит: шаг останавливается, причина и ответ git без токена — в
|
||||
# журнале и в сводке шага.
|
||||
kind=$(node scripts/merge-candidate.mjs --push-refusal="$push_err" --ref=dev \
|
||||
--stage=release-review --summary="$GITHUB_STEP_SUMMARY") || kind=unknown
|
||||
if [ "$kind" != "stale" ]; then
|
||||
echo "::error::push $DOC в dev отклонён ($kind) — это не сдвиг dev, повтор не поможет; причина и ответ git — выше и в сводке шага"
|
||||
exit 1
|
||||
fi
|
||||
echo "::warning::dev ушёл вперёд — попытка $attempt из 3, документ собирается заново"
|
||||
sleep $((attempt * 10))
|
||||
done
|
||||
|
||||
Reference in New Issue
Block a user