diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index b6348c2..41af0d0 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -25,6 +25,11 @@ GitHub release whose tag is the path apk requests: | `edge` | everything except `extra-repos/systemd` | `main/aarch64` | `mirrors.pmaports_custom` = `.../releases/download` | | `systemd-edge` | `extra-repos/systemd` (phosh, ...) | `systemd/main/aarch64` | `mirrors.systemd_custom` = `.../releases/download/systemd` | +Each tree also has an `x86_64` release (`main/x86_64`, `systemd/main/x86_64`) +holding a signed index with no packages. pmbootstrap reads a custom mirror's +index for the host's native architecture as well as the target's, and aborts +with "getting APKINDEX from binary package mirror failed!" on a 404. + pmbootstrap turns a mirror into `/` and apk appends `//APKINDEX.tar.gz` (`pmb/helpers/repo.py`). `branch_pmaports` for edge is `main` in the current channels.cfg. A release channel such as v26.06 would @@ -73,8 +78,8 @@ All in `.github/workflows/` on the pmaports branch. | workflow | trigger | jobs | | --- | --- | --- | -| CI | push, pull request | commit trailer check (DCO sign-off on pull requests), APKBUILD lint with a version bump check, sources and patches check for changed aports | -| Build | push, pull request, manual | select packages; build each on an aarch64 runner; publish (pushes to `taimen-bringup` only) | +| CI | push, pull request, merge group | commit check (DCO sign-off on pull requests), APKBUILD lint with a version bump check, sources and patches check for changed aports | +| Build | push, pull request, merge group, manual | select packages; build each on an aarch64 runner; publish (pushes to `taimen-bringup` only, every push) | | Upstream check | weekly, manual | sources and patches of every listed fork; one issue listing forks an upstream package outranks | pmbootstrap runs in a privileged Alpine container, prepared the way pmaports' @@ -89,19 +94,26 @@ longer applies fails in about a minute, before any compiler runs. ## Publishing -For each local repository with new packages, the publish job: +`.github/scripts/publish.sh` on the pmaports branch. On every push to +`taimen-bringup`, for each release (both trees, `aarch64` and `x86_64`) that +has new packages, an index naming an `unpublished` aport (`packages.conf`), or +an index that is missing or does not verify, the publish job: -1. downloads the release's current packages; +1. downloads the release's current packages, and fails unless it got all of + them; 2. adds the new ones; a package whose file name is already published is kept - as it is (published versions are immutable), and older versions of the same - package are dropped; + as it is (published versions are immutable), older versions of the same + package are dropped, and so is any package of an `unpublished` aport; 3. rebuilds `APKINDEX.tar.gz` with `apk index` and signs it with `abuild-sign` and the repository key; 4. verifies the signature against the committed public key before uploading; 5. uploads new packages, then the index, then deletes superseded packages, so the published index never names a missing file; 6. downloads the index back, checks it is byte-identical and correctly signed, - and that every package it names is a release asset. + that every package it names is a release asset, and that it names no + `unpublished` aport; +7. attests the provenance of every uploaded file (`actions/attest`), once the + pmaports repository is public. Every package must carry `packager = Giuseppe Maggio `; CI sets it and publish refuses anything else. @@ -132,3 +144,4 @@ CI sets it and publish refuses anything else. | CI build dependencies | forks rebuilt in each job | downloaded from this repository | | select "already published" | needs `PACKAGES_READ_TOKEN` | anonymous | | Actions minutes | 2,000 a month, 2-vCPU arm runners | unlimited, 4-vCPU arm runners | +| build provenance attestations | not available (needs GitHub Enterprise Cloud) | on every uploaded file | diff --git a/README.md b/README.md index fbed762..0e97299 100644 --- a/README.md +++ b/README.md @@ -24,10 +24,15 @@ requests, so the download URLs are ordinary apk repository URLs: | --- | --- | --- | | postmarketOS edge | `main/aarch64` | forks of Alpine and pmaports packages | | postmarketOS edge, systemd | `systemd/main/aarch64` | forks of `extra-repos/systemd` packages, such as phosh | +| (both, for x86_64 hosts) | `main/x86_64`, `systemd/main/x86_64` | an empty signed index | `main` is the pmaports branch of the edge channel (`branch_pmaports` in [channels.cfg](https://gitlab.postmarketos.org/postmarketOS/pmaports/-/blob/main/channels.cfg)). Firmware packages are never published here; pmbootstrap builds them locally. +Neither are host tools such as `crossdirect`, which run in pmbootstrap's native +chroot: pmbootstrap on an x86_64 host also reads the mirror's x86_64 index, so +the empty one is there to answer instead of a 404, and pmbootstrap builds those +tools itself. The repository index is signed with [`keys/porthole-dev-packages-20260915.rsa.pub`](keys/porthole-dev-packages-20260915.rsa.pub). @@ -83,6 +88,16 @@ repository instead: gh release download main/aarch64 -R porthole-dev/pmos-packages -D repo/main/aarch64 ``` +## Verify where a package came from + +Once the pmaports repository is public, every file the build workflow uploads +here (packages and indexes) carries a signed build provenance attestation +naming the workflow run and commit that produced it: + +```sh +gh attestation verify mesa-26.2.2-r51.apk -R porthole-dev/pmaports +``` + ## Contributing Packages are changed in