Skip to content

feat(project): Offer configPath property to workspace configs (workspace/1.1) - #1643

Open
maxreichmann wants to merge 36 commits into
mainfrom
offer-configPath-to-workspace-yaml
Open

maxreichmann wants to merge 36 commits into
mainfrom
offer-configPath-to-workspace-yaml

Conversation

@maxreichmann

@maxreichmann maxreichmann commented Oct 8, 2026 •

Copy link
Copy Markdown
Member

This offers a configPath property to workspace dependency resolution entries as follows:

specVersion: workspace/1.1                      # new specVersion
metadata:
    name: default
dependencyManagement:
    resolutions:
        - path: ../test.library
          configPath: custom-config.yaml        # new customizable paths

(Introducing new specVersion workspace/1.1)


Other sub features:

  • Improve error handling when path is absolute
  • Improve error handling when multiple resolutions for the same dependency exist (by path property)
  • Forbid absolute paths for configPath
  • Allow relative paths for configPath (for path it's already allowed)
  • Fix pre-existing trailing-slash bug

The workspace resolution logic is now explicitly implemented as "Most specific wins" (the resolution entry with the deepest path gets precedence). Entries are sequentially processed while keeping file reads, glob expansion, and traversal within each entry async.

Closes: #1369
JIRA: CPOUI5FOUNDATION-1233

@maxreichmann maxreichmann changed the title Offer configPath property to workspace yamls (workspace/1.1) feat(project): Offer configPath property to workspace yamls (workspace/1.1) Oct 8, 2026
@maxreichmann maxreichmann changed the title feat(project): Offer configPath property to workspace yamls (workspace/1.1) feat(project): Offer configPath property to workspace configs (workspace/1.1) Oct 8, 2026
@maxreichmann
maxreichmann marked this pull request as draft October 8, 2026 14:21
@maxreichmann

Copy link
Copy Markdown
Member Author

Kindly asking @KlattG to review the documentation part of this PR already (Workspace.md).

(I didn't add this feature to the usual migrate-v5.md because we planned to downport to v4 too)

Comment thread packages/project/lib/graph/Workspace.js Resolved
KlattG
KlattG previously approved these changes Oct 12, 2026

@KlattG KlattG left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@maxreichmann
maxreichmann force-pushed the offer-configPath-to-workspace-yaml branch 8 times, most recently from 398ace8 to 5c857ed Compare October 12, 2026 15:42
@maxreichmann
maxreichmann marked this pull request as ready for review October 12, 2026 16:07
@maxreichmann
maxreichmann requested a review from a team October 12, 2026 16:07

@d3xter666 d3xter666 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, check the log when you try to build with this new validation/schema:

strict mode: missing type "object" for keyword "properties" at "ui5-workspace.json#/then/properties/dependencyManagement" (strictTypes)
strict mode: missing type "array" for keyword "items" at "ui5-workspace.json#/then/properties/dependencyManagement/properties/resolutions" (strictTypes)
strict mode: missing type "object" for keyword "required" at "ui5-workspace.json#/then/properties/dependencyManagement/properties/resolutions/items/then/not" (strictTypes)

This is from AJV's strict mode

@maxreichmann

Copy link
Copy Markdown
Member Author

Please, check the log when you try to build with this new validation/schema:

strict mode: missing type "object" for keyword "properties" at "ui5-workspace.json#/then/properties/dependencyManagement" (strictTypes)
strict mode: missing type "array" for keyword "items" at "ui5-workspace.json#/then/properties/dependencyManagement/properties/resolutions" (strictTypes)
strict mode: missing type "object" for keyword "required" at "ui5-workspace.json#/then/properties/dependencyManagement/properties/resolutions/items/then/not" (strictTypes)

This is from AJV's strict mode

Resolved with 4ebdb73

Comment thread packages/project/lib/graph/Workspace.js Resolved
@maxreichmann
maxreichmann marked this pull request as draft October 15, 2026 14:42
@maxreichmann
maxreichmann force-pushed the offer-configPath-to-workspace-yaml branch 6 times, most recently from b5f28b4 to 2a27fc6 Compare October 20, 2026 14:32
@maxreichmann
maxreichmann force-pushed the offer-configPath-to-workspace-yaml branch from adf732b to 6e7dcd2 Compare October 27, 2026 17:29
maxreichmann and others added 14 commits November 10, 2026 17:02
Implements the previously created concept markdown for "specificity wins + Error on duplicate"
NodePackageDependencies silently ignored the `configPath` of a workspace-resolved dependency.
It's now carried through to projectGraphBuilder so the custom config is loaded instead of the default ui5.yaml.
When a workspace declares a resolution for a collection and a more specific
one for a nested sub-collection or library inside it, the nested resolution
must own its subtree's configPath.

Which one applied depended on the order the async traversals finished: first
to mark a node visited won. For members reached via recursion that order is
I/O dependent, so a broader resolution could claim a module meant for a more
specific one.

Record the declared resolution roots up front and skip recursion into any
member that is itself a declared resolution, leaving it and its subtree to
that resolution.
Resolve workspace entries one at a time and track visited paths per
resolution to prevent cycles. Preserve the most specific configuration
when workspace globs overlap.
Treat paths with and without trailing slashes as the same directory,
so overlapping resolutions load only the most specific config.

+ Add tests
@maxreichmann
maxreichmann force-pushed the offer-configPath-to-workspace-yaml branch from 51acda3 to d3b7fb4 Compare November 10, 2026 16:02
@maxreichmann
maxreichmann force-pushed the offer-configPath-to-workspace-yaml branch from b4ee83b to 75f8e5e Compare November 10, 2026 16:08
@maxreichmann

Copy link
Copy Markdown
Member Author

Kindly asking @KlattG to review the newest added docu part (d80a8ab)

KlattG
KlattG previously approved these changes Nov 11, 2026
@maxreichmann

maxreichmann commented Nov 11, 2026 •

Copy link
Copy Markdown
Member Author

As this PR is quite huge, this review order might ease the start:

  1. ui5-workspace.json: new specVersion and the actual configPath parameter (which only works for this new specVersion)
  2. Workspace.js: Most of the logic: using configPath in the module collection; (also new: explicit "most specific wins" logic)
  3. Module.js: exposing configPath by a getter
  4. NodePackageDependencies.js: forwarding this exposed configPath to the creation of the ProjectGraph
  5. Tests

The many new files under ./package/project/test are mostly just fixtures necessary for the new tests which represent file structures (nested workspaces with custom configs).
Here's the structure in case you'll need it:

Fixture: collection.c

Located under packages/project/test/fixtures/.
Every library also contains package.json, ui5.yaml, ui5-another-custom.yaml and it's source.

collection.c/
├── package.json
├── library.a/
│   └── ui5-custom.yaml
├── library.b/
│   └── ui5-custom.yaml
└── collection.a/
    ├── package.json
    ├── library.c/
    │   └── ui5-custom.yaml
    └── library.d/
        └── ui5-custom.yaml
Fixture: collection.c.noCustomConfigForLibA

Located under packages/project/test/fixtures/.
Every library also contains package.json, ui5.yaml, ui5-another-custom.yaml and it's source.

collection.c.noCustomConfigForLibA/
├── package.json
├── library.a/                 (ui5-custom.yaml intentionally absent)
├── library.b/
│   └── ui5-custom.yaml
└── collection.a/
    ├── package.json
    ├── library.c/
    │   └── ui5-custom.yaml
    └── library.d/
        └── ui5-custom.yaml

The added tests mostly test if the correct config was loaded in various scenarios.

@maxreichmann
maxreichmann marked this pull request as ready for review November 11, 2026 13:44
@maxreichmann
maxreichmann requested a review from a team November 11, 2026 13:44
Comment thread packages/project/lib/graph/Workspace.js Outdated
log.verbose(`Module located at ${nodePath} has already been visited`);
return [];
async _getModulesFromPath(
visitedNodesPerResolution,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[suggestion only] you could make visitedNodesPerResolution the last parameter and give it a default of new Set(). The recursive call in lines 282-283 would propagate the parameter to nested calls. The call on top level (line 180) would not provide a value (-> the default applies).

That way, this helper collection would be fully local to _getModulesFromPath and not be spread over two levels.

const absolutePath = path.resolve(this.#cwd, resolutionPath);
if (seenAbsolutePaths.includes(absolutePath)) {
throw new Error(
`Multiple resolutions for the same dependency '${path.basename(absolutePath)}' ` +

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[suggestion only] I find the term dependency misleading / confusing. A resolution path is not necessarily the same as a dependency in the sense of the ui5.yaml. It might e.g. point to the openui5 repository as a whole, covering multiple dependencies.

Suggestion: "Two resolutions in workspace '${this.getName()}' point to the same folder: ${resolutionPath} and ${earlierResolutionPath}"

To be able to name the earlier resolution path, the bookkeeping seenAbsolutePaths would have to be changed maybe to a map (key: absolute path; value: original resolutionPath).

But again, only a suggestion :-)

@maxreichmann maxreichmann Nov 11, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but what about more than two duplicate resolution paths? I would suggest:

"Two or more resolutions for '${path.basename(absolutePath)}' point to the same folder '${absolutePath}' in workspace '${this.getName()}'"

I guess, you also want to provide the full resolutionPath (what is written in the yaml)? Then we'd need to do some bookkeeping

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your text proposal is acceptable. And yes, I thought that naming the original resolution path(s) would be helpful to the developer.

@devtomtom devtomtom left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall it looks good to me.

# UI5 Workspaces

::: info
**UI5 Workspaces is a new feature available since UI5 CLI [`v3.0.0`](https://github.com/SAP/ui5-cli/releases/tag/v3.0.0)**

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO we can get rid of the info and let the documentation start with the General Concept section

This branch has not been deployed

No deployments
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.

Option to specify custom UI5 config for workspace dependency resolution

5 participants