Ops platform / Publish
Publish docs
Keep docs beside your code as Markdown; ops stores every version and the docs site shows it.
Docs live in a docs folder beside the code they describe. Each version of a package or
each production deploy of a service publishes the folder as a new version of its doc
set, and the docs site shows it within seconds. Nothing is rebuilt for it.
Doc sets are public: anyone can read them without logging in. Never put anything private in a docs folder.
The folder
Pages are Markdown, and the folder's own layout is the navigation. index.md is the first
page of a folder.
docs/
index.md
install.md
guides/
index.md
streaming.md
images/flow.png
Every page starts with front matter. title is required; description and order are
optional, and nothing else is allowed:
---
title: Streaming bodies
description: Read and write objects without buffering them.
order: 2
---
order is a whole number and sorts the pages of a folder. Write each value on one line.
What is checked
Nothing is published when a check fails, and the answer names every page that broke it.
- Every page has a
title, and its front matter uses only the three keys. - Every relative link and image points at a file in the same folder; a link may leave out
.mdor point at a folder. - Images are PNG, JPEG, WebP or SVG, 2 MB at most, and an SVG holds no script.
- Every other file is refused. Hidden files, such as
.DS_Store, are left out. - The folder fits the size limit, 64 MB unless your ops sets another.
Links to other sites, #anchors and absolute paths are not checked.
Publishing
A package publishes its docs in its publish run. A module's docs folder, beside its
crate and layer, becomes the version the tag published. The docs folder beside a
crate or an npm package that is no module, such as crates/billing/docs or
packages/ui/docs, becomes a version of that package's set, named like the package
without its scope, at the package's own version. A broken folder refuses the tag before
anything publishes. A package without a folder publishes without docs, and the run says
so. Pages changed under a version that has its docs already wait for the next version.
Guides that are no package's go in the folder the project file names. A tag's publish run publishes it at the tag's version:
export default defineProject({
services: {},
docs: { set: 'rungholt-guides', path: 'docs' },
})
A service names its folder the same way:
export default defineProject({
services: { api: { dockerfile: 'Dockerfile', port: 8080 } },
docs: { set: 'rungholt-api', path: 'docs' },
})
Every production deploy then publishes the folder after the service is healthy, as the
version named by the deployed commit. A broken folder fails that docs step and notifies
you; the deploy itself stands.
Anything else pushes with the CLI and a token that holds package.publish in the
project. The Project admin and Developer roles hold it:
ops docs push ./docs --set rungholt-api --version 1.4.0
A set name is lowercase letters, digits and dashes. A set named like a module or a package
is that package's set, and its versions must be versions the package has published. Any other
set is a service set and names its project the first time: pass --project rungholt, or
--kind service to use the project chosen with ops use.
Versions
A version is published once. The same folder pushed again is accepted and changes nothing; other content under the same version is refused, so publish a new version instead.
Yanking a version hides it from readers and keeps its archive. The newest version that is not yanked is the one the docs site shows first.
ops docs # every doc set, with its latest version
ops docs rungholt-api # one set's versions, newest first
ops docs yank rungholt-api 1.4.0
Yanking needs package.publish in the set's project, like a push. Reading needs no login.
In the console
Library, Docs lists every doc set with its latest version, and each reader with
the revision it serves and how long it took to pick it up. A set's page lists its
versions, with Yank from the site in each version's menu, and the pages of the latest.
A project's own sets are under Docs in its sidebar, and a deployment or publish run
shows its docs step.
Showing doc sets on your own site
A project that renders doc sets declares itself a reader. Ops then calls it on every new version or yank, so it never has to rebuild:
docsReader: { service: 'web', path: '/api/docs/refresh', secret: 'OPS_DOCS_SECRET' },
Ops sends POST <path> to the production service with {"revision": n} and the value of
OPS_DOCS_SECRET from the service's secret group in the x-ops-docs-secret header. The
service answers within 60 seconds, with a 2xx status and {"revision": n}, the revision
it now serves.
A call that fails is not repeated, so the service also asks on a timer:
GET /api/v1/docs/revision?since=<n> answers what changed, and the service sends
x-ops-docs-reader (the project slug), x-ops-docs-secret and x-ops-docs-served (the
revision it serves) with it, so ops always knows what each reader shows and how long it
took to catch up.