feat(ci): skip .deb rebuild when version already published

build-deb now checks the Debian registry first and skips the slow source
compile+upload when the pinned version already exists. Add a force_deb
workflow_dispatch input to rebuild anyway, and make upload.sh idempotent
(HTTP 409 -> already published, skip).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Georg K
2026-06-12 06:02:20 +03:00
parent e3592514f1
commit 0abfe348c1
3 changed files with 43 additions and 5 deletions

View File

@@ -19,6 +19,11 @@ on:
description: rlm_raw module branch description: rlm_raw module branch
required: false required: false
default: v3.2.4 default: v3.2.4
force_deb:
description: Rebuild the .deb even if this version is already published
required: false
default: false
type: boolean
concurrency: concurrency:
group: release group: release
@@ -67,13 +72,35 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Decide whether to (re)build
id: decide
env:
DEB_USER: ${{ secrets.PACKAGES_USER }}
DEB_PASS: ${{ secrets.PACKAGES_TOKEN }}
FORCE: ${{ inputs.force_deb }}
run: |
set -euo pipefail
url="${{ env.DEB_REGISTRY }}/dists/${{ env.DEB_DISTRIBUTION }}/${{ env.DEB_COMPONENT }}/binary-amd64/Packages"
exists=false
if curl -fsSL --user "$DEB_USER:$DEB_PASS" "$url" 2>/dev/null \
| grep -q "Version: ${{ needs.prepare.outputs.pkg_version }}"; then
exists=true
fi
should_build=true
if [ "$exists" = "true" ] && [ "$FORCE" != "true" ]; then
should_build=false
echo "Package ${{ needs.prepare.outputs.pkg_version }} already published — skipping build (set force_deb to rebuild)."
fi
echo "should_build=$should_build" >> "$GITHUB_OUTPUT"
- name: Build .deb builder image - name: Build .deb builder image
if: ${{ steps.decide.outputs.should_build == 'true' }}
run: | run: |
docker build packaging/deb -f packaging/deb/Dockerfile \ docker build packaging/deb -f packaging/deb/Dockerfile \
--build-arg RADIUS_TAG=${{ needs.prepare.outputs.radius_tag }} \ --build-arg RADIUS_TAG=${{ needs.prepare.outputs.radius_tag }} \
--build-arg RLM_RAW_BRANCH=${{ inputs.rlm_raw_branch }} \ --build-arg RLM_RAW_BRANCH=${{ inputs.rlm_raw_branch }} \
-t freerad-builder:${{ needs.prepare.outputs.version }} -t freerad-builder:${{ needs.prepare.outputs.version }}
- name: Upload .deb to Gitea Debian registry - name: Upload .deb to Gitea Debian registry
if: ${{ steps.decide.outputs.should_build == 'true' }}
env: env:
DEB_USER: ${{ secrets.PACKAGES_USER }} DEB_USER: ${{ secrets.PACKAGES_USER }}
DEB_PASS: ${{ secrets.PACKAGES_TOKEN }} DEB_PASS: ${{ secrets.PACKAGES_TOKEN }}

View File

@@ -40,6 +40,8 @@ prepare ──► build-deb ──► build-image ──► package-helm
- `.deb` - источник истины: `build-image` и `package-hosted` имеют `needs: build-deb` - `.deb` - источник истины: `build-image` и `package-hosted` имеют `needs: build-deb`
И дополнительно проверяют, что версия `3.2.8+git` уже опубликована в Debian-реестре И дополнительно проверяют, что версия `3.2.8+git` уже опубликована в Debian-реестре
(GET `dists/noble/main/binary-amd64/Packages`), иначе fail. (GET `dists/noble/main/binary-amd64/Packages`), иначе fail.
- `build-deb` пропускает долгую пересборку, если версия уже в реестре. Принудительно -
input `force_deb=true`. Заливка идемпотентна: `upload.sh` пропускает HTTP 409 (уже есть).
- Авторизация: репо-секреты `PACKAGES_USER` / `PACKAGES_TOKEN` (Gitea token, scope - Авторизация: репо-секреты `PACKAGES_USER` / `PACKAGES_TOKEN` (Gitea token, scope
`write:package`). `write:package`).
- Раннер: `ubuntu-latest` с доступным Docker. - Раннер: `ubuntu-latest` с доступным Docker.
@@ -90,8 +92,9 @@ prepare ──► build-deb ──► build-image ──► package-helm
- Образ при сборке тянет .deb из Debian-реестра Gitea - предполагается публичный read для - Образ при сборке тянет .deb из Debian-реестра Gitea - предполагается публичный read для
owner `pub`. Если реестр приватный, сборку образа надо чинить (read-токен/buildkit secret), owner `pub`. Если реестр приватный, сборку образа надо чинить (read-токен/buildkit secret),
а на нодах нужен `DEB_AUTH` для apt. а на нодах нужен `DEB_AUTH` для apt.
- Реестр может отклонить повторную заливку той же версии .deb (релиз - переиздание версии - Повторная заливка той же версии .deb обрабатывается: `build-deb` её пропускает, а
требует bump `VERSION`). `upload.sh` не падает на HTTP 409. Переиздать изменённое содержимое той же версии нельзя -
нужно либо bump `VERSION`, либо удалить пакет в Gitea. `force_deb` только пересобирает.
- Пароль БД: в hosted - в `.env_cnf` (gitignored, `*.env_cnf`); в k8s - в Secret. В git не - Пароль БД: в hosted - в `.env_cnf` (gitignored, `*.env_cnf`); в k8s - в Secret. В git не
попадает. попадает.

View File

@@ -31,11 +31,19 @@ if [ "${#debs[@]}" -eq 0 ]; then
exit 1 exit 1
fi fi
uploaded=0
skipped=0
for file in "${debs[@]}"; do for file in "${debs[@]}"; do
echo "Uploading ${file} -> ${upload_url}" echo "Uploading ${file} -> ${upload_url}"
curl -fsSL --user "${DEB_USER}:${DEB_PASS}" \ code="$(curl -sS -o /tmp/deb-upload.out -w '%{http_code}' \
--user "${DEB_USER}:${DEB_PASS}" \
--upload-file "./${file}" \ --upload-file "./${file}" \
"${upload_url}" "${upload_url}")"
case "$code" in
20*) echo " ok ($code)"; uploaded=$((uploaded + 1)) ;;
409) echo " already published ($code), skipping"; skipped=$((skipped + 1)) ;;
*) echo " upload failed (HTTP $code):" >&2; cat /tmp/deb-upload.out >&2; exit 1 ;;
esac
done done
echo "Uploaded ${#debs[@]} package(s)" echo "Done: ${uploaded} uploaded, ${skipped} already present"