From ddb1cdd849478ded7b75e201771e9967dee42243 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 30 Aug 2026 21:34:44 +0000 Subject: [PATCH 1/3] feat: gate the release numbers the docs name, regenerate the sample gallery Two rots, one pattern - a number in prose that nothing re-measures: verify-refs learns check 5: every three-part release number the docs mention must be the framework release the checkout actually pins (static version on z2ui5_if_app - the same place the prose points its readers at), or an allowlisted entry with a reason. The pin is named in nine places across four pages today; the day the port moves it, every one of them goes stale at once, and this makes that a failing check with file and line instead of a discovery. 1.143.0 (the upstream release where the bindings merged - history) and 1.113.0 (an OpenUI5 number) are allowlisted with their reasons; the pin itself is read from the checkout and deliberately never listed. docs/guide/samples.md had already rotted the same way: upstream gained sample 497 and the page still said 104 apps / 97 in the gallery. Regenerated (105/98), and gen-samples --check joins check:ci so the next new sample fails the workflow instead of aging the page - the generator existed, nothing ran its check in CI. Co-Authored-By: Claude Claude-Session: https://claude.ai/code/session_01BuzK8EC2CdQ5PJ6YCdfKJc --- docs/.verify-refs-ignore | 7 +++++++ docs/guide/samples.md | 3 ++- package.json | 2 +- scripts/verify-refs.mjs | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 44 insertions(+), 2 deletions(-) diff --git a/docs/.verify-refs-ignore b/docs/.verify-refs-ignore index c9d2a68..3a61d4d 100644 --- a/docs/.verify-refs-ignore +++ b/docs/.verify-refs-ignore @@ -28,3 +28,10 @@ ClassName # literal placeholder in the URL-parameter description z2ui5_cl_xml_view # upstream's retired view builder — replaced here by z2ui5_cl_ui5_view_builder z2ui5_cl_xml_view_cc # its custom-control decorator, retired with it z2ui5_cl_pop_bal # one of upstream's frozen built-in popups, superseded by the popups add-on + +# --- release numbers that are NOT the pinned framework release -------------- +# The pin itself (1.142.0 today) is read from the checkout and never listed +# here — listing it would keep the old number green after a pin move, which +# is the one defect the release check exists to catch. +1.143.0 # the upstream release where _bind/_bind_edit merged — history, stays true whatever the pin says +1.113.0 # the OpenUI5 release served locally — a UI5 number, not a framework release diff --git a/docs/guide/samples.md b/docs/guide/samples.md index 2dfdc59..3e4929f 100644 --- a/docs/guide/samples.md +++ b/docs/guide/samples.md @@ -3,7 +3,7 @@ # Sample Catalogue -The framework ships 104 sample apps in `core/srv/app/samples/` — the abap2UI5 demo collection, transpiled to JavaScript. 97 of them are listed in the built-in gallery, and this page is that gallery's own table: it is generated from `z2ui5_cl_smp_app_000`, the sample browser the framework itself renders, so it cannot drift from what the playground offers. +The framework ships 105 sample apps in `core/srv/app/samples/` — the abap2UI5 demo collection, transpiled to JavaScript. 98 of them are listed in the built-in gallery, and this page is that gallery's own table: it is generated from `z2ui5_cl_smp_app_000`, the sample browser the framework itself renders, so it cannot drift from what the playground offers. Every title links into the [browser playground](./playground) — no install, no server. The same apps run on your own CAP server under the same names: `?app_start=`, or `client.nav_app_call()` from an app of your own. @@ -29,6 +29,7 @@ Two markers are carried over from the upstream gallery: **(A)** marks a sample t | Sample | Class | Topics | |---|---|---| +| [A View Built From RTTI, No Field Named](https://cap2ui5.github.io/web-cap2UI5-build/?app_start=z2ui5_cl_smp_app_497) | [`z2ui5_cl_smp_app_497`](https://github.com/cap2UI5/cap2UI5/blob/main/core/srv/app/samples/z2ui5_cl_smp_app_497.js) | rtti generic view runtime columns get_components describe_by_data no field name itab structure column cell binding | | [Currency Amounts (sap.ui.model.type.Currency)](https://cap2ui5.github.io/web-cap2UI5-build/?app_start=z2ui5_cl_smp_app_067) | [`z2ui5_cl_smp_app_067`](https://github.com/cap2UI5/cap2UI5/blob/main/core/srv/app/samples/z2ui5_cl_smp_app_067.js) | amount decimals leading zeros number format | | [Dynamic Table Typed at Runtime (RTTI)](https://cap2ui5.github.io/web-cap2UI5-build/?app_start=z2ui5_cl_smp_app_061) | [`z2ui5_cl_smp_app_061`](https://github.com/cap2UI5/cap2UI5/blob/main/core/srv/app/samples/z2ui5_cl_smp_app_061.js) | generic data reference create data ddic dynamic itab | | [Expression Binding, Types and Composite Parts](https://cap2ui5.github.io/web-cap2UI5-build/?app_start=z2ui5_cl_smp_app_027) | [`z2ui5_cl_smp_app_027`](https://github.com/cap2UI5/cap2UI5/blob/main/core/srv/app/samples/z2ui5_cl_smp_app_027.js) | formatter parts conditional regexp visible enabled syntax | diff --git a/package.json b/package.json index 8702b21..b76a3e4 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "docs:preview": "vitepress preview docs", "verify": "node scripts/verify-refs.mjs", "check": "npm run verify && npm run docs:build", - "check:ci": "node scripts/verify-refs.mjs --require-checkout && npm run docs:build", + "check:ci": "node scripts/verify-refs.mjs --require-checkout && node scripts/gen-samples.mjs --check && npm run docs:build", "gen:samples": "node scripts/gen-samples.mjs" }, "devDependencies": { diff --git a/scripts/verify-refs.mjs b/scripts/verify-refs.mjs index 4e64bec..7931836 100644 --- a/scripts/verify-refs.mjs +++ b/scripts/verify-refs.mjs @@ -25,6 +25,9 @@ * 3. every z2ui5 class named in backticks exists somewhere in the app * 4. every `require("abap2UI5/…")` in a FENCED CODE BLOCK resolves through * the exports map of core/package.json, and onto a file that exists + * 5. every three-part release number (1.x.y) the docs mention is the + * framework release the checkout actually pins (`static version` on + * z2ui5_if_app), or an allowlisted historical/UI5 number * * Check 4 exists because the first three did not see the largest defect this * site ever had. Fenced blocks were skipped wholesale as "examples, not @@ -154,6 +157,27 @@ const add = (file, line, msg) => const PATH_ROOTS = ["core/", "srv/", "db/", "app/", "test/"]; const PATH_RE = /`([A-Za-z0-9_@./-]+\/[A-Za-z0-9_@./-]+)`/g; const APP_START_RE = /app_start=([a-z0-9_]+)/gi; +/* Check 5: release numbers. The site names the pinned framework release in + * NINE places across four pages ("Here, on 1.142.0", "cap2UI5 pins abap2UI5 + * **1.142.0**"), and the day the port moves its pin, every one of them goes + * stale at once - the exact defect class checks 1-4 exist for, one level up. + * The ground truth is the same place the prose itself points at: `static + * version` on z2ui5_if_app in the checkout. Every three-part 1.x.y the docs + * mention must be that version, or an entry in .verify-refs-ignore with a + * reason - which is where the HISTORICAL numbers live (1.143.0, the upstream + * release where the bindings merged, stays true whatever the pin says) and + * the UI5 ones (1.113.0 is an OpenUI5 release, not a framework release). + * Two-part floors like 1.71 are UI5 talk and deliberately not matched. */ +const RELEASE_RE = /\b1\.\d{2,3}\.\d+\b/g; +const VERSION_SOURCE = "core/srv/z2ui5/02/z2ui5_if_app.js"; +const PINNED_RELEASE = (() => { + try { + return fs.readFileSync(path.join(APP, VERSION_SOURCE), "utf8") + .match(/static version = `(\d+\.\d+\.\d+)`/)?.[1] ?? null; + } catch { + return null; + } +})(); // A backticked span that STARTS with a z2ui5 class name. It deliberately does // not require the closing backtick to follow the identifier: the docs write // `z2ui5_cl_xml_view.js`, `z2ui5_cl_util.register_app_dir(dir)` and @@ -202,6 +226,16 @@ for (const file of markdownFiles(DOCS)) { if (/^\s*```/.test(line)) { inFence = !inFence; return; } const n = i + 1; + // release numbers are claims wherever they stand, prose or example + if (PINNED_RELEASE) { + for (const m of line.matchAll(RELEASE_RE)) { + if (m[0] === PINNED_RELEASE || IGNORE.has(m[0])) continue; + add(file, n, `names release ${m[0]}, but the checkout pins ${PINNED_RELEASE} ` + + `(static version in ${VERSION_SOURCE}) - update the prose, or add the number ` + + `to .verify-refs-ignore with the reason it stays`); + } + } + if (inFence) { for (const m of line.matchAll(REQUIRE_RE)) { const sub = m[1] || ``; From 650ff01db73630b6ada85ecc5561dad76bd9b410 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 30 Aug 2026 22:05:07 +0000 Subject: [PATCH 2/3] chore: give every job the timeout ceiling the organisation's norm sets abap2UI5 sets timeout-minutes on all of its jobs and most repositories follow; this one had jobs without a ceiling, so a hung run could hold its slot (and in the publish workflows, the downstream pipeline) for GitHub's six-hour default. Values follow the job's real budget. Co-Authored-By: Claude Claude-Session: https://claude.ai/code/session_01BuzK8EC2CdQ5PJ6YCdfKJc --- .github/workflows/deploy.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 926dd2b..04fddef 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -17,6 +17,7 @@ concurrency: jobs: build: runs-on: ubuntu-latest + timeout-minutes: 15 steps: - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -61,6 +62,7 @@ jobs: deploy: needs: build runs-on: ubuntu-latest + timeout-minutes: 15 environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} From f5d334f703bd99379cc36f50cba2b5074b46053a Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 30 Aug 2026 22:10:10 +0000 Subject: [PATCH 3/3] docs: square the two crooked boxes in the architecture diagram Every box in the component diagram is 31 columns wide except the two handler headers (35 and 30), whose right edges did not meet their own bodies. Both are 31 now. Co-Authored-By: Claude Claude-Session: https://claude.ai/code/session_01BuzK8EC2CdQ5PJ6YCdfKJc --- docs/reference/architecture.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/reference/architecture.md b/docs/reference/architecture.md index b449443..5337900 100644 --- a/docs/reference/architecture.md +++ b/docs/reference/architecture.md @@ -25,12 +25,12 @@ This page shows in detail **how a roundtrip flows through the system** — from └────────────┬────────────────┘ │ ▼ -┌──── z2ui5_cl_ui5_http_handler ──┐ +┌─ z2ui5_cl_ui5_http_handler ─┐ │ unwrap req.data.value │ └────────────┬────────────────┘ │ ▼ -┌──── z2ui5_cl_ui5_handler ──┐ +┌──── z2ui5_cl_ui5_handler ───┐ │ 1. action.factory_main │── ▶ DB.loadApp(id) │ 2. validate │ │ 3. apply XX delta │