diff --git a/internal/documentation/docs/pages/Builder.md b/internal/documentation/docs/pages/Builder.md
index d36be96ec98..176357cc5ed 100644
--- a/internal/documentation/docs/pages/Builder.md
+++ b/internal/documentation/docs/pages/Builder.md
@@ -44,7 +44,7 @@ All available standard tasks are documented [in the API reference](https://ui5.g
| generateBundle | *disabled* 4 | *disabled* 4 | *disabled* 4 | |
| buildThemes | | | enabled | enabled |
| generateThemeDesignerResources | | | *disabled* 5 | *disabled* 5 |
-| generateVersionInfo | *disabled* 1 | | | |
+| generateVersionInfo | enabled 6 | | | |
| generateCachebusterInfo | *disabled* | *disabled* | | |
| generateApiIndex | *disabled* 1 | | | |
| generateResourcesJson | *disabled* | *disabled* | *disabled* | *disabled* |
@@ -57,7 +57,8 @@ All available standard tasks are documented [in the API reference](https://ui5.g
2 Enabled for projects defining a [component preload configuration](./Configuration.md#component-preload-generation)
3 Enabled in `self-contained` build, which disables `generateComponentPreload` and `generateLibraryPreload`
4 Enabled for projects defining a [bundle configuration](./Configuration.md#custom-bundling)
-5 Can be enabled for framework projects via the `includeTask` option. For other projects, this task is skipped
+5 Can be enabled for framework projects via the `includeTask` option. For other projects, this task is skipped
+6 Disabled for the server due to a corresponding middleware producing the same output
### minify
diff --git a/internal/documentation/docs/pages/Server.md b/internal/documentation/docs/pages/Server.md
index 64d6ae46155..1239753b885 100644
--- a/internal/documentation/docs/pages/Server.md
+++ b/internal/documentation/docs/pages/Server.md
@@ -146,6 +146,10 @@ In case a directory has been requested, this middleware renders an HTML with a l
## Standard Tasks
As with the UI5 Builder, a set of standard tasks is being executed during a server build. Individual tasks can be included or excluded using the respective CLI options `--include-task` and `--exclude-task`.
+::: info Exception
+For the server, task [`generateVersionInfo`](../api/module-@ui5_builder_tasks_generateVersionInfo.md) is not executed because the corresponding middleware [`versionInfo`](#versioninfo) creates the same output file `sap-ui-version.json`.
+:::
+
::: info
See [Builder Standard Tasks](./Builder.md#standard-tasks) for more explanation about each task.
:::
diff --git a/internal/documentation/docs/updates/migrate-v5.md b/internal/documentation/docs/updates/migrate-v5.md
index c9db7b58dac..5609d3d4345 100644
--- a/internal/documentation/docs/updates/migrate-v5.md
+++ b/internal/documentation/docs/updates/migrate-v5.md
@@ -320,6 +320,16 @@ Update your `ui5.yaml` configuration to reference an existing middleware instead
| `serveThemes` | CSS files pre-built by `buildThemes` task and served via `serveResources` | `serveResources` |
| `testRunner` | TestRunner resources served via `serveResources` from the UI5 framework | `serveResources` |
+## `sap-ui-version.json`
+
+When running `ui5 build`, the standard task [`generateVersionInfo`](../api/module-@ui5_builder_tasks_generateVersionInfo) (producing a `sap-ui-version.json` file under `resources/`) is now **executed by default**. This applies to every build type (default, jsdoc, and self-contained) for projects of type `application`. For projects of other types (e.g. `library`), the behavior remains the same and [`generateVersionInfo`](../api/module-@ui5_builder_tasks_generateVersionInfo) is not executed.
+
+::: info Tip
+To see which standard tasks are executed for each project type, check out the [Standard Tasks](../pages/Builder#standard-tasks) table in the UI5 Builder page.
+:::
+
+When running `ui5 serve`, [`generateVersionInfo`](../api/module-@ui5_builder_tasks_generateVersionInfo) continues to **not be executed by default** because a corresponding middleware [`versionInfo`](../pages/Server.md#versioninfo) produces the same `sap-ui-version.json` output file.
+
## Learn More
- [Project: Type `component`](../pages/Project#component)
diff --git a/packages/builder/test/expected/build/application.m/dest/resources/sap-ui-version.json b/packages/builder/test/expected/build/application.m/dest/resources/sap-ui-version.json
new file mode 100644
index 00000000000..a109feea58d
--- /dev/null
+++ b/packages/builder/test/expected/build/application.m/dest/resources/sap-ui-version.json
@@ -0,0 +1,7 @@
+{
+ "name": "application.m",
+ "version": "1.0.0",
+ "buildTimestamp": "WILL_BE_IGNORED_BY_TESTS",
+ "scmRevision": "",
+ "libraries": []
+}
diff --git a/packages/builder/test/expected/build/application.o/dest/resources/sap-ui-version.json b/packages/builder/test/expected/build/application.o/dest/resources/sap-ui-version.json
new file mode 100644
index 00000000000..b6212fb25e3
--- /dev/null
+++ b/packages/builder/test/expected/build/application.o/dest/resources/sap-ui-version.json
@@ -0,0 +1,7 @@
+{
+ "name": "application.o",
+ "version": "1.0.0",
+ "buildTimestamp": "WILL_BE_IGNORED_BY_TESTS",
+ "scmRevision": "",
+ "libraries": []
+}
diff --git a/packages/builder/test/lib/builder/builder.js b/packages/builder/test/lib/builder/builder.js
index cf0f0c0c46b..8772cbda0a6 100644
--- a/packages/builder/test/lib/builder/builder.js
+++ b/packages/builder/test/lib/builder/builder.js
@@ -71,14 +71,20 @@ async function checkFileContentsIgnoreLineFeeds(t, expectedFiles, expectedPath,
currentContent = JSON.parse(currentContent.replace(/(:\s+)(\d+)/g, ": 0"));
expectedContent = JSON.parse(expectedContent.replace(/(:\s+)(\d+)/g, ": 0"));
t.deepEqual(currentContent, expectedContent);
- } else {
- if (expectedFile.endsWith(".json")) {
- try {
- t.deepEqual(JSON.parse(currentContent), JSON.parse(expectedContent), expectedFile);
- } catch (e) {
- t.falsy(e, expectedFile);
+ } else if (expectedFile.endsWith(".json")) {
+ try {
+ const currentJson = JSON.parse(currentContent);
+ const expectedJson = JSON.parse(expectedContent);
+ // Check if file is "sap-ui-version.json" and ignore the buildTimestamp property for comparison:
+ if (expectedFile.endsWith("sap-ui-version.json")) {
+ delete currentJson.buildTimestamp;
+ delete expectedJson.buildTimestamp;
}
+ t.deepEqual(currentJson, expectedJson, expectedFile);
+ } catch (e) {
+ t.falsy(e, expectedFile);
}
+ } else {
t.is(currentContent.replace(newLineRegexp, "\n"),
expectedContent.replace(newLineRegexp, "\n"),
relativeFile);
diff --git a/packages/project/lib/build/helpers/composeTaskList.js b/packages/project/lib/build/helpers/composeTaskList.js
index 11a23d39dcb..dca89a180e3 100644
--- a/packages/project/lib/build/helpers/composeTaskList.js
+++ b/packages/project/lib/build/helpers/composeTaskList.js
@@ -25,7 +25,6 @@ export default function composeTaskList(allTasks, {selfContained, jsdoc, include
selectedTasks.generateCachebusterInfo = false;
selectedTasks.generateApiIndex = false;
selectedTasks.generateThemeDesignerResources = false;
- selectedTasks.generateVersionInfo = false;
// Disable generateResourcesJson due to performance.
// When executed it analyzes each module's AST and therefore
@@ -45,7 +44,6 @@ export default function composeTaskList(allTasks, {selfContained, jsdoc, include
selectedTasks.generateJsdoc = true;
selectedTasks.executeJsdocSdkTransformation = true;
selectedTasks.generateApiIndex = true;
- selectedTasks.generateVersionInfo = true;
// Include theme build as required for SDK
selectedTasks.buildThemes = true;
diff --git a/packages/project/lib/graph/ProjectGraph.js b/packages/project/lib/graph/ProjectGraph.js
index 653e6f7901b..1788d80c009 100644
--- a/packages/project/lib/graph/ProjectGraph.js
+++ b/packages/project/lib/graph/ProjectGraph.js
@@ -768,6 +768,15 @@ class ProjectGraph {
cache = Cache.Default,
ui5DataDir,
}) {
+ // Explicitly exclude task "generateVersionInfo" for Server builds
+ // because middleware "versionInfo" will generate the version info anyways.
+ if (!Array.isArray(excludedTasks)) {
+ excludedTasks = [];
+ }
+ if (!excludedTasks.includes("generateVersionInfo")) {
+ excludedTasks.push("generateVersionInfo");
+ }
+
this.seal(); // Do not allow further changes to the graph
if (this._builtOrServed) {
throw new Error(
diff --git a/packages/project/test/lib/build/BuildServer.integration.js b/packages/project/test/lib/build/BuildServer.integration.js
index 0abcf7765a9..e9da904b2d8 100644
--- a/packages/project/test/lib/build/BuildServer.integration.js
+++ b/packages/project/test/lib/build/BuildServer.integration.js
@@ -275,7 +275,7 @@ test.serial("Serve application.a, create and delete a source file", async (t) =>
// #5 the second file is no longer served, but requesting it triggers a build of the dependencies
// because the file is not known anymore and might come from a different project.
// Note: This is special for applications, which are served at root level. For libraries, the server
- // can determine whether a resources is inside a project namespace and only trigger a build for the affected
+ // can determine whether a resource is inside a project namespace and only trigger a build for the affected
// project. The logic could be improved, especially like in this case where the requested resource is outside
// of /resources or /test-resources.
await fixtureTester.requestResource({
@@ -614,7 +614,7 @@ test.serial("Serve application.a with --cache=Off", async (t) => {
}
});
- // #2: Request with cache=Off (again) --> all tasks execute again (no cache reuse)
+ // #2: Request with cache=Off (again) --> nothing rebuilds (cache not written, but no changes)
await fixtureTester.requestResource({
resource: "/test.js",
assertions: {
@@ -1027,6 +1027,36 @@ test.serial("Source change during second build retries cleanly without no_cache
"Retry served content reflecting the mid-build-2 change");
});
+test.serial("Serve application.a (test exclusion of generateVersionInfo)", async (t) => {
+ // This test verifies that task "generateVersionInfo" is excluded
+ // (default for server builds).
+
+ const fixtureTester = t.context.fixtureTester = await FixtureTester.create(t, "application.a");
+
+ await fixtureTester.serveProject();
+
+ // Request a resource to trigger the build:
+ await fixtureTester.requestResource({
+ resource: "/test.js",
+ assertions: {
+ projects: {
+ "application.a": {
+ executedTasks: [
+ "escapeNonAsciiCharacters",
+ "replaceCopyright",
+ "replaceVersion",
+ "minify",
+ "generateFlexChangesBundle",
+ "enhanceManifest",
+ "generateComponentPreload"
+ // no "generateVersionInfo" as expected
+ ],
+ },
+ }
+ },
+ });
+});
+
function getFixturePath(fixtureName) {
return fileURLToPath(new URL(`../../fixtures/${fixtureName}`, import.meta.url));
}
@@ -1159,6 +1189,18 @@ class FixtureTester {
const expectedProjects = Object.keys(projects);
this._t.deepEqual(projectsInOrder, expectedProjects);
+ // Optional check: Assert executed tasks
+ for (const [projectName, expected] of Object.entries(projects)) {
+ if (!expected.executedTasks) {
+ continue; // no executedTasks specified -> skip the check
+ }
+ const expectedExecuted = expected.executedTasks || [];
+ const actualExecuted = (tasksByProject[projectName]?.executed || []).sort();
+ const expectedArray = expectedExecuted.sort();
+ this._t.deepEqual(actualExecuted, expectedArray,
+ "All executed tasks of all projects should match expected");
+ }
+
// Assert skipped tasks per project
for (const [projectName, expectedSkipped] of Object.entries(projects)) {
const skippedTasks = expectedSkipped.skippedTasks || [];
diff --git a/packages/project/test/lib/build/ProjectBuilder.integration.js b/packages/project/test/lib/build/ProjectBuilder.integration.js
index c754b7213f1..1cbd535860f 100644
--- a/packages/project/test/lib/build/ProjectBuilder.integration.js
+++ b/packages/project/test/lib/build/ProjectBuilder.integration.js
@@ -44,6 +44,13 @@ test.serial("Build application.a project multiple times", async (t) => {
config: {destPath, cleanDest: false},
assertions: {
projects: {
+ // Default builds of project type "application" include the "generateVersionInfo"
+ // task which requires dependencies to be built, so all dependencies are expected to be built here.
+ // Subsequent builds can reuse the cached results of these dependencies.
+ "library.d": {},
+ "library.a": {},
+ "library.b": {},
+ "library.c": {},
"application.a": {}
}
}
@@ -75,6 +82,7 @@ test.serial("Build application.a project multiple times", async (t) => {
"replaceCopyright",
"enhanceManifest",
"generateFlexChangesBundle",
+ "generateVersionInfo",
]
}
}
@@ -90,12 +98,10 @@ test.serial("Build application.a project multiple times", async (t) => {
await fixtureTester.buildProject({
config: {destPath, cleanDest: true, dependencyIncludes: {includeAllDependencies: true}},
assertions: {
- projects: {
- "library.d": {},
- "library.a": {},
- "library.b": {},
- "library.c": {},
- }
+ // Dependencies are NOT rebuilt because
+ // they were already built in build #1 and can be reused from cache.
+ // Thus, empty assertion for built projects.
+ projects: {}
}
});
@@ -180,6 +186,7 @@ test.serial("Build application.a project multiple times", async (t) => {
"enhanceManifest",
"escapeNonAsciiCharacters",
"generateFlexChangesBundle",
+ "generateVersionInfo",
"replaceCopyright"
]
}
@@ -204,6 +211,7 @@ test.serial("Build application.a project multiple times", async (t) => {
"escapeNonAsciiCharacters",
"generateFlexChangesBundle",
"replaceCopyright",
+ "generateVersionInfo",
]
}}
}
@@ -264,6 +272,7 @@ test.serial("Build application.a (with various dependencies)", async (t) => {
"escapeNonAsciiCharacters",
"generateFlexChangesBundle",
"replaceCopyright",
+ "generateVersionInfo",
]
}
}
@@ -308,6 +317,7 @@ test.serial("Build application.a (with various dependencies)", async (t) => {
"escapeNonAsciiCharacters",
"generateFlexChangesBundle",
"replaceCopyright",
+ "generateVersionInfo",
]
}
}
@@ -330,6 +340,7 @@ test.serial("Build application.a (with various dependencies)", async (t) => {
"escapeNonAsciiCharacters",
"generateFlexChangesBundle",
"replaceCopyright",
+ "generateVersionInfo",
]
}
}
@@ -342,18 +353,25 @@ test.serial("Build application.a (including only some dependencies)", async (t)
const destPath = fixtureTester.destPath;
// In this test, we're testing the "dependencyIncludes" build option
- // which allows to include only a subset of the dependencies of a project in the build.
+ // which allows to include only a subset of the dependencies of a project in the build result.
// "application.a" has 4 dependencies defined: library.a, library.b, library.c and library.d.
// #1 build
// Only include library.a and library.b as dependencies, but not library.c and library.d:
+
+ // Note: For the initial build, ALL dependencies are built,
+ // due to the execution of the "generateVersionInfo" task in application.a which requires dependencies to be built.
+ // In subsequent builds, the cached results of the dependencies can be reused,
+ // so "includeDependency" can come to effect.
await fixtureTester.buildProject({
config: {destPath, cleanDest: false,
dependencyIncludes: {includeDependency: ["library.a", "library.b"]}},
assertions: {
projects: {
+ "library.d": {},
"library.a": {},
"library.b": {},
+ "library.c": {},
"application.a": {}
}
}
@@ -364,6 +382,10 @@ test.serial("Build application.a (including only some dependencies)", async (t)
{encoding: "utf8"}));
await t.notThrowsAsync(fs.readFile(`${destPath}/resources/library/b/library-preload.js`,
{encoding: "utf8"}));
+
+ // Check that the remaining dependencies are NOT in the destPath:
+ // (Note: although library.c and library.d were built,
+ // they are not included in the build result because of the flag)
await t.throwsAsync(fs.readFile(`${destPath}/resources/library/c/library-preload.js`,
{encoding: "utf8"}));
await t.throwsAsync(fs.readFile(`${destPath}/resources/library/d/library-preload.js`,
@@ -372,14 +394,12 @@ test.serial("Build application.a (including only some dependencies)", async (t)
// #2 build
// Exclude library.d as dependency, but include all other dependencies
- // (builds of library.a and library.b can be reused from cache):
+ // (builds of library.a, library.b and library.c can be reused from cache):
await fixtureTester.buildProject({
config: {destPath, cleanDest: true,
dependencyIncludes: {includeAllDependencies: true, excludeDependency: ["library.d"]}},
assertions: {
- projects: {
- "library.c": {},
- }
+ projects: {}
}
});
@@ -390,20 +410,20 @@ test.serial("Build application.a (including only some dependencies)", async (t)
{encoding: "utf8"}));
await t.notThrowsAsync(fs.readFile(`${destPath}/resources/library/c/library-preload.js`,
{encoding: "utf8"}));
+
+ // Check that the excluded dependency is NOT in the destPath:
await t.throwsAsync(fs.readFile(`${destPath}/resources/library/d/library-preload.js`,
{encoding: "utf8"}));
// #3 build
- // Include all dependencies (only library.d is built)
- // (builds of library.a, library.b, and library.c can be reused from cache):
+ // Include all dependencies
+ // (builds of ALL libraries can be reused from cache):
await fixtureTester.buildProject({
config: {destPath, cleanDest: true,
dependencyIncludes: {includeAllDependencies: true}},
assertions: {
- projects: {
- "library.d": {},
- }
+ projects: {}
}
});
@@ -448,6 +468,10 @@ test.serial("Build application.a (custom task and tag handling)", async (t) => {
config: {destPath, cleanDest: true},
assertions: {
projects: {
+ "library.d": {},
+ "library.a": {},
+ "library.b": {},
+ "library.c": {},
"application.a": {}
}
}
@@ -471,6 +495,7 @@ test.serial("Build application.a (custom task and tag handling)", async (t) => {
"replaceCopyright",
"enhanceManifest",
"generateFlexChangesBundle",
+ "generateVersionInfo",
]
}
}
@@ -523,6 +548,10 @@ test.serial("Build application.a (multiple custom tasks)", async (t) => {
config: {destPath, cleanDest: true},
assertions: {
projects: {
+ "library.d": {},
+ "library.a": {},
+ "library.b": {},
+ "library.c": {},
"application.a": {}
}
}
@@ -561,6 +590,7 @@ test.serial("Build application.a (multiple custom tasks)", async (t) => {
"escapeNonAsciiCharacters",
"generateFlexChangesBundle",
"replaceCopyright",
+ "generateVersionInfo",
]
}
}
@@ -582,6 +612,10 @@ test.serial("Build application.a (multiple custom tasks 2)", async (t) => {
config: {destPath, cleanDest: true},
assertions: {
projects: {
+ "library.d": {},
+ "library.a": {},
+ "library.b": {},
+ "library.c": {},
"application.a": {}
}
}
@@ -606,6 +640,7 @@ test.serial("Build application.a (multiple custom tasks 2)", async (t) => {
"replaceCopyright",
"enhanceManifest",
"generateFlexChangesBundle",
+ "generateVersionInfo",
]
}
}
@@ -635,6 +670,7 @@ test.serial("Build application.a (multiple custom tasks 2)", async (t) => {
"escapeNonAsciiCharacters",
"generateFlexChangesBundle",
"replaceCopyright",
+ "generateVersionInfo",
]
}
}
@@ -834,6 +870,7 @@ builder:
"generateFlexChangesBundle",
"replaceCopyright",
"replaceVersion",
+ "generateVersionInfo",
]
},
}
@@ -985,6 +1022,10 @@ test.serial("Build application.a (Custom Component preload configuration)", asyn
config: {destPath, cleanDest: true},
assertions: {
projects: {
+ "library.d": {},
+ "library.a": {},
+ "library.b": {},
+ "library.c": {},
"application.a": {}
}
}
@@ -1064,6 +1105,7 @@ test.serial("Build application.a (self-contained build)", async (t) => {
"generateFlexChangesBundle",
"replaceCopyright",
"transformBootstrapHtml",
+ "generateVersionInfo",
]
}
}
@@ -1181,6 +1223,7 @@ test.serial("Build application.a (Custom bundling)", async (t) => {
"escapeNonAsciiCharacters",
"generateFlexChangesBundle",
"replaceCopyright",
+ "generateVersionInfo",
]
}
}
@@ -1217,6 +1260,7 @@ test.serial("Build application.a (Custom bundling)", async (t) => {
"escapeNonAsciiCharacters",
"generateFlexChangesBundle",
"replaceCopyright",
+ "generateVersionInfo",
]
}
}
@@ -2465,6 +2509,10 @@ test.serial("Build application.a with --cache=Default", async (t) => {
config: {destPath, cleanDest: false, cache: Cache.Default},
assertions: {
projects: {
+ "library.d": {},
+ "library.a": {},
+ "library.b": {},
+ "library.c": {},
"application.a": {}
}
}
@@ -2493,6 +2541,7 @@ test.serial("Build application.a with --cache=Default", async (t) => {
"replaceCopyright",
"enhanceManifest",
"generateFlexChangesBundle",
+ "generateVersionInfo",
]
}
}
@@ -2514,7 +2563,11 @@ test.serial("Build application.a with --cache=Off", async (t) => {
config: {destPath, cleanDest: false, cache: Cache.Off},
assertions: {
projects: {
- "application.a": {}
+ "library.d": {},
+ "library.a": {},
+ "library.b": {},
+ "library.c": {},
+ "application.a": {},
}
}
});
@@ -2524,7 +2577,11 @@ test.serial("Build application.a with --cache=Off", async (t) => {
config: {destPath, cleanDest: true, cache: Cache.Off},
assertions: {
projects: {
- "application.a": {}
+ "library.d": {},
+ "library.a": {},
+ "library.b": {},
+ "library.c": {},
+ "application.a": {},
}
}
});
@@ -2534,7 +2591,11 @@ test.serial("Build application.a with --cache=Off", async (t) => {
config: {destPath, cleanDest: true, cache: Cache.Default},
assertions: {
projects: {
- "application.a": {}
+ "library.d": {},
+ "library.a": {},
+ "library.b": {},
+ "library.c": {},
+ "application.a": {},
}
}
});
@@ -2552,7 +2613,11 @@ test.serial("Build application.a with --cache=Off", async (t) => {
config: {destPath, cleanDest: true, cache: Cache.Off},
assertions: {
projects: {
- "application.a": {}
+ "library.d": {},
+ "library.a": {},
+ "library.b": {},
+ "library.c": {},
+ "application.a": {},
}
}
});
@@ -2567,6 +2632,10 @@ test.serial("Build application.a with --cache=ReadOnly", async (t) => {
config: {destPath, cleanDest: false, cache: Cache.Default},
assertions: {
projects: {
+ "library.d": {},
+ "library.a": {},
+ "library.b": {},
+ "library.c": {},
"application.a": {}
}
}
@@ -2595,6 +2664,7 @@ test.serial("Build application.a with --cache=ReadOnly", async (t) => {
"replaceCopyright",
"enhanceManifest",
"generateFlexChangesBundle",
+ "generateVersionInfo",
]
}
}
@@ -2618,6 +2688,7 @@ test.serial("Build application.a with --cache=ReadOnly", async (t) => {
"replaceCopyright",
"enhanceManifest",
"generateFlexChangesBundle",
+ "generateVersionInfo",
]
}
}
@@ -2634,6 +2705,10 @@ test.serial("Build application.a with --cache=Force (1)", async (t) => {
config: {destPath, cleanDest: false, cache: Cache.Default},
assertions: {
projects: {
+ "library.d": {},
+ "library.a": {},
+ "library.b": {},
+ "library.c": {},
"application.a": {}
}
}
@@ -2680,6 +2755,51 @@ test.serial("Build application.a with --cache=Force (2)", async (t) => {
`Use "Default", "ReadOnly" or "Off" to rebuild.`));
});
+test.serial("Build application.a with --exclude-task=generateVersionInfo", async (t) => {
+ // This test verifies that when task generateVersionInfo is excluded,
+ // the sap-ui-version.json file is NOT generated in the output
+ // AND the dependencies are not automatically built.
+
+ const fixtureTester = new FixtureTester(t, "application.a");
+ const destPath = fixtureTester.destPath;
+
+ // #1 Build with empty cache and exclude generateVersionInfo task
+ await fixtureTester.buildProject({
+ config: {destPath, cleanDest: false, excludedTasks: ["generateVersionInfo"]},
+ assertions: {
+ projects: {
+ // Only application.a is built, dependencies are skipped
+ "application.a": {}
+ }
+ }
+ });
+
+ // Verify that sap-ui-version.json does NOT exist in the output
+ const versionInfoPath = `${destPath}/resources/sap-ui-version.json`;
+ await t.throwsAsync(fs.readFile(versionInfoPath, {encoding: "utf8"}), undefined,
+ "sap-ui-version.json should NOT exist when generateVersionInfo task is excluded");
+
+
+ // #2 Build with empty cache and include all default tasks now
+ await fixtureTester.buildProject({
+ config: {destPath, cleanDest: false},
+ assertions: {
+ projects: {
+ // All dependencies are built now
+ "library.d": {},
+ "library.a": {},
+ "library.b": {},
+ "library.c": {},
+ "application.a": {}
+ }
+ }
+ });
+
+ // Verify that sap-ui-version.json DOES exist in the output now
+ await t.notThrowsAsync(fs.readFile(versionInfoPath, {encoding: "utf8"}), undefined,
+ "sap-ui-version.json should exist when generateVersionInfo task is included");
+});
+
function getFixturePath(fixtureName) {
return fileURLToPath(new URL(`../../fixtures/${fixtureName}`, import.meta.url));
}
diff --git a/packages/project/test/lib/build/TaskRunner.js b/packages/project/test/lib/build/TaskRunner.js
index c4451c556c3..2dd78996b34 100644
--- a/packages/project/test/lib/build/TaskRunner.js
+++ b/packages/project/test/lib/build/TaskRunner.js
@@ -1295,6 +1295,7 @@ test("Custom task attached to a disabled task", async (t) => {
"generateFlexChangesBundle",
"generateComponentPreload",
"myTask",
+ "generateVersionInfo",
],
"Correct tasks execution");
});
@@ -1423,11 +1424,17 @@ test("getRequiredDependencies: Custom Task", async (t) => {
});
test("getRequiredDependencies: Default application", async (t) => {
+ // This test includes a mock project of type "application".
+ // By default, builds of this project type always contain the "generateVersionInfo" task,
+ // which requires dependencies to be built.
+
const project = getMockProject("application");
project.getBundles = () => [];
const taskRunner = createTaskRunner(t, project);
- t.deepEqual(await taskRunner.getRequiredDependencies(), new Set([]),
- "Default application project does not require dependencies");
+ t.deepEqual(await taskRunner.getRequiredDependencies(), new Set([
+ "dep.a",
+ "dep.b",
+ ]), "Default application project DOES require dependencies");
});
test("getRequiredDependencies: Default component", async (t) => {
diff --git a/packages/project/test/lib/build/helpers/composeTaskList.js b/packages/project/test/lib/build/helpers/composeTaskList.js
index 910994aabec..f1fb5f905c4 100644
--- a/packages/project/test/lib/build/helpers/composeTaskList.js
+++ b/packages/project/test/lib/build/helpers/composeTaskList.js
@@ -55,6 +55,7 @@ const allTasks = [
"minify",
"buildThemes",
"generateLibraryManifest",
+ "generateVersionInfo",
"generateFlexChangesBundle",
"generateComponentPreload",
"generateBundle",
@@ -76,6 +77,7 @@ const allTasks = [
"minify",
"buildThemes",
"generateLibraryManifest",
+ "generateVersionInfo",
"generateFlexChangesBundle",
"generateComponentPreload",
"generateBundle",
@@ -98,9 +100,10 @@ const allTasks = [
"buildThemes",
"transformBootstrapHtml",
"generateLibraryManifest",
+ "generateVersionInfo",
"generateFlexChangesBundle",
"generateStandaloneAppBundle",
- "generateBundle"
+ "generateBundle",
]
],
[
@@ -134,6 +137,7 @@ const allTasks = [
"minify",
"buildThemes",
"generateLibraryManifest",
+ "generateVersionInfo",
"generateFlexChangesBundle",
"generateComponentPreload",
"generateResourcesJson",
@@ -195,6 +199,7 @@ const allTasks = [
"minify",
"buildThemes",
"generateLibraryManifest",
+ "generateVersionInfo",
"generateFlexChangesBundle",
"generateComponentPreload",
"generateBundle",
@@ -219,6 +224,7 @@ const allTasks = [
"minify",
"buildThemes",
"generateLibraryManifest",
+ "generateVersionInfo",
"generateFlexChangesBundle",
"generateComponentPreload",
"generateBundle",