Files
LiHaohua 774d9a86fa Bootstrap apt repository structure
This is the initial shape of the CardputerZero deb repository. The design
follows the GitHub Pages (metadata) + Releases (deb assets) pattern that
sibling projects like ryanfortner/box64-debs and AdityaGarg8/t2-ubuntu-repo
use successfully — it deliberately avoids Git LFS because the free plan's
1 GB/1 GB storage+bandwidth limits apply to public repos too.

Files landing here:

- README.md / docs/ARCHITECTURE.md / docs/MAINTAINERS.md explain the flow
  for users, the design tradeoffs, and the maintainer runbook (including
  GPG key setup).
- .github/workflows/validate-submission.yml runs on pull_request with a
  read-only token and no secrets, verifying any incoming/*.deb is a valid
  arm64 package. Safe to run on external contributor PRs.
- .github/workflows/publish.yml runs on push to main (after merge). It
  uploads incoming/*.deb to a rolling "apt-pool" GitHub Release, rebuilds
  Packages/Release/InRelease with apt-ftparchive, GPG-signs if
  GPG_PRIVATE_KEY is set (warns loudly otherwise), and publishes the
  metadata tree to gh-pages.
- incoming/czrepo-hello_0.1-1_arm64.deb is a 784-byte sentinel package
  used to exercise the publish pipeline end-to-end on this very first
  PR merge.

The workflow is intentionally safe-by-default: without a GPG key
configured it will still produce a usable (unsigned) apt index so the
plumbing can be validated before trusted signing keys are generated.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 14:56:07 +08:00

98 lines
3.3 KiB
YAML

name: Validate submission
# Safe PR validation: no secrets, read-only token. Checks that files added
# under incoming/ are well-formed arm64 .deb packages. Signing + publishing
# happens later in publish.yml after merge.
on:
pull_request:
paths:
- 'incoming/**'
- '.github/workflows/validate-submission.yml'
permissions:
contents: read
jobs:
validate:
runs-on: ubuntu-24.04
steps:
- name: Checkout PR head
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Enumerate new debs under incoming/
id: enumerate
run: |
set -euo pipefail
git fetch origin main
base=$(git merge-base origin/main HEAD)
added=$(git diff --name-only --diff-filter=A "$base"...HEAD -- 'incoming/*.deb' || true)
if [ -z "$added" ]; then
echo "No new .deb files under incoming/ in this PR."
echo "files=" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "Found:"
printf ' %s\n' $added
{
echo 'files<<EOF'
printf '%s\n' $added
echo 'EOF'
} >> "$GITHUB_OUTPUT"
- name: Install tooling
if: steps.enumerate.outputs.files != ''
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends dpkg-dev
- name: Inspect each .deb
if: steps.enumerate.outputs.files != ''
shell: bash
run: |
set -euo pipefail
fail=0
while IFS= read -r f; do
[ -z "$f" ] && continue
echo "::group::$f"
if ! [ -f "$f" ]; then
echo "::error file=$f::file does not exist"
fail=1
echo "::endgroup::"
continue
fi
# 1. Must be a valid .deb (dpkg-deb fails loudly otherwise).
if ! dpkg-deb -I "$f" > /tmp/ctrl.txt 2>&1; then
echo "::error file=$f::dpkg-deb -I failed:"
cat /tmp/ctrl.txt
fail=1
echo "::endgroup::"
continue
fi
cat /tmp/ctrl.txt
# 2. Architecture must be arm64.
arch=$(dpkg-deb --field "$f" Architecture)
if [ "$arch" != "arm64" ]; then
echo "::error file=$f::Architecture=$arch, expected arm64"
fail=1
fi
# 3. Filename convention: <pkg>_<version>_arm64.deb
base=$(basename "$f")
if [[ ! "$base" =~ ^[a-z0-9][a-z0-9._+-]*_[A-Za-z0-9.~+:-]+_arm64\.deb$ ]]; then
echo "::warning file=$f::filename '$base' does not match <pkg>_<version>_arm64.deb"
fi
# 4. Size sanity: warn if > 50 MiB.
size_mb=$(( $(stat -c%s "$f") / 1024 / 1024 ))
if [ "$size_mb" -gt 50 ]; then
echo "::warning file=$f::${size_mb} MiB — large packages slow apt update"
fi
echo "::endgroup::"
done <<< "${{ steps.enumerate.outputs.files }}"
exit $fail
- name: Summary
if: steps.enumerate.outputs.files == ''
run: echo "No .deb additions in this PR — nothing to validate."