|
|
@@ -4,25 +4,31 @@ A Statum + Spry application that browses **and serves** any number of USM
|
|
|
repositories: human-facing pages for exploring packages (an all-repository
|
|
|
overview plus per-repository browse views), plus the exact HTTP endpoints a
|
|
|
real USM client (`usm repository list` / `verify` / `install`) expects to
|
|
|
-fetch from a repository host.
|
|
|
+fetch from a repository host. Alongside USM source repositories it also
|
|
|
+serves **DCBA artifact repositories** — repositories of pre-built build
|
|
|
+artifacts (`.dcba`) that `usm install` fetches instead of building a package
|
|
|
+from source (`usm dcba add-repo` / `usm dcba repository list`).
|
|
|
|
|
|
## What it serves
|
|
|
|
|
|
| Endpoint | Purpose |
|
|
|
|---|---|
|
|
|
-| `GET /` | Overview: every repository (name, summary, package count, total size), per-repo add-repository instructions (`sudo usm add-repo <repo.usmr URL>`), the global install-USM block, and a combined package table with repo badges + server-side search across all repositories |
|
|
|
-| `GET /repo/{name}` | Single-repo browse: that repository's overview card, instructions and package table, search scoped to it |
|
|
|
-| `GET /repo/{name}/package/{file}` | Package detail: manifest fields read out of the `.usmc` (licences, flags, provides/depends tables), sha512, on-disk size/mtime, download button |
|
|
|
-| `GET /repo/{name}/PACKAGES.usml` | That repository's listing streamed **verbatim** (`application/json`) |
|
|
|
+| `GET /` | Overview: every repository of both kinds as a card (name, summary, chip, kind-appropriate counts and `sudo usm add-repo` / `sudo usm dcba add-repo` instructions), the global install-USM block, and a **source-package-only** combined table (usmc rows from USM repositories, repo badges) with server-side search across them — DCBA repositories appear as cards, never as package rows |
|
|
|
+| `GET /repo/{name}` | Single-repo browse: that repository's overview card and instructions. A USM repository renders its package table with search scoped to it; a DCBA repository renders an artifacts table (name, version, size, download) instead — search stays source-package-only |
|
|
|
+| `GET /repo/{name}/package/{file}` | Package detail: manifest fields read out of the `.usmc` (licences, flags, provides/depends tables), sha512, on-disk size/mtime, download button, plus a "Pre-built artifacts" section listing every DCBA repository carrying an artifact for this exact name + version |
|
|
|
+| `GET /repo/{name}/artifact/{file}` | Artifact detail (DCBA repositories): listing-derived name/version, sha512, on-disk size/mtime, download button, the `usm dcba add-repo` instruction and — on an exact name+version match — a one-directional link to the source package's detail page |
|
|
|
+| `GET /repo/{name}/PACKAGES.usml` | That USM repository's listing streamed **verbatim** (`application/json`); a DCBA repository has none and answers 404 |
|
|
|
+| `GET /repo/{name}/ARTIFACTS.usml` | That DCBA repository's artifact listing streamed **verbatim** (`application/json`) so signatures and checksums stay valid; a USM repository answers 404 |
|
|
|
| `GET /repo/{name}/repo.usmr` | A rewritten copy of the `.usmr` with its embedded `url` replaced by the derived base + `repo/{name}/` — the URL `sudo usm add-repo` consumes |
|
|
|
-| `GET /repo/{name}/{file}.usmc` | Package archives streamed from that repository's `public/` (`application/octet-stream`, exact content-length) |
|
|
|
+| `GET /repo/{name}/repo.dcbar` | The rewritten DCBA counterpart: a copy of the `.dcbar` with its `url` replaced by the derived base + `repo/{name}/` — the URL `sudo usm dcba add-repo` consumes (the route name is canonical regardless of the on-disk descriptor's filename) |
|
|
|
+| `GET /repo/{name}/{file}.usmc` / `GET /repo/{name}/{file}.dcba` | Package archives / pre-built artifacts streamed from that repository's `public/` (`application/octet-stream`, exact content-length); the suffix selects the repository kind, so the wrong kind (or a listing the other kind owns) answers 404 |
|
|
|
| `GET /install-usm.sh` | The configured installer script (`installer.path` mode only), served by the root-level catch-all |
|
|
|
|
|
|
The derived base is `base_url` from the config when set, else
|
|
|
`X-Forwarded-Proto`/`X-Forwarded-Host`, else the request's own scheme/host —
|
|
|
so clients behind a reverse proxy resolve against the public name. Each
|
|
|
-repository is addressed by the `name` in its `.usmr`, which is also its
|
|
|
-routing segment.
|
|
|
+repository is addressed by the `name` in its `.usmr` or `.dcbar`, which is
|
|
|
+also its routing segment.
|
|
|
|
|
|
## Configuration
|
|
|
|
|
|
@@ -44,8 +50,8 @@ carries the static Statum keys plus an optional `"usm-web"` section:
|
|
|
|
|
|
| Key | Meaning |
|
|
|
|---|---|
|
|
|
-| `repo` | The parent directory holding the repositories (each a subdirectory with a `.usmr` and `public/`); relative paths resolve against the config file's directory |
|
|
|
-| `repositories` | Optional explicit list of repository subdirectories to serve (in that order); when absent or empty every subdirectory containing a `.usmr` is discovered by scanning |
|
|
|
+| `repo` | The parent directory holding the repositories (each a subdirectory with a `.usmr` **or** a `.dcbar` plus `public/`); relative paths resolve against the config file's directory |
|
|
|
+| `repositories` | Optional explicit list of repository subdirectories to serve, of either kind, in that order; when absent or empty every subdirectory containing a `.usmr` or a `.dcbar` is discovered by scanning |
|
|
|
| `installer.url` | External installer location; the homepage links out and shows `curl -fsSL <url> \| sh` |
|
|
|
| `installer.path` | Installer script this app serves at `/install-usm.sh`; relative paths resolve against the config file's directory |
|
|
|
| `base_url` | Optional override of the request-derived repository base (normalised to a trailing slash) |
|
|
|
@@ -67,17 +73,60 @@ the `USM_WEB_REPO_DIR` environment variable, the config's `repo` key, or the
|
|
|
│ └── public/
|
|
|
│ ├── PACKAGES.usml
|
|
|
│ └── <name>-<version>.usmc
|
|
|
+├── prebuilt/
|
|
|
+│ ├── prebuilt.dcbar (same JSON shape as a .usmr)
|
|
|
+│ ├── keys/
|
|
|
+│ └── public/
|
|
|
+│ ├── ARTIFACTS.usml
|
|
|
+│ └── <name>-<version>.dcba
|
|
|
└── extra/
|
|
|
└── …
|
|
|
```
|
|
|
|
|
|
+USM source repositories and DCBA artifact repositories live side by side
|
|
|
+under the same parent — there is no separate configuration for the second
|
|
|
+kind. A subdirectory is classified by its descriptor: `.usmr` makes it a
|
|
|
+USM source repository (`.usmc` packages in `public/PACKAGES.usml`), `.dcbar`
|
|
|
+a DCBA artifact repository (`.dcba` artifacts in `public/ARTIFACTS.usml`).
|
|
|
+A directory holding **both** descriptors is a configuration error; split it
|
|
|
+into two subdirectories instead.
|
|
|
+
|
|
|
A legacy single-repository layout with the `.usmr` directly inside the
|
|
|
-configured directory is still served as one repository. Discovery re-runs on
|
|
|
+configured directory is still served as one repository (this fallback stays
|
|
|
+`.usmr`-only; a bare `.dcbar` in the parent is not discovered). Discovery re-runs on
|
|
|
every request, so repositories added or removed on disk are picked up without
|
|
|
-a restart, and each repository's `.usmr` and `PACKAGES.usml` re-read when
|
|
|
-their mtimes change — one repository can be rebuilt without disturbing the
|
|
|
-others. There is **no database and no authentication**; all Statum state is
|
|
|
-stateless PAGE slots.
|
|
|
+a restart, and each repository's descriptor (`.usmr`/`.dcbar`) and listing
|
|
|
+(`PACKAGES.usml`/`ARTIFACTS.usml`) re-read when their own mtimes change —
|
|
|
+one repository can be rebuilt without disturbing the others. There is **no
|
|
|
+database and no authentication**; all Statum state is stateless PAGE slots.
|
|
|
+
|
|
|
+### DCBA repositories
|
|
|
+
|
|
|
+A DCBA repository distributes **pre-built build artifacts**: one `.dcba`
|
|
|
+archive per package name + version (built and published upstream with
|
|
|
+`usm dcba repository init` / `add` / `publish`), described by a `.dcbar`
|
|
|
+(the same JSON shape as a `.usmr`) and listed in a signed
|
|
|
+`public/ARTIFACTS.usml`. With such a repository configured, `usm install`
|
|
|
+fetches the artifact instead of building the package from source.
|
|
|
+
|
|
|
+Two things differ from the usmc flow when pointing a client at one:
|
|
|
+
|
|
|
+- the verb carries the `dcba` subcommand: `sudo usm dcba add-repo <url>`
|
|
|
+ (not `sudo usm add-repo`), where `<url>` is the served
|
|
|
+ `.../repo/<name>/repo.dcbar` rewrite;
|
|
|
+- clients match artifacts by **plain name + version string comparison**, so
|
|
|
+ the package detail pages surface pre-built artifacts only when a DCBA
|
|
|
+ repository carries that exact version — a newer or older artifact version
|
|
|
+ never shows up as "for" that package.
|
|
|
+
|
|
|
+The views keep the two kinds apart: the home page lists DCBA repositories
|
|
|
+as cards (with artifact counts and their own add-repo instruction) but the
|
|
|
+package table, the Packages/Total-size hero counts and search stay
|
|
|
+usmc-only; a DCBA repository's browse page shows its artifacts table, and
|
|
|
+each artifact has a detail page with its sha512 and a one-directional link
|
|
|
+to the matching source package (a package page then lists every DCBA
|
|
|
+repository carrying its pre-built artifacts, so the pair is discoverable
|
|
|
+from both sides).
|
|
|
|
|
|
## Development
|
|
|
|
|
|
@@ -107,8 +156,8 @@ ninja -C builddir
|
|
|
|
|
|
`--repo` points at the parent directory holding the repositories (see the
|
|
|
layout above). Repo parsing uses libusm (`Usm.Repository`,
|
|
|
-`Usm.RepositoryListing`, `Usm.Manifest.from_package`) — no hand-rolled
|
|
|
-usml/usmr mappers.
|
|
|
+`Usm.RepositoryListing`, `Usm.DcbaListing`, `Usm.Manifest.from_package`) —
|
|
|
+no hand-rolled usml/usmr/dcbar mappers.
|
|
|
|
|
|
## Layout
|
|
|
|
|
|
@@ -116,13 +165,13 @@ usml/usmr mappers.
|
|
|
|---|---|
|
|
|
| `src/main.vala` | application wiring: modules, config, pages, action, endpoints |
|
|
|
| `src/UsmWebConfig.vala` | the `"usm-web"` config section (repo parent, repositories, installer url\|path, base_url, name) |
|
|
|
-| `src/RepositoryService.vala` | multi-repository discovery + libusm-backed read side with per-repo mtime reload |
|
|
|
+| `src/RepositoryService.vala` | multi-repository discovery (`.usmr` and `.dcbar` subdirectories, kind-guarded members) + libusm-backed read side with per-repo mtime reload |
|
|
|
| `src/DerivedBase.vala` | base-URI derivation from config/forwarded headers |
|
|
|
-| `src/PackagesState.vala` | shared `packages` slot-state builder (overview + repo-scoped) and size/fingerprint formatting |
|
|
|
-| `src/entrypoints/` | `HomeEntrypoint` (/), `RepoBrowseEntrypoint` (/repo/{name}) and `PackageDetailEntrypoint` (/repo/{name}/package/{file}) |
|
|
|
+| `src/PackagesState.vala` | shared `packages` slot-state builder (overview + repo-scoped, both repository kinds, DCBA artifact rows) and size/fingerprint formatting |
|
|
|
+| `src/entrypoints/` | `HomeEntrypoint` (/), `RepoBrowseEntrypoint` (/repo/{name}), `PackageDetailEntrypoint` (/repo/{name}/package/{file}) and `ArtifactDetailEntrypoint` (/repo/{name}/artifact/{file}) |
|
|
|
| `src/actions/` | `SearchPackagesAction` — server-side table filtering (all repositories or one) |
|
|
|
-| `src/endpoints/` | the USM-facing endpoints listed above |
|
|
|
-| `src/pages/*.html` | Statum pages, compiled by `statum-mkpstm` at build time |
|
|
|
+| `src/endpoints/` | the USM/DCBA-facing endpoints listed above (`PackagesListingEndpoint`, `RepositoryDefinitionEndpoint`, `ArtifactsListingEndpoint`, `DcbaDefinitionEndpoint`, `PackageDownloadEndpoint`, `InstallerScriptEndpoint`) |
|
|
|
+| `src/pages/*.html` | Statum pages (`home`, `repo`, `package`, `artifact`), compiled by `statum-mkpstm` at build time |
|
|
|
| `src/Static/main.css` | stylesheet embedded by `statum-mkres` |
|
|
|
| `MANIFEST.usm` | USM package manifest: `provides bin:usm-web`, build/runtime/manage deps |
|
|
|
| `usm-scripts/` | USM build + install scripts (meson staging) |
|
|
|
@@ -174,4 +223,4 @@ podman run -d -p 8080:8080 \
|
|
|
```
|
|
|
|
|
|
`/repo` inside the container is the repositories **parent** directory: every
|
|
|
-subdirectory holding a `.usmr` is served at `/repo/<name>/…`.
|
|
|
+subdirectory holding a `.usmr` or a `.dcbar` is served at `/repo/<name>/…`.
|