Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
28 changes: 28 additions & 0 deletions .changeset/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Changesets

Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
with multi-package repos, or single-package repos to help you version and publish your code. You can
find the full documentation for it [in our repository](https://github.com/changesets/changesets).

We have a quick list of common questions to get you started engaging with this project in
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md).

## How this repo uses Changesets

This monorepo replaced Lerna with [Changesets](https://github.com/changesets/changesets) for
versioning and releases. The flow is:

1. **In your PR**, run `yarn changeset` and answer the prompts (which packages, semver level,
summary). Commit the generated `.changeset/<random-name>.md` file alongside your code change.
2. When your PR is merged to `main`, the **Release** workflow opens (or updates) a single
`Version Packages` PR that aggregates all pending changesets — bumping versions and updating
each package's `CHANGELOG.md`.
3. **Merging the `Version Packages` PR** triggers the same workflow to publish the new versions
to npm.

Private packages (`test-packages/*`, `demos/*`) are skipped automatically by `changeset publish`.
Only the public packages under `packages/*` are released.

If a change does not warrant a release (docs-only, internal tooling, test refactors, etc.) just
don't add a changeset — the PR will surface a "no changeset detected" hint, which is fine to
acknowledge and merge.
Comment thread
petermuessig marked this conversation as resolved.
Outdated
11 changes: 11 additions & 0 deletions .changeset/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
"changelog": ["@changesets/changelog-github", { "repo": "UI5/typescript" }],
"commit": false,
"fixed": [],
"linked": [],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": ["@ui5/openui5-snapshot-test", "@ui5/typed-json-model"]
}
2 changes: 2 additions & 0 deletions .changeset/fresh-cobras-send.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
51 changes: 51 additions & 0 deletions .github/workflows/changeset.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: Changeset

# Verifies that every PR carries a changeset (or an explicit empty one).
# Runs only on pull_request — `push` to main carries already-merged
# changesets that the Release workflow then consumes.

on:
pull_request:
branches: [main]
workflow_dispatch:
inputs:
pr_number:
description: "PR number to test (for fork PRs)"
required: true
type: string

permissions:
contents: read

jobs:
changeset:
name: Changeset present
runs-on: ubuntu-latest
# Skip on the auto-generated "Version Packages" PR (it consumes all changesets).
if: github.head_ref != 'changeset-release/main'
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
ref: ${{ inputs.pr_number && format('refs/pull/{0}/head', inputs.pr_number) || '' }}
# Full history so `changeset status --since=origin/main` can diff.
fetch-depth: 0

- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 24.x

- name: Install dependencies
run: yarn --frozen-lockfile

# Fails the PR if no changeset describes the change.
# Add one with `yarn changeset` (or `yarn changeset:empty` for PRs
# that don't need a release entry) and commit it.
# We check `.changesets` (not `.releases`) so that empty changesets
# — which have 0 package bumps but still document the PR — pass.
- name: Verify changeset is present
run: |
yarn changeset status --since=origin/main --output=/tmp/cs.json
if [ "$(jq '.changesets | length' /tmp/cs.json)" -eq 0 ]; then
echo "::error::No changeset found on this PR. Run 'yarn changeset' (or 'yarn changeset:empty' for PRs that don't need a release entry) and commit the file."
exit 1
fi
61 changes: 45 additions & 16 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,40 +1,69 @@
name: Release

on:
push:
branches: [main]
workflow_dispatch:
workflow_dispatch: # Manual trigger

env:
HUSKY_SKIP: true

# Skip when the head commit is the workflow's own version-bump commit, to avoid loops.
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false

permissions:
contents: read
id-token: write
contents: write # create the "Version Packages" PR and tags
pull-requests: write # open/update the version PR
id-token: write # REQUIRED for npm OIDC trusted publishing

jobs:
release:
runs-on: ubuntu-latest
# Only gate push events by commit message; allow workflow_dispatch always
if: >
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'push' && contains(github.event.head_commit.message, 'chore(release): publish'))
if: "!contains(github.event.head_commit.message, 'skip ci')"
Comment thread
petermuessig marked this conversation as resolved.
Outdated
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- name: Checkout
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
fetch-depth: 0

- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
- name: Setup node
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 24.15.0
registry-url: https://registry.npmjs.org

- name: Install dependencies
run: yarn --frozen-lockfile

- name: Build
run: yarn build

# Choose publish command based on the event type
- name: Publish to NPM (push)
if: github.event_name == 'push'
run: npm run release:publish
- name: Detect token usage (optional safety)
run: |
if npm whoami 2>/dev/null; then
echo "::warning::Token-based auth active (expected only when OIDC isn't configured)"
else
echo "OIDC auth active"
fi
Comment thread
petermuessig marked this conversation as resolved.
Outdated

- name: Publish to NPM (manual)
if: github.event_name == 'workflow_dispatch'
run: npm run release:publish-manual
- name: Configure NPM bootstrap token (non OIDC flow)
env:
NPM_BOOTSTRAP_TOKEN: ${{ secrets.NPM_BOOTSTRAP_TOKEN }}
if: ${{ env.NPM_BOOTSTRAP_TOKEN != '' }}
run: |
echo "//registry.npmjs.org/:_authToken=${NPM_BOOTSTRAP_TOKEN}" >> ~/.npmrc

- name: Create Release Pull Request or Publish
id: changesets
uses: changesets/action@63a615b9cd06ba9a3e6d13796c7fbcb080a60a0b # v1.8.0
with:
version: yarn run version-packages
publish: yarn run release-publish
commit: "chore(release): publish"
title: "chore(release): publish"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_BOOTSTRAP_TOKEN }}
NPM_CONFIG_PROVENANCE: "true"
153 changes: 138 additions & 15 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Contribution Guide

This is the common top-level contribution guide for this monorepo.
A sub-package **may** have an additional CONTRIBUTING.md file if needed.
This is the common top-level contribution guide for the [UI5/typescript](https://github.com/UI5/typescript) monorepo. A sub-package **may** have an additional CONTRIBUTING.md file if needed.

Thanks for your interest in contributing! All forms of contribution are welcome — bug reports, fixes, documentation, new features, and reviewing other contributors' PRs.

## Legal

Expand All @@ -17,12 +18,21 @@ As artificial intelligence evolves, AI-generated code is becoming valuable for m

Please see our [guideline for AI-generated code contributions to SAP Open Source Software Projects](https://github.com/UI5/.github/blob/main/CONTRIBUTING_USING_GENAI.md) for these requirements.

## Reporting Issues

Open a [GitHub issue](https://github.com/UI5/typescript/issues) on the topic that fits your case best:

- For `@ui5/dts-generator` — issues with the **generation logic** itself. Issues in the generated UI5 type definitions usually originate from JSDoc comments in [OpenUI5](https://github.com/UI5/openui5/issues) / SAPUI5 — please open the ticket there in that case.
- For `@ui5/ts-interface-generator` — anything related to control-interface generation for TypeScript controls.

A reproducible example (a minimal repo or a [TypeScript Hello World](https://github.com/SAP-samples/ui5-typescript-helloworld) fork) is the single biggest thing that helps get an issue triaged quickly.

## Development Environment

### pre-requisites
### Pre-requisites

- [Yarn](https://yarnpkg.com/lang/en/docs/install/) >= 1.4.2
- A current [Long-Term Support version](https://nodejs.org/en/about/releases/) of node.js
- A current [Long-Term Support version](https://nodejs.org/en/about/releases/) of Node.js (>= 22; CI tests on 22.x and 24.x).
- [Yarn 1.x](https://classic.yarnpkg.com/lang/en/docs/install/) — this repo uses yarn classic with workspaces.
- (optional) [commitizen](https://github.com/commitizen/cz-cli#installing-the-command-line-tool) for managing commit messages.

### Initial Setup
Expand All @@ -32,6 +42,22 @@ The initial setup is trivial:
- clone this repo
- `yarn`

The repo's `.yarnrc` enforces `--frozen-lockfile`, exact-version saves (`save-prefix ""`), and a pinned registry — that's intentional supply-chain hardening, please don't loosen it without discussion.

### Repository Layout

```text
packages/ # public, published to npm
dts-generator/ # @ui5/dts-generator
ts-interface-generator/ # @ui5/ts-interface-generator
test-packages/ # private, never published
openui5-snapshot-test/
typed-json-model/
demos/ # private, never published
```

Only the two `packages/*` are released to npm. Everything under `test-packages/*` and `demos/*` is `"private": true` and is automatically ignored by Changesets.

### Commit Messages format

This project enforces the [conventional-commits][conventional_commits] commit message formats.
Expand All @@ -48,16 +74,46 @@ It is recommended to use `git cz` to construct valid conventional commit message
[commit_types]: https://github.com/commitizen/conventional-commit-types/blob/master/index.json
[conventional_commits]: https://www.conventionalcommits.org/en/v1.0.0/

Use the package directory name as the **scope** when the change is package-specific:

```text
feat(dts-generator): support union types in api.json
fix(ts-interface-generator): handle aggregations with cardinality 0..1
chore: bump root devDependencies
```

The scope is also what `yarn changeset:auto` uses to figure out which packages to bump (see [Releases](#release-process) below). Breaking changes are signalled with a `!` after the type/scope **or** a `BREAKING CHANGE:` footer in the body — either flips the bump to `major`.

### Formatting

[Prettier](https://prettier.io/) is used to ensure consistent code formatting in this repository.
This is normally transparent as it automatically activated in a pre-commit hook using [lint-staged](https://github.com/okonet/lint-staged).
However, this does mean that dev flows that do not use a full dev env (e.g editing directly on github) may result in voter failures due to formatting errors.

To run it manually:

```sh
yarn format:fix # rewrite files
yarn format:validate # check, no rewrite (this is what CI runs)
```

### Compiling

See the respective sub-packages for instructions (if needed at all).

To build both publishable packages from the root:

```sh
yarn build
```

Per-package work uses yarn's workspace shorthand:

```sh
yarn workspace @ui5/dts-generator build
yarn workspace @ui5/ts-interface-generator test
```

### Testing

[Mocha][mocha] and [Chai][chai] are used for unit-testing.
Expand All @@ -68,22 +124,89 @@ See the respective sub-packages for instructions (if needed at all).
- To run the tests, execute `yarn test` in a specific sub-package.
- Note that not all sub-packages contain tests.

When adding a feature or fixing a bug, **please add or extend a test**. PRs without tests will get a friendly nudge.

### Full Build

To run the full **C**ontinuous **I**ntegration build run `yarn ci` in either the top-level package or a specific subpackage.

### Release Life-Cycle
## Pull Requests

1. Fork the repo (or branch from `main` if you have write access).
2. Create a topic branch with a descriptive name (`feat/union-types`, `fix/aggregation-cardinality`).
3. Make your change, with tests, in commits that each follow the conventional-commits format.
4. Add a changeset (see [Release Process](#release-process) below) — required for any change that should produce a new release.
5. Push and open a PR against `main`.
6. The CI workflows ([`Continuous Integration`](.github/workflows/ci.yml), [`Lint Commit Messages`](.github/workflows/commitlint.yml), [`CodeQL`](.github/workflows/codeql-analysis.yml)) must all pass.

Reviews aim for two pairs of eyes on substantive changes; small fixes and chore commits may be merged with a single approval.

## Release Life-Cycle

This monorepo uses [Changesets](https://github.com/changesets/changesets) for versioning and publishing. Each public package under `packages/*` keeps its own version (independent versioning) and its own `CHANGELOG.md`. Private packages under `test-packages/*` and `demos/*` are never released.

## Release Process

The release flow is fully automated through [GitHub Actions](.github/workflows/release.yml) — there's no local `lerna`, and no contributor needs npm-publish or push-to-`main` rights.

### For contributors — adding a changeset

When your PR changes one or more public packages, add a changeset alongside your code change. Pick whichever of the three commands fits best:

| Command | When to use |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `yarn changeset:auto` | **Recommended for most PRs.** Walks the conventional-commit history on your branch and writes one `.changeset/auto-<sha>.md` per qualifying commit (packages from the commit `scope`, bump from the `type`, summary from the `subject`). Idempotent — safe to re-run. Already-covered commits are skipped, so any hand-written changeset always wins. |
| `yarn changeset` | Interactive — pick packages, bump type, and write a summary by hand. Use when the auto-derived bump or summary is wrong (e.g. a `chore:` commit that secretly contains a `feat:`). The next `:auto` run will then skip the commit because it's covered. |
| `yarn changeset:empty` | Docs- or tooling-only PRs that touch no public package. Writes an empty `.changeset/*.md` so the "no changeset detected" hint goes away without producing any CHANGELOG entry. |

Whichever you pick, **commit the resulting `.changeset/*.md` file alongside your code change**.

How `yarn changeset:auto` chooses the bump:

| Conventional-commit `type` (or marker) | Bump |
| ---------------------------------------------------------- | ------- |
| `feat:` | `minor` |
| `fix:`, `perf:`, `refactor:`, `chore:`, `build:`, `style:` | `patch` |
| `docs(<scope>):` (only when scoped to a package) | `patch` |
| `<type>!:` or a `BREAKING CHANGE:` footer | `major` |
| `ci:`, anything scoped `release` | skipped |

Commits whose only file changes are under `packages/<pkg>/test/` are also skipped — test-only changes don't ship in the published tarball.

If a change does not warrant a release at all (CI tweaks, internal tooling, etc.) just don't add a changeset — the PR can still be merged.
Comment thread
petermuessig marked this conversation as resolved.
Outdated

### For maintainers — cutting a release

The release itself happens entirely on GitHub. You don't need npm credentials or a clean local checkout.

1. When a PR with at least one changeset is merged into `main`, the [`Release`](.github/workflows/release.yml) workflow opens (or updates) a single **`Version Packages`** PR. That PR aggregates every pending changeset, bumps the affected `package.json` versions, regenerates each package's `CHANGELOG.md`, and refreshes `yarn.lock`.
2. Review and merge that **`Version Packages`** PR when you're ready to cut a release.
3. Merging it triggers the same workflow again, this time on the `publish` path: `changeset publish` runs, the new versions go to npm (with [npm provenance](https://docs.npmjs.com/generating-provenance-statements)), and matching git tags are pushed.
4. Spot-check the newly published artifacts on [npmjs.com](https://www.npmjs.com/package/@ui5/dts-generator).

You can also trigger the workflow manually via **Actions → Release → Run workflow** — useful if a previous run failed mid-publish. Re-running publishes whatever versions are currently on `main` that haven't been released yet (`changeset publish` is idempotent — it skips versions already on the registry).

#### npm authentication

The workflow prefers npm OIDC trusted publishing (no token required). If OIDC isn't configured for a package, it falls back to `secrets.NPM_BOOTSTRAP_TOKEN`. The "Detect token usage" step in the workflow prints which path is active.

#### Pre-releases / snapshots

Not currently configured. If we need them, [`changeset pre enter <tag>`](https://github.com/changesets/changesets/blob/main/docs/prereleases.md) is the standard mechanism — open an issue first to discuss the tag scheme.

This monorepo uses Lerna's [Independent][lerna-mode] mode which allows subpackages to have different versions.
## Upgrading the version of the dependencies

[lerna-mode]: https://github.com/lerna/lerna#independent-mode
To upgrade the version of the dependencies, [`npm-check-updates`](https://github.com/raineorshine/npm-check-updates) is wired up at the root:

### Release Process
```sh
yarn ncu # list outdated packages across the workspace
yarn ncu-u # apply the bumps to every package.json
yarn install # refresh yarn.lock
yarn ci # sanity-check before opening the PR
```

Performing a release requires push permissions to the repository.
## Where to ask questions

- Ensure you are on the default branch and synced with origin.
- `yarn run release:version`
- Follow the lerna CLI instructions.
- Track the newly pushed commit with the message `chore(release): publish` in the build system for a successful completion (the `Release` GitHub action must be triggered!).
- Inspect the newly published artifacts on npmjs.com.
- For UI5 + TypeScript usage questions, the [ui5.github.io/typescript](https://ui5.github.io/typescript) docs are the best starting point.
- For sample applications, see the [TypeScript Hello World app](https://github.com/SAP-samples/ui5-typescript-helloworld) and the [TypeScript branch of the UI5 CAP Event App](https://github.com/SAP-samples/ui5-cap-event-app/tree/typescript).
- For tooling-specific bugs, please open an [issue](https://github.com/UI5/typescript/issues).
Loading
Loading