Files
LiHaohuaandClaude Opus 4.7 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

83 lines
2.6 KiB
Markdown

# Maintainers runbook
## One-time setup (before first real publication)
### 1. Generate a GPG signing key
On a trusted machine (not the CI runner):
```bash
gpg --batch --gen-key <<EOF
%no-protection
Key-Type: RSA
Key-Length: 4096
Subkey-Type: RSA
Subkey-Length: 4096
Name-Real: CardputerZero Repository
Name-Email: repo@m5stack.local
Expire-Date: 3y
%commit
EOF
# Grab the fingerprint
FPR=$(gpg --list-keys --with-colons repo@m5stack.local | awk -F: '/^fpr/ {print $10; exit}')
echo "$FPR"
# Export the public key (commit this file)
gpg --armor --export "$FPR" > KEY.gpg
# Export the private key (store as secret, never commit)
gpg --armor --export-secret-keys "$FPR" > gpg-private.asc
```
Add `KEY.gpg` to the repo (normal commit). Set repo secrets:
- `GPG_PRIVATE_KEY` = contents of `gpg-private.asc`
- `GPG_PASSPHRASE` = passphrase if you used one (leave unset if `%no-protection`)
Shred `gpg-private.asc` once the secret is saved.
### 2. Enable GitHub Pages
- Settings → Pages → Source: `gh-pages` branch, `/` root.
- The first `publish.yml` run will create the branch; rerun the workflow if
Settings doesn't offer `gh-pages` yet.
### 3. Flip the Pages URL into README
Once the site is live (check `https://<owner>.github.io/<repo>/`), add its URL
to `README.md` so users can copy-paste the `sources.list` line.
## Accepting a submission
1. CI must be green on the PR (`validate-submission.yml`).
2. Inspect the `.deb` metadata in the PR diff (GitHub renders `dpkg-deb -I`
output from the action logs).
3. Merge with "Squash and merge".
4. `publish.yml` runs automatically:
- uploads the `.deb` to the `apt-pool` release,
- removes it from `incoming/`,
- rebuilds `Packages` / `Release` / `InRelease`,
- pushes metadata to `gh-pages`.
## Removing a package
1. `gh release delete-asset apt-pool <file>.deb` (or via UI).
2. `gh workflow run publish.yml` to rebuild the index without it.
## Rotating the GPG key
1. Generate a new key, commit the new `KEY.gpg`.
2. Update `GPG_PRIVATE_KEY` + `GPG_PASSPHRASE` secrets.
3. Re-run `publish.yml`; clients will see a new `InRelease` signature.
4. Announce the key change — users need to re-import `KEY.gpg`.
## Monitoring
- GitHub → Insights → Traffic: watch Pages bandwidth.
- GitHub → Releases → apt-pool: sum of asset sizes = total deb storage.
- If the repo crosses 1 GB: audit `pool/` (should be empty in committed tree —
a trailing `.deb` there means `publish.yml` didn't clean up).
- If Pages bandwidth gets close to 100 GB/month: plan migration to Cloudflare
R2 (see `ARCHITECTURE.md` — apt client impact is only the URL change).