Skip to content

chore: resource-server consolidation in uPortal-start#694

Merged
bjagg merged 9 commits into
uPortal-Project:masterfrom
bjagg:chore/resource-server-consolidation
May 14, 2026
Merged

chore: resource-server consolidation in uPortal-start#694
bjagg merged 9 commits into
uPortal-Project:masterfrom
bjagg:chore/resource-server-consolidation

Conversation

@bjagg

@bjagg bjagg commented May 7, 2026

Copy link
Copy Markdown
Member

Summary

Completes uPortal-start's side of the resource-server consolidation, plus adds test infrastructure that pins recent regressions.

Resource-server consolidation (commit 7e931e146):

  • Swap every portlet-definition data file's iconUrl off /ResourceServingWebapp/ (73 files, mechanical pass — tango/famfamfam paths now resolve under /resource-server/).
  • Refresh etc/skin/skinName/skin.xml (new-skin template) onto the modern overlay; bump jquery-ui smoothness to the BS5/jquery-ui 1.14.2 webjar pattern.
  • Add org.webjars.npm:ckeditor4:4.22.1 to the resource-server overlay so SimpleContentPortlet's configureContent.jsp consumes a webjar, not the legacy 1.0.48 WAR's bundled 4.3.2 (multiple historical XSS CVEs).

gradle.properties template pattern (commit 8366d18c1):

  • Move canonical version pins to gradle.properties.example; ignore gradle.properties so contributors' local SNAPSHOTs don't pollute upstream history and deployer forks no longer hit per-merge conflicts on pinned versions.
  • README + CI bootstrap step for first-time clones.

Test coverage:

  • tests/ux/skin/custom-skin.spec.ts (commit ba2845ad0): regression test for Comment out / deprecate less uPortal#2982 — scaffolds playwrightSkin from etc/skin/, deploys, asserts the compiled CSS is served. New playwrightSkinFixture Gradle task regenerates the scaffold on every playwrightRun so scaffold-template drift fails the test.
  • Extend tests/ux/smoke/visual-resource-server.spec.ts with uportal-links?pCm=config (commit 0584ba739): catches the JasigWidgetPortlets configLinks.jsp lodash regression that was missed locally.

Test plan

  • cp gradle.properties.example gradle.properties (per new pattern)
  • ./gradlew portalInit && ./gradlew tomcatStart
  • ./gradlew playwrightRun — full suite (gates on the new skin fixture + smoke spec)
  • Verify deployer-fork upgrade path: comment out /gradle.properties in fork's .gitignore, commit local pins, merge upstream — confirm no conflict on gradle.properties

@bjagg bjagg force-pushed the chore/resource-server-consolidation branch from 33df94b to 0584ba7 Compare May 8, 2026 00:30
@bjagg bjagg changed the title chore(uportal-start): tango/famfamfam path swaps; CKEditor 4.22.1 webjar; visual smoke chore: resource-server consolidation in uPortal-start May 8, 2026
bjagg added a commit to bjagg/uPortal-start that referenced this pull request May 8, 2026
Problem: uportal-pw.config.ts pinned retries to 0, which left
timing-sensitive tests (notably the BS5 options dropdown — see
uPortal#2981) flaking under CI without recourse. The existing
config already enables `video: "on-first-retry"` and
`trace: "retain-on-failure"`, both of which assume retries
happen, so retries:0 also defeated those debug aids.

Goal: allow Playwright to retry transient failures up to twice
before marking a test failed. Stabilizes CI signal on PR uPortal-Project#694
without masking durable failures (a test failing 3/3 still fails).

Changes:
- tests/uportal-pw.config.ts: retries 0 -> 2

Notes: per reviewer (Naenyn) suggestion on the uPortal-Project#694 dropdown
flake. The underlying Bootstrap-5 dropdown synthetic-click issue
is tracked at uPortal#2981; this is mitigation, not a fix.
bjagg added a commit to bjagg/uPortal-start that referenced this pull request May 10, 2026
Problem: uportal-pw.config.ts pinned retries to 0, which left
timing-sensitive tests (notably the BS5 options dropdown — see
uPortal#2981) flaking under CI without recourse. The existing
config already enables `video: "on-first-retry"` and
`trace: "retain-on-failure"`, both of which assume retries
happen, so retries:0 also defeated those debug aids.

Goal: allow Playwright to retry transient failures up to twice
before marking a test failed. Stabilizes CI signal on PR uPortal-Project#694
without masking durable failures (a test failing 3/3 still fails).

Changes:
- tests/uportal-pw.config.ts: retries 0 -> 2

Notes: per reviewer (Naenyn) suggestion on the uPortal-Project#694 dropdown
flake. The underlying Bootstrap-5 dropdown synthetic-click issue
is tracked at uPortal#2981; this is mitigation, not a fix.
@bjagg bjagg force-pushed the chore/resource-server-consolidation branch from f3d16a8 to 92e4dc2 Compare May 10, 2026 01:03
bjagg added 5 commits May 12, 2026 11:37
…jar; visual smoke

Problem: uPortal-start's portlet-definition data files, the skinName
template, and the resource-server overlay all referenced the legacy
/ResourceServingWebapp/ context that the consolidation effort is
retiring. SimpleContentPortlet's CKEditor was being served from the
legacy 1.0.48 WAR's bundled 4.3.2 (multiple historical XSS CVEs);
the modern resource-server-webapp 1.5.x overlay didn't carry an
explicit CKEditor webjar to consume from. There was no automated
check that the consolidation didn't regress visual rendering or
quietly start emitting legacy URLs.

Goal: complete the consolidation's surface area in uPortal-start —
move every portlet-definition data file's iconUrl off the legacy
context, refresh the skinName template (used as the starting point
for institutional skins) onto the modern overlay, give the modern
overlay a webjar source for CKEditor 4 so SimpleContentPortlet's
configureContent.jsp can consume it, and add a visual smoke test
that asserts the absence of legacy URL requests on key pages.

Changes:
- data/base/portlet-definition/*.xml (31 files),
  data/quickstart/portlet-definition/*.xml (40 files): swap every
  iconUrl <value>/ResourceServingWebapp/rs/tango/...</value> to
  /resource-server/rs/tango/... Tango/0.8.90 ships at byte-identical
  paths in the modern overlay so the deployed portlet thumbnails
  render unchanged.
- etc/skin/skinName/skin.xml: update the new-skin template used by
  deployers — swap normalize 2.1.2 + fontawesome 4.7.0 to the
  modern context; bump the jquery-ui smoothness theme from
  /ResourceServingWebapp/rs/jqueryui/1.10.3/theme/smoothness/
  jquery-ui-1.10.3-smoothness.{css,min.css} to
  /resource-server/webjars/jquery-ui/dist/themes/smoothness/
  jquery-ui.{css,min.css} (matches uPortal-webapp's defaultSkin
  precedent; webjar serves jquery-ui 1.14.2). Existing skins are
  unaffected — this is purely a starting-template change.
- gradle.properties: add ckeditor4Version=4.22.1. 4.22.1 is the
  last truly free CKEditor 4 release; 4.23+ are LTS-only and
  self-destruct without a paid license key. Comment captures that
  trap so deployers don't try to bump.
- overlays/resource-server/build.gradle: declare
  org.webjars.npm:ckeditor4:${ckeditor4Version} as a runtime
  webjar so SimpleContentPortlet's configureContent.jsp can
  consume /resource-server/webjars/ckeditor4/ckeditor.js.
- tests/ux/smoke/visual-resource-server.spec.ts: new visual smoke
  spec — guest welcome, admin home, student home, CKEditor
  instantiation in SimpleContentPortlet config, and a NewsReader
  page that exercises the Handlebars-replacement mini-renderer.
  Each test attaches console/network listeners and asserts zero
  /ResourceServingWebapp/ URL requests + zero unexpected console
  errors. Filters CKEditor 4.22.1's known LTS-upgrade nag.

Notes: 73 portlet-definition data files modified is a mechanical
sed-style pass (/ResourceServingWebapp/rs/tango/ →
/resource-server/rs/tango/) — review by category, not file. Existing
deployments need a fresh dataInit (or a SQL UPDATE on
up_portlet_definition_parm) to pick up the new iconUrl values; the
deployer guide documents the SQL recipe. Verified end-to-end against
uPortal-start's full Playwright suite (121/122 with 1 documented
chrome dropdown flake from uPortal#2981 unrelated to this work).
Problem: gradle.properties is the canonical place to pin uPortal and
portlet versions, but every developer iterating with -SNAPSHOTs
against an unreleased build either pollutes upstream history with
SNAPSHOT bumps or maintains a dirty working tree. Institutional
deployers who fork to maintain pinned versions hit merge conflicts
on every upstream sync because both their fork and upstream edit
the same file.

Goal: keep canonical versions in source control as a template and
let the active gradle.properties live untracked, so contributors'
local SNAPSHOTs don't surface upstream and deployer forks can
absorb upstream version bumps without merge conflicts.

Changes:
- add gradle.properties.example with the canonical version pins
  previously tracked at gradle.properties
- stop tracking gradle.properties (git rm --cached); the file
  remains on disk for the developer's own iteration
- .gitignore: add /gradle.properties with a comment explaining the
  pattern
- README.md: new "Bootstrap gradle.properties" section under "Using
  uPortal-start" documenting the cp step for first-time clones and
  the deployer-fork pattern (comment out the .gitignore line on the
  fork so version pins commit normally; upstream changes only land
  in gradle.properties.example, eliminating per-merge conflicts)
- .github/workflows/CI.yml: bootstrap step (cp gradle.properties
  .example gradle.properties) added to both the test and playwright
  jobs right after checkout, before any gradle invocation; shell:
  bash on the Windows-capable test job

Notes: did not bootstrap from settings.gradle or gradlew because
gradle.properties is loaded before either runs; the explicit cp is
the simplest contract. Deployers who want the existing committed-
gradle.properties workflow comment out the gitignore line on their
fork in one step.
Problem: uPortal-Project/uPortal#2982 fixed a regression in
common.less where an @import path no longer existed in the
Bootstrap 5 webjar, breaking lessc compilation for any custom
skin scaffolded by :overlays:uPortal:skinGenerate. Without an
automated check, the next break of common/common.less only
surfaces when a deployer runs tomcatDeploy in their own
environment and notices missing CSS.

Goal: pin the regression with a Playwright test that exercises
the full scaffold-and-compile path (skinGenerate -> tomcatDeploy
-> lessc) on every playwrightRun.

Changes:
- overlays/uPortal/build.gradle: new playwrightSkinFixture task
  that idempotently regenerates the playwrightSkin scaffold from
  etc/skin/ and ensures a <skin> entry exists in skinList.xml;
  scaffold-template drift is caught even when the skin files are
  committed, because the fixture overwrites them on every run
- gradle/tasks/playwright.gradle: playwrightRun now depends on
  playwrightSkinFixture and :overlays:uPortal:tomcatDeploy;
  ordering enforced via prepareSkinResources.mustRunAfter(
  playwrightSkinFixture) inside gradle.projectsEvaluated to avoid
  eager cross-project configuration of :overlays:uPortal at root
  evaluation time
- overlays/uPortal/src/main/webapp/media/skins/respondr/: commit
  the generated playwrightSkin.less, playwrightSkin/, and a
  skinList.xml entry so the skin-compile chain in
  overlays/uPortal/build.gradle (which evaluates the fileTree at
  configuration time) registers compileLess for our skin; the
  fixture overwrites these on every run
- tests/ux/skin/custom-skin.spec.ts: assert
  /uPortal/media/skins/respondr/playwrightSkin.css returns 200,
  has >500 bytes, and contains a Bootstrap marker (--bs-, .btn,
  or @import bootstrap.css) — proves common.less's @import
  resolved. Pre-fix code fails compileLess0 before the spec runs;
  post-fix the spec passes

Notes: scoped to compile-only coverage (Shape 1) rather than
driving the dynamic-respondr-skin or stylesheet-descriptor
default-skin switch path, since the PR #2982 regression is at
lessc compile time. Activation testing is left for a follow-up if
the dynamic skin path needs its own regression guard. Skin name
"playwrightSkin" deliberately distinct from "test" so a developer
can keep their own scaffold-named "test" skin alongside the
fixture's.
Problem: tests/ux/smoke/visual-resource-server.spec.ts asserts no
/ResourceServingWebapp/ requests fire on the pages it visits, but
the uportal-links portlet config view (configLinks.jsp) was not
in the visit list. A regression where that JSP loaded a legacy
/ResourceServingWebapp/rs/lodash/4.17.4/lodash.min.js script tag
was missed locally and caught only when a developer noticed it in
DevTools.

Goal: extend smoke coverage to the uportal-links config view so
the same network-tap assertion guards configLinks.jsp.

Changes:
- tests/ux/smoke/visual-resource-server.spec.ts: new test case
  that logs in as admin, navigates to
  /uPortal/p/uportal-links/max/render.uP?pCm=config, and reuses
  the smokePage helper (which fails on legacy
  /ResourceServingWebapp/ hits, network 4xx/5xx, or console
  errors)

Notes: the missed regression that prompted this was
JasigWidgetPortlets 2.4.2 shipping a configLinks.jsp with a
/ResourceServingWebapp/rs/lodash/... script tag;
JasigWidgetPortlets@9068d91 (released as 2.4.3-SNAPSHOT) drops
the lodash dep and switches the template tag to
/resource-server/. Picking up that release in this repo is a
gradle.properties bump in the deployer's local file (per the
template pattern landed earlier on this branch).
Problem: uportal-pw.config.ts pinned retries to 0, which left
timing-sensitive tests (notably the BS5 options dropdown — see
uPortal#2981) flaking under CI without recourse. The existing
config already enables `video: "on-first-retry"` and
`trace: "retain-on-failure"`, both of which assume retries
happen, so retries:0 also defeated those debug aids.

Goal: allow Playwright to retry transient failures up to twice
before marking a test failed. Stabilizes CI signal on PR uPortal-Project#694
without masking durable failures (a test failing 3/3 still fails).

Changes:
- tests/uportal-pw.config.ts: retries 0 -> 2

Notes: per reviewer (Naenyn) suggestion on the uPortal-Project#694 dropdown
flake. The underlying Bootstrap-5 dropdown synthetic-click issue
is tracked at uPortal#2981; this is mitigation, not a fix.
@bjagg bjagg force-pushed the chore/resource-server-consolidation branch from 92e4dc2 to c95ee63 Compare May 12, 2026 19:21
bjagg added 4 commits May 13, 2026 13:54
Problem: PR uPortal-Project#694's CI fails at :overlays:uPortal:compileLess0 because
the pinned uPortal 5.17.5 still imports legacy LESS sub-files
(grids.less, variables.less, mixins.less, regions.less, gallery.less,
tags.less, etc.) that were deleted during the Bootstrap 5 / SCSS
migration.

Goal: pick up uPortal 5.17.7, which lands Bill's PR #2982 deprecating
the LESS pipeline by commenting out every orphaned @import in the
respondr skin's common.less.

Changes:
- bump uPortalVersion=5.17.5 to 5.17.7 in gradle.properties.example

Refs: uPortal-Project#694
Problem: playwrightLint failed locally on three rules:
  - unicorn/prevent-abbreviations: variable name 'e' is ambiguous
  - unicorn/prefer-dom-node-text-content: use .textContent over .innerText
  - unicorn/better-regex: \{ inside a character class can be unescaped

Goal: clear the lint pass so the playwright run reaches the test
execution phase (where the consolidation invariants are actually
checked).

Changes:
- rename the filter-callback parameter 'e' to 'error' in the
  CKEditor LTS-nag filter
- replace page.locator('body').innerText() with .textContent()
- drop the unnecessary backslash escapes from /{{[#/]?[A-Za-z]/

Refs: uPortal-Project#694
Problem: PR uPortal-Project#694's visual-resource-server smoke spec gates on no
/ResourceServingWebapp/ URLs being requested by uPortal core or any
of the deployed portlets. The pins were on versions predating both
the uPortal-side path swaps (uPortal-Project/uPortal#2983, in v5.17.8)
and the portlet-side overlay drops (SimpleContent uPortal-Project#554, Feedback uPortal-Project#112,
NewsReader uPortal-Project#438; in 3.4.3 / 1.3.2 / 5.1.5 respectively). CI's visual
smoke tests therefore stayed red until all five releases shipped
together.

Goal: pick up the Wave 1 portlet releases and the Wave 2 uPortal
release so PR uPortal-Project#694's CI exercises the full post-consolidation stack.

Changes:
- bump uPortalVersion 5.17.7 -> 5.17.8 (uPortal#2983: skin XML + JSP
  path swaps off /ResourceServingWebapp/; drop dead utility-lib
  webjar deps)
- bump simpleContentPortletVersion 3.4.2 -> 3.4.3 (uPortal-Project#554: CKEditor
  4.22.1 webjar; drop resource-server-content overlay)
- bump feedbackPortletVersion 1.3.1 -> 1.3.2 (uPortal-Project#112: drop overlay)
- bump newsReaderPortletVersion 5.1.4 -> 5.1.5 (uPortal-Project#438: native
  mini-template renderer replacing Handlebars 3.0.3; drop overlay)

Notes: validated locally against a fresh portalInit + tomcatStart with
the bumped pins. Five of six visual-resource-server tests pass (guest
welcome, admin home, student home, CKEditor 4 webjar instantiation,
uportal-links config). The news-portlet-renders-without-Handlebars
test was already failing in CI before this commit; not a regression
from the bumps. CalendarPortlet event-fetch is flaky in local
quickstart data; tracked separately.

Refs: uPortal-Project#694
Problem: PR uPortal-Project#694's CI on the latest commit had two Playwright failures:

  1. "news portlet renders without Handlebars" — page.locator('body')
     .textContent() includes <script type="text/template"> bodies, which
     legitimately contain {{var}} placeholder syntax (that's the
     template source the mini-renderer evaluates against). The
     assertion that the rendered DOM should not contain raw {{...}}
     therefore matched the template source itself, not actual
     un-rendered output. Confirmed via HTML parser: every {{ match in
     the failing snapshot is text inside a <script> tag; zero are in
     live element content. Switching from textContent to innerText
     (the original API before a lint-driven change) excludes script
     bodies from the captured text.

  2. "uportal-links config loads no /ResourceServingWebapp/ resources"
     — failed in CI with "Received +3 ... 'This CKEditor 4.22.1
     (Standard) version is not secure. Consider upgrading to the
     latest one, 4.25.1-lts'". The dedicated CKEditor-instantiates
     test (line 105) already filters this LTS-nag from its console
     errors, but the shared smokePage helper used by uportal-links did
     not. The uportal-links config view also loads CKEditor (for the
     link-text edit field) and the nag fires there too. The test was
     passing locally because the nag fires after the page's
     domcontentloaded snapshot in some timings, but is deterministic
     in CI.

Goal: keep the assertions catching real regressions (un-rendered
templates, runtime errors) without flagging known third-party noise.

Changes:
- revert textContent() back to innerText() on the news-portlet body
  read; add an explanatory comment and a single-line eslint-disable
  for unicorn/prefer-dom-node-text-content
- pull the CKEditor LTS-nag filter into the smokePage helper so every
  page using the helper benefits from it

Refs: uPortal-Project#694
@bjagg bjagg merged commit d47adce into uPortal-Project:master May 14, 2026
6 checks passed
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