ci: подбирать протёкшие buildx-билдеры на входе сборочных job'ов
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 9s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped

Поправка к первому коммиту: там я написал, что post-step у setup-buildx-action
«не срабатывает». Замер это опроверг.

Даты создания 20 висящих билдеров: 17.05, 30.05, 31.05, 13.06, 17.06, 20.06,
28.06, 05.07 — и НИ ОДНОГО за пять недель между 05.07 и 13.08. Два последних
созданы 13.08 в 11:57:43, ровно тем прогоном, что упал с
`no space left on device`. То есть штатная уборка работает, а билдеры текут,
когда job умирает АВАРИЙНО (ENOSPC, OOM, отмена concurrency-группой) — тогда
контейнер job'а мёртв и завершающие шаги не выполняются вообще.

Из этого следует, что завершающий шаг из первого коммита сам по себе почти
бесполезен: он не отработает ровно в тех случаях, которые и создают мусор.
Поэтому добавлен шаг НА ВХОДЕ: подбирает чужие протёкшие билдеры старше
6 часов (самый долгий job — ~17 минут, живой прогон под порог не попадает)
вместе с их `_state`-томами и печатает, сколько убрал и сколько места на диске.

Завершающий шаг оставлен — он дешёвый и закрывает обычные падения.

Refs #2869
This commit is contained in:
bot-backend 2026-08-13 17:43:43 +05:00
parent 4f5d61f0e8
commit 9a43f00a5e
2 changed files with 168 additions and 0 deletions

View file

@ -227,6 +227,34 @@ jobs:
run: |
echo "$GHCR_PAT" | docker login ghcr.io -u lekss361 --password-stdin
- name: Подобрать протёкшие buildx-билдеры (#2869)
# Билдеры протекают НЕ на обычном падении, а когда job умирает аварийно
# (ENOSPC, OOM, отмена concurrency-группой): тогда ни post-step действия,
# ни завершающий шаг не выполняются — контейнер job'а уже мёртв.
# Замер 13.08: 20 висящих билдеров, созданных в 8 дат за три месяца
# (17.05, 30.05, 31.05, 13.06, 17.06, 20.06, 28.06, 05.07) — и ни одного
# за пять недель между 05.07 и 13.08, когда аварий не было. Два последних
# созданы 13.08 11:57:43 — ровно тот прогон, что упал с
# `no space left on device`.
# Поэтому чистим ЧУЖОЙ мусор НА ВХОДЕ: всё старше 6 часов заведомо не
# принадлежит живому прогону (самый долгий job — ~17 минут).
run: |
now=$(date +%s); reaped=0; kept=0
for c in $(docker ps -a --filter "name=^buildx_buildkit_builder-" --format '{{.Names}}'); do
created=$(docker inspect "$c" --format '{{.Created}}' 2>/dev/null) || continue
ts=$(date -d "$created" +%s 2>/dev/null) || continue
age_h=$(( (now - ts) / 3600 ))
if [ "$age_h" -ge 6 ]; then
echo "buildx: убираю протёкший билдер $c (возраст ${age_h} ч)"
docker rm -f "$c" >/dev/null && reaped=$((reaped+1))
docker volume rm "${c}_state" >/dev/null 2>&1 || true
else
kept=$((kept+1))
fi
done
echo "buildx: убрано протёкших ${reaped}, оставлено свежих ${kept}"
df -h / | tail -1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
id: buildx
@ -285,6 +313,34 @@ jobs:
run: |
echo "$GHCR_PAT" | docker login ghcr.io -u lekss361 --password-stdin
- name: Подобрать протёкшие buildx-билдеры (#2869)
# Билдеры протекают НЕ на обычном падении, а когда job умирает аварийно
# (ENOSPC, OOM, отмена concurrency-группой): тогда ни post-step действия,
# ни завершающий шаг не выполняются — контейнер job'а уже мёртв.
# Замер 13.08: 20 висящих билдеров, созданных в 8 дат за три месяца
# (17.05, 30.05, 31.05, 13.06, 17.06, 20.06, 28.06, 05.07) — и ни одного
# за пять недель между 05.07 и 13.08, когда аварий не было. Два последних
# созданы 13.08 11:57:43 — ровно тот прогон, что упал с
# `no space left on device`.
# Поэтому чистим ЧУЖОЙ мусор НА ВХОДЕ: всё старше 6 часов заведомо не
# принадлежит живому прогону (самый долгий job — ~17 минут).
run: |
now=$(date +%s); reaped=0; kept=0
for c in $(docker ps -a --filter "name=^buildx_buildkit_builder-" --format '{{.Names}}'); do
created=$(docker inspect "$c" --format '{{.Created}}' 2>/dev/null) || continue
ts=$(date -d "$created" +%s 2>/dev/null) || continue
age_h=$(( (now - ts) / 3600 ))
if [ "$age_h" -ge 6 ]; then
echo "buildx: убираю протёкший билдер $c (возраст ${age_h} ч)"
docker rm -f "$c" >/dev/null && reaped=$((reaped+1))
docker volume rm "${c}_state" >/dev/null 2>&1 || true
else
kept=$((kept+1))
fi
done
echo "buildx: убрано протёкших ${reaped}, оставлено свежих ${kept}"
df -h / | tail -1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
id: buildx
@ -357,6 +413,34 @@ jobs:
run: |
echo "$GHCR_PAT" | docker login ghcr.io -u lekss361 --password-stdin
- name: Подобрать протёкшие buildx-билдеры (#2869)
# Билдеры протекают НЕ на обычном падении, а когда job умирает аварийно
# (ENOSPC, OOM, отмена concurrency-группой): тогда ни post-step действия,
# ни завершающий шаг не выполняются — контейнер job'а уже мёртв.
# Замер 13.08: 20 висящих билдеров, созданных в 8 дат за три месяца
# (17.05, 30.05, 31.05, 13.06, 17.06, 20.06, 28.06, 05.07) — и ни одного
# за пять недель между 05.07 и 13.08, когда аварий не было. Два последних
# созданы 13.08 11:57:43 — ровно тот прогон, что упал с
# `no space left on device`.
# Поэтому чистим ЧУЖОЙ мусор НА ВХОДЕ: всё старше 6 часов заведомо не
# принадлежит живому прогону (самый долгий job — ~17 минут).
run: |
now=$(date +%s); reaped=0; kept=0
for c in $(docker ps -a --filter "name=^buildx_buildkit_builder-" --format '{{.Names}}'); do
created=$(docker inspect "$c" --format '{{.Created}}' 2>/dev/null) || continue
ts=$(date -d "$created" +%s 2>/dev/null) || continue
age_h=$(( (now - ts) / 3600 ))
if [ "$age_h" -ge 6 ]; then
echo "buildx: убираю протёкший билдер $c (возраст ${age_h} ч)"
docker rm -f "$c" >/dev/null && reaped=$((reaped+1))
docker volume rm "${c}_state" >/dev/null 2>&1 || true
else
kept=$((kept+1))
fi
done
echo "buildx: убрано протёкших ${reaped}, оставлено свежих ${kept}"
df -h / | tail -1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
id: buildx

View file

@ -71,6 +71,34 @@ jobs:
run: |
echo "$GHCR_PAT" | docker login ghcr.io -u lekss361 --password-stdin
- name: Подобрать протёкшие buildx-билдеры (#2869)
# Билдеры протекают НЕ на обычном падении, а когда job умирает аварийно
# (ENOSPC, OOM, отмена concurrency-группой): тогда ни post-step действия,
# ни завершающий шаг не выполняются — контейнер job'а уже мёртв.
# Замер 13.08: 20 висящих билдеров, созданных в 8 дат за три месяца
# (17.05, 30.05, 31.05, 13.06, 17.06, 20.06, 28.06, 05.07) — и ни одного
# за пять недель между 05.07 и 13.08, когда аварий не было. Два последних
# созданы 13.08 11:57:43 — ровно тот прогон, что упал с
# `no space left on device`.
# Поэтому чистим ЧУЖОЙ мусор НА ВХОДЕ: всё старше 6 часов заведомо не
# принадлежит живому прогону (самый долгий job — ~17 минут).
run: |
now=$(date +%s); reaped=0; kept=0
for c in $(docker ps -a --filter "name=^buildx_buildkit_builder-" --format '{{.Names}}'); do
created=$(docker inspect "$c" --format '{{.Created}}' 2>/dev/null) || continue
ts=$(date -d "$created" +%s 2>/dev/null) || continue
age_h=$(( (now - ts) / 3600 ))
if [ "$age_h" -ge 6 ]; then
echo "buildx: убираю протёкший билдер $c (возраст ${age_h} ч)"
docker rm -f "$c" >/dev/null && reaped=$((reaped+1))
docker volume rm "${c}_state" >/dev/null 2>&1 || true
else
kept=$((kept+1))
fi
done
echo "buildx: убрано протёкших ${reaped}, оставлено свежих ${kept}"
df -h / | tail -1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
id: buildx
@ -120,6 +148,34 @@ jobs:
run: |
echo "$GHCR_PAT" | docker login ghcr.io -u lekss361 --password-stdin
- name: Подобрать протёкшие buildx-билдеры (#2869)
# Билдеры протекают НЕ на обычном падении, а когда job умирает аварийно
# (ENOSPC, OOM, отмена concurrency-группой): тогда ни post-step действия,
# ни завершающий шаг не выполняются — контейнер job'а уже мёртв.
# Замер 13.08: 20 висящих билдеров, созданных в 8 дат за три месяца
# (17.05, 30.05, 31.05, 13.06, 17.06, 20.06, 28.06, 05.07) — и ни одного
# за пять недель между 05.07 и 13.08, когда аварий не было. Два последних
# созданы 13.08 11:57:43 — ровно тот прогон, что упал с
# `no space left on device`.
# Поэтому чистим ЧУЖОЙ мусор НА ВХОДЕ: всё старше 6 часов заведомо не
# принадлежит живому прогону (самый долгий job — ~17 минут).
run: |
now=$(date +%s); reaped=0; kept=0
for c in $(docker ps -a --filter "name=^buildx_buildkit_builder-" --format '{{.Names}}'); do
created=$(docker inspect "$c" --format '{{.Created}}' 2>/dev/null) || continue
ts=$(date -d "$created" +%s 2>/dev/null) || continue
age_h=$(( (now - ts) / 3600 ))
if [ "$age_h" -ge 6 ]; then
echo "buildx: убираю протёкший билдер $c (возраст ${age_h} ч)"
docker rm -f "$c" >/dev/null && reaped=$((reaped+1))
docker volume rm "${c}_state" >/dev/null 2>&1 || true
else
kept=$((kept+1))
fi
done
echo "buildx: убрано протёкших ${reaped}, оставлено свежих ${kept}"
df -h / | tail -1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
id: buildx
@ -169,6 +225,34 @@ jobs:
run: |
echo "$GHCR_PAT" | docker login ghcr.io -u lekss361 --password-stdin
- name: Подобрать протёкшие buildx-билдеры (#2869)
# Билдеры протекают НЕ на обычном падении, а когда job умирает аварийно
# (ENOSPC, OOM, отмена concurrency-группой): тогда ни post-step действия,
# ни завершающий шаг не выполняются — контейнер job'а уже мёртв.
# Замер 13.08: 20 висящих билдеров, созданных в 8 дат за три месяца
# (17.05, 30.05, 31.05, 13.06, 17.06, 20.06, 28.06, 05.07) — и ни одного
# за пять недель между 05.07 и 13.08, когда аварий не было. Два последних
# созданы 13.08 11:57:43 — ровно тот прогон, что упал с
# `no space left on device`.
# Поэтому чистим ЧУЖОЙ мусор НА ВХОДЕ: всё старше 6 часов заведомо не
# принадлежит живому прогону (самый долгий job — ~17 минут).
run: |
now=$(date +%s); reaped=0; kept=0
for c in $(docker ps -a --filter "name=^buildx_buildkit_builder-" --format '{{.Names}}'); do
created=$(docker inspect "$c" --format '{{.Created}}' 2>/dev/null) || continue
ts=$(date -d "$created" +%s 2>/dev/null) || continue
age_h=$(( (now - ts) / 3600 ))
if [ "$age_h" -ge 6 ]; then
echo "buildx: убираю протёкший билдер $c (возраст ${age_h} ч)"
docker rm -f "$c" >/dev/null && reaped=$((reaped+1))
docker volume rm "${c}_state" >/dev/null 2>&1 || true
else
kept=$((kept+1))
fi
done
echo "buildx: убрано протёкших ${reaped}, оставлено свежих ${kept}"
df -h / | tail -1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
id: buildx