feat: swagger-ui from node_modules

Merged
WI
4d ago
+156-1866

Serve Swagger UI from node_modules instead of a committed vendor copy

Summary

/api loads Swagger UI from files copied out of the locked swagger-ui-dist package at build time. Nothing from the distribution is committed, so a Dependabot bump no longer needs a manual re-vendor step and no longer turns the Netlify build red.

flowchart LR
    lock[yarn.lock<br/>version + integrity] --> nm[node_modules/swagger-ui-dist]
    nm -->|swagger-ui-assets plugin<br/>on start/build| gen[generated-static/swagger-ui/<br/>gitignored, 11 files]
    static[static/<br/>api.html, swagger-initializer.js] --> build[build/]
    gen -->|staticDirectories| build
 build:netlify
   verify-git-history
   verify-indexnow-vendor
-  verify-swagger-ui-vendor      # failed on every swagger-ui-dist bump
   npm ci site-build-gate
   docusaurus build
+    swagger-ui-assets plugin    # copies the files api.html loads
   run-post-build-gates
 src/plugins/
+└── swagger-ui-assets.js          # copy list + staging, fails if a file disappears upstream
 static/
 ├── api.html                      # unchanged
 ├── swagger-initializer.js        # unchanged
-├── swagger-ui*.js|css|map|LICENSE.txt, index.css, favicon-*.png   # 19 files
-├── oauth2-redirect.html|js       # unused: the API spec has no OAuth2 scheme
-└── swagger-ui-vendor.json        # version/integrity/SHA-256 contract
 scripts/
-└── verify-swagger-ui-vendor.js
 tests/
-├── swagger_ui_vendor.test.js
+└── swagger_ui_assets.test.js     # api.html refs ⊆ copy list; installed package ships them

Also in this PR:

  • Drops the unused swagger-ui dependency. Nothing imports it; it removes about 80 packages from yarn.lock and no remaining package changes version.
  • Moves swagger-ui-dist into the browser-runtime Dependabot group. tests/dependency_authority.test.js is updated to match, and its "Swagger must stay independent" assertion is removed.
  • Removes oauth2-redirect.html from the Cloudflare analytics gate's sensitive routes and from two tests. api.html stays protected.
  • Rewrites the README's Swagger section, including how to restore the OAuth2 redirect page if the API ever adds OAuth2.
  • dependency-impact workflow is not only triggered for Dependabot.

Evidence

  • Before: a Dependabot-style bump (only package.json and the yarn.lock entry changed) fails before Docusaurus even starts:

    $ node scripts/verify-swagger-ui-vendor.js      # swagger-ui-dist 5.33.1 → 5.33.0
    Swagger UI vendor verification failed: Swagger UI vendor contract does not match the locked distribution
    exit=1
    

    #3082 (5.32.14 → 5.33.1) shows the same thing in practice: every GitHub check was green, netlify/netdata-docusaurus/deploy-preview was red, and the PR was closed until #3136 re-vendored by hand.

    After: the plugin stages whatever version is installed, with no manual step:

    stageSwaggerUiAssets(<site with swagger-ui-dist 5.33.0>)
    { version: '5.33.0', files: 11 }
    
  • Full Netlify build (npm run build:netlify, Node 22.23.2): passes. Site build gate: 0 findings across 2,030 pages. Cloudflare analytics gate: "1 credential-handling route" (api.html). Broken-anchor warnings: 297, the same as master.

  • Tests: yarn test:run passes: Vitest 494 passed and 1 skipped, plus the first-touch (26), IndexNow (64), swagger-ui-assets (3), dependency-authority (3) and site-build-gate (4) suites.

  • Browser (headless Chromium, local docusaurus serve): /api renders 72 API operations. swagger-ui.css, index.css, swagger-ui-bundle.js, swagger-ui-standalone-preset.js and swagger-initializer.js all return 200. No console errors or warnings.

  • Build output, master vs this branch (both built from directories at the same depth, compared file by file):

    OutputResult
    All JS chunks, sitemapidentical
    Files /api loads (bundle, preset, CSS, index.css, favicons, bundle source map)byte-identical
    es-bundle*, swagger-ui.js, oauth2-redirect.*, swagger-ui-vendor.jsonremoved (never loaded by /api)
    styles.cssabout 4 KB smaller: Tailwind no longer generates unused utilities from strings inside the committed Swagger bundles
    main.jsonly the new plugin entry and the extra staticDirectories value
    HTML pagesnew main/styles hash names and one extra blank line; no content change

Merge Danger

Door: two-way

Reverting this PR restores the vendored files and the check exactly. The one thing that doesn't come back on its own is the /oauth2-redirect.html URL: it returns 404 from the first deploy after merge. It is an OAuth callback page, not content, but backlinks for that path haven't been checked yet.

Blast Radius: /api

  • If the copy step broke, the cause is visible and blocking: the build fails, or the dep-impact /api check (.swagger-ui .opblock count) shows the page as broken.
  • Other pages change only by losing unused Tailwind utilities that came from Swagger's bundles. Those classes weren't used anywhere else in Learn's sources.
  • This changes earlier policy decisions: Swagger kept out of Dependabot groups, and the vendor contract required at build time. @ktsaou needs to agree before merge.

Summary by cubic

/api now serves Swagger UI copied from the locked swagger-ui-dist package at build/start time instead of a committed vendor copy, so Dependabot bumps no longer fail the Netlify build or require a manual re-vendor step.

Notable changes

  • The new swagger-ui-assets plugin stages the 11 files api.html loads into the gitignored generated-static/swagger-ui/ directory; the committed vendor copy, its contract, and the build-time verification script are removed.
  • The unused swagger-ui dependency is dropped (~80 fewer packages in yarn.lock), and swagger-ui-dist is now grouped with browser-runtime in Dependabot.
  • /oauth2-redirect.html and its script are removed; the URL now 404s, but it was dead because the API spec has no OAuth2 scheme.
  • The dependency-impact workflow's author filter is commented out, so its advisory job also runs for non-Dependabot PR authors.

Merge notes

  • The first deploy after merging will 404 on /oauth2-redirect.html; backlinks to that path haven't been checked yet.
  • This reverses earlier decisions to keep Swagger out of Dependabot groups and to require a build-time vendor contract, so sign-off is needed before merge.

Summary by CodeRabbit

  • Documentation
    • Updated the API documentation to explain that Swagger UI assets are prepared during site builds and that builds fail if required assets are missing.
    • Clarified that the site does not publish an OAuth2 redirect page and documented the assets needed if OAuth2 support is added.
    • Updated analytics guidance to exclude only the API page from beacon and third-party analytics checks.
  • Changes
    • The OAuth2 redirect page is no longer published.