Skip to content

Automate SDK bump PRs, and fix the CODEOWNERS and CDN updater bugs - #101

Open
ritz078 wants to merge 3 commits into
mainfrom
ritz078/automatic-update
Open

Automate SDK bump PRs, and fix the CODEOWNERS and CDN updater bugs#101
ritz078 wants to merge 3 commits into
mainfrom
ritz078/automatic-update

Conversation

@ritz078

@ritz078 ritz078 commented Aug 27, 2026

Copy link
Copy Markdown
Collaborator

⚡ TL;DR

A new @nutrient-sdk/viewer release now opens its own bump PR, already formatted and e2e-tested, instead of waiting for someone to notice. Two silent bugs that let stale versions sit in the repo for months are fixed along the way.

🎯 What this improves

  • 🤖 No manual bumps: a daily job detects a new release, bumps every example, and opens the PR by itself.
  • 👀 Reviewers actually get asked: CODEOWNERS pointed at @PSPDFKit/nickel, a team that does not exist, so GitHub silently requested nobody on every PR in this repo.
  • 🔎 Stale CDN versions surface instead of hiding: examples/gatsbyjs sat eight minor versions behind because of a one-character typo nothing was checking.
  • 🛑 Failures stop being green: a run that pushes a branch and then dies, or an e2e suite that fails, now fails the job rather than reporting success.
  • ♻️ Closed bumps stay closed: declining a version no longer means it reappears tomorrow, and every day after.

🔧 What changed

  • Was: version bumps were run by hand via npm run update-nutrient-version; the CDN updater keyed one example as gatsby while the directory is gatsbyjs, so that entry was never looked up and never updated; CODEOWNERS named a nonexistent team.
  • Now: .github/workflows/update-nutrient-sdk.yml runs daily (and on workflow_dispatch, optionally against a given version). scripts/check-nutrient-update.sh decides whether to act and refuses to start a bump already in flight. update-nutrient-in-cdn.js rejects a map key matching no directory, rejects a mapped file that is missing, and rejects a replace that matched nothing. A workflow-level grep then catches any example carrying a CDN tag that the map does not know about at all.
  • Impact: no user-facing or API change. Repository automation and CI only.

🔍 Root cause

  • CDN staleness: cdnOcurrences is a hand-maintained map from example name to file list. A key that matches no directory is simply never looked up, so the gatsby/gatsbyjs typo produced no error, no warning, and no diff. examples/nuxtjs had a second variant of the same failure: it was absent from the map entirely.
  • The replace could not fail either: the old pattern /pspdfkit-web@([0-9]+.[0-9]+.[0-9]+)?/g made the version group optional, so a file with no version still "matched", got rewritten byte-identical, and was reported as updated.
  • CODEOWNERS: GitHub treats an unresolvable team as a no-op rather than an error, so @PSPDFKit/nickel reviewed nothing and said nothing.

🤔 Why

  • Decision: guard the hand-maintained map at three levels in the script, and add one independent check in the workflow. The script guards give a precise early error; the workflow grep is the one that catches an example missing from the map, which no in-script guard can see.
  • Alternative considered: deriving the file map by scanning examples/ for CDN tags, removing the hand-maintained list entirely. Rejected for this PR: it trades a small include-list for an exclude-list (examples/salesforce/README.md documents the CDN URL with a worked @1.0.0 example and must never be bumped), and it rewrites a script this PR is already changing. Worth doing separately.
  • Decision: run the e2e suite inside the bump job. A PR opened with GITHUB_TOKEN does not trigger the Biome or Playwright workflows, and main requires no status checks, so the bump would otherwise arrive with no signal at all.
  • Decision: a failing suite opens the PR as a draft and fails the run. GitHub does not request code owners on drafts, so without the explicit failure the bad path would notify nobody while staying green.

🧪 How to test

  • Detection, without opening anything:
./scripts/check-nutrient-update.sh            # 1.18.0 -> 1.21.0, should_update=true
./scripts/check-nutrient-update.sh 1.18.0     # already on 1.18.0
./scripts/check-nutrient-update.sh 1.19.0     # a pull request already exists
./scripts/check-nutrient-update.sh 1.20.0-nightly   # exits 1, prereleases are never shipped
  • The CDN guard that reproduces the original bug. Rename the gatsbyjs key to gatsby and it now refuses to run:
node scripts/update-nutrient-in-cdn.js webpack 9.9.9
# Keys matching no example directory: gatsby
  • Confirm the salesforce README is left alone while its Visualforce page is bumped:
node scripts/update-nutrient-in-cdn.js salesforce 9.9.9
grep -rn 'pspdfkit-web@' examples/salesforce/ | grep -v node_modules
git checkout -- examples/salesforce/
  • Lint and version consistency:
npx @biomejs/biome@1.9.4 ci .
./scripts/check-biome-version.sh
  • End to end, against a version already released:
gh workflow run update-nutrient-sdk.yml -f version=1.21.0

⚠️ Risks / notes

  • 🔑 Needs "Allow GitHub Actions to create and approve pull requests" enabled for the repo, or the gh pr create step fails with a permissions error.
  • 📉 Two examples are still behind on this branch: nuxtjs is on 1.3.0 and gatsbyjs on 1.8.0. This PR does not bump them; it makes the next scheduled run bump them and fail loudly if it cannot.
  • 🧹 Formatting is staged from examples/ only: pnpm run format writes unsafe Biome fixes repository-wide, so the commit step uses git add -u examples/ and discards the rest.
  • ⏱️ The job installs every example and runs the full e2e suite, so a bump run takes a while; the timeout is set to 90 minutes.
  • 🧭 update-nutrient-in-examples.sh still hard-codes its 20 example directories. A new example is silently never bumped, which is the same class of drift this PR fixes in the CDN map. Left out because generalizing it changes which examples get bumped (wasm-benchmark pins a range deliberately) and needs its own verification.

The CODEOWNERS file referenced @PSPDFKit/nickel, a team that does not
exist, so no review was ever auto-requested. Point it at @PSPDFKit/web,
which has write access to this repository.

The CDN updater keyed its map on "gatsby" while the directory is
"gatsbyjs", and omitted nuxtjs and the Salesforce README entirely. Those
three files were left pinned at 1.8.0, 1.3.0 and 1.0.0 while every other
example moved to 1.18.0. Correct the key, add the missing entries, and
validate all paths before writing so a moved file fails the run instead
of silently half-updating an example.

Both scripts now take the target version as a required argument instead
of resolving @latest at install time, so a release landing mid-run cannot
produce a bump whose title and lockfiles disagree.
Adds a daily workflow that checks the npm latest dist-tag, bumps every
example, and opens a pull request. @PSPDFKit/web is requested for review
through CODEOWNERS rather than by the workflow, so no token needs
permission to resolve org teams.

Detection refuses to act twice on the same release: it exits when the
repository is already on the version, when the branch exists, or when a
pull request for it was opened before, so a bump closed without merging
is not reopened on the next run. Prereleases are rejected outright, so
nightly builds never trigger a bump.

Biome and the e2e suite run inside the job before the pull request is
opened. A pull request created with GITHUB_TOKEN does not trigger the
Biome or Playwright workflows, and main requires no status checks, so a
bump would otherwise arrive with nothing having verified it. A failing
suite still opens the pull request, as a draft, with the report attached.

pnpm is pinned to 10 because pnpm 11 stops reading the pnpm.overrides
field in package.json, which would silently drop the security overrides
added in #98.
@ebardonerocheel213-jpg

ebardonerocheel213-jpg commented Aug 27, 2026 via email

Copy link
Copy Markdown

@ritz078
ritz078 marked this pull request as draft August 27, 2026 08:32
Refuse to reopen a closed bump, fail loudly when a run stops part-way,
and reject a CDN map key or file that matches nothing. Exempt the
salesforce README, whose version is an illustration rather than a pin.
@ritz078
ritz078 requested a review from MahmoudElsayad August 27, 2026 09:05
@ritz078 ritz078 self-assigned this Aug 27, 2026
@ritz078
ritz078 marked this pull request as ready for review August 27, 2026 09:05
@ritz078
ritz078 enabled auto-merge (squash) August 27, 2026 09:08
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