Skip to content

How the Stoplight Elements bundle is vendored

just vendor-elements is the only way the files under assets/ should change. It downloads @stoplight/elements from the npm registry, checks the tarball against the registry's published integrity, and writes four files plus a record of where they came from.

just vendor-elements          # re-vendor the pinned version
just vendor-elements 9.1.0    # move the pin to 9.1.0

The recipe runs scripts/vendor-elements.sh, which needs curl, jq, tar and openssl. It stops without touching assets/ if the registry has no such version or the tarball does not match its integrity.

What lands in assets/

File From the package Embedded and served
web-components.min.js package/web-components.min.js yes
web-components.min.js.LICENSE.txt package/web-components.min.js.LICENSE.txt yes
styles.min.css package/styles.min.css yes
LICENSE package/LICENSE no
stoplight-elements.json written by the script no

web-components.min.js.LICENSE.txt holds the notices for the third-party libraries webpack bundled into the JavaScript, and the bundle's first line names it, so it is served beside the bundle.

stoplight-elements.json is the provenance record, and its version is the pin: the recipe re-vendors that version when it is given none.

{
  "package": "@stoplight/elements",
  "version": "<version>",
  "tarball": "https://registry.npmjs.org/@stoplight/elements/-/elements-<version>.tgz",
  "integrity": "sha512-…",
  "sha256": { "web-components.min.js": "…", "…": "…" }
}

TestVendoredAssetsMatchProvenance hashes each vendored file and compares it with the record, so a hand edit to assets/ fails the build.

Checking the vendored files against npm

Re-running the recipe at the pin reproduces the files byte for byte, so this shows nothing when assets/ is what npm published:

just vendor-elements && git status --short assets/

Releasing a new version

Commit the result as fix(deps): update Stoplight Elements to <version>, with a Release-Note: trailer naming the old and new versions. The fix type is what makes colophon cut a release, and consumers only get the new UI by upgrading this module.

The scheduled refresh

A weekly schedule keeps the pin on npm's latest. The refresh-elements job runs scripts/refresh-elements.sh, which compares the pinned version with the registry's latest dist-tag:

  • Already latest: nothing, and an open refresh merge request is closed.
  • Newer on npm: it runs scripts/vendor-elements.sh, the script behind the recipe, and replaces the standing chore/refresh-stoplight-elements branch with one fix(deps) commit carrying a Release-Note: trailer, then opens or updates its merge request. Merge it as you would any other; it cuts a patch release. Anything pushed to that branch by hand is replaced on the next run.
  • The run failed: it raises an issue titled Stoplight Elements refresh failing, or comments on the open one.

The job runs the script rather than just, because the CI image does not ship just; the recipe is a one-line wrapper over the same script.

It runs only in a scheduled pipeline that sets REFRESH_ELEMENTS=true, and it authenticates with two variables: the RENOVATE_TOKEN group variable for the commit and merge request, and the REPORTER_TOKEN project variable for the failure issue. Both are protected, so the schedule must target main. Whoever creates the schedule owns it, so a maintainer creates it:

glab schedule create --repo phpboyscout/go/transport-openapi \
  --description "refresh-elements" --cron "0 4 * * 1" --ref main \
  --variable "REFRESH_ELEMENTS:true"

To refresh now, play it with glab schedule run <schedule id>. To see what a run would do without touching GitLab, run DRY_RUN=1 scripts/refresh-elements.sh from a checkout. It vendors into your working tree and prints the API calls it would make.