Drop the hosted setup-pixi step for the self-hosted runner, install the locked environment in the site workflow, run the quick check before building, and serialize publishes. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
66 lines
4.0 KiB
Markdown
66 lines
4.0 KiB
Markdown
# Deploying the website
|
|
|
|
This folder holds what it takes to serve the paperspec website at <https://paperspec.scient.ing>.
|
|
The site is static: `tools/site.py` builds it into `_site/`, and any web server can serve that folder.
|
|
|
|
## What the site serves
|
|
|
|
The site mirrors the repository, so a file at `schemas/anchor.schema.json` in the repository is served at `https://paperspec.scient.ing/schemas/anchor.schema.json`.
|
|
Three addresses that the formats themselves name depend on that:
|
|
|
|
| Address | What is there |
|
|
| --- | --- |
|
|
| `https://paperspec.scient.ing/schemas/<file>` | Each JSON Schema, at the address in its `$id`. |
|
|
| `https://paperspec.scient.ing/context/scienting-1.jsonld` | The JSON-LD context every layer and annotation lists. |
|
|
| `https://paperspec.scient.ing/vocab` | The vocabulary page, whose fragments are the IRIs of the context's terms. |
|
|
|
|
Beside every Markdown file the builder writes a rendered page: `README.md` becomes its folder's `index.html`, and `X.md` becomes `X.html`.
|
|
A folder without a README gets a listing page, so every fixture and vector can be browsed.
|
|
The pages need no server-side code; search runs in the browser over a small index of headings, `search.json`.
|
|
|
|
## Build it
|
|
|
|
```sh
|
|
pixi run python tools/site.py # writes _site/
|
|
pixi run python tools/site.py --out /tmp/paperspec-site
|
|
```
|
|
|
|
`pixi run check` builds the site into a temporary folder and checks that every Markdown file has a page, that every internal link and fragment resolves, that no Markdown is left unrendered, and that each schema's `$id`, the context's address and the vocabulary's IRIs are files of the site.
|
|
|
|
To look at it locally, serve the folder with any static server, for example:
|
|
|
|
```sh
|
|
pixi run python -m http.server --directory _site 8000
|
|
```
|
|
|
|
## Serve it with Caddy
|
|
|
|
[Caddyfile](Caddyfile) serves `/srv/paperspec` at `paperspec.scient.ing`.
|
|
It sets the media types the data needs (`application/ld+json` for the context, `application/schema+json` for schemas, `application/jsonl` for vectors and package files), allows every file to be fetched from any origin, and serves `404.html` for missing paths.
|
|
Add it to the server's Caddy configuration, for example with an `import` line, and reload Caddy.
|
|
|
|
## Publish from CI
|
|
|
|
The workflow `.gitea/workflows/site.yml` runs on every push to `main`.
|
|
It installs the environment from `pixi.lock`, runs `pixi run quick`, builds the site, and publishes it with `rsync` when the repository secret `SITE_PATH` is set.
|
|
A failed check stops the publish, so the site never serves a release that does not pass its own checks.
|
|
Without `SITE_PATH` the workflow still builds and checks the site, and says that it did not publish.
|
|
|
|
| Secret | Holds |
|
|
| --- | --- |
|
|
| `SITE_PATH` | The folder Caddy serves, such as `/srv/paperspec`: an absolute path at least two levels deep. |
|
|
| `SITE_HOST` | The server's host name. Leave it unset when the runner is the web server, and the site is copied to `SITE_PATH` on the runner. |
|
|
| `SITE_USER` | The account that owns the site folder. |
|
|
| `SITE_SSH_KEY` | A private SSH key whose public half is in that account's `authorized_keys`, and that can do nothing else. |
|
|
| `SITE_KNOWN_HOSTS` | The server's host keys, as lines of `known_hosts`. |
|
|
|
|
The last three are needed only with `SITE_HOST`.
|
|
Take `SITE_KNOWN_HOSTS` from `ssh-keyscan -H <host>` on a network you trust, and compare its fingerprints with `ssh-keygen -lf` on the server; the workflow refuses a server whose key does not match.
|
|
Copying only changed files keeps the `Last-Modified` and `ETag` of every other file, so caches stay valid across releases.
|
|
|
|
## Distributing packages
|
|
|
|
A zipped package is an ordinary file, and the site serves the fixtures as such.
|
|
For a team's own packages, the Gitea instance speaks the OCI distribution protocol, so packages can be pushed to and pulled from its package registry as OCI artifacts with ORAS, and signed there with cosign; the media type of the artifact is the package's, `application/vnd.scienting.doc+zip`.
|
|
Nothing in the formats depends on how packages travel.
|