[67ac9ea13687a52717474eadc363cb7d43a3d46a] #bass #github 

Код с GitHub как distfile

https://github.blog/changelog/2023-01-30-git-archive-checksums-may-change/
https://www.cambus.net/on-the-importance-of-distfiles/
https://marc.info/?l=openbsd-ports&m=151973450514279&w=2
не годится, так как они не дают никаких гарантий что не изменится
алгоритм формирования автогенерируемых tarball-ов. В итоге все
контрольные суммы поедут. Грамотный способ делать релизы на GitHub:
заливать самостоятельно сделанные tarball-ы. Насколько вижу по BASS,
большинство так и делает.

[оставить комментарий]
комментарий 0:
From: kmeaw
Date: 2026-03-12 17:15:11Z

Я писал утилиту для зеркалирования distfiles, и специально для snapshot с
vcs-систем добавил туда костыль. Если URL распознаётся правилом "это snapshot
с vcs", то преобразуем (если этого ещё не сделано) branch в commitid, а
потом используем его в качестве cache key.

Например, если на вход подали ссылку
https://www.cpan.org/src/5.0/perl-5.36.0.tar.gz, то всё хорошо, это не vcs
snapshot, поэтому ничего специально не делаем. Cache key будет hash($uri).

А если
https://github.com/NetworkConfiguration/dhcpcd/archive/refs/tags/v10.2.2.tar.gz,
то резолвим tags/v10.2.2, и cache key теперь f6983c18dbf….

Если на следующем цикле зеркалирования tags/v10.2.2 вдруг поменяется, то
только в этом случае попытаемся его перекачать. Не поменяется - значит
можно вообще не дёргать snapshot и сэкономить ресурсы апстрима.

Для всех файлов в базе хранятся Last-Modified, Content-Length и ETag. Если
апстрим не поддерживает ETag, то делаем HEAD и сверяем Last-Modified и
Content-Length. Если Last-Modified не отдаётся или слишком часто меняется,
а апстрим часто отвечает 4xx или 5xx, то проверяем только Content-Length.

Если интересно, то вот схема:

CREATE TABLE errors (
    uri character varying(4096) NOT NULL,
    fetched_at timestamp with time zone DEFAULT now() NOT NULL,
    status_code integer DEFAULT 500 NOT NULL,
    body character varying(8192)
);

CREATE TABLE distfiles (
    sha256 character varying(64) NOT NULL,
    fetched_at timestamp with time zone DEFAULT now() NOT NULL,
    size integer DEFAULT 0 NOT NULL,
    uri character varying(4096) NOT NULL,
    etag character varying(8192),
    last_modified timestamp with time zone,
    head boolean DEFAULT false
);
комментарий 1:
From: Sergey Matveev
Date: 2026-03-12 18:43:18Z

*** kmeaw@kmeaw.com [2026-03-12 17:15]:
>Я писал утилиту для зеркалирования distfiles, и специально для snapshot с
>vcs-систем добавил туда костыль. Если URL распознаётся правилом "это snapshot
>с vcs", то преобразуем (если этого ещё не сделано) branch в commitid, а
>потом используем его в качестве cache key.

Ну у меня redo цели используются. Если есть foo.do, то будет выполнятся
он, и только в противном случае default.do, который будет пытаться
качать обычные файлы. Можно бы было сделать default.vcs.do какую-нибудь
цель, чтобы для VCS-got tarball-ов не писать отдельный .do каждый раз.
Но их у меня не много, пока не напрягает. Плюс у некоторых не просто
надо стянуть, но ещё и submodule-и достать, сформировать архив со всем
этим добром вместе. Но идея VCS-specific URLs импонирует.

    % cat distfiles/dl/opustags-1.10.1.tar.zst.do
    redo-ifchange ../utils/git-to-tarball
    ../utils/git-to-tarball opustags \
        https://github.com/fmang/opustags.git \
        d9b051210ba756d28086c9b75e983e84ae11e730 \
        ${1%.tar.zst}

>Если на следующем цикле зеркалирования tags/v10.2.2 вдруг поменяется, то
>только в этом случае попытаемся его перекачать. Не поменяется - значит
>можно вообще не дёргать snapshot и сэкономить ресурсы апстрима.

Я бы вообще не ориентировался на тех, кто может поменять значение tag.
Не хорошо так делать (только если быстро, пока никто не заметит :-)).
Ну и использовать GitHub API для скачивания tarball-ов я тоже перестал.
Так как они сами заявляют что нет гарантий что алгоритм не поменяется и
все хэши разойдутся. Я теперь VCS-ы клонирую и уже сам формирую tar-ы.
Что ещё и правильнее тем, что хоть какие-то хэши у нас (коммиты) появляются.

>Для всех файлов в базе хранятся Last-Modified, Content-Length и ETag. Если
>апстрим не поддерживает ETag, то делаем HEAD и сверяем Last-Modified и
>Content-Length. Если Last-Modified не отдаётся или слишком часто меняется,
>а апстрим часто отвечает 4xx или 5xx, то проверяем только Content-Length.

Для локальной установки вроде как-то избыточно. Я отталкиваюсь от того,
что tar-ы будут immutable. Если скачали один раз и хэши напротив
закоммиченного эталона сошлись, то больше к upstream и не надо обращаться.
Любые обновления делаются вручную человеком, который забьёт коммиты/хэши,
напротив которых всё будет проверяться. Не очень понимаю use-case для БД
с хранением ETag/времени. Это же не Atom/RSS которые периодически надо
опрашивать и проверять не обновилось ли чего.

Или это для проверки вообще кто жив из зеркал, к кому можно обращаться?
комментарий 2:
From: Sergey Matveev
Date: 2026-03-12 18:51:37Z

*** kmeaw@kmeaw.com [2026-03-12 17:15]:
>Если интересно, то вот схема: [...]

Для своего RSS/Atom feeder я всё на ФС храню:

    feeder/state % l feeds/antirez.com_rss/
    cur/ download.hash etag feed hdr new/ out parse.hash title tmp/ url

Тоже учитывается ETag и time condition. Плюс хэши чтобы проверять точно
ли поменялось что скачалось.
комментарий 3:
From: kmeaw
Date: 2026-03-13 10:55:36Z

> Не очень понимаю use-case для БД с хранением ETag/времени.

Для себя я бы тоже хранил просто в ФС, но тут причина в организационной
структуре. Это сервис зеркалирования, который торчит наружу по http и
находится близко к сборочной ферме, где собирается ОС.

Сборочное окружение устроено так, что весь трафик идёт через
перехватывающий (и перешифровывающий) прокси, который пишет логи. Прокси
может читать мои таблицы, а я могу читать логи прокси. Когда я вижу, что
в логах появился новый URI, то ставлю его в очередь на скачивание и
добавляю запись в files. Когда в files появляется новая запись, прокси
перестаёт ходить в апстрим, и начинает ходить ко мне. Запустить
downloader и proxy на одной машине сложно, ими занимаются разные люди, и
их зоны ответственности и релизные циклы не совпадают.

Меня бы тоже VCS не особо напрягали, но downloader напрягает админов
Gitlab - у них от частого хождения в ручку, отдающую tarball,
заканчиваются ресурсы, и они меня банят по IP. Поэтому пришлось написать
код, специфичный для Gitlab, GitHub, cgit и ещё нескольких систем, чтобы
они не делали для меня export тогда, когда этого не нужно.

Проблема с воспроизводимостью тут решается за счёт того, что я однажды
скачав файл буду отдавать одно и то же содержимое до тех пор, пока ref
не начнёт указывать в другое место. Сборочное окружение следит за
целостностью build inputs и создаёт тикеты на владельцев пакетов, если
что-то изменилось, например прокси отдал другой файл. Тут база данных
тоже оказывается полезной - в таблицу легко пустить человека, чтобы
он разобрался, почему произошли изменения.
комментарий 4:
From: Sergey Matveev
Date: 2026-03-13 14:36:39Z

*** kmeaw@kmeaw.com [2026-03-13 10:55]:
>Сборочное окружение устроено так, что весь трафик идёт через [...]

Ага, спасибо за удовлетворение любопытства!
СУБД тут уже удобна будет, согласен.