diff --git a/.github/workflows/wheels-released.yml b/.github/workflows/wheels-released.yml index 12c412d..52757fd 100644 --- a/.github/workflows/wheels-released.yml +++ b/.github/workflows/wheels-released.yml @@ -199,6 +199,12 @@ jobs: env: GPG_PASSPHRASE: ${{ secrets.WHEELS_REPO_GPG_PASSPHRASE }} GPG_KEY_ID: ${{ env.GPG_KEY_ID }} + # Regenerate ONLY the dispatched channel. The sync step above pulls + # just pool// into the runner, so regenerating the *other* + # channel here would scan an empty local pool, emit an empty Packages, + # and the upload below would clobber that channel's index on R2. + # (Stable was vanishing on every bleeding-edge run this way — #2838.) + CHANNELS: ${{ steps.inputs.outputs.channel }} run: | set -euo pipefail chmod +x scripts/regenerate-apt-metadata.sh @@ -222,9 +228,11 @@ jobs: find pool/${CHANNEL} -type f -name '*.deb' | while read -r f; do upload_one "$f" "application/vnd.debian.binary-package" done - # Upload regenerated dists tree. apt-ftparchive rewrites these on - # every run; upload all files in dists/ regardless of channel. - find dists -type f | while read -r f; do + # Upload the regenerated dists tree for THIS channel only. The regen + # step rewrote dists/${CHANNEL}/ (and only that channel — see #2838), + # so scope the upload to match. Uploading dists/ wholesale used to + # push the other channel's (stale/empty) index back to R2. + find dists/${CHANNEL} -type f | while read -r f; do # Pick a sensible content-type per file case "$f" in *.gz) ct="application/gzip" ;; diff --git a/README.md b/README.md index e87c484..44438be 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ the metadata + uploads to R2 on every release. End users do: ```bash # Stable channel curl -fsSL https://apt.wheels.dev/wheels.gpg \ - | sudo tee /usr/share/keyrings/wheels.gpg >/dev/null + | sudo gpg --dearmor -o /usr/share/keyrings/wheels.gpg echo "deb [signed-by=/usr/share/keyrings/wheels.gpg] https://apt.wheels.dev stable main" \ | sudo tee /etc/apt/sources.list.d/wheels.list sudo apt update && sudo apt install wheels @@ -141,7 +141,7 @@ Before this repo will publish a usable repository: ```bash curl -fsSL https://apt.wheels.dev/wheels.gpg \ - | sudo tee /usr/share/keyrings/wheels.gpg >/dev/null + | sudo gpg --dearmor -o /usr/share/keyrings/wheels.gpg echo "deb [signed-by=/usr/share/keyrings/wheels.gpg] https://apt.wheels.dev stable main" \ | sudo tee /etc/apt/sources.list.d/wheels.list sudo apt update diff --git a/index.html b/index.html index afb48c2..b6e682b 100644 --- a/index.html +++ b/index.html @@ -62,7 +62,7 @@

apt.wheels.dev

Stable channel

curl -fsSL https://apt.wheels.dev/wheels.gpg \
-  | sudo tee /usr/share/keyrings/wheels.gpg >/dev/null
+  | sudo gpg --dearmor -o /usr/share/keyrings/wheels.gpg
 echo "deb [signed-by=/usr/share/keyrings/wheels.gpg] https://apt.wheels.dev stable main" \
   | sudo tee /etc/apt/sources.list.d/wheels.list
 sudo apt update && sudo apt install wheels
@@ -70,7 +70,7 @@

Stable channel

Bleeding-edge channel

Published on every merge to develop. The package is named wheels-be so it can coexist with the stable wheels install on the same host.

curl -fsSL https://apt.wheels.dev/wheels.gpg \
-  | sudo tee /usr/share/keyrings/wheels.gpg >/dev/null
+  | sudo gpg --dearmor -o /usr/share/keyrings/wheels.gpg
 echo "deb [signed-by=/usr/share/keyrings/wheels.gpg] https://apt.wheels.dev bleeding-edge main" \
   | sudo tee /etc/apt/sources.list.d/wheels-be.list
 sudo apt update && sudo apt install wheels-be
diff --git a/scripts/regenerate-apt-metadata.sh b/scripts/regenerate-apt-metadata.sh index f1c7f6e..9143767 100755 --- a/scripts/regenerate-apt-metadata.sh +++ b/scripts/regenerate-apt-metadata.sh @@ -1,15 +1,21 @@ #!/bin/bash -# Regenerates apt metadata for both `stable` and `bleeding-edge` distributions -# under dists/, then signs Release with GPG (detached → Release.gpg, inline → -# InRelease). Both signed forms are required: older apt clients read Release + -# Release.gpg, newer clients prefer InRelease. +# Regenerates apt metadata for the selected distributions (default: `stable` + +# `bleeding-edge`) under dists/, then signs Release with GPG (detached → +# Release.gpg, inline → InRelease). Both signed forms are required: older apt +# clients read Release + Release.gpg, newer clients prefer InRelease. # # Inputs (env vars): # GPG_PASSPHRASE — passphrase for the imported signing key # GPG_KEY_ID — long-form key ID (set by the workflow after `gpg --import`) +# CHANNELS — space-separated channels to (re)generate. Defaults to +# "stable bleeding-edge". The release workflow sets this to +# the single dispatched channel so a run only ever rewrites +# the dist whose pool it actually synced (see wheels#2838). # # Idempotent: safe to run by hand against an existing tree to repair a torn -# release. Re-reads everything in pool/ and rewrites dists/ from scratch. +# release. Re-reads everything in pool/ for the selected CHANNELS and rewrites +# their dists/ from scratch — so the pool for each selected channel MUST be +# present locally first, otherwise that channel's index is emitted empty. set -euo pipefail @@ -20,7 +26,12 @@ fi ARCHITECTURES="amd64" COMPONENTS="main" -DISTRIBUTIONS="stable bleeding-edge" +# Only regenerate the channels we were asked to. The workflow syncs just the +# dispatched channel's pool (pool//), so regenerating a channel whose +# pool isn't present would scan an empty dir, emit an empty Packages, and the +# upload would clobber that channel's index on R2. Defaulting to both preserves +# the by-hand full-tree repair path (which must sync both pools first). #2838. +DISTRIBUTIONS="${CHANNELS:-stable bleeding-edge}" # apt-ftparchive uses a config file to know where the pool lives. The same # config drives both distributions — only the dist-name and the scan path