README.md (5603B)
1 unos-repository 2 =============== 3 4 The UNOS package repository: every `.apk` that makes up the OS, the tooling 5 that builds and signs them, and the CI pipeline that publishes them. 6 7 This repo produces a signed apk repository. It does not assemble a rootfs, an 8 image or an installer -- that is the `unos` repo, which consumes what is 9 published here over HTTP. The `unosd` daemon's source lives in its own repo and 10 arrives here as a tag-pinned tarball like any other dependency. 11 12 Published to `https://repo.unos.finwo.net/<arch>`. 13 14 15 Layout 16 ------ 17 18 packages/<name>/template build recipe (sourced by mk/build.sh) 19 packages/<name>/files/ static files installed by the template 20 packages/<name>/patches/ *.patch, applied in order to WRKSRC 21 mk/ the build driver and its tooling 22 .conductor.yml CI pipeline, GENERATED from the dep graph 23 24 25 Building 26 -------- 27 28 ./mk/bootstrap-host.sh build pinned muon + apk into build/host/bin 29 ./mk/build.sh <pkg> build one package 30 ./mk/build-all.sh build everything in dependency order 31 ./mk/repo-index.sh (re)generate and sign APKINDEX.tar.gz 32 33 `mk/bootstrap-host.sh` must run first: `apk-tools` declares `muon` as a 34 hostmakedepends, and it is built here rather than installed from a 35 distribution, so `mk/deps.sh check` reports it missing until bootstrap has 36 produced it. 37 38 See `mk/README.md` for the full tooling reference and `packages/README.md` for 39 the template format. 40 41 42 Where source comes from 43 ----------------------- 44 45 Two mutually exclusive mechanisms, kept apart deliberately: 46 47 `distfiles=` is third-party upstream source. It **must** carry a matching 48 `checksum=` sha256; `mk/build.sh` refuses to build without one. We are trusting 49 a server nobody here controls, so the tarball is pinned by content. 50 51 `srcfiles=` is our own source, fetched by tag from `git.finwo.net`. It carries 52 no checksum: the tag is the pin and TLS is the transport, and a forge 53 regenerates tag archives, so they are not byte-stable and a sha256 would fail 54 for reasons indistinguishable from tampering. Only `unosd` uses this today. 55 56 Keeping them separate means "no checksum" can never silently apply to an 57 upstream tarball. 58 59 Cached source lives in `build/work/sources/`, and is only fetched when absent. 60 `srcfiles` entries are cached under `<pkg>-<basename>` because these URLs end 61 in the tag, so the bare basename is often just `v0.1.0.tar.gz` and two 62 first-party packages at the same version would otherwise share one entry. 63 64 **While git.finwo.net does not yet serve tag archives**, seed the cache by 65 hand and the fetch is skipped: 66 67 git -C ../unosd archive --format=tar --prefix=unosd/ HEAD \ 68 | gzip -n > build/work/sources/unosd-v0.1.0.tar.gz 69 70 71 Signing 72 ------- 73 74 Packages and the index are signed with RSA-4096 (apk mandates RSA). The key is 75 resolved by `mk/sign-key.inc`, in order: 76 77 $UNOS_KEY_APK_RSA_PRI provided by the unos-sign-key CI worker feature 78 $UNOS_SIGN_KEY manual override 79 ./.sign-key local selection, via mk/keymgmt.sh use 80 the single *.rsa in ~/.unos-keys/ 81 82 `mk/build.sh` names the signature record after the key that signed it 83 (`.SIGN.RSA.<keyname>.rsa.pub`), and the apk client verifies it against 84 `/etc/apk/keys/<keyname>.rsa.pub`, shipped by `packages/unos-keys`. 85 86 **Every CI worker has a distinct keypair**, so the signer is whichever worker 87 the conductor scheduled the build on. `packages/unos-keys` therefore trusts all 88 four. Ship fewer and verification fails for an arbitrary subset of packages 89 that changes run to run -- a failure that looks like corruption rather than a 90 missing key. Adding a worker means publishing `unos-keys` *before* that worker 91 builds anything. 92 93 Any one worker can consequently sign packages every client trusts. The intended 94 end state is a release step that re-signs with a single key and merely accepts 95 these as inputs; it does not exist yet. 96 97 98 CI 99 -- 100 101 `.conductor.yml` is **generated** -- do not edit it: 102 103 ./mk/gen-pipeline.sh --write regenerate 104 ./mk/gen-pipeline.sh --check fail if stale (run by tests/unit/test_deps.sh) 105 106 The conductor treats the pipeline as data and will not execute repository code 107 to build its task graph, so the per-package `needs` edges have to be written 108 out literally. Generating them from `makedepends` keeps the templates the 109 single source of truth; drift is a test failure rather than a package building 110 against a stale dependency. 111 112 Tasks run in ephemeral containers with no mounts and no artifact sharing, so 113 each package seeds its sysroot from the published repo (`mk/sysroot.sh`) and 114 publishes its own result (`mk/publish.sh`). `needs` provides ordering only. 115 116 The pipeline requires a worker advertising the **`unos-sign-key`** feature, 117 which mounts the signing key and exports `UNOS_KEY_APK_RSA_PRI`, 118 `UNOS_KEY_APK_RSA_PUB`, `UNOS_KEY_SUPERCOP_PRI` and `UNOS_KEY_SUPERCOP_PUB`. 119 Feature names are global to the conductor, which hosts more than UNOS, hence 120 the project prefix. A task requiring a feature no worker advertises is never 121 scheduled -- it does not fail, it silently never runs. 122 123 S3 credentials arrive as `BUCKET_ACCESS_KEY`, `BUCKET_SECRET_KEY`, 124 `BUCKET_NAME`, `BUCKET_ENDPOINT` (a URL) and `BUCKET_REGION` (a region name). 125 126 127 Testing 128 ------- 129 130 ./tests/run.sh 131 132 Graph validation, pipeline freshness, applet policy and packaging layout. Tests 133 that need a package built will skip rather than fail when it is absent, so the 134 suite is meaningful in a fresh container; anything needing a booted machine 135 lives in the `unos` repo.