[infra] Gitea git-http отдаёт пустой pack — git clone/fetch не работают (actions/checkout падает) #59

Open
opened 2026-10-28 22:02:37 +03:00 by embeddevio · 1 comment
Owner

Найдено: devops при выполнении #17 (CI-пайплайн, попытка прогнать actions/checkout на runner'е). Приоритет: высокий — ломает любой git-доступ к репозиторию по HTTP и вместе с ним сверку git-blob-SHA.

Симптомы

С любой машины (хост агентов 192.168.1.44, build-хост 192.168.1.147, job-контейнер runner'а):

$ git clone --depth 1 http://192.168.1.111:3000/embeddevio/awg-dash.git /tmp/x
fatal: early EOF
fatal: fetch-pack: invalid index-pack output

Protocol v0: fatal: protocol error: bad pack header.

В CI это выглядит так (из лога actions/checkout@v4):

fatal: protocol error: bad pack header
The process '/usr/bin/git' failed with exit code 128
::error::The process '/usr/bin/git' failed with exit code 128

Что именно ломается (измерено)

GIT_TRACE_CURL на git clone --depth 1 показывает, что сервер отвечает HTTP 200 и сам объявляет крошечное тело:

<= Recv header: Content-Type: application/x-git-upload-pack-result
<= Recv header: Content-Length: 90
<= Recv data: 0011shallow-info.0034shallow 4ff22f43238c04519be24b20ec3438fcdc2f63020001000dpackfile.0000

Т.е. в ответе только shallow-info и маркер packfile — ни одного объекта; pack пустой, поток закрыт корректно (0000). Это не клиент и не сеть (Content-Length задаёт сервер).

Что при этом работает

Проверка Результат
git ls-remote OK, все ветки/SHA отдаются
GET /archive/<sha>.tar.gz 200 OK, 77990 Б, валидный tar (91 запись) — и с хостов, и из job-контейнера
GET /api/v1/version OK (Gitea 1.26.0)
registry /v2/ 401 (включён, требует авторизации) — норма

Т.е. объекты в репозитории живы (archive их читает), падает именно git-upload-pack.

Гипотезы (нужен доступ к хосту Gitea 192.168.1.111)

  1. git pack-objects на стороне Gitea завершается пусто/с ошибкой — классика при переполненном диске или /tmp (pack-objects пишет временные файлы).
  2. Рассинхрон версии git на хосте Gitea и в контейнере Gitea.
  3. Промежуточный слой (reverse-proxy/WAF) режет chunked-ответ именно для git-upload-pack (менее вероятно — Content-Length ставит сам Gitea).

Что нужно сделать (эскалация владельцу, у агентов нет SSH к 192.168.1.111)

# на хосте Gitea
df -h / /tmp; docker exec <gitea> git --version; docker logs --tail 200 <gitea> | grep -iE 'upload-pack|pack-objects|error'
# проверка целостности репозитория
docker exec <gitea> git -C /data/git/repositories/embeddevio/awg-dash.git fsck --full
docker exec <gitea> git -C /data/git/repositories/embeddevio/awg-dash.git repack -adf

Временный обход (уже в CI)

В .gitea/workflows/ci.yml основной путь — actions/checkout@v4 с continue-on-error: true; при падении исходники забираются архивом:

curl -fsSL -o /tmp/src.tar.gz "http://192.168.1.111:3000/${IMAGE_NAME}/archive/${GITHUB_SHA}.tar.gz"
tar -xzf /tmp/src.tar.gz --strip-components=1 -C .

Когда git-http починят, fallback перестанет срабатывать сам.

Refs #17

**Найдено:** devops при выполнении #17 (CI-пайплайн, попытка прогнать `actions/checkout` на runner'е). **Приоритет:** высокий — ломает любой git-доступ к репозиторию по HTTP и вместе с ним сверку git-blob-SHA. ## Симптомы С любой машины (хост агентов `192.168.1.44`, build-хост `192.168.1.147`, job-контейнер runner'а): ``` $ git clone --depth 1 http://192.168.1.111:3000/embeddevio/awg-dash.git /tmp/x fatal: early EOF fatal: fetch-pack: invalid index-pack output ``` Protocol v0: `fatal: protocol error: bad pack header`. В CI это выглядит так (из лога `actions/checkout@v4`): ``` fatal: protocol error: bad pack header The process '/usr/bin/git' failed with exit code 128 ::error::The process '/usr/bin/git' failed with exit code 128 ``` ## Что именно ломается (измерено) `GIT_TRACE_CURL` на `git clone --depth 1` показывает, что сервер отвечает HTTP 200 и **сам** объявляет крошечное тело: ``` <= Recv header: Content-Type: application/x-git-upload-pack-result <= Recv header: Content-Length: 90 <= Recv data: 0011shallow-info.0034shallow 4ff22f43238c04519be24b20ec3438fcdc2f63020001000dpackfile.0000 ``` Т.е. в ответе только `shallow-info` и маркер `packfile` — **ни одного объекта**; pack пустой, поток закрыт корректно (`0000`). Это не клиент и не сеть (Content-Length задаёт сервер). ## Что при этом работает | Проверка | Результат | |---|---| | `git ls-remote` | OK, все ветки/SHA отдаются | | `GET /archive/<sha>.tar.gz` | **200 OK**, 77990 Б, валидный tar (91 запись) — и с хостов, и из job-контейнера | | `GET /api/v1/version` | OK (Gitea 1.26.0) | | registry `/v2/` | 401 (включён, требует авторизации) — норма | Т.е. объекты в репозитории живы (archive их читает), падает именно `git-upload-pack`. ## Гипотезы (нужен доступ к хосту Gitea 192.168.1.111) 1. `git pack-objects` на стороне Gitea завершается пусто/с ошибкой — классика при **переполненном диске или `/tmp`** (pack-objects пишет временные файлы). 2. Рассинхрон версии git на хосте Gitea и в контейнере Gitea. 3. Промежуточный слой (reverse-proxy/WAF) режет chunked-ответ именно для `git-upload-pack` (менее вероятно — Content-Length ставит сам Gitea). ## Что нужно сделать (эскалация владельцу, у агентов нет SSH к 192.168.1.111) ```bash # на хосте Gitea df -h / /tmp; docker exec <gitea> git --version; docker logs --tail 200 <gitea> | grep -iE 'upload-pack|pack-objects|error' # проверка целостности репозитория docker exec <gitea> git -C /data/git/repositories/embeddevio/awg-dash.git fsck --full docker exec <gitea> git -C /data/git/repositories/embeddevio/awg-dash.git repack -adf ``` ## Временный обход (уже в CI) В `.gitea/workflows/ci.yml` основной путь — `actions/checkout@v4` с `continue-on-error: true`; при падении исходники забираются архивом: ```bash curl -fsSL -o /tmp/src.tar.gz "http://192.168.1.111:3000/${IMAGE_NAME}/archive/${GITHUB_SHA}.tar.gz" tar -xzf /tmp/src.tar.gz --strip-components=1 -C . ``` Когда git-http починят, fallback перестанет срабатывать сам. **Refs #17**
Author
Owner

devops — дополнение к отчёту (28.10, 23:40 MSK).

1. Симптом подтверждён на всех workflow

Помимо ci.yml (где обход уже есть), дефект ломает и второй workflow — contract-openapi.yml. Из лога job'а ts-client-is-current:

fatal: protocol error: bad pack header
The process '/usr/bin/git' failed with exit code 128
❌  Failure - Main checkout

Прогоны runs/60/jobs/178, runs/60/jobs/179, runs/62/jobs/186, runs/62/jobs/187 — падение на checkout за 28–50 с.

Следствие: статусы contract-openapi / openapi-contract и contract-openapi / ts-client-is-current красные на каждом коммите → combined status любого PR = failure (проверено на PR #60: все ci / * зелёные/skipped, но combined = failure).

2. Обход внедрён и проверен (PR #63)

fix/59-checkout-fallback → PR #63: в оба job'а добавлен тот же archive-fallback, что в ci.yml (/archive/<sha>.tar.gz, endpoint работает), плюс ts-client-is-current умеет сравнивать без .git (sha256 сгенерированного schema.d.ts) — семантика проверок не менялась.

Живой прогон: run #64 (sha ca14ae6) — success:

Job Было Стало
openapi-contract ❌ checkout (48 с) ✅ все 6 шагов, включая pytest (contract + unit)
ts-client-is-current ❌ checkout (50 с) ✅ регенерация совпала с закоммиченной схемой

3. Что остаётся на хосте Gitea

Обход не отменяет корневую причину: git-upload-pack по-прежнему отдаёт пустой pack (Content-Length: 90, без объектов), git clone/fetch не работают нигде. Диагностика из шапки этого issue в силе — нужны df -h / /tmp, git fsck --full, git repack -adf внутри контейнера Gitea (нет SSH к 192.168.1.111).

Когда upload-pack починят, fallback перестанет срабатывать сам (основной путь — actions/checkout), менять ничего не придётся.

Refs #17

**devops — дополнение к отчёту (28.10, 23:40 MSK).** ## 1. Симптом подтверждён на всех workflow Помимо `ci.yml` (где обход уже есть), дефект ломает и второй workflow — `contract-openapi.yml`. Из лога job'а `ts-client-is-current`: ``` fatal: protocol error: bad pack header The process '/usr/bin/git' failed with exit code 128 ❌ Failure - Main checkout ``` Прогоны `runs/60/jobs/178`, `runs/60/jobs/179`, `runs/62/jobs/186`, `runs/62/jobs/187` — падение на `checkout` за 28–50 с. **Следствие:** статусы `contract-openapi / openapi-contract` и `contract-openapi / ts-client-is-current` красные на **каждом** коммите → combined status любого PR = `failure` (проверено на PR #60: все `ci / *` зелёные/skipped, но combined = failure). ## 2. Обход внедрён и проверен (PR #63) `fix/59-checkout-fallback` → PR [#63](http://192.168.1.111:3000/embeddevio/awg-dash/pulls/63): в оба job'а добавлен тот же archive-fallback, что в `ci.yml` (`/archive/<sha>.tar.gz`, endpoint работает), плюс `ts-client-is-current` умеет сравнивать без `.git` (sha256 сгенерированного `schema.d.ts`) — семантика проверок не менялась. Живой прогон: run [#64](http://192.168.1.111:3000/embeddevio/awg-dash/actions/runs/64) (sha `ca14ae6`) — **success**: | Job | Было | Стало | |---|---|---| | `openapi-contract` | ❌ checkout (48 с) | ✅ все 6 шагов, включая `pytest` (contract + unit) | | `ts-client-is-current` | ❌ checkout (50 с) | ✅ регенерация совпала с закоммиченной схемой | ## 3. Что остаётся на хосте Gitea Обход не отменяет корневую причину: `git-upload-pack` по-прежнему отдаёт пустой pack (`Content-Length: 90`, без объектов), `git clone/fetch` не работают нигде. Диагностика из шапки этого issue в силе — нужны `df -h / /tmp`, `git fsck --full`, `git repack -adf` внутри контейнера Gitea (нет SSH к `192.168.1.111`). Когда upload-pack починят, fallback перестанет срабатывать сам (основной путь — `actions/checkout`), менять ничего не придётся. **Refs #17**
embeddevio added the blockerdevops labels 2026-10-29 20:55:53 +03:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: embeddevio/awg-dash#59