# Ночной полный прогон (#479). # # Тяжёлые job Validate — смоки, golden, performance_smoke — на обычном пуше не # идут: они ни разу не ловили дефект в момент ревью и стоили ~6 минут # критического пути на каждую итерацию. Полный набор идёт на кандидате беты # (трейлер `Release:`), по кнопке и здесь — каждую ночь на голове `dev`. # # Почему не `schedule` прямо в validate.yml: расписание исполняется на ветке # по умолчанию (`main`), а проверять надо `dev`. Один dispatch с `--ref dev` # делает это без переписывания checkout во всех job. Reuse (#208) сохраняется: # при неизменённом дереве ночной прогон обойдётся маркерами. # # Красный ночной прогон — сигнал автору последних коммитов на dev, не гейт: # гейт беты по-прежнему требует зелёный Validate на точном SHA кандидата, и # там полный набор идёт заново. Адресат сигнала (#736) — задачи, чьи коммиты # классов A/B вошли в dev после последней зелёной ночи: job `night_red` пишет # каждой один комментарий (`scripts/night-red.mjs`, PROCESS.md §10.4). # # Сигнал обязан быть настоящим (#492 §7): до этой задачи job завершалась # успехом в момент постановки Validate в очередь, и красный полный прогон не # делал ночной workflow красным. Теперь job находит запущенный прогон и ждёт # его: успешный dispatch — не успешная проверка. # # #727: после Validate при любом его исходе ночь запускает пакетное ревью ship # (`ship-review.yml -f tag=nightly`) на SHA прогона Validate: оно читает код, а # не прогон. Ship-задача узнаёт о дефектах в ночь после слияния, а бета читает # только то, что ночь не прочла (PROCESS.md §11.7). Цвет ночи — цвет Validate. name: "Ночной полный прогон dev · тело (#623)" on: # #623: тело вызывается тонким файлом `nightly.yml` из ветки по умолчанию # по ссылке `@dev`; триггеры, run-name и concurrency живут там. workflow_call: permissions: actions: write contents: read jobs: dispatch: name: "Запустить Validate на dev с полным набором и дождаться результата" runs-on: ubuntu-24.04 timeout-minutes: 90 outputs: # #727: SHA прогона Validate — отдельным шагом до ожидания, красный Validate его не теряет. head_sha: ${{ steps.validate.outputs.head_sha }} # #736: прогон Validate для разбора красной ночи — тем же шагом, до ожидания. run_id: ${{ steps.validate.outputs.run_id }} steps: # #658: при плане 02:30 UTC ночь фактически стартовала в 07:42–08:05 и # кончалась в рабочее время владельца. Сдвиг старта больше часа — видимое # предупреждение, а не молча съеденная ночь. `github.event.schedule` — # строка cron вызывающего `nightly.yml`; NOW_EPOCH подставляет только тест. - name: "Сдвиг старта ночи против расписания" if: github.event_name == 'schedule' env: SCHEDULE: ${{ github.event.schedule }} run: | set -euo pipefail read -r minute hour _ <<< "$SCHEDULE" now=${NOW_EPOCH:-$(date -u +%s)} planned=$(date -u -d "@$now" +%F) planned=$(date -u -d "$planned $hour:$minute" +%s) [ "$planned" -le "$now" ] || planned=$((planned - 86400)) lag=$(( (now - planned) / 60 )) echo "- Старт по расписанию \`$SCHEDULE\` (UTC): сдвиг $lag мин" >> "$GITHUB_STEP_SUMMARY" if [ "$lag" -gt 60 ]; then echo "::warning::ночной прогон стартовал на $lag мин позже расписания ($SCHEDULE UTC) — очередь расписаний GitHub (#658)" fi - name: "Запустить Validate и найти его прогон" id: validate env: GH_TOKEN: ${{ github.token }} REPO: ${{ github.repository }} run: | set -euo pipefail since=$(date -u +%FT%TZ) gh workflow run validate.yml --repo "$REPO" --ref dev -f full=true echo "Validate(dev, full=true) поставлен в очередь: $since" # Найти именно этот прогон: workflow_dispatch на dev, созданный не # раньше момента запуска. До трёх минут на появление в списке. run_id="" for _ in $(seq 1 18); do sleep 10 run_id=$(gh run list --repo "$REPO" --workflow validate.yml --branch dev \ --event workflow_dispatch --json databaseId,createdAt --limit 5 \ --jq "[.[] | select(.createdAt >= \"$since\")] | sort_by(.createdAt) | last | .databaseId // empty") [ -n "$run_id" ] && break done if [ -z "$run_id" ]; then echo "::error::прогон Validate не появился за 3 минуты — dispatch не равен проверке" exit 1 fi url="${{ github.server_url }}/$REPO/actions/runs/$run_id" echo "дочерний прогон: $url" echo "- Validate(dev, full=true): $url" >> "$GITHUB_STEP_SUMMARY" head_sha=$(gh run view "$run_id" --repo "$REPO" --json headSha --jq .headSha) echo "run_id=$run_id" >> "$GITHUB_OUTPUT" echo "head_sha=$head_sha" >> "$GITHUB_OUTPUT" - name: "Дождаться Validate" env: GH_TOKEN: ${{ github.token }} REPO: ${{ github.repository }} RUN_ID: ${{ steps.validate.outputs.run_id }} run: | set -euo pipefail run_id="$RUN_ID" # Ждём завершения; красный дочерний прогон — красный ночной. gh run watch "$run_id" --repo "$REPO" --exit-status --interval 30 # #727 К6: ночное пакетное ревью ship на SHA прогона Validate — при любом его # исходе. Dispatch тонкого `ship-review.yml` (`github.token` порождает прогон, # как у Validate; входы и права тонких файлов уже в main). Job ждёт только # появления прогона, не его конца; не появился — предупреждение, не красная # ночь: цвет ночи — цвет Validate. ship_review: name: "Запустить ночное пакетное ревью ship на SHA прогона Validate" needs: dispatch if: always() continue-on-error: true runs-on: ubuntu-24.04 timeout-minutes: 10 steps: - name: "Запустить ship-ревью и дождаться появления прогона" env: GH_TOKEN: ${{ github.token }} REPO: ${{ github.repository }} CANDIDATE: ${{ needs.dispatch.outputs.head_sha }} run: | set -euo pipefail if [ -z "$CANDIDATE" ]; then echo "::warning::нет SHA прогона Validate — ночное ship-ревью не запущено" echo "- Ship-ревью ночью: не запущено — нет SHA прогона Validate" >> "$GITHUB_STEP_SUMMARY" exit 0 fi since=$(date -u +%FT%TZ) if ! gh workflow run ship-review.yml --ref dev -f tag=nightly -f candidate="$CANDIDATE" --repo "$REPO"; then echo "::warning::ship-ревью ночью не запущено: dispatch отклонён — ночь не красится" echo "- Ship-ревью ночью: dispatch отклонён" >> "$GITHUB_STEP_SUMMARY" exit 0 fi run_id="" for _ in $(seq 1 18); do sleep 10 run_id=$(gh run list --repo "$REPO" --workflow ship-review.yml --branch dev \ --event workflow_dispatch --json databaseId,createdAt --limit 5 \ --jq "[.[] | select(.createdAt >= \"$since\")] | sort_by(.createdAt) | last | .databaseId // empty") [ -n "$run_id" ] && break done if [ -z "$run_id" ]; then echo "::warning::прогон ship-ревью не появился за 3 минуты — ночь не красится, её цвет — цвет Validate" echo "- Ship-ревью ночью (\`$CANDIDATE\`): прогон не появился за 3 минуты" >> "$GITHUB_STEP_SUMMARY" exit 0 fi echo "- Ship-ревью ночью (\`$CANDIDATE\`): ${{ github.server_url }}/$REPO/actions/runs/$run_id" >> "$GITHUB_STEP_SUMMARY" # #736: красная ночь — один комментарий в каждую задачу, чьи коммиты классов # A/B вошли в dev после последней зелёной ночи (`scripts/night-red.mjs`, # PROCESS.md §10.4). Только при красном dispatch с известным прогоном; # исход прогона (failure, а не cancelled/timed_out) скрипт читает сам. # Actions — `github.token`, issue — `HP_PROCESS_TOKEN`: `issues: write` у # ночи нет, и потолок тонкого `nightly.yml` в main не меняется. Сбой — # предупреждение, не красная ночь сверх Validate. night_red: name: "Красная ночь: комментарий в задачи, слитые после последней зелёной" needs: dispatch if: always() && needs.dispatch.result == 'failure' && needs.dispatch.outputs.run_id != '' continue-on-error: true runs-on: ubuntu-24.04 timeout-minutes: 15 permissions: actions: read contents: read steps: # Нужны коммиты и деревья, не блобы; скрипт и его импорты — без зависимостей, npm ci не нужен. - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: ref: dev fetch-depth: 0 filter: blob:none persist-credentials: false - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7 with: node-version: 22 - name: "Комментарий в задачи диапазона от последней зелёной ночи до красной" env: ACTIONS_TOKEN: ${{ github.token }} GH_TOKEN: ${{ secrets.HP_PROCESS_TOKEN }} REPO: ${{ github.repository }} RED_RUN: ${{ needs.dispatch.outputs.run_id }} run: | set -euo pipefail # Сбои API, токена и git скрипт сам сводит к предупреждению; упавший # скрипт — тоже предупреждение: цвет ночи — цвет Validate. if ! node scripts/night-red.mjs --repo="$REPO" --red-run="$RED_RUN"; then echo "::warning::красная ночь (#736): скрипт упал — комментарии не написаны; цвет ночи — цвет Validate" echo "- Красная ночь (#736): скрипт упал — комментарии не написаны" >> "$GITHUB_STEP_SUMMARY" fi