@ui5/task-adaptation 1.6.5-rc.3 → 1.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/.env.test +1 -0
  2. package/CHANGELOG.md +10 -57
  3. package/README.md +4 -0
  4. package/dist/adapters/abapAdapter.d.ts +7 -5
  5. package/dist/adapters/abapAdapter.js +9 -11
  6. package/dist/adapters/adapter.d.ts +9 -5
  7. package/dist/adapters/adapter.js +20 -0
  8. package/dist/adapters/cfAdapter.d.ts +8 -5
  9. package/dist/adapters/cfAdapter.js +16 -10
  10. package/dist/adapters/commands/command.d.ts +26 -23
  11. package/dist/adapters/commands/command.js +73 -46
  12. package/dist/adapters/commands/fetchEndpointsCommand.d.ts +9 -0
  13. package/dist/adapters/commands/fetchEndpointsCommand.js +21 -0
  14. package/dist/adapters/commands/fetchPreviewResourcesCommand.d.ts +15 -0
  15. package/dist/adapters/commands/fetchPreviewResourcesCommand.js +102 -0
  16. package/dist/adapters/commands/filterFilesCommand.d.ts +4 -0
  17. package/dist/adapters/commands/filterFilesCommand.js +22 -0
  18. package/dist/adapters/commands/omitDeletedResourcesCommand.d.ts +10 -0
  19. package/dist/adapters/commands/omitDeletedResourcesCommand.js +31 -0
  20. package/dist/adapters/commands/processPreviewResourcesCommand.d.ts +9 -0
  21. package/dist/adapters/commands/processPreviewResourcesCommand.js +51 -0
  22. package/dist/adapters/commands/renameFilesCommand.d.ts +20 -0
  23. package/dist/{util/filesUtil.js → adapters/commands/renameFilesCommand.js} +34 -43
  24. package/dist/adapters/commands/writeResourcesCommand.d.ts +7 -0
  25. package/dist/adapters/commands/writeResourcesCommand.js +20 -0
  26. package/dist/adapters/commands/xsAppJsonEnhanceRoutesCommand.d.ts +3 -3
  27. package/dist/adapters/commands/xsAppJsonEnhanceRoutesCommand.js +4 -4
  28. package/dist/adapters/previewAdapter.d.ts +12 -6
  29. package/dist/adapters/previewAdapter.js +28 -7
  30. package/dist/{appVariantManager.d.ts → appVariant.d.ts} +2 -9
  31. package/dist/{appVariantManager.js → appVariant.js} +14 -26
  32. package/dist/{baseAppManager.js → baseApp.js} +6 -12
  33. package/dist/bundle.js +53 -12
  34. package/dist/cache/cacheHolder.d.ts +1 -1
  35. package/dist/index.d.ts +1 -1
  36. package/dist/index.js +34 -69
  37. package/dist/model/configuration.d.ts +1 -0
  38. package/dist/model/configuration.js +1 -0
  39. package/dist/model/types.d.ts +9 -2
  40. package/dist/repositories/localRepository.d.ts +2 -3
  41. package/dist/repositories/localRepository.js +54 -33
  42. package/dist/util/cf/xsAppJsonUtil.d.ts +16 -3
  43. package/dist/util/cf/xsAppJsonUtil.js +7 -18
  44. package/dist/util/commonUtil.d.ts +6 -0
  45. package/dist/util/commonUtil.js +17 -0
  46. package/dist/util/fsUtil.d.ts +1 -2
  47. package/dist/util/fsUtil.js +12 -33
  48. package/dist/util/renamingUtil.js +1 -1
  49. package/dist/util/resourceUtil.js +1 -1
  50. package/dist/util/validator/abapValidator.js +2 -2
  51. package/dist/util/validator/validator.d.ts +1 -0
  52. package/dist/util/validator/validator.js +11 -0
  53. package/package.json +11 -12
  54. package/.hyperspace/pull_request_bot.json +0 -19
  55. package/dist/previewManager.d.ts +0 -14
  56. package/dist/previewManager.js +0 -147
  57. package/dist/util/filesUtil.d.ts +0 -19
  58. package/scripts/metadataDownloadHelper.ts +0 -88
  59. package/scripts/publish.ts +0 -256
  60. package/scripts/test-integration-prep.sh +0 -4
  61. /package/dist/{baseAppManager.d.ts → baseApp.d.ts} +0 -0
@@ -14,7 +14,7 @@ export function renameMap(content, references, ignoreInStrings) {
14
14
  if (ignoredReferenceKeys.length > 0) {
15
15
  log.info(`Ignored renaming: ${ignoredReferenceKeys.join(", ")}`);
16
16
  }
17
- const searchTerms = [...references.keys()];
17
+ const searchTerms = [...references.keys()].filter(key => key.length > 0);
18
18
  if (!content || !searchTerms || searchTerms.length === 0) {
19
19
  return content;
20
20
  }
@@ -78,7 +78,7 @@ export default class ResourceUtil {
78
78
  ].concat(excludes));
79
79
  }
80
80
  static getString(resource) {
81
- return resource.getBuffer().then((buffer) => buffer.toString(UTF8));
81
+ return resource.getBuffer().then((buffer) => buffer.toString(UTF8).replaceAll("\r\n", "\n"));
82
82
  }
83
83
  static getJson(resource) {
84
84
  return resource.getBuffer().then((buffer) => JSON.parse(buffer.toString(UTF8)));
@@ -1,5 +1,5 @@
1
1
  import { validateObject } from "../commonUtil.js";
2
- import BtpUtils from "@sap-ux/btp-utils";
2
+ import { isAppStudio } from "@sap-ux/btp-utils";
3
3
  import { getLogger } from "@ui5/logger";
4
4
  const log = getLogger("@ui5/task-adaptation::AbapValidator");
5
5
  export default class AbapValidator {
@@ -9,7 +9,7 @@ export default class AbapValidator {
9
9
  // if target configuration appears, we validate that it should be
10
10
  // either target/destination for BAS or target/url for IDE we're
11
11
  // trying to detect is it destination for BAS or url for IDE
12
- const abapTargetProperties = BtpUtils.isAppStudio() ? ["destination"] : ["url"];
12
+ const abapTargetProperties = isAppStudio() ? ["destination"] : ["url"];
13
13
  validateObject(target, abapTargetProperties, "should be specified in ui5.yaml configuration/target");
14
14
  return target;
15
15
  }
@@ -4,3 +4,4 @@ export default interface IValidator {
4
4
  validateConfiguration(configuration: IConfiguration): void;
5
5
  }
6
6
  export declare function isOneOf<T extends readonly unknown[]>(values: T, value: unknown): value is T[number];
7
+ export declare function validateAppId(id: string): void;
@@ -1,4 +1,15 @@
1
1
  export function isOneOf(values, value) {
2
2
  return values.includes(value);
3
3
  }
4
+ export function validateAppId(id) {
5
+ if (!id) {
6
+ throw new Error(`The application id must not be empty.`);
7
+ }
8
+ // https://help.sap.com/docs/bas/developing-sap-fiori-app-in-sap-business-application-studio/releasing-sap-fiori-application-to-be-extensible-in-adaptation-projects-on-sap-s-4hana-cloud
9
+ // In the manifest.json file, make sure that the attribute
10
+ // sap.app/id has at least 2 segments.
11
+ if (id.split(".").filter(Boolean).length < 2) {
12
+ throw new Error(`The application id '${id}' must have at least two parts, separated by a period.`);
13
+ }
14
+ }
4
15
  //# sourceMappingURL=validator.js.map
package/package.json CHANGED
@@ -1,21 +1,20 @@
1
1
  {
2
2
  "name": "@ui5/task-adaptation",
3
- "version": "1.6.5-rc.3",
3
+ "version": "1.6.5",
4
4
  "description": "Custom task for ui5-builder which allows building UI5 Flexibility Adaptation Projects for SAP BTP, Cloud Foundry environment",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
7
  "test": "npm run lint && npm run build && npm run coverage",
8
8
  "lint": "eslint ./src ./test/lib",
9
- "dev": "UI5_LOG_LVL=error mocha --no-timeouts --no-warnings --import=tsx 'test/lib/**/*.spec.ts'",
10
- "perf": "UI5_LOG_LVL=error mocha --no-timeouts --no-warnings --import=tsx 'test/lib/**/*.perf.ts'",
9
+ "dev": "mocha --no-timeouts --no-warnings --import=tsx \"test/lib/**/*.spec.ts\"",
10
+ "perf": "mocha --no-timeouts --no-warnings --import=tsx \"test/lib/**/*.perf.ts\"",
11
11
  "coverage": "c8 npm run dev",
12
12
  "preversion": "npm test",
13
13
  "version": "git-chglog --next-tag v$npm_package_version -o CHANGELOG.md && git add CHANGELOG.md",
14
14
  "prepublishOnly": "git push --follow-tags",
15
15
  "release-note": "git-chglog -c .chglog/release-config.yml v$npm_package_version",
16
16
  "rollup": "tsx rollup/rollup.ts",
17
- "build": "npm run rollup && tsc -p ./",
18
- "download-metadata": "tsx scripts/metadataDownloadHelper.ts"
17
+ "build": "npm run rollup && tsc -p ./"
19
18
  },
20
19
  "repository": {
21
20
  "type": "git",
@@ -33,10 +32,10 @@
33
32
  "author": "SAP SE",
34
33
  "license": "Apache-2.0",
35
34
  "dependencies": {
36
- "@sap-ux/axios-extension": "^1.22.9",
37
- "@sap-ux/btp-utils": "^1.1.3",
38
- "@sap-ux/store": "^1.5.13",
39
- "@sap-ux/system-access": "^0.7.5",
35
+ "@sap-ux/axios-extension": "^2.0.1",
36
+ "@sap-ux/btp-utils": "^2.0.1",
37
+ "@sap-ux/store": "^2.0.1",
38
+ "@sap-ux/system-access": "^1.0.1",
40
39
  "@sap/cf-tools": "^3.2.2",
41
40
  "@ui5/fs": "^4.0.1",
42
41
  "@ui5/logger": "^4.0.1",
@@ -45,6 +44,7 @@
45
44
  "crc": "^4.3.2",
46
45
  "dotenv": "^16.0.3",
47
46
  "filenamify": "^6.0.0",
47
+ "glob": "^13.0.0",
48
48
  "jsdom": "^23.0.1",
49
49
  "transliteration": "^2.3.5",
50
50
  "xml-js": "^1.6.11"
@@ -73,17 +73,16 @@
73
73
  "eslint": "^9.22.0",
74
74
  "eslint-plugin-import": "^2.31.0",
75
75
  "esmock": "^2.7.3",
76
- "glob": "^13.0.0",
77
76
  "js-yaml": "^4.1.0",
78
77
  "meriyah": "^6.0.3",
79
78
  "minimatch": "^9.0.3",
80
- "mocha": "^11.7.5",
79
+ "mocha": "^11.7.6",
81
80
  "mock-require": "^3.0.3",
82
81
  "rollup": "^4.24.0",
83
82
  "semver": "^7.3.5",
84
83
  "sinon": "^18.0.1",
85
84
  "source-map-support": "^0.5.19",
86
- "tsx": "^4.21.0",
85
+ "tsx": "4.21.0",
87
86
  "typescript": "^6.0.2",
88
87
  "typescript-eslint": "^8.58.0",
89
88
  "yargs": "^17.7.2"
@@ -1,19 +0,0 @@
1
- {
2
- "$schema": "https://devops-insights-pr-bot.cfapps.eu10-004.hana.ondemand.com/schema/pull_request_bot.json",
3
- "features": {
4
- "control_panel": false,
5
- "summarize": {
6
- "auto_generate_summary": true,
7
- "auto_insert_summary": true,
8
- "auto_run_on_draft_pr": true,
9
- "use_custom_summarize_prompt": false,
10
- "use_custom_summarize_output_template": false,
11
- "use_tabular_summarize_output_template": false
12
- },
13
- "review": {
14
- "auto_generate_review": true,
15
- "auto_run_on_draft_pr": true,
16
- "use_custom_review_focus": false
17
- }
18
- }
19
- }
@@ -1,14 +0,0 @@
1
- import { IConfiguration } from "./model/types.js";
2
- import IRepository from "./repositories/repository.js";
3
- export default class PreviewManager {
4
- private readonly fetchLibsPromises;
5
- private readonly configuration;
6
- static createFromRoot(appId: string, repository: IRepository, configuration: IConfiguration): Promise<PreviewManager>;
7
- static isPreviewRequested(): boolean;
8
- private constructor();
9
- processPreviewResources(baseAppFiles: ReadonlyMap<string, string>): Promise<void>;
10
- private preReadLibs;
11
- private searchBaseAppXsAppJsonFile;
12
- private static moveLibraryFiles;
13
- private static modifyRoutes;
14
- }
@@ -1,147 +0,0 @@
1
- import { getLogger } from "@ui5/logger";
2
- import ResourceUtil from "./util/resourceUtil.js";
3
- import path from "path";
4
- import { fetchCredentialsAndEnhanceRoutes, merge } from "./util/cf/xsAppJsonUtil.js";
5
- import FsUtil from "./util/fsUtil.js";
6
- const log = getLogger("@ui5/task-adaptation::PreviewManager");
7
- const REUSE_DIR = ".adp/reuse";
8
- const APP_INFO_FILE = "ui5AppInfo.json";
9
- const XS_APP_JSON_FILE = "xs-app.json";
10
- export default class PreviewManager {
11
- fetchLibsPromises = new Map();
12
- configuration;
13
- static async createFromRoot(appId, repository, configuration) {
14
- let ui5AppInfo = "";
15
- if (PreviewManager.isPreviewRequested()) {
16
- try {
17
- ui5AppInfo = await FsUtil.readInProject(APP_INFO_FILE);
18
- }
19
- catch (error) {
20
- throw new Error(`ui5AppInfo.json is missing in project root, cannot process preview resources: ${error instanceof Error ? error.message : String(error)}`);
21
- }
22
- }
23
- else {
24
- log.verbose("Preview mode not requested (env variable ADP_BUILDER_MODE=preview is not set), skipping preview resources processing.");
25
- }
26
- return new PreviewManager(appId, ui5AppInfo, repository, configuration);
27
- }
28
- static isPreviewRequested() {
29
- return process.env.ADP_BUILDER_MODE === "preview";
30
- }
31
- constructor(appId, ui5AppInfo, repository, configuration) {
32
- this.configuration = configuration;
33
- // If no ui5AppInfo is provided, no preview processing is needed
34
- if (!ui5AppInfo) {
35
- log.verbose("No ui5AppInfo provided, skipping preview resources processing.");
36
- return;
37
- }
38
- const appInfo = JSON.parse(ui5AppInfo)[appId];
39
- if (!appInfo) {
40
- throw new Error(`No app info found for original app id '${appId}' in ui5AppInfo.json`);
41
- }
42
- const reuseLibs = appInfo.asyncHints.libs.filter(lib => lib.html5AppHostId && lib.html5AppName && lib.html5AppVersion);
43
- if (reuseLibs.length > 0) {
44
- this.fetchLibsPromises = this.preReadLibs(reuseLibs, repository);
45
- }
46
- const logMap = {
47
- Error: log.error,
48
- Warning: log.warning,
49
- Info: log.info,
50
- debug: log.verbose
51
- };
52
- appInfo.messages.forEach((message) => {
53
- const logger = logMap[message.severity] || log.info;
54
- logger(`ui5AppInfo.json: ${message.severity} Message: ${message.message} (Error Code: ${message.errorCode})`);
55
- });
56
- }
57
- async processPreviewResources(baseAppFiles) {
58
- if (!PreviewManager.isPreviewRequested()) {
59
- log.verbose("Preview mode not requested, skipping downloading reuse libraries and xs-app.json processing.");
60
- return;
61
- }
62
- log.verbose(`Downloading reuse libraries to reuse folder`);
63
- const xsAppFiles = new Array();
64
- if (this.fetchLibsPromises.size === 0) {
65
- log.verbose("No reuse libraries defined in ui5AppInfo.json for preview");
66
- }
67
- const mergedFiles = new Map();
68
- for (const [libName, libFilesPromise] of this.fetchLibsPromises) {
69
- const libFiles = await libFilesPromise;
70
- if (!libFiles || libFiles.size === 0) {
71
- log.warn(`No files found in reuse library ${libName} for preview`);
72
- continue;
73
- }
74
- for (const [filename, content] of libFiles) {
75
- mergedFiles.set(filename, content);
76
- if (filename.includes(XS_APP_JSON_FILE)) {
77
- xsAppFiles.push(content);
78
- }
79
- }
80
- }
81
- this.searchBaseAppXsAppJsonFile(xsAppFiles, baseAppFiles);
82
- let xsAppJson = merge(xsAppFiles);
83
- if (xsAppJson) {
84
- xsAppJson = await fetchCredentialsAndEnhanceRoutes(xsAppJson, this.configuration);
85
- mergedFiles.set(XS_APP_JSON_FILE, xsAppJson);
86
- }
87
- if (mergedFiles.size === 0) {
88
- return;
89
- }
90
- await ResourceUtil.writeInProject(REUSE_DIR, mergedFiles);
91
- }
92
- preReadLibs(reuseLibs, repository) {
93
- const promises = new Map();
94
- reuseLibs.forEach(lib => {
95
- log.info(`Downloading reuse library '${lib.html5AppName}' version '${lib.html5AppVersion}'`);
96
- const resource = {
97
- appName: lib.html5AppName,
98
- appVersion: lib.html5AppVersion,
99
- appHostId: lib.html5AppHostId,
100
- cacheBusterToken: Promise.resolve(lib.html5CacheBusterToken)
101
- };
102
- const promise = repository
103
- .fetch(resource)
104
- .then((libFiles) => PreviewManager.moveLibraryFiles(libFiles, lib.html5AppName, lib.name));
105
- promises.set(lib.html5AppName, promise);
106
- });
107
- return promises;
108
- }
109
- searchBaseAppXsAppJsonFile(xsAppFiles, baseAppFiles) {
110
- const xsAppJsonContent = baseAppFiles.get(XS_APP_JSON_FILE);
111
- if (xsAppJsonContent) {
112
- xsAppFiles.push(xsAppJsonContent);
113
- }
114
- else {
115
- log.warn("xs-app.json is missing in the downloaded base app files for preview");
116
- }
117
- }
118
- static moveLibraryFiles(inputFiles, libraryName, libId) {
119
- const files = new Map();
120
- inputFiles.forEach((content, filename) => {
121
- const newFilename = path.join(libraryName, filename);
122
- // Source path in xs-app.json needs to be adjusted to new location
123
- if (filename.includes(XS_APP_JSON_FILE)) {
124
- content = PreviewManager.modifyRoutes(content, libraryName, libId);
125
- }
126
- files.set(newFilename, content);
127
- });
128
- return files;
129
- }
130
- ;
131
- static modifyRoutes(xsAppJson, libName, libId) {
132
- const xsApp = JSON.parse(xsAppJson);
133
- xsApp.routes = xsApp.routes.map((route) => {
134
- route.source = route.source.replace(new RegExp("^\\^\\/?(resources/)?"), `^/resources/${libId.replaceAll(".", "/")}/`);
135
- if (route.service === "html5-apps-repo-rt") {
136
- route = {
137
- source: route.source,
138
- target: route.target,
139
- localDir: path.join(REUSE_DIR, libName)
140
- };
141
- }
142
- return route;
143
- });
144
- return JSON.stringify(xsApp);
145
- }
146
- }
147
- //# sourceMappingURL=previewManager.js.map
@@ -1,19 +0,0 @@
1
- import { IChange } from "../model/types.js";
2
- export default class FilesUtil {
3
- static filter(files: ReadonlyMap<string, string>): ReadonlyMap<string, string>;
4
- static sortByTimeStamp(a: IChange, b: IChange): number;
5
- /**
6
- * 1p. i18n.properties are not renamed and property keys are ignored during
7
- * the renaming across the files.
8
- * @param files - all files both base and appVariants
9
- * @param references - Reference maps of the app variant
10
- * @returns A map of renamed files
11
- */
12
- static rename(files: ReadonlyMap<string, string>, references: Map<string, string>): ReadonlyMap<string, string>;
13
- private static getManifestSAPUI5DependencyIds;
14
- private static getI18nPropertyKeys;
15
- }
16
- /**
17
- * We might rename appVariantIdHierarchy and dependencies, so we restore them after the renaming.
18
- */
19
- export declare function restoreWhatShouldntBeRenamed(): (_target: any, _propertyKey: string, descriptor: PropertyDescriptor) => void;
@@ -1,88 +0,0 @@
1
- import * as dotenv from "dotenv";
2
- import * as fs from "fs/promises";
3
-
4
- import { Agent } from "https";
5
- import RequestUtil from "../src/util/requestUtil.js";
6
-
7
- dotenv.config();
8
- const httpsAgent = new Agent({ rejectUnauthorized: false });
9
-
10
- export default class MetadataDownloadHelper {
11
-
12
- static async readAllUrls() {
13
- await fs.readdir("./test/resources/annotations/inline", { encoding: "utf8" });
14
- const resultsObject = JSON.parse(await fs.readFile("./test/resources/allReleasedODataServices.json", { encoding: "utf8" }));
15
- return this.exractUrlsFromResponse(resultsObject);
16
- }
17
-
18
- static async fetchAllUrls(host: string) {
19
- const REQUEST_OPTIONS_JSON = {
20
- headers: {
21
- "Content-Type": "application/json; charset=utf-8",
22
- 'Cookie': process.env.cookie,
23
- },
24
- httpsAgent
25
- };
26
- const url = "/sap/bc/ui2/app_index?sap.fiori/cloudDevAdaptationStatus=released&fields=sap.app/id,sap.app/dataSources/OData/uri";
27
- const response = await RequestUtil.get(host + url, REQUEST_OPTIONS_JSON);
28
- const allUris = this.exractUrlsFromResponse(response);
29
- for (const [index, url] of allUris.entries()) {
30
- try {
31
- const metadataFile = await this.fetchMetadataFileByUri(host, url);
32
- if (typeof metadataFile === "object") {
33
- console.error(`Received object instead of xml file with content: ${JSON.stringify(metadataFile)}`)
34
- continue;
35
- }
36
- // @ts-ignore
37
- await fs.writeFile(`test/resources/metadata/download/${index}__${url.replaceAll("/", "_")}.xml`, metadataFile, { encoding: "utf8" });
38
- } catch (e: any) {
39
- console.error(`Error fetching metadata file with url ${url} with error \n\n ${e}`);
40
- continue;
41
- }
42
- }
43
- }
44
-
45
- private static exractUrlsFromResponse(resultsObject: any) {
46
- let allUrls: string[] = [];
47
- resultsObject.results.map((value: any) => {
48
- allUrls = allUrls.concat(value["sap.app/dataSources/OData/uri"]);
49
- });
50
- return allUrls;
51
- }
52
-
53
- static readMetadataFileByFilePath(filePath: string) {
54
- return fs.readFile(filePath, { encoding: "utf8" });
55
- }
56
-
57
- static fetchMetadataFileByUri(host: string, url: string) {
58
- const REQUEST_OPTIONS_XML = {
59
- headers: {
60
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
61
- 'Cookie': process.env.cookie,
62
- },
63
- httpsAgent,
64
- timeout: 4000
65
- };
66
- url = url.endsWith("/") ? `${url}$metadata` : `${url}/$metadata`;
67
- return RequestUtil.get(host + url, REQUEST_OPTIONS_XML);
68
- }
69
- }
70
-
71
- // Get the command line arguments
72
- const args = process.argv;
73
-
74
- // Find the index of the `--host=` argument
75
- const hostArgIndex = args.findIndex(arg => arg.startsWith('--host='));
76
-
77
- // If the `--host=` argument is found
78
- if (hostArgIndex !== -1) {
79
- // Extract the value of the `--host=` argument
80
- const hostArg = args[hostArgIndex];
81
- let host = hostArg.split('=')[1];
82
- host = host.endsWith("/") ? host.substring(0, host.lastIndexOf("/")) : host;
83
-
84
- // Use the `host` variable as needed
85
- MetadataDownloadHelper.fetchAllUrls(host);
86
- } else {
87
- console.info("Please provide missing host parameter");
88
- }
@@ -1,256 +0,0 @@
1
- import { promises as fs } from "fs";
2
- import path from "path";
3
- import yargs from "yargs";
4
- import { hideBin } from "yargs/helpers";
5
- import { Octokit } from "@octokit/rest";
6
- import { retry } from "@octokit/plugin-retry";
7
-
8
- const OctokitClass = Octokit.plugin(retry);
9
-
10
-
11
- /**
12
- * Recursively get all file paths in the workspace root, excluding:
13
- * - test/lib/integration
14
- * - test/fixtures
15
- * - test/expected
16
- * - test/lib/index.perf.ts
17
- * Returns relative paths from the root.
18
- */
19
- async function getAllRootFilesExceptTestExclusions(root: string): Promise<string[]> {
20
- const excludeDirs = [
21
- "test/lib/integration",
22
- "test/fixtures",
23
- "test/expected",
24
- ".git",
25
- "coverage",
26
- ".DS_Store",
27
- "node_modules",
28
- ".nyc_output",
29
- "coverage",
30
- "dist",
31
- "dist-debug",
32
- "dist.zip",
33
- ".env",
34
- "test/resources/metadata/download"
35
- ];
36
- const excludeFiles = [
37
- "test/lib/index.perf.ts",
38
- "scripts/test-integration-prep.sh",
39
- "Jenkinsfile"
40
- ];
41
-
42
- async function walk(dir: string): Promise<string[]> {
43
- const dirents = await fs.readdir(dir, { withFileTypes: true });
44
- const files: string[] = [];
45
- for (const dirent of dirents) {
46
- const relPath = path.relative(root, path.join(dir, dirent.name));
47
- if (excludeDirs.some(ex => relPath === ex || relPath.startsWith(ex + path.sep))) {
48
- continue;
49
- }
50
- if (excludeFiles.includes(relPath)) {
51
- continue;
52
- }
53
- if (dirent.isDirectory()) {
54
- files.push(...await walk(path.join(dir, dirent.name)));
55
- } else {
56
- files.push(relPath);
57
- }
58
- }
59
- return files;
60
- }
61
- return walk(root);
62
- }
63
-
64
- const FILES = await getAllRootFilesExceptTestExclusions(process.cwd());
65
-
66
-
67
- interface PublishArgs {
68
- p?: string;
69
- dryRun?: boolean;
70
- tag?: string;
71
- branch?: string;
72
- [key: string]: unknown;
73
- }
74
-
75
- async function publish() {
76
- const argv = yargs(hideBin(process.argv))
77
- .option("p", {
78
- type: "string",
79
- description: "GitHub token (-p)",
80
- alias: "p"
81
- })
82
- .option("dryRun", {
83
- type: "boolean",
84
- description: "Run without publishing",
85
- default: false
86
- })
87
- .option("tag", {
88
- type: "string",
89
- description: "Publish with a specific tag"
90
- })
91
- .option("branch", {
92
- type: "string",
93
- description: "Branch to update (default: main)",
94
- default: "main",
95
- alias: "b"
96
- })
97
- .help()
98
- .alias("h", "help")
99
- .parseSync() as PublishArgs;
100
-
101
- if (argv.dryRun) {
102
- console.log("Dry run: no publishing will be performed.");
103
- return;
104
- }
105
- const auth = argv.p;
106
- if (auth) {
107
- const octokit = new OctokitClass({ auth });
108
- const ORGANIZATION = "SAP";
109
- const REPO = "ui5-task-adaptation";
110
- await uploadToRepo(octokit, ORGANIZATION, REPO, argv.branch);
111
- if (argv.tag) {
112
- console.log(`Published with tag: ${argv.tag}`);
113
- }
114
- } else {
115
- console.log("Github token is not provided.");
116
- }
117
- }
118
-
119
-
120
- async function getLatestVersion(): Promise<string> {
121
- const pkg = await fs.readFile(path.join(process.cwd(), "package.json"), { encoding: "utf-8" });
122
- const pkgJson = JSON.parse(pkg);
123
- return pkgJson.version;
124
- }
125
-
126
-
127
- async function uploadToRepo(
128
- octokit: InstanceType<typeof OctokitClass>,
129
- org: string,
130
- repo: string,
131
- branch: string = "main"
132
- ): Promise<void> {
133
- const fileBlobs = await Promise.all(Object.values(FILES).map(file => toBlob(octokit, org, repo, path.join(process.cwd(), file))));
134
- const currentCommit = await getCurrentCommit(octokit, org, repo, branch);
135
- const newTree = await createNewTree(
136
- octokit,
137
- org,
138
- repo,
139
- fileBlobs,
140
- FILES,
141
- currentCommit.treeSha
142
- );
143
- const currentVersion = await getLatestVersion();
144
- const commitMessage = `Release ${currentVersion}`;
145
- const newCommit = await createNewCommit(
146
- octokit,
147
- org,
148
- repo,
149
- commitMessage,
150
- newTree.sha,
151
- currentCommit.commitSha
152
- );
153
- await setBranchToCommit(octokit, org, repo, branch, newCommit.sha);
154
- }
155
-
156
-
157
- async function getCurrentCommit(
158
- octokit: InstanceType<typeof OctokitClass>,
159
- org: string,
160
- repo: string,
161
- branch: string = "main"
162
- ): Promise<{ commitSha: string; treeSha: string }> {
163
- const { data: refData } = await octokit.git.getRef({
164
- owner: org,
165
- repo,
166
- ref: `heads/${branch}`,
167
- });
168
- const commitSha = refData.object.sha
169
- const { data: commitData } = await octokit.git.getCommit({
170
- owner: org,
171
- repo,
172
- commit_sha: commitSha,
173
- });
174
- return {
175
- commitSha,
176
- treeSha: commitData.tree.sha,
177
- }
178
- }
179
-
180
-
181
- async function toBlob(
182
- octokit: InstanceType<typeof OctokitClass>,
183
- org: string,
184
- repo: string,
185
- filePath: string
186
- ): Promise<{ sha: string }> {
187
- const content = await fs.readFile(filePath, { encoding: "utf8" });
188
- const blobData = await octokit.git.createBlob({
189
- owner: org,
190
- repo,
191
- content,
192
- encoding: "utf-8",
193
- })
194
- return blobData.data;
195
- }
196
-
197
-
198
- async function createNewTree(
199
- octokit: InstanceType<typeof OctokitClass>,
200
- owner: string,
201
- repo: string,
202
- blobs: { sha: string }[],
203
- paths: string[],
204
- parentTreeSha: string
205
- ): Promise<any> {
206
- const tree = blobs.map(({ sha }, i) => ({
207
- path: paths[i],
208
- mode: "100644" as const,
209
- type: "blob" as const,
210
- sha,
211
- }));
212
- const { data } = await octokit.git.createTree({
213
- owner,
214
- repo,
215
- tree,
216
- base_tree: parentTreeSha,
217
- })
218
- return data;
219
- }
220
-
221
-
222
- async function createNewCommit(
223
- octokit: InstanceType<typeof OctokitClass>,
224
- org: string,
225
- repo: string,
226
- message: string,
227
- currentTreeSha: string,
228
- currentCommitSha: string
229
- ): Promise<any> {
230
- const commit = await octokit.git.createCommit({
231
- owner: org,
232
- repo,
233
- message,
234
- tree: currentTreeSha,
235
- parents: [currentCommitSha],
236
- });
237
- return commit.data;
238
- };
239
-
240
-
241
- async function setBranchToCommit(
242
- octokit: InstanceType<typeof OctokitClass>,
243
- org: string,
244
- repo: string,
245
- branch: string = "main",
246
- commitSha: string
247
- ): Promise<any> {
248
- return octokit.git.updateRef({
249
- owner: org,
250
- repo,
251
- ref: `heads/${branch}`,
252
- sha: commitSha,
253
- });
254
- }
255
-
256
- publish();
@@ -1,4 +0,0 @@
1
- for d in test/fixtures/*/ ; do
2
- echo "$d"
3
- npm --prefix $d i
4
- done
File without changes