mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
ci: mirror mutation-gate.yml in main after #620
Ночной реестр исполняется из ветки по умолчанию; файл обязан совпадать с dev. Зеркало dev@ee4bbf8f: пропуск ночи по неизменённому дереву, окружение шарда по плану. Issue: #620 User-Visible: no
This commit is contained in:
@@ -19,6 +19,13 @@ name: Мутационный гейт
|
|||||||
# tsc), а реестр режется на четыре чересполосных шарда — полный прогон
|
# tsc), а реестр режется на четыре чересполосных шарда — полный прогон
|
||||||
# укладывается в десятки минут вместо часов. Локальный дифф-режим:
|
# укладывается в десятки минут вместо часов. Локальный дифф-режим:
|
||||||
# node scripts/mutation-gate.mjs --changed origin/dev..HEAD
|
# node scripts/mutation-gate.mjs --changed origin/dev..HEAD
|
||||||
|
#
|
||||||
|
# #620: ночь по расписанию на дереве, уже доказанном зелёным полным прогоном
|
||||||
|
# (тот же tree материала, тот же SHA workflow, маркер не старше недели), шарды не
|
||||||
|
# гоняет — в сводке «reused from run N». Маркер пишет только зелёный агрегатор,
|
||||||
|
# поэтому красный не переносится: следующая ночь гонит реестр заново и снова
|
||||||
|
# заводит issue (#472). Ручной dispatch гонит полный реестр всегда. Решение —
|
||||||
|
# чистая функция scripts/mutation-nightly-reuse.mjs.
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
@@ -54,6 +61,8 @@ jobs:
|
|||||||
sha: ${{ steps.identity.outputs.sha }}
|
sha: ${{ steps.identity.outputs.sha }}
|
||||||
tree: ${{ steps.identity.outputs.tree }}
|
tree: ${{ steps.identity.outputs.tree }}
|
||||||
ref: ${{ steps.identity.outputs.ref }}
|
ref: ${{ steps.identity.outputs.ref }}
|
||||||
|
reuse: ${{ steps.reuse.outputs.reuse }}
|
||||||
|
reused_run: ${{ steps.reuse.outputs.reused_run }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
||||||
with:
|
with:
|
||||||
@@ -65,10 +74,48 @@ jobs:
|
|||||||
echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
|
echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
|
||||||
echo "tree=$(git rev-parse 'HEAD^{tree}')" >> "$GITHUB_OUTPUT"
|
echo "tree=$(git rev-parse 'HEAD^{tree}')" >> "$GITHUB_OUTPUT"
|
||||||
echo "ref=${{ github.event_name == 'workflow_dispatch' && inputs.ref || 'dev' }}" >> "$GITHUB_OUTPUT"
|
echo "ref=${{ github.event_name == 'workflow_dispatch' && inputs.ref || 'dev' }}" >> "$GITHUB_OUTPUT"
|
||||||
|
# #620: самый свежий маркер зелёного прогона этого tree и этого workflow.
|
||||||
|
# Ключ уникален на прогон (кэш неизменяем), восстанавливается по префиксу —
|
||||||
|
# иначе перепроверка после недели не смогла бы освежить маркер.
|
||||||
|
- name: Маркер зелёного прогона этого дерева
|
||||||
|
if: github.event_name == 'schedule'
|
||||||
|
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
|
||||||
|
with:
|
||||||
|
path: artifacts/mutation-green
|
||||||
|
key: mutation-green-v1-${{ steps.identity.outputs.tree }}-${{ github.workflow_sha }}-${{ github.run_id }}
|
||||||
|
restore-keys: |
|
||||||
|
mutation-green-v1-${{ steps.identity.outputs.tree }}-${{ github.workflow_sha }}-
|
||||||
|
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
|
||||||
|
with:
|
||||||
|
node-version: 22
|
||||||
|
# Любой сбой решения — полный прогон: пропуск должен быть доказан, а не
|
||||||
|
# выведен из ошибки. Материал без скрипта (dispatch старого ref) — тоже.
|
||||||
|
- name: Нужен ли прогон
|
||||||
|
id: reuse
|
||||||
|
env:
|
||||||
|
EVENT_NAME: ${{ github.event_name }}
|
||||||
|
TREE: ${{ steps.identity.outputs.tree }}
|
||||||
|
WORKFLOW_SHA: ${{ github.workflow_sha }}
|
||||||
|
RUN_URL_BASE: ${{ github.server_url }}/${{ github.repository }}/actions/runs
|
||||||
|
run: |
|
||||||
|
decision="$RUNNER_TEMP/mutation-reuse.txt"
|
||||||
|
if [ -f scripts/mutation-nightly-reuse.mjs ] && node scripts/mutation-nightly-reuse.mjs --decide \
|
||||||
|
--event="$EVENT_NAME" --tree="$TREE" --workflow-sha="$WORKFLOW_SHA" \
|
||||||
|
--marker=artifacts/mutation-green/marker.json \
|
||||||
|
--summary="$GITHUB_STEP_SUMMARY" --run-url-base="$RUN_URL_BASE" > "$decision"; then
|
||||||
|
cat "$decision" >> "$GITHUB_OUTPUT"
|
||||||
|
if grep -qx 'reuse=true' "$decision"; then
|
||||||
|
echo "::notice::reused from run $(sed -n 's/^reused_run=//p' "$decision")"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "::warning::решение о повторном использовании не получено — полный прогон"
|
||||||
|
echo "reuse=false" >> "$GITHUB_OUTPUT"
|
||||||
|
fi
|
||||||
|
|
||||||
mutants:
|
mutants:
|
||||||
name: "Мутанты: каждый обязан красить тесты (шард ${{ matrix.shard }} из 6)"
|
name: "Мутанты: каждый обязан красить тесты (шард ${{ matrix.shard }} из 6)"
|
||||||
needs: material
|
needs: material
|
||||||
|
if: needs.material.outputs.reuse != 'true'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
@@ -164,7 +211,7 @@ jobs:
|
|||||||
evidence:
|
evidence:
|
||||||
name: "Доказать единый material всех шардов"
|
name: "Доказать единый material всех шардов"
|
||||||
needs: [material, mutants]
|
needs: [material, mutants]
|
||||||
if: always()
|
if: always() && needs.material.outputs.reuse != 'true'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
||||||
@@ -189,6 +236,36 @@ jobs:
|
|||||||
--workflow-sha=${{ github.workflow_sha }} \
|
--workflow-sha=${{ github.workflow_sha }} \
|
||||||
--run-id=${{ github.run_id }} --run-attempt=${{ github.run_attempt }}
|
--run-id=${{ github.run_id }} --run-attempt=${{ github.run_attempt }}
|
||||||
|
|
||||||
|
# #620: маркер пишется ТОЛЬКО после зелёного агрегатора — все шесть шардов
|
||||||
|
# доказаны на одном material. Красный или неполный прогон маркера не оставляет,
|
||||||
|
# и следующая ночь гонит реестр заново.
|
||||||
|
green_marker:
|
||||||
|
name: "Записать маркер зелёного прогона"
|
||||||
|
needs: [material, mutants, evidence]
|
||||||
|
if: needs.material.outputs.reuse != 'true' && needs.mutants.result == 'success' && needs.evidence.result == 'success'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
||||||
|
with:
|
||||||
|
ref: ${{ needs.material.outputs.sha }}
|
||||||
|
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
|
||||||
|
with:
|
||||||
|
node-version: 22
|
||||||
|
- name: Маркер
|
||||||
|
run: |
|
||||||
|
node scripts/mutation-nightly-reuse.mjs \
|
||||||
|
--write-marker=artifacts/mutation-green/marker.json \
|
||||||
|
--tree=${{ needs.material.outputs.tree }} \
|
||||||
|
--sha=${{ needs.material.outputs.sha }} \
|
||||||
|
--workflow-sha=${{ github.workflow_sha }} \
|
||||||
|
--run-id=${{ github.run_id }} --run-attempt=${{ github.run_attempt }} \
|
||||||
|
--event=${{ github.event_name }}
|
||||||
|
- name: Сохранить маркер
|
||||||
|
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
|
||||||
|
with:
|
||||||
|
path: artifacts/mutation-green
|
||||||
|
key: mutation-green-v1-${{ needs.material.outputs.tree }}-${{ github.workflow_sha }}-${{ github.run_id }}
|
||||||
|
|
||||||
# Адресат у отказа (#472). Только по расписанию: ручной dispatch остаётся
|
# Адресат у отказа (#472). Только по расписанию: ручной dispatch остаётся
|
||||||
# для отладки самого гейта, его результат смотрят в прогоне — issue на
|
# для отладки самого гейта, его результат смотрят в прогоне — issue на
|
||||||
# каждый такой отказ был бы шумом, который снова перестанут читать.
|
# каждый такой отказ был бы шумом, который снова перестанут читать.
|
||||||
@@ -198,7 +275,10 @@ jobs:
|
|||||||
report:
|
report:
|
||||||
name: "Отказ расписания: issue и Telegram"
|
name: "Отказ расписания: issue и Telegram"
|
||||||
needs: [material, mutants, evidence]
|
needs: [material, mutants, evidence]
|
||||||
if: always() && github.event_name == 'schedule' && (needs.mutants.result != 'success' || needs.evidence.result != 'success')
|
# #620: ночь, принявшая доказательство прошлого зелёного прогона, отказом не
|
||||||
|
# является — её шарды пропущены намеренно. Любой другой пропуск шардов
|
||||||
|
# (упал material) по-прежнему заводит issue.
|
||||||
|
if: always() && github.event_name == 'schedule' && needs.material.outputs.reuse != 'true' && (needs.mutants.result != 'success' || needs.evidence.result != 'success')
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
|||||||
Reference in New Issue
Block a user