Skip to content

packaging: .deb/.rpm + apt.moq.dev / rpm.moq.dev workers#1457

Merged
kixelated merged 7 commits into
mainfrom
claude/linux-packages-distribution-cjAUm
May 23, 2026
Merged

packaging: .deb/.rpm + apt.moq.dev / rpm.moq.dev workers#1457
kixelated merged 7 commits into
mainfrom
claude/linux-packages-distribution-cjAUm

Conversation

@kixelated
Copy link
Copy Markdown
Collaborator

Summary

Wires up native Linux distribution for moq-relay, moq-cli, moq-token-cli, and the moq-gst GStreamer plugin. Each tagged release now also produces signed .deb and .rpm artifacts attached to the GitHub Release, and a follow-up workflow regenerates the apt/rpm repository metadata behind two new Cloudflare Workers.

What ships to Linux users

Package Lives in apt as Lives in rpm as Contents
moq-relay moq-relay moq-relay binary + systemd unit + /etc/moq-relay/relay.toml (conffile)
moq-cli moq-cli moq-cli /usr/bin/moq
moq-token-cli moq-token-cli moq-token-cli /usr/bin/moq-token-cli
moq-gst plugin gstreamer1.0-moq gstreamer1-moq libgstmoq.so in the right multiarch dir

End-user one-liner (after the operator bootstrap below is done once):

curl -fsSL https://apt.moq.dev/moq-archive-keyring.gpg \
  | sudo tee /usr/share/keyrings/moq-archive-keyring.gpg > /dev/null
echo "deb [signed-by=/usr/share/keyrings/moq-archive-keyring.gpg] https://apt.moq.dev stable main" \
  | sudo tee /etc/apt/sources.list.d/moq.list
sudo apt update && sudo apt install moq-relay

Design decisions

  • nfpm is the packager. Single Go binary, produces both .deb and .rpm from one YAML, no Ruby/Python runtime dep, no need to pollute Cargo.toml with [package.metadata.deb] blocks. Configs live in packaging/<crate>/nfpm.yaml.
  • Built natively per target distro, not via Nix. .deb/.rpm dynamically link against the consumer's glibc; a Nix-pinned glibc wouldn't match. So .deb builds on ubuntu-22.04 (glibc 2.35 → Ubuntu 22.04+ and Debian 12+) and .rpm builds inside an almalinux:9 container (glibc 2.34 → RHEL/Rocky/Alma 9, Fedora 38+, openSUSE Leap 15.5+). For moq-gst specifically, this also means linking against the distro's libgstreamer1.0-dev / gstreamer1-devel so the .so is symbol-compatible with the GStreamer the user actually has. The existing Nix-built .tar.gz flow is preserved as the generic-Linux fallback.
  • moq-relay systemd unit uses DynamicUser=yes + StateDirectory=moq-relay. No postinst adduser script, no chown dance. Drop cert.pem / key.pem / root.jwk into /var/lib/moq-relay/ and systemctl enable --now moq-relay. The /etc/moq-relay/relay.toml is registered as a conffile so operator edits survive package upgrades.
  • Apt/rpm repos are Cloudflare Workers + R2 matching the rom.moq.dev (demo/boy/) and vid.moq.dev (demo/pub/) pattern. New infra-only workers go under infra/{apt,rpm}/. Existing demo/cdn workers stay where they are since they're co-located with their content; consolidating them under infra/ would be a separate refactor.
  • Apt/rpm publish triggers via gh workflow run apt-repo.yml -f tag=... from each release job. Cannot rely on release:published cascade because GITHUB_TOKEN-created releases don't trigger downstream workflows.

Layered distribution recommendation

The PR description in doc/setup/linux.md documents the full set of options for "how should we distribute to Linux users in general":

  1. Per-distro .deb / .rpm with hosted repos (this PR)
  2. Generic static binary on GitHub Releases (already present, recommended to add a musl variant later)
  3. Docker images (already shipping)
  4. Nix flake + Cachix (already shipping)
  5. cargo install from crates.io (already shipping)
  6. AUR for Arch (out of scope, mentioned as community-maintainable)
  7. Snap / Flatpak: explicitly skipped (Snap conflicts with .deb, Flatpak is desktop-app oriented)

One-time operator bootstrap

infra/README.md is the runbook. TL;DR:

  1. Create R2 buckets apt-moq-dev and rpm-moq-dev.
  2. just infra deploy to bring up the apt.moq.dev and rpm.moq.dev custom domains.
  3. Generate a project GPG signing key, upload the public key to both buckets.
  4. Add five GitHub secrets: R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, R2_ACCOUNT_ID, APT_SIGNING_KEY, APT_SIGNING_KEY_ID.

After that, every moq-relay-v* / moq-cli-v* / moq-token-cli-v* / moq-gst-v* tag automatically populates both repositories.

Test plan

These need to run after the operator bootstrap above, since CI talks to real R2 and GPG infrastructure.

  • Local nfpm smoke: just rs package moq-relay deb produces a valid .deb (Ubuntu host with nfpm installed). Confirm dpkg-deb -I shows the right dependencies and conffile.
  • .deb install in a clean container: docker run --rm -v $PWD/dist:/p ubuntu:22.04 bash -c "apt update && apt install -y /p/moq-relay_*.deb && moq-relay --help". Confirm /lib/systemd/system/moq-relay.service lands and dpkg-query -W -f='${Conffiles}\n' moq-relay lists /etc/moq-relay/relay.toml.
  • .rpm install in AlmaLinux 9: docker run --rm -v $PWD/dist:/p almalinux:9 bash -c "dnf install -y /p/moq-relay-*.rpm && moq-relay --help".
  • GStreamer plugin discovery: docker run --rm -v $PWD/dist:/p ubuntu:22.04 bash -c "apt update && apt install -y gstreamer1.0-tools /p/gstreamer1.0-moq_*.deb && gst-inspect-1.0 moq". No GST_PLUGIN_PATH overrides needed.
  • Conffile preservation: install N, edit /etc/moq-relay/relay.toml, install N+1, confirm the edit survives.
  • Wrangler dry-run: bun wrangler deploy --dry-run in infra/apt/ and infra/rpm/ validates the route+binding.
  • Apt repo publish dry-run: against a throwaway R2 bucket, run infra/apt/publish.sh, then apt update from a clean Ubuntu container pointing at the test domain. Confirm signature verification passes and the advertised version matches the GitHub Release.
  • End-to-end CI dry-run: cut a pre-release tag like moq-relay-v0.0.0-test against a fork. Confirm the workflow produces .deb/.rpm artifacts on the release page and that apt-repo.yml / rpm-repo.yml get dispatched and complete.

https://claude.ai/code/session_013XdpQ4kZDWh7F94b8RwSwx


Generated by Claude Code

…rkers

Ship native Linux packages for moq-relay, moq-cli, moq-token-cli, and the
moq-gst plugin via apt.moq.dev (Debian/Ubuntu) and rpm.moq.dev (Fedora /
RHEL / AlmaLinux). Each tagged release builds .deb/.rpm artifacts with
nfpm, attaches them to the GitHub Release, and dispatches a follow-up
workflow that regenerates the signed repository metadata on R2.

Distribution-format packages link against the consumer's glibc, so the
build matrix is pinned to ubuntu-22.04 (glibc 2.35) and almalinux:9
(glibc 2.34) instead of Nix, which would carry its own glibc. Nix still
owns the existing reproducible tarball flow for moq-gst and the Cachix
path; this is a parallel track with different compatibility tradeoffs.

The apt and rpm workers follow the rom.moq.dev / vid.moq.dev pattern: a
small TypeScript worker proxying GETs out of a per-domain R2 bucket
with content-type and cache-control headers tuned for repo metadata
versus content-addressed package blobs. A new infra/ folder collects
infra-only workers; existing demo/pub, demo/boy, doc, cdn folders stay
put since they are co-located with the content they serve.

User-facing install one-liners live at doc/setup/linux.md; operator
bootstrap (R2 buckets, GPG key, GitHub secrets) lives at infra/README.md.
@kixelated kixelated marked this pull request as ready for review May 23, 2026 16:55
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 23, 2026

Review Change Stack

Warning

Review limit reached

@kixelated, we couldn't start this review because you've used your available PR reviews for now.

Your plan currently allows 4 reviews/hour. Refill in 7 minutes and 19 seconds.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more review capacity refills, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than trial, open-source, and free plans. In all cases, review capacity refills continuously over time.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 89009433-8992-4d98-8d19-06e8d9efcc46

📥 Commits

Reviewing files that changed from the base of the PR and between 8dd444d and 8ece13b.

⛔ Files ignored due to path filters (2)
  • infra/apt/bun.lock is excluded by !**/*.lock
  • infra/rpm/bun.lock is excluded by !**/*.lock
📒 Files selected for processing (20)
  • .github/actions/setup-packaging/action.yml
  • .github/workflows/apt-repo.yml
  • .github/workflows/moq-cli.yml
  • .github/workflows/moq-gst.yml
  • .github/workflows/moq-relay.yml
  • .github/workflows/moq-token-cli.yml
  • .github/workflows/rpm-repo.yml
  • CLAUDE.md
  • doc/setup/linux.md
  • flake.nix
  • infra/README.md
  • infra/apt/publish.sh
  • infra/apt/src/worker.ts
  • infra/rpm/publish.sh
  • justfile
  • packaging/moq-gst/nfpm.yaml
  • packaging/moq-relay/moq-relay.service
  • packaging/moq-relay/relay.toml
  • rs/justfile
  • rs/moq-gst/package.sh

Walkthrough

This PR implements complete Linux package distribution infrastructure for MoQ projects. It adds Cloudflare Workers-backed apt and rpm repositories (apt.moq.dev and rpm.moq.dev) served from R2 buckets, complete with publishing scripts that regenerate repository metadata and upload artifacts. New GitHub Actions workflows build and release packages for moq-cli, moq-token-cli, and updated workflows for moq-relay and moq-gst. The PR includes nfpm packaging definitions for all binaries and plugins, local packaging scripts, a systemd service unit for moq-relay with extensive hardening, comprehensive Linux installation documentation covering Debian/Ubuntu and Fedora-family distributions, and infrastructure deployment automation via justfile tasks.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding native Linux packaging (.deb/.rpm) and hosted repository workers (apt.moq.dev/rpm.moq.dev) for the MoQ project.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, explaining what ships, design decisions, distribution layers, operator bootstrap, and test plan.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/linux-packages-distribution-cjAUm
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch claude/linux-packages-distribution-cjAUm

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Resolves conflicts in moq-relay.yml (kept new .deb/.rpm packaging steps,
adopted main's SHA-pinned actions) and justfile (kept mod infra, dropped
mod cdn since the cdn folder was removed on main). Also pinned actions
in the new moq-cli.yml, moq-token-cli.yml, apt-repo.yml, rpm-repo.yml,
and moq-gst.yml jobs to match main's pinning convention.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 16

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/scripts/install-nfpm.sh:
- Around line 21-27: Download the nfpm tarball into a temp file instead of
streaming to tar; also download the release checksums file for v${NFPM_VERSION},
verify the tarball with sha256sum -c, and only on successful verification
extract and install; update usage of TMP, URL, NFPM_VERSION and NFPM_ARCH to (1)
curl -fSL to save to "$TMP/nfpm_${NFPM_VERSION}_Linux_${NFPM_ARCH}.tar.gz", (2)
curl -fSL to fetch the corresponding checksums.txt, (3) run sha256sum -c against
the checksum entry for that tarball and exit non‑zero on failure, then (4) tar
-xz -C "$TMP" nfpm from the verified archive and sudo install -m 0755
"$TMP/nfpm" /usr/local/bin/nfpm.

In @.github/workflows/apt-repo.yml:
- Line 33: Replace the floating actions/checkout@v6 usage with a pinned commit
SHA and explicitly disable credential persistence: find the line using "uses:
actions/checkout@v6" and change it to the actions/checkout action pinned to a
specific commit SHA (instead of `@v6`) and add the input "persist-credentials:
false" under that step (optionally keep fetch-depth as needed); this hardens the
workflow by preventing supply-chain drift and avoids leaving repository
credentials in the runner.

In @.github/workflows/moq-cli.yml:
- Around line 30-33: The workflow uses floating refs for third-party GitHub
Actions and leaves checkout credentials persisted; update each uses entry (e.g.,
"actions/checkout@v6", "dtolnay/rust-toolchain@stable",
"actions/upload-artifact@v7", "actions/download-artifact@v8") to a pinned
immutable SHA (replace the tag with the specific commit SHA for that action) and
for every actions/checkout invocation add the input persist-credentials: false
so credentials are not persisted; apply these changes to all occurrences
referenced in the diff.

In @.github/workflows/moq-gst.yml:
- Around line 72-75: Update the workflow to harden actions: set actions/checkout
to include persist-credentials: false (so credentials are not retained), and
replace floating tags with pinned commit SHAs for uses of actions/checkout,
dtolnay/rust-toolchain, actions/upload-artifact,
DeterminateSystems/nix-installer-action, and
DeterminateSystems/magic-nix-cache-action (i.e., change
dtolnay/rust-toolchain@stable, actions/upload-artifact@v7,
DeterminateSystems/*`@main` to specific commit SHAs) so each action reference is
immutable and secure.

In @.github/workflows/moq-token-cli.yml:
- Around line 30-33: Update the workflow to pin all GitHub Actions to specific
commit SHAs and disable persisted checkout credentials: for each checkout step
using actions/checkout@v6 add with: persist-credentials: false (both
occurrences) and replace floating refs like dtolnay/rust-toolchain@stable,
actions/upload-artifact@v7, and actions/download-artifact@v8 with their
corresponding commit SHAs (use the latest known stable SHA for each action).
Ensure every action reference in the file is a SHA-pinned ref and that all
checkout steps include persist-credentials: false to avoid leaking tokens.

In @.github/workflows/rpm-repo.yml:
- Line 31: Replace the floating actions/checkout@v6 usage with an immutable
commit SHA and explicitly disable credential persistence: update the step that
uses actions/checkout@v6 to reference the action by its full commit SHA and add
persist-credentials: false to the checkout step; locate the checkout step by the
identifier actions/checkout@v6 in the workflow and modify it accordingly so the
action is pinned and credentials are not persisted.

In `@doc/setup/linux.md`:
- Around line 93-98: Rename the misleading subsection that currently shows the
commands "gpg --import moq-archive-keyring.gpg" and "gpg --verify Release.gpg
Release" so it clearly states that it verifies repository metadata (e.g.,
"Verify repository metadata / Release signature") instead of implying it
validates a downloaded `.deb` file; update any nearby text to reference
"Release.gpg" and the repository metadata verification flow rather than `.deb`
verification, and optionally add a short note suggesting the correct
approach/tool for verifying a `.deb` if needed.
- Line 57: The doc's copy command "sudo cp cert.pem key.pem root.jwk
/var/lib/moq-relay/" can fail if /var/lib/moq-relay doesn't exist; update the
instructions to create the state dir first (e.g., run a safe pre-step like "sudo
mkdir -p /var/lib/moq-relay" and set appropriate ownership/permissions) before
executing the cp, or suggest using an install/rsync command that creates the
destination; mention the exact path /var/lib/moq-relay and the copy command so
readers know where to add the mkdir step.

In `@infra/apt/publish.sh`:
- Around line 38-40: The temp GPG home (GNUPGHOME) isn't always removed on
error; update the cleanup to always remove both WORK and GNUPGHOME by replacing
the single trap with a robust cleanup function (e.g., cleanup() { rm -rf "$WORK"
"${GNUPGHOME:-}" ; } ) and register it for EXIT and ERR (trap 'cleanup' EXIT
ERR) or expand the existing trap to rm -rf "$WORK" "${GNUPGHOME:-}"; reference
the WORK and GNUPGHOME variables and the trap invocation so GNUPGHOME is removed
even when signing fails.
- Around line 41-43: The rclone sync call currently swallows failures with `||
mkdir -p "$WORK/pool"`, allowing the script to continue on auth/network errors;
change the flow so the local directory is created first (`mkdir -p
"$WORK/pool"`) and then run `rclone sync "r2:${BUCKET}/pool" "$WORK/pool"` and
if rclone exits non‑zero, log an error and exit the script (e.g., exit 1).
Update the block around the `rclone sync` invocation to remove the fallback that
masks failures and explicitly fail fast on rclone errors, referencing the
`rclone sync "r2:${BUCKET}/pool" "$WORK/pool"`, `$BUCKET`, and `$WORK/pool`
symbols.

In `@infra/apt/src/worker.ts`:
- Around line 35-39: The cacheControl function currently marks all ".gpg" files
immutable which wrongly pins mutable apt signatures like
"dists/.../Release.gpg"; update cacheControl so only .deb files and files in
"/pool/" get "public, max-age=2592000, immutable" and treat ".gpg" signatures as
short-lived (e.g., "public, max-age=300") unless they are located under "/pool/"
or another immutable path; change the logic in cacheControl to detect ".gpg"
filenames (e.g., "Release.gpg" or paths containing "/dists/") and return the
short-max-age value for those cases.

In `@infra/rpm/publish.sh`:
- Around line 45-56: When iterating new_rpms in the publish script, validate the
detected rpm arch (variable arch from rpm -qp) against the allowed ARCHES array
and fail fast (exit non-zero with an error message) if arch is not in ARCHES —
except allow "noarch" which should be expanded into every ARCHES entry; update
the same validation before the metadata/signing step so only supported arches
are processed. Locate the loop over new_rpms and the metadata/signing block (the
variables/arrays ARCHES, new_rpms, WORK, DIST and the arch variable) and add an
explicit membership check to reject unsupported architectures with a clear error
and non-zero exit.

In `@packaging/moq-relay/moq-relay.service`:
- Line 9: The systemd unit passes the wrong flag: update the ExecStart in
moq-relay.service to use --file instead of --config (change ExecStart to call
/usr/bin/moq-relay --file /etc/moq-relay/relay.toml) so it matches the
configuration struct (pub file: Option<String>) and Config::load() which expects
--file; also search and update any docs or example usages that currently use
--config to use --file for consistency.

In `@packaging/moq-relay/relay.toml`:
- Around line 36-40: Update the misleading comment above the [auth.public]
section so it accurately reflects the publish scope in the config: change the
text that currently says "Allow anonymous publish under anon/** only." to state
that anonymous publish includes both "anon/**" and "demo/viewer" (or
alternatively remove "only" if you prefer). Ensure the comment references the
publish key and values (publish = ["anon", "demo/viewer"]) so the comment and
the actual settings for subscribe and publish remain consistent.

In `@rs/justfile`:
- Around line 80-81: The Debian branch sets arch with a hardcoded fallback
"amd64" when dpkg is missing; change the fallback to derive the host
architecture instead of using amd64 by replacing the fallback in the deb) case
that calls dpkg --print-architecture (refer to the deb) arch=... assignment and
the dpkg --print-architecture command) so it uses uname -m (or a small mapping
from uname -m to Debian arch strings if needed) to produce a correct arch value
on non-debian systems.

In `@rs/moq-gst/package.sh`:
- Around line 37-43: The option parser in the while/case loop reads $2 directly
(for flags --packager, --version, --arch, --target, --output) which will trigger
an unbound-variable error if a flag is passed without a value; update each case
arm in the loop to validate that a non-empty value exists before shifting (e.g.,
check that "$2" is set and does not start with "-" or handle missing value) and
on failure print a clear usage/error message and exit non‑zero so missing flag
values produce a friendly error instead of an unbound-variable crash.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 794179a3-92a5-43c6-a333-66d2913e001c

📥 Commits

Reviewing files that changed from the base of the PR and between 357bd87 and 5cfe234.

📒 Files selected for processing (34)
  • .github/scripts/install-nfpm.sh
  • .github/scripts/trigger-repo-publish.sh
  • .github/workflows/apt-repo.yml
  • .github/workflows/moq-cli.yml
  • .github/workflows/moq-gst.yml
  • .github/workflows/moq-relay.yml
  • .github/workflows/moq-token-cli.yml
  • .github/workflows/rpm-repo.yml
  • README.md
  • doc/.vitepress/config.ts
  • doc/setup/linux.md
  • infra/README.md
  • infra/apt/justfile
  • infra/apt/package.json
  • infra/apt/publish.sh
  • infra/apt/src/worker.ts
  • infra/apt/wrangler.jsonc
  • infra/justfile
  • infra/rpm/justfile
  • infra/rpm/package.json
  • infra/rpm/publish.sh
  • infra/rpm/src/worker.ts
  • infra/rpm/wrangler.jsonc
  • justfile
  • packaging/moq-cli/nfpm.yaml
  • packaging/moq-gst/nfpm.yaml
  • packaging/moq-relay/moq-relay.service
  • packaging/moq-relay/nfpm.yaml
  • packaging/moq-relay/relay.toml
  • packaging/moq-token-cli/nfpm.yaml
  • rs/justfile
  • rs/moq-gst/README.md
  • rs/moq-gst/package.sh
  • rs/moq-relay/README.md

Comment thread .github/scripts/install-nfpm.sh Outdated
Comment thread .github/workflows/apt-repo.yml Outdated
Comment thread .github/workflows/moq-cli.yml Outdated
Comment thread .github/workflows/moq-gst.yml Outdated
Comment thread .github/workflows/moq-token-cli.yml Outdated
Comment thread infra/rpm/publish.sh
Comment thread packaging/moq-relay/moq-relay.service Outdated
Comment thread packaging/moq-relay/relay.toml
Comment thread rs/justfile Outdated
Comment thread rs/moq-gst/package.sh Outdated
Soften the implicit "no comments" default toward "no comments when the code is self-explanatory." The non-obvious WHY (constraints, invariants, workarounds, surprising behavior) still warrants a comment.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (5)
.github/workflows/rpm-repo.yml (1)

31-31: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Disable persisted checkout credentials.

actions/checkout@v6 still defaults persist-credentials to true, so later steps in this job keep authenticated Git access unless you opt out. This workflow already uses GH_TOKEN directly for the GitHub API call path, so persisting the checkout credential is unnecessary. (github.com)

Suggested fix
-      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
+      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
+        with:
+          persist-credentials: false
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/rpm-repo.yml at line 31, The checkout step currently uses
actions/checkout@de0fac2... which defaults persist-credentials to true; update
the checkout step (the actions/checkout usage) to explicitly opt out by adding a
with: persist-credentials: false entry so the job does not keep the repository
authentication after checkout (since GH_TOKEN is used elsewhere).
.github/workflows/moq-token-cli.yml (1)

30-30: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Disable persisted checkout credentials on both checkout steps.

actions/checkout@v6 still defaults persist-credentials to true, so later steps retain authenticated Git access unless you opt out. The release flow here already uses GH_TOKEN explicitly, so both checkout steps can disable credential persistence. (github.com)

Suggested fix
       - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
+        with:
+          persist-credentials: false
...
       - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
         with:
           fetch-depth: 0
+          persist-credentials: false

Also applies to: 103-105

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/moq-token-cli.yml at line 30, Update both checkout steps
that use "uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd" to
explicitly disable persisting credentials by adding a "with" block containing
"persist-credentials: false"; ensure the same change is applied to the second
checkout step (the other actions/checkout usage) so GH_TOKEN is used explicitly
and no authenticated Git credentials are left in later steps.
.github/workflows/moq-gst.yml (1)

30-32: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Disable persisted checkout credentials on every checkout step.

actions/checkout@v6 still defaults persist-credentials to true, so later steps retain authenticated Git access unless you opt out. This workflow already passes explicit credentials where needed, so all four checkout steps can set persist-credentials: false. (github.com)

Suggested fix
       - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
         with:
           fetch-depth: 0
+          persist-credentials: false
...
       - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
+        with:
+          persist-credentials: false
...
       - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
+        with:
+          persist-credentials: false
...
       - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
         with:
           fetch-depth: 0
+          persist-credentials: false

Also applies to: 72-72, 129-129, 188-190

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/moq-gst.yml around lines 30 - 32, In each
actions/checkout@... step (the checkout steps currently showing e.g. the one
using actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd and the other
three checkout steps at the indicated locations), add the key
persist-credentials: false to the step's with: block so the checkout does not
retain authenticated Git credentials for later steps; leave other explicit
credential usages unchanged and ensure the key is added under the existing with:
mapping for each checkout step.
.github/workflows/apt-repo.yml (1)

33-33: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Disable persisted checkout credentials.

actions/checkout@v6 still defaults persist-credentials to true, so later steps in this job keep authenticated Git access unless you opt out. This workflow already passes GH_TOKEN directly to gh, so the checkout credential is unnecessary here. (github.com)

Suggested fix
-      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
+      - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
+        with:
+          persist-credentials: false
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/apt-repo.yml at line 33, The checkout step using
actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd (v6) leaves persisted
credentials enabled; update that checkout invocation to opt out by setting the
persist-credentials input to false (persist-credentials: false) so later steps
don’t retain the repo token (you can keep passing GH_TOKEN directly to gh as
already done).
.github/workflows/moq-cli.yml (1)

30-30: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Disable persisted checkout credentials on both checkout steps.

actions/checkout@v6 still defaults persist-credentials to true, so later steps retain authenticated Git access unless you opt out. In this workflow, release operations already use GH_TOKEN explicitly, so both checkouts can disable credential persistence. (github.com)

Suggested fix
       - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
+        with:
+          persist-credentials: false
...
       - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
         with:
           fetch-depth: 0
+          persist-credentials: false

Also applies to: 103-105

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/moq-cli.yml at line 30, The checkout steps currently use
actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd (v6) and leave
persist-credentials at its default (true); update both checkout steps to
explicitly set persist-credentials: false so later steps do not retain
authenticated Git credentials (i.e., add with: persist-credentials: false to the
actions/checkout uses lines referenced in the diff and the other occurrence
around lines 103-105).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/moq-relay.yml:
- Line 33: The workflow's actions/checkout steps currently leave
persist-credentials at its default true; update both checkout steps in the
moq-relay workflow to set persist-credentials: false (the build checkout step
and the release checkout step where fetch-depth: 0 is set) so Git credentials
are not persisted to later steps; locate the steps that use actions/checkout@...
and add persist-credentials: false alongside their existing settings.

---

Duplicate comments:
In @.github/workflows/apt-repo.yml:
- Line 33: The checkout step using
actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd (v6) leaves persisted
credentials enabled; update that checkout invocation to opt out by setting the
persist-credentials input to false (persist-credentials: false) so later steps
don’t retain the repo token (you can keep passing GH_TOKEN directly to gh as
already done).

In @.github/workflows/moq-cli.yml:
- Line 30: The checkout steps currently use
actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd (v6) and leave
persist-credentials at its default (true); update both checkout steps to
explicitly set persist-credentials: false so later steps do not retain
authenticated Git credentials (i.e., add with: persist-credentials: false to the
actions/checkout uses lines referenced in the diff and the other occurrence
around lines 103-105).

In @.github/workflows/moq-gst.yml:
- Around line 30-32: In each actions/checkout@... step (the checkout steps
currently showing e.g. the one using
actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd and the other three
checkout steps at the indicated locations), add the key persist-credentials:
false to the step's with: block so the checkout does not retain authenticated
Git credentials for later steps; leave other explicit credential usages
unchanged and ensure the key is added under the existing with: mapping for each
checkout step.

In @.github/workflows/moq-token-cli.yml:
- Line 30: Update both checkout steps that use "uses:
actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd" to explicitly disable
persisting credentials by adding a "with" block containing "persist-credentials:
false"; ensure the same change is applied to the second checkout step (the other
actions/checkout usage) so GH_TOKEN is used explicitly and no authenticated Git
credentials are left in later steps.

In @.github/workflows/rpm-repo.yml:
- Line 31: The checkout step currently uses actions/checkout@de0fac2... which
defaults persist-credentials to true; update the checkout step (the
actions/checkout usage) to explicitly opt out by adding a with:
persist-credentials: false entry so the job does not keep the repository
authentication after checkout (since GH_TOKEN is used elsewhere).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e78838a0-2f71-4d6b-97c3-622cd10d510b

📥 Commits

Reviewing files that changed from the base of the PR and between 5cfe234 and 8dd444d.

📒 Files selected for processing (9)
  • .github/workflows/apt-repo.yml
  • .github/workflows/moq-cli.yml
  • .github/workflows/moq-gst.yml
  • .github/workflows/moq-relay.yml
  • .github/workflows/moq-token-cli.yml
  • .github/workflows/rpm-repo.yml
  • CLAUDE.md
  • infra/README.md
  • justfile
✅ Files skipped from review due to trivial changes (2)
  • CLAUDE.md
  • infra/README.md

Comment thread .github/workflows/moq-relay.yml
kixelated and others added 4 commits May 23, 2026 12:42
nfpm and the apt/rpm repo tooling now come from the project flake
(`packages.packaging`) instead of an ad-hoc `curl | tar` of a github
release or `apt-get install`. Versions are pinned via flake.lock, the
same binaries are available locally via `nix develop`, and there's no
more unchecked tarball in the supply chain.

The composite `setup-packaging` action installs Nix, builds the
packaging bundle, and prepends its `bin/` to `$GITHUB_PATH` so the rest
of the job sees a stable nfpm/rclone/gnupg/apt/dpkg/createrepo_c/rpm.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three independent bugs in the deb/rpm pipeline plus the bun lockfiles
that wrangler creates when the infra workers install their deps.

* infra/{apt,rpm}/publish.sh: the pull-from-R2 step was an `rclone sync`
  with a fallback to `mkdir -p`. If the sync partially completed before
  failing, the local mirror went stale, and the push step at the end of
  the script either deleted .rpms from R2 (rpm side, `rclone sync` push)
  or dropped them from the regenerated `Packages` indexes (apt side,
  ftparchive only sees local files). Switch to `rclone copy` for the
  pull so a partial fetch can never cause deletion; on the rpm push,
  split the upload into an additive `copy` for the .rpms and a `sync`
  for the regenerated repodata only.

* packaging/moq-gst: gstreamer-rs 0.23 requires GStreamer >= 1.22 at
  compile time, but the previous workflow built on Ubuntu 22.04 which
  ships 1.20. The build would have failed on the first tag. Move the
  .deb build inside a debian:12 container, which pairs gst 1.22 with
  glibc 2.36; update the libc6 dep accordingly and note in the install
  docs that gstreamer1.0-moq drops Ubuntu 22.04.

* infra: rename APT_SIGNING_KEY{,_ID} -> REPO_SIGNING_KEY{,_ID}. The
  same GPG key signs both repos; the apt-prefixed name was actively
  misleading on the rpm side. Cheap to rename now before the secrets
  are minted on the GitHub repo.

* infra/{apt,rpm}/bun.lock: the worker justfiles run `bun install`
  before deploy. Commit the lockfiles so the wrangler version is
  reproducibly pinned.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ish)

* packaging/moq-relay/moq-relay.service: ExecStart was passing --config
  but moq-relay's clap parser exposes the TOML path as --file (see
  rs/moq-relay/src/config.rs). The service would have failed to start
  on every install.

* infra/apt/src/worker.ts: stop applying immutable Cache-Control to all
  .gpg files. The only static one is moq-archive-keyring.gpg; Release.gpg
  is rewritten every release and was getting pinned at the edge.

* infra/rpm/publish.sh: reject .rpms whose arch isn't in ARCHES (or
  noarch). Previously an unsupported arch silently produced a directory
  that never got indexed or signed.

* infra/{apt,rpm}/publish.sh: move GNUPGHOME removal into the EXIT trap
  so key material is wiped even when signing fails.

* .github/workflows: set persist-credentials: false on every checkout in
  the workflows this PR introduced (moq-cli, moq-token-cli, apt-repo,
  rpm-repo, and the new moq-gst package-deb / package-rpm jobs). Brings
  them in line with the convention from #1463.

* packaging/moq-relay/relay.toml: the comment claimed anonymous publish
  was anon/** only; config also grants demo/viewer. Fixed.

* rs/justfile: drop the hardcoded amd64 fallback when dpkg isn't
  installed. Map from uname -m so `just rs package` produces the right
  arch label on arm64 hosts.

* rs/moq-gst/package.sh: validate that flag values are present before
  reading $2, so a missing value produces a usage error instead of an
  unbound-variable crash.

* doc/setup/linux.md: create /var/lib/moq-relay before the cp step (it
  doesn't exist until the service starts and creates its StateDirectory)
  and rename the misleading "verify a .deb directly" heading.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@kixelated kixelated enabled auto-merge (squash) May 23, 2026 19:55
@kixelated kixelated merged commit 7756dda into main May 23, 2026
1 check passed
@kixelated kixelated deleted the claude/linux-packages-distribution-cjAUm branch May 23, 2026 20:13
kixelated pushed a commit that referenced this pull request May 23, 2026
Resolves conflicts between this branch's nix-based tarball workflows
for moq-cli/moq-relay/moq-token-cli and main's #1457 .deb/.rpm
packaging flow added to the same files. The merged workflows now do
both: main's linux cargo build + .deb + .rpm + apt/rpm repo publish
trigger, plus this branch's macOS tarball build via nix for Homebrew.

Per-crate workflow structure (moq-cli, moq-relay, moq-token-cli):
- build job (main's): linux x86_64+aarch64, cargo, plus a new
  "Package tarball (Homebrew)" step that produces a .tar.gz alongside
  the bare binary and .deb/.rpm. Trigger paths cover the workflow,
  release.sh, package-binary.sh, the packaging/<crate>/ directory, and
  the setup-packaging composite action.
- build-tarball-macos job (new): macOS x86_64+arm64 via nix, runs
  package-binary.sh to produce a .tar.gz for the Homebrew tap.
- release job: needs [build, build-tarball-macos], gated to push
  events so PR dry-runs don't try to upload assets or trigger
  apt/rpm repo publish.

moq-clock keeps the all-nix matrix from this branch (main didn't add
.deb/.rpm packaging for it). moq-gst takes main's content verbatim
(.deb/.rpm + nix tarball), with no PR dry-run.

Dry-run versioning: each Parse version step has a pull_request
fallback that reads from rs/<crate>/Cargo.toml instead of release.sh
parse-version (which requires a GITHUB_REF tag).

https://claude.ai/code/session_015J5tVAQ7ESjBhnzdeXfhgX
kixelated pushed a commit that referenced this pull request May 23, 2026
The merged-in workflow from #1457 references target/release/moq in the
bare-binary copy, .deb BINARY_PATH, and the docker rpm rebuild, but
cargo actually produces target/release/moq-cli (no [[bin]] override on
the moq-cli crate). No moq-cli release has been cut yet so the bug
hadn't been caught, but this PR's dry-run hits it: all four moq-cli
matrix jobs fail at "Package bare binary" with cp: cannot stat 'moq'.

Fix it the smallest way: after cargo build, copy
target/release/moq-cli to target/release/moq on the runner, and inside
the AlmaLinux docker (which does its own cargo build) cp from
target/release/moq-cli straight to target/moq.rpm-build instead of
through a nonexistent target/release/moq. The .deb nfpm BINARY_PATH
keeps pointing at target/release/moq because the host-side rename
makes that path exist.

https://claude.ai/code/session_015J5tVAQ7ESjBhnzdeXfhgX
@moq-bot moq-bot Bot mentioned this pull request May 23, 2026
@moq-bot moq-bot Bot mentioned this pull request Jun 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants