Include programatically generated API docs - initial first step - #3376
Conversation
dfe365b to
d6cbb33
Compare
|
Pull request environment is available at https://stoctodocspr3376.z22.web.core.windows.net. You can view the ephemeral environment status in Octopus Deploy. This environment will be automatically deprovisioned when the pull request is closed, or after 7 days of inactivity. |
f5ffa1a to
22d1aa1
Compare
|
I have done some simple testing: Feel free to take these offline into separate PRs, or do later if you feel its out of scope of this pr (hence why adding as a comment)
|
FYI that's the case for the main site as well (example page). It's been on my mind for a while as something I'd really like to see fixed! |
enf0rc3
left a comment
There was a problem hiding this comment.
Reviewed the infrastructure code only, skipping the generated content per your note. The plugin design is sound — deriving "first H2" from the tree rather than closure state keeps it stateless, and the ordering note for apiExampleDirective after attributeMarkdown in astro.config.mjs is exactly the kind of thing that gets lost otherwise. The Playwright tests are genuinely good, especially running them with javaScriptEnabled: false and asserting the column-stack breakpoint by bounding box.
One real bug and three routing issues. Grouped by urgency, keeping in mind that nothing links to /docs/api yet:
Fix now — these ship publicly on merge regardless of whether anything links to them:
- Breadcrumbs render empty on every API page (wrong props to
Breadcrumbs). Pure code bug, ~4 lines. README.mdpublishes at/docs/api/README/, internal generator instructions and all.index.mdhas no frontmatter, so/docs/api/renders as a bare unstyled page, and all 106 of its links 404.- A decision on
navSearch/navSitemap— the ~100 pages enter the sitemap and site search on merge, so Google will index them before you light the section up.
Can wait — the dead CSS rule, Astro.request.url, the crawl skip regex, and the microdata/JSON-LD inconsistency. All flagged inline as deferrable.
Worth noting on 3 and 4: the durable fix belongs in the generator in the Server repo, since these files get overwritten. The suggestions below fix the checked-in copy so this PR is correct today.
I verified the component signatures against source rather than by building, and confirmed the markdownlint ignore works by reproducing your CI invocation locally — that part is fine.
| "astro": "astro", | ||
| "build": "astro build", | ||
| "crawl": "linkinator ./dist --skip \"^(?!http://localhost)\" --recurse --verbosity error", | ||
| "crawl": "linkinator ./dist --skip \"^(?!http://localhost)\" --skip \"/docs/api(\\$|/)\" --recurse --verbosity error", |
There was a problem hiding this comment.
Deferrable, but worth a note. Two things:
-
The JSON
\\$survives as a literal$under Windowscmd, which is what npm/pnpm shell out to, so the$alternative never matches there. The/alternative still covers every subpage, so the only gap is the bare/docs/apiURL. On CI'sshit works as intended. -
More importantly, this skip is why the 106 broken links on
index.mddon't fail the build. Once those are fixed it's worth checking whether the skip is still needed, or whether it can be narrowed — right now nothing validates links across 76k lines of generated content, and the generator could start emitting bad ones without anyone noticing.
Fine to leave for now; just worth not letting it become permanent.
| lang={lang} | ||
| breadcrumbs={breadcrumbs} | ||
| /> | ||
| <article itemscope itemtype="https://schema.org/Article"> |
There was a problem hiding this comment.
Deferrable. This uses schema.org microdata (itemscope/itemprop), which Default.astro dropped in favour of JSON-LD via <JsonLd>. Once the crumbs fix above is in, the site will emit two different structured-data schemes depending on which layout a page uses.
Not urgent and harmless for search engines, but worth collapsing onto JSON-LD next time this file is touched so the two layouts don't drift further apart.
|
Following on from my review above — I read the generator in OctopusDeploy/OctopusDeploy#46319 and left a longer review there about the format contract between the two repos: https://github.com/OctopusDeploy/OctopusDeploy/pull/46319#pullrequestreview-4957018861 Summarising the part that lands on this repo, since some of it changes what I'd do with my earlier comments. The short versionThe generated Markdown encodes this site's implementation details — the Astro layout path and CSS class names — alongside the API content. The clearest symptom is here in function methodFromBadge(node) {
return METHODS.find((method) => hasClass(node, `api-${method}`)) ?? null;
}The generator has a The consequence for us: restyling a method badge currently requires a PR in the Server repo and 107 regenerated files. Adding PATCH support is the same. We can't style the endpoint path at all, because it arrives as plain inline code indistinguishable from any other backtick span. What I've proposed over thereThe generator emits data, we decide the paint: :endpoint{method="POST" path="/api/users/access-token"}
:::deprecatedPlus dropping How this changes my earlier reviewThe
So I'd treat my Still worth fixing here regardless of any of the above: the empty breadcrumbs (four suggestions above — that's a plain bug, unrelated to the format question), and the One thing to correct in this PR either wayThe comment on Suggested sequencingGiven nothing links to |
|
@enf0rc3 @rosslovas I've pushed a commit which should address the concerns raised. It temporarily excludes the API folder from search and the sitemap, fixes search integration, json-ld, breadcrumbs, etc
This wasn't intentional (claude just did it and I didn't notice), but thinking about I think I'd prefer to leave it as-is. In the main site, the carats mean "Expand" but that typically happens if a node represents a folder with multiple documents within it. The nav here is one level down. Each entry is a single document and the only thing within the document is multiple H2's. This is equivalent to a normal page in the main docs, and those don't have expanders. Also, in the near future we're going to intermix human-written content into the api area, and that might well have nested folders, where the expander would have meaning. |
b84a4d0 to
3836752
Compare
# Conflicts: # astro.config.mjs
3836752 to
a1fb952
Compare
|
Edited: an earlier version of this comment flagged a brace-escaping divergence between the two repos. That has since been fixed on the Server side and the section is updated below to say so. Everything I raised is addressed, and a few of the fixes are better than what I suggested. Verified fixed:
Brace escaping — resolvedBriefly the two repos disagreed here: the Fixed on the Server side by
One small nit
Still open upstream, affects this repo
|
enf0rc3
left a comment
There was a problem hiding this comment.
Approving. The infrastructure code is in good shape and everything blocking from my earlier reviews is fixed.
Verified against a1fb952:
- Breadcrumbs render properly via
buildApiCrumbs, andHeadgetscrumbsso the JSON-LD is there. _index.mdand_README.mdare out of routing, so nothing publishes unstyled and the internal README stays internal.- The
crawlskip is gone, so linkinator validates links across the API section. underConstruction.tskeeps the section out of site search and the sitemap until it goes live, and both call sites skip before any processing.:endpointcarriesmethod,pathanddeprecatedas data. The plugin errors on a missing method and warns namingapi.csson an unbadged one, so a future PATCH endpoint surfaces at build time instead of silently losing its badge.- Brace escaping is resolved on both sides. I diffed five generated pages against
source/ApiDocsata28f5d5— byte-for-byte identical, and the only file that differs across the two repos is_README.md, which correctly stays in the Server repo.
Deliberately deferred, recorded here so they are findable later rather than lost:
pubDate/modDatehardcoded to2026-08-11in the generator, so pages report a fixed "last updated" date. Matters most once the section leaves under-construction and reaches the sitemap.layout: src/layouts/Api.astrowritten by the generator, naming a docs-repo path from the Server repo. Worth revisiting when the shovel is built, along with a possible move to an Astro content collection.buildApiCrumbsinserts at index 0 iffindIndexreturns-1, putting the section crumb before Docs. I could not find a route where that happens, so this is defensive only.
None of these affect readers today. Companion PR is OctopusDeploy/OctopusDeploy#46319.

This is the first part of a staged introduction of our API docs into the documentation site.
It adds
/docs/apiwith all the auto-generated API docs, copy pasted from the Octopus Server reposatteri-api-examplesplugin which processes themHow to review this PR
Ignore all the stuff under
pages/docs/api. It is programatically generated based on the Octopus Server codebase, and it is equivalent to our swagger content on https://demo.octopus.app/swaggerui/index.html. There are many flaws in the documentation content, however it is already public material and we haven't changed that, so it is not the responsibility of this PR to fix it.Claude wrote the rest of the code. It may not be ideal, technically, but it is very limited in what it needs to do, and the blast radius is contained (a bug will only impact a small section of the site and should not affect other things) so it should be good enough
Treat this as a stepping stone. Once it merges I will proceed with the next steps:
Things this PR does not include
/docs/apiwhich can help people find common things, such as introductory material and explaining that this documentation is for octopus cloud and that LTS versions might be different./docs/octopus-rest-apiinto/docs/apiand mix it in with the generated content. The generated content may well move to a subfolder such as/docs/api/reference. Will cross that bridge when we get to it.When this PR merges, the new files under
/docs/apiwill be live, but nothing will link to them. We will start linking to them and "light them up" as part of that other work.The API docs format
This is best explained by taking one of the files as an example
It's normal markdown, with these enhancements:
:endpoint{method="POST" path="/api/users/access-token"}to emit<span class="api-post">POST</span> `/api/users/access-token`. CSS styles the API badge to make it look nice, and the navigation generator also has something it can latch onto for reliable nav-generation:span[string]{.type-label}to emitstringwith thetype-labelCSS class:::api-example{label="Request|Response"}directive which emits a div for example request/responses. We need something special here because the examples go in a right-hand side column, and Markdown itself has no way to express columns or layout. The satteri plugin sees this directive and emits the example HTML in the right-hand column rather than in-line with the other content.It looks like this