Files
paperspec/deploy/README.md
T
alexmandClaude 88379d152c feat!: one paperspec command with subcommands, help and examples
The six console scripts (paperspec-check, -build, -validate, -load,
-stress, -site) become subcommands of a single `paperspec` command:
paperspec validate, load, check, build, stress and site. `python -m
paperspec COMMAND` runs the same thing.

- paperspec/cli/main.py builds the whole parser, apart from the commands,
  so `paperspec --help` and `paperspec COMMAND --help` work without a
  checkout or the tools extra; a command's module is imported only when
  it runs.
- `paperspec` with no command prints the overview: what each command does,
  examples, and which work anywhere (validate, load) and which need a
  checkout (check, build, stress, site). Each command's help has a
  description with advice, and worked examples; a misspelled command gets
  a suggestion (argparse suggest_on_error); `--version` prints the version
  and the pinned Unicode version.
- Each command module exposes run(args) and returns the exit status.
  Arguments that parse but do not fit together raise UsageError, which
  prints the command's usage and exits 2: load now also refuses
  --built-from or --store without --bundle.
- The failure messages say what to do: install paperspec[tools], clone the
  repository, rerun stress with the printed seed, or run paperspec build
  when the rebuild check differs. check and stress say how many failures
  they did not list.
- check runs the rebuild as `python -m paperspec build`.
- pyproject installs one script, `paperspec`; the pixi tasks and the docs
  use the subcommands.

pixi run check passes (run here as `python -m paperspec check` with src/ on
the path); the rebuild is byte-identical. pixi.lock still needs
`pixi lock`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 09:28:30 -04:00

60 lines
3.6 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: `paperspec site` 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 site # writes _site/
pixi run site --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/www/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 copies it with `rsync` to `/srv/www/paperspec`, the folder Caddy serves.
A failed check stops the publish, so the site never serves a release that does not pass its own checks.
The copy is local: the `linux-base` runner starts each job in a container with the host's `/srv/www` mounted at the same path, so no key or secret is involved.
On a runner without that mount the workflow still builds and checks the site, and says that it did not publish.
`SITE_ROOT` and `SITE_SLUG` at the top of the workflow name the folder.
Only changed files are copied, so every other file keeps its `Last-Modified` and `ETag` and caches stay valid across releases.
The environment in `.pixi/envs` is cached between runs under the hash of `pixi.lock`, so a fresh container installs it only when the lock file changes.
## 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.