Skip to content

toolchain: keep the live suite's player libraries current (one rolling pull request) - #566

Merged
Nawid3333 merged 5 commits into
mainfrom
ci/player-libraries-updates
Oct 24, 2026
Merged

Nawid3333 merged 5 commits into
mainfrom
ci/player-libraries-updates

Conversation

@Nawid3333

Copy link
Copy Markdown
Owner

The 16 npm player libraries the live suite plays (tests/e2e/live-specs/players.e2e.mjs) were pinned in the spec, and nothing kept them current. This is the second update gap found while checking what Dependabot does not cover. #565 was the first.

Why not Dependabot

A Dependabot npm entry for a folder that holds only a package.json would not stay in that folder. When the configured folder has no lockfile, dependabot-core's npm fetcher (npm_and_yarn/lib/dependabot/npm_and_yarn/file_fetcher.rb) takes pnpm-lock.yaml and pnpm-workspace.yaml from a parent folder (fetch_file_from_parent_directories). So Dependabot would bring in the repository's own lockfile. What its pnpm updater then does to that lockfile is not established, and a lockfile of the libraries' own would add their whole dependency trees to the alerts, though the suite never loads those trees. The toolchain workflow already handles pins Dependabot cannot see, so these join it.

What changes

  • The pins move to tests/e2e/live-specs/player-libraries.json, which the spec reads. Its lookup takes own keys only (Object.hasOwn): a path such as /npm/constructor/... would otherwise have found Object.prototype's.
  • tools/check-toolchain.mjs computes the set (playerTargets()):
    • Each library goes to its newest release inside its pin's caret range that is at least 3 days old (MIN_AGE_DAYS) and not deprecated.
    • The ranges the libraries declare on each other must hold, and so must the ones on the repository's own hls.js. A library too new for another's range steps down first. One that needs a newer library than the set can have steps down. One whose range cannot be read is not taken new.
    • Real cases: xgplayer-hls asks for its exact xgplayer, and hls-video-element for a custom-media-element. The tests cover both.
    • A newer major is only reported.
    • Run against the registry today, it proposes video.js 8.24.2, shaka-player 5.3.1, @clappr/player 0.14.8 and @clappr/hlsjs-playback 3.1.3. Releases under 3 days old (media-chrome 4.19.4, hls-video-element 1.5.12, custom-media-element 1.4.7, shaka 5.3.2) wait. video.js 10.1.0 is reported as a newer major.
  • toolchain-updates.yml keeps ONE rolling pull request, "Toolchain update: player libraries" on toolchain/player-libraries. It is rebuilt in place on main when the set changes, and CI and the live suite are started on each new head (the runs before the text).
    • The body marks its set. A pull request closed unmerged by hand skips that set; this workflow's own close takes the marker out first.
    • A pull request holding someone else's commits is left to them, also when main has caught up.
    • A set of the wrong shape fails the run, instead of being read as "caught up".
    • --apply-players refuses a library going back, a library it does not know, or a version that is not x.y.z.
    • Newer majors: one issue, "Player libraries: newer majors". It is keyed by name and major, so a release within a major already listed changes nothing, and a hand-closed issue stays closed until another major comes.
  • update-prs.yml learns the kind players. Only that JSON may change. "Ready" also needs the live suite (live-streams.yml) to have passed on the very commit, because CI does not play these libraries. This is asked last, once everything else holds:
    • no run on the commit: the live suite is started;
    • a run still going (any status but completed): never started again, since a second run would cancel it;
    • cancelled: started again while the commit has fewer than two runs, so a run that keeps timing out cannot loop;
    • failed: a reason with its link;
    • the runs cannot be listed: a reason, not a dead run.
      On the update-branch path the live suite is started too, since no push starts it.
  • live-streams.yml gets a last job, hand-off. On that branch, once the suite ended (always()), it starts update-prs.yml with the CI run on the same commit, but only if that CI run passed; otherwise CI's own hand-off decides. It is tried three times, and then opens or comments on the issue ci.yml's hand-off uses.
  • Docs: docs/maintenance.md (two rows), docs/notes/workflows.md, docs/notes/playback-testing.md.

Tested

  • Unit tests (tests/unit/checkToolchain.test.mjs, 172):
    • relation() on every range form;
    • the candidate list, the newer majors and playerTargets(), including both real families, cycles of exact peers, a conflict already on main, and a library held back;
    • applyPlayers();
    • the real file against the spec: every package the pages load is pinned, and nothing else.
    • A glm review found partial bounds read wrong (npm reads >1.2 as >=1.3.0 and <=1.2 as <1.3.0). The 5 new rows fail without the fix.
    • Whole suite: 3039 passed.
  • Workflow tests in WSL (Ubuntu 26.04, verify:linux workflows, which also ran actionlint, shellcheck and zizmor):
    • toolchain-updates.test.sh: 224 checks, 0 failed, 83 of them new for the rolling pull request (new set, same set, changed set, conflict, someone else's commits, caught up, skipped, next set, malformed set, refused apply, each majors-issue case);
    • update-prs-decide.test.sh: 690 checks, 0 failed (every live-suite state, the update-branch path, the migration texts);
    • new live-streams-hand-off.test.sh.
  • The live suite runs on this pull request (it changes tests/e2e/live-specs/**), with the pins read from the JSON.

Not established yet: the real chain in Actions (the rolling pull request, its two dispatched runs, both hand-offs, the verdict). After the merge, one dispatch of toolchain-updates.yml on main raises the first rolling pull request (four updates are due today) and shows it.

glm reviewed the design, the workflow parts, the code and the docs; the findings that held up against the code are fixed here.

🤖 Generated with Claude Code

Nawid3333 and others added 4 commits October 24, 2026 03:16
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…st is ready (docs check)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment thread tools/check-toolchain.mjs Fixed
Comment thread tools/check-toolchain.mjs Fixed
Comment thread tools/check-toolchain.mjs Fixed
Comment thread tools/check-toolchain.mjs Fixed
Comment thread tools/check-toolchain.mjs Fixed
- playerTargets keeps its state in Maps and builds the set with
  Object.fromEntries: a library named __proto__ (a key JSON.parse makes
  from a file or the registry) was silently dropped from the set (CodeQL
  js/remote-property-injection, 4 alerts; the new test fails without it).
  player-libraries.json's names must be npm package names, and a scoped
  name is encoded with replaceAll.
- A live run that timed out is started again once, as a cancelled one is
  (bounded at two runs per commit), and the reason after that no longer
  blames a public stream for what was cancelled.
- The pull request's text renders the libraries held back by a range
  (it printed a field the plan does not have) and the ranges that do
  not hold on main already.
- docs: 11 libraries are 16 packages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Nawid3333
Nawid3333 merged commit 96c9ff5 into main Oct 24, 2026
26 checks passed
@Nawid3333
Nawid3333 deleted the ci/player-libraries-updates branch October 24, 2026 01:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants