Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/workflows/check-page-titles.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: check-page-titles

# The page a sample opens with says it is abap2UI5: its main page title starts
# with `abap2UI5 - `. Nothing else fails when a title drifts - three had, before
# this gate existed - so a renamed or newly written sample would carry its own
# private naming scheme for as long as nobody happened to look.
#
# Plain node, no dependencies, so it stays a few seconds.

on:
pull_request:
push:
branches: [main]

permissions:
contents: read

concurrency:
group: check-page-titles-${{ github.ref }}
cancel-in-progress: true

jobs:
check-page-titles:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '22'
- run: node scripts/check-page-titles.mjs
35 changes: 35 additions & 0 deletions .github/workflows/check-released-api.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: check-released-api

# Does a package whose "Runs on" says Cloud name an API that ABAP Cloud does
# not release? The Cloud lint of create-package-branches judges the LANGUAGE
# version only - an unknown non-Z class sits outside errorNamespace and stays
# silent there. This run lints every cloud-capable package with errorNamespace
# matching every name, so whatever the steampunk-2305-api dependency (the list
# of released objects) does not carry is an error. The documented exceptions -
# src/10/01 and src/10/03 - and any open finding are listed in the script and
# printed on every run. See scripts/check-released-api.mjs.

on:
pull_request:
push:
branches: [main]

permissions:
contents: read

concurrency:
group: check-released-api-${{ github.ref }}
cancel-in-progress: true

jobs:
check-released-api:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: '22'
cache: 'npm'
- run: npm ci
- run: node scripts/check-released-api.mjs
26 changes: 25 additions & 1 deletion .github/workflows/create-package-branches.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ name: create-package-branches
# Every branch is verified before it is pushed: abaplint at the release that
# package declares, which is what keeps the "Runs on" column of the README
# honest and what catches a package that has quietly grown a dependency on one
# of the other nine. On a pull request the whole thing runs except the push,
# of the other nine - and, for a package whose "Runs on" says Cloud, abaplint
# in the ABAP Cloud language version as well. On a pull request the whole thing runs except the push,
# so a change that would break a branch fails while it can still be fixed.

on:
Expand Down Expand Up @@ -71,6 +72,29 @@ jobs:

# the package alone, at the release it says it needs
- run: npx abaplint ./abaplint.jsonc

# ...and, where its "Runs on" says Cloud, once more in the ABAP Cloud
# language version. A release check reads statements ABAP Cloud refuses
# (a read of sy-datum, a statement outside the Cloud language scope) as
# fine - this is the run that found the sy-datum reads in src/03 and
# src/04. It does NOT judge API release state: a non-Z class absent from
# the steampunk dependency is outside errorNamespace and stays silent -
# check-released-api.yaml is the run that does. "Cloud-capable" is decided
# exactly as scripts/lib/read-packages.mjs decides it for catalogue.json:
# /cloud/i on runsOn. The config is a throwaway copy; the branch keeps the
# release config.
- name: abaplint in ABAP Cloud language version (cloud-capable packages)
run: |
if jq -e --arg b '${{ matrix.branch }}' \
'.[] | select(.branch == $b) | .runsOn | test("cloud"; "i")' \
.github/packages.json > /dev/null; then
sed -E 's/"version": "[^"]*"/"version": "Cloud"/' abaplint.jsonc > abaplint-cloud.jsonc
npx abaplint ./abaplint-cloud.jsonc
rm abaplint-cloud.jsonc
else
echo '${{ matrix.branch }} runs on Standard only - no Cloud run'
fi

- run: node scripts/check-overview.mjs

- name: Commit and push
Expand Down
33 changes: 29 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,22 +87,40 @@ What that costs you when you edit:
BY NAME and resolves them at runtime for exactly that reason — and it carries
its own url helper rather than calling one, because `src/00` travels only
with the two packages that name it in `shared`. `check:overview` fails on a
static `Z2UI5_CL_SMPS_*` reference that would not survive every branch.
static `Z2UI5_*_SMPS_*` reference — a class, an interface, a table, a CDS
entity — that would not survive every branch.
- Each branch is linted at **its own** release before it is pushed, which is
what makes the "Runs on" column in the README true rather than aspirational.
A branch whose "Runs on" says Cloud is linted a second time at
`"version": "Cloud"` — the release run reads a `sy-datum` as fine, the Cloud
run does not. It does not judge API release state — an unknown non-Z class is
outside `errorNamespace` either way. That is `npm run check:released-api`
(`scripts/check-released-api.mjs`, its own workflow): every cloud-capable
package once more at Cloud with `errorNamespace` matching every name, so
whatever the `steampunk-2305-api` dependency — the released objects — does
not carry is an error. Its exception list names `src/10/01` and `src/10/03`
(Standard-only and SDK-only by design, see `src/10/README.md`) and one open
finding in `src/05`; both kinds are printed on every run.
- `SAMPLES.md` and `catalogue.json` are **regenerated** on each branch, by the
same generators over the reduced tree, so they list that package alone and
link to nothing the branch does not carry. The generators scan the tree they
run in; that is the only branch-specific behaviour, and on `main` it drops
nothing.

## 4. Build & verify

```sh
npm ci
npm run check # abaplint + abap2UI5-linter + overview + keywords + abapdoc + SAMPLES.md + catalogue.json + app-rules
npm run check # pin + abaplint + abap2UI5-linter + overview + keywords + titles + abapdoc + SAMPLES.md
# + catalogue.json + app-rules + atc + prose + catalogue-derived.json + released-api
```

Individually: `npm run lint` (abaplint), `npm run check:abap2ui5` (the app
class and the view it builds, including a headless render of every view),
`npm run check:overview` (the five consistency directions between the overview
`npm run check:overview` (the six consistency directions between the overview
app, the tree, `packages.json` and the two README tables — the package table
and the *Which package do I need?* decision table).
and the *Which package do I need?* decision table — plus the branch names the
overview tells a reader to pull when a package is not on the system).

`npm run fmt:chains` applies the house chain layout. It rewrites whitespace
between chain segments only — but it needs the ABAP to be *balanced* to know
Expand Down Expand Up @@ -215,6 +233,13 @@ gone.
"validations run at COMMIT" would otherwise surprise a reader.
- The class description in `.clas.xml` (`<DESCRIPT>`) is what the overview app
shows. Keep it in Title Case and specific.
- **The main page title starts with `abap2UI5 - `** — the first `Page` after
each `Shell`, as a literal: `abap2UI5 - Smart Controls - SmartTable`. What
follows is the sample's own name and is not prescribed (the RAP steps number
themselves, the session samples say `Sample: …`). A page with `showHeader`
false has no title and is exempt — the launchpad samples leave it to the
shell. Checked by `npm run check:titles` (`scripts/check-page-titles.mjs`,
its own workflow): three titles had drifted before it existed.
- **Every app carries three lines about itself, and they are the only place
each fact lives** — checked by `npm run check:keywords`:

Expand Down
13 changes: 8 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,9 @@ repository you are in. Always name a sample by its class.
You do not have to look a number up. `?app_start=z2ui5_cl_smps_app_000` lists
**every sample of this repository**, one collapsible section per package, and
starts each one in a new browser tab — so the overview stays where it is and
several samples can run side by side. Its header button fills the demo data of
both RAP packages.
several samples can run side by side. Its header button, *Regenerate Demo Data*,
deletes every travel of both RAP packages — yours included — and creates the demo
set again.

It is also the honest answer to *what does my system actually support*: the
overview looks every sample up at runtime instead of referencing it statically, so
Expand Down Expand Up @@ -267,7 +268,7 @@ check:overview`. `npm run fmt:chains` applies the house chain layout.

Every `check-*` workflow below is a step of `npm run check`, and every step
has its workflow — which is what makes a green run here mean a green run
there. The last two rows are build-and-publish jobs, not checks, and run only
there. The last row is a build-and-publish job, not a check, and runs only
in CI. The node checks carry no dependencies, so they take seconds.

| Workflow | What it does |
Expand All @@ -276,13 +277,15 @@ in CI. The node checks carry no dependencies, so they take seconds.
| `check-abap2UI5` | [`abap2ui5lint`](https://github.com/abap2UI5/linter) — the app class and the view it produces, together; also writes the two badges above |
| `check-overview` | the hand-kept indexes: every sample is listed in the overview app, the package table matches `.github/packages.json`, and the *Which package do I need?* table routes to every package |
| `check-samples-md` | [`SAMPLES.md`](SAMPLES.md) still is what the generator would write — and every app that exists is in an entry |
| `check-catalogue` | [`catalogue.json`](catalogue.json) still is what the generator would write — the same catalogue as data, committed for tooling that fetches one file instead of scanning the tree |
| `check-keywords` | every app carries `@keywords` and `@summary`, and the overview's detail line still is the class's `@summary` |
| `check-page-titles` | every sample's main page title starts with `abap2UI5 - ` |
| `check-abapdoc` | every `"!` block documents the declaration below it, rather than attaching to nothing |
| `check-atc` | the extended-check (SLIN/ATC) findings a script can decide — a `SELECT` without `WHERE` that does not say so, `sy-subrc` after a dynamic `ASSIGN`, a text symbol passed as a `string` |
| `check-app-rules` | the shared abaplint rule block still matches its source in [abap2UI5](https://github.com/abap2UI5/abap2UI5) |
| `check-prose-names` | every class name written in prose exists — including the sibling repositories' |
| `check-framework-pin` | the abaplint config pins abap2UI5 to a release tag, never to whatever is on `main` |
| `check-catalogue` | `catalogue.json` and `catalogue-derived.json` are in sync with the tree — and with them every package has a README row that parses, every app sits in a package, and none is missing its `@summary` or `@keywords` |
| `check-released-api` | every package whose *Runs on* says Cloud, linted at Cloud against the released objects — an API ABAP Cloud does not release is an error |
| `check-catalogue` | [`catalogue.json`](catalogue.json) and `catalogue-derived.json` still are what the generators would write — the same catalogue as data, committed for tooling that fetches one file instead of scanning the tree — and with them every package has a README row that parses, every app sits in a package, and none is missing its `@summary` or `@keywords` |
| `create-package-branches` | rebuilds the ten per-package branches, each verified with abaplint at its own release before it is pushed |

`check-overview` exists because the overview app names its samples as strings and
Expand Down
4 changes: 2 additions & 2 deletions SAMPLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ type who does not know it exists. `Ctrl+F` on this page uses them.

| Sample | Class |
|---|---|
| **MIME** — Audio and Play Sound<br>a success and an error tone, addressed by their ICF path<br><sub>mime audio sound play_audio wav follow_up_action</sub> | [`Z2UI5_CL_SMPS_APP_487`](src/08/z2ui5_cl_smps_app_487.clas.abap) |
| **MIME** — Audio and Play Sound<br>a success and an error tone, addressed by their ICF path<br><sub>mime audio sound play_audio mp3 follow_up_action</sub> | [`Z2UI5_CL_SMPS_APP_487`](src/08/z2ui5_cl_smps_app_487.clas.abap) |

### Launchpad — `src/09`

Expand Down Expand Up @@ -136,7 +136,7 @@ able to say they exist.
| [`Z2UI5_CL_SMPS_DATA_TRD`](src/04/01/z2ui5_cl_smps_data_trd.clas.abap) | abap2UI5 EML sample - demo data (draft) |
| [`Z2UI5_CL_SMPS_BP_TCK`](src/05/01/z2ui5_cl_smps_bp_tck.clas.abap) | RAP Events Demo - Ticket Behavior Pool |
| [`Z2UI5_CL_SMPS_EVT_TCK`](src/05/01/z2ui5_cl_smps_evt_tck.clas.abap) | RAP Events Demo - Local Event Consumer (writes log) |
| [`Z2UI5_CL_SMPS_APP_489_WS`](src/07/z2ui5_cl_smps_app_489_ws.clas.abap) | Generated APC WebSocket protocol impementation class |
| [`Z2UI5_CL_SMPS_APP_489_WS`](src/07/z2ui5_cl_smps_app_489_ws.clas.abap) | Generated APC WebSocket protocol implementation class |
| [`Z2UI5_CL_SMPS_LLM_CLAUDE`](src/10/z2ui5_cl_smps_llm_claude.clas.abap) | LLM - Anthropic Messages API |
| [`Z2UI5_CL_SMPS_LLM_FACTORY`](src/10/z2ui5_cl_smps_llm_factory.clas.abap) | LLM - Configuration and Provider Factory |
| [`Z2UI5_CL_SMPS_LLM_JSON`](src/10/z2ui5_cl_smps_llm_json.clas.abap) | LLM - JSON Written and Read by Hand |
Expand Down
16 changes: 8 additions & 8 deletions catalogue-derived.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,18 +69,18 @@
"noChain": 0
},
"samples": [
{"class":"Z2UI5_CL_SMPS_APP_000","minUi5":"1.71","needs":[],"controls":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17],"controlCount":238},
{"class":"Z2UI5_CL_SMPS_APP_000","minUi5":"1.71","needs":[],"controls":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17],"controlCount":248},
{"class":"Z2UI5_CL_SMPS_APP_001","minUi5":"1.71","needs":[],"controls":[1,22,37,7,10,17,38],"controlCount":21},
{"class":"Z2UI5_CL_SMPS_APP_002","minUi5":"1.71","needs":[],"controls":[1,39,22,37,7,10,17,38],"controlCount":22},
{"class":"Z2UI5_CL_SMPS_APP_003","minUi5":"1.71","needs":[],"controls":[1,2,3,22,7,10,11,12,13,18,17],"controlCount":19},
{"class":"Z2UI5_CL_SMPS_APP_004","minUi5":"1.71","needs":[],"controls":[1,2,3,7,10,11,12,13,18,17],"controlCount":19},
{"class":"Z2UI5_CL_SMPS_APP_005","minUi5":"1.71","needs":[],"controls":[1,2,3,39,40,31,22,37,6,7,10,11,12,13,18,41,15,17,38],"controlCount":58},
{"class":"Z2UI5_CL_SMPS_APP_006","minUi5":"1.71","needs":[],"controls":[1,2,3,6,7,10,11,12,13,18,41,17],"controlCount":25},
{"class":"Z2UI5_CL_SMPS_APP_007","minUi5":"1.71","needs":[],"controls":[1,2,3,7,10,11,12,13,18,17],"controlCount":19},
{"class":"Z2UI5_CL_SMPS_APP_008","minUi5":"1.71","needs":[],"controls":[1,2,3,22,5,7,10,11,12,13,18,17],"controlCount":17},
{"class":"Z2UI5_CL_SMPS_APP_009","minUi5":"1.71","needs":[],"controls":[1,2,3,31,5,7,10,11,12,13,18,17],"controlCount":19},
{"class":"Z2UI5_CL_SMPS_APP_007","minUi5":"1.71","needs":[],"controls":[1,2,3,7,10,11,12,13,18,41,17],"controlCount":21},
{"class":"Z2UI5_CL_SMPS_APP_008","minUi5":"1.71","needs":[],"controls":[1,2,3,22,5,7,10,11,12,13,18,41,17],"controlCount":19},
{"class":"Z2UI5_CL_SMPS_APP_009","minUi5":"1.71","needs":[],"controls":[1,2,3,31,5,7,10,11,12,13,18,41,17],"controlCount":21},
{"class":"Z2UI5_CL_SMPS_APP_010","minUi5":"1.71","needs":[],"controls":[1,2,3,39,40,22,37,6,7,10,11,12,13,18,41,15,17,38],"controlCount":55},
{"class":"Z2UI5_CL_SMPS_APP_011","minUi5":"1.71","needs":[],"controls":[1,2,3,22,37,7,10,11,12,13,18,41,17,38],"controlCount":29},
{"class":"Z2UI5_CL_SMPS_APP_011","minUi5":"1.71","needs":[],"controls":[1,2,3,22,37,5,7,10,11,12,13,18,41,17,38],"controlCount":33},
{"class":"Z2UI5_CL_SMPS_APP_012","minUi5":"1.71","needs":[],"controls":[1,2,3,7,10,11,12,13,18,41,17],"controlCount":18},
{"class":"Z2UI5_CL_SMPS_APP_013","minUi5":"1.71","needs":[],"controls":[1,50,22,37,5,23,7,51,10,41,52,17,38],"controlCount":28},
{"class":"Z2UI5_CL_SMPS_APP_014","minUi5":"1.71","needs":[],"controls":[1,43,44,22,45,5,7,10,14,17],"controlCount":11},
Expand All @@ -98,11 +98,11 @@
{"class":"Z2UI5_CL_SMPS_APP_482","minUi5":"1.71","needs":[],"controls":[1,22,37,5,7,10,17,38],"controlCount":10},
{"class":"Z2UI5_CL_SMPS_APP_483","minUi5":"1.71","needs":[],"controls":[1,22,37,5,7,10,17,38],"controlCount":11},
{"class":"Z2UI5_CL_SMPS_APP_484","minUi5":"1.71","needs":[],"controls":[1,22,37,5,7,10,17,38],"controlCount":13},
{"class":"Z2UI5_CL_SMPS_APP_485","minUi5":"1.71","needs":[],"controls":[1,31,37,5,7,10,14,42,17],"controlCount":17},
{"class":"Z2UI5_CL_SMPS_APP_485","minUi5":"1.71","needs":[],"controls":[1,31,37,5,7,10,14,42,17],"controlCount":18},
{"class":"Z2UI5_CL_SMPS_APP_486","minUi5":"1.71","needs":[],"controls":[1,31,37,7,10,14,42,17],"controlCount":11},
{"class":"Z2UI5_CL_SMPS_APP_487","minUi5":"1.71","needs":[],"controls":[1,22,5,7,12,14,17],"controlCount":8},
{"class":"Z2UI5_CL_SMPS_APP_487","minUi5":"1.71","needs":[],"controls":[1,22,5,7,10,12,14,17],"controlCount":9},
{"class":"Z2UI5_CL_SMPS_APP_489","minUi5":"1.71","needs":[],"controls":[1,43,44,22,37,45,5,23,7,46,47,10,48,41,42,15,17,38,49],"controlCount":21},
{"class":"Z2UI5_CL_SMPS_APP_490","minUi5":"1.71","needs":[],"controls":[1,31,22,7,10,13,14,17,38],"controlCount":13},
{"class":"Z2UI5_CL_SMPS_APP_490","minUi5":"1.71","needs":[],"controls":[1,31,22,5,7,10,13,14,17,38],"controlCount":14},
{"class":"Z2UI5_CL_SMPS_APP_493","minUi5":"1.71","needs":[],"controls":[2,3,31,22,5,7,10,11,12,35,36,32,17],"controlCount":27}
]
}
2 changes: 1 addition & 1 deletion catalogue.json
Original file line number Diff line number Diff line change
Expand Up @@ -737,7 +737,7 @@
"audio",
"sound",
"play_audio",
"wav",
"mp3",
"follow_up_action"
],
"runsOn": "Standard only, ≥ 7.50",
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading