This is an automated email from the ASF dual-hosted git repository.

tiagobento pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie-tools.git


The following commit(s) were added to refs/heads/main by this push:
     new 6769e9ab105 kie-issues#1113: On KIE Tools, log all `build-env` 
property access errors to check, after a build, if any error happened (#2280)
6769e9ab105 is described below

commit 6769e9ab105d071bb898fada7da86e324525f255
Author: Tiago Bento <[email protected]>
AuthorDate: Thu May 2 10:41:09 2024 -0400

    kie-issues#1113: On KIE Tools, log all `build-env` property access errors 
to check, after a build, if any error happened (#2280)
---
 .github/workflows/ci_build.yml                     |   9 ++
 scripts/bootstrap/generate_build_env_report.mjs    |  18 +--
 scripts/build-env/src/bin.ts                       | 113 ++++++++---------
 scripts/build-env/src/console_logs.ts              |  79 ++++++++++++
 scripts/build-env/src/index.ts                     | 136 ++-------------------
 scripts/build-env/src/lib.ts                       | 102 ++++++++++++++++
 .../src/{bin.ts => special_print_cases.ts}         |  65 ++--------
 scripts/build-env/src/types.ts                     |  31 +++++
 8 files changed, 301 insertions(+), 252 deletions(-)

diff --git a/.github/workflows/ci_build.yml b/.github/workflows/ci_build.yml
index e1bd63f1b58..b35d8a42b78 100644
--- a/.github/workflows/ci_build.yml
+++ b/.github/workflows/ci_build.yml
@@ -13,6 +13,7 @@ concurrency:
 
 env:
   TMPDIR: "/tmp"
+  BUILD_ENV__accessErrorsLogFileAbsolutePath: 
"/tmp/build-env-access-errors.log"
 
 jobs:
   run:
@@ -150,6 +151,14 @@ jobs:
             const script = 
require("./scripts/check-junit-report-results/src/index.js");
             await script({ core, glob, patterns });
 
+      - name: "Check build-env access errors log"
+        if: always() && !cancelled() && steps.setup_build_mode.outputs.mode != 
'none'
+        shell: bash
+        run: |
+          touch "$BUILD_ENV__accessErrorsLogFileAbsolutePath"
+          cat "$BUILD_ENV__accessErrorsLogFileAbsolutePath"
+          [ "0" == "$(cat "$BUILD_ENV__accessErrorsLogFileAbsolutePath" | wc 
-l | tr -d ' ')" ]
+
       - name: "Check hanging uncommitted files (you should commit those!)"
         if: always() && !cancelled() && steps.setup_build_mode.outputs.mode != 
'none'
         shell: bash
diff --git a/scripts/bootstrap/generate_build_env_report.mjs 
b/scripts/bootstrap/generate_build_env_report.mjs
index c44965b5546..af1d99bf7a4 100644
--- a/scripts/bootstrap/generate_build_env_report.mjs
+++ b/scripts/bootstrap/generate_build_env_report.mjs
@@ -18,10 +18,9 @@
  */
 
 import * as path from "path";
-import * as url from "url";
 import * as fs from "fs";
 import { markdownTable } from "markdown-table";
-import { treatVarToPrint } from "@kie-tools-scripts/build-env";
+import { treatVarToPrint, requireEnv } from 
"@kie-tools-scripts/build-env/dist/lib.js";
 import { pnpmFilter } from "./pnpm_filter.js";
 
 let pnpmFilterString;
@@ -50,21 +49,16 @@ async function main() {
   }
 
   // NOTE: This is not recursive as build-env
-  const pkgPathsWithEnvDir = Object.keys(await pnpmFilter(pnpmFilterString, { 
alwaysIncludeRoot: false })).filter(
+  const pkgDirsWithEnvDir = Object.keys(await pnpmFilter(pnpmFilterString, { 
alwaysIncludeRoot: false })).filter(
     (pkgPath) => fs.existsSync(path.resolve(pkgPath, "env"))
   );
 
   const pkgs = await Promise.all(
-    pkgPathsWithEnvDir.map(async (pkgPath) => {
-      const envPathJS = path.resolve(path.join(pkgPath, "env", "index.js"));
-      const envPathCJS = path.resolve(path.join(pkgPath, "env", "index.cjs"));
-      const envPathJSExist = fs.existsSync(envPathJS);
-      const envPath = envPathJSExist ? envPathJS : envPathCJS;
-
+    pkgDirsWithEnvDir.map(async (pkgDir) => {
       return {
-        env: (await import(url.pathToFileURL(envPath))).default,
-        manifest: JSON.parse(fs.readFileSync(path.resolve(pkgPath, 
"package.json"), "utf-8")),
-        dir: pkgPath,
+        env: await requireEnv(pkgDir),
+        manifest: JSON.parse(fs.readFileSync(path.resolve(pkgDir, 
"package.json"), "utf-8")),
+        dir: pkgDir,
       };
     })
   );
diff --git a/scripts/build-env/src/bin.ts b/scripts/build-env/src/bin.ts
index ca1606c2b98..7ebb2b471eb 100644
--- a/scripts/build-env/src/bin.ts
+++ b/scripts/build-env/src/bin.ts
@@ -17,70 +17,38 @@
  * under the License.
  */
 
+import { ERROR_ACCESS_LOG_FILE_ABSOLUTE_PATH_ENV_VAR_NAME, findEnv } from 
"./lib";
+import { LOGS } from "./console_logs";
+
 import * as path from "path";
+import * as fs from "fs";
+import * as os from "os";
+
+import { treatSpecialPrintCases } from "./special_print_cases";
 
-import { findEnv, flattenObj, logs, parseVars } from "./index";
+const opt = process.argv[2];
+const flag = process.argv[3];
 
 async function main() {
   const { env, vars, self } = await findEnv(path.resolve("."), 
path.resolve("."));
 
-  const opt = process.argv[2];
-  const flags = process.argv[3];
-
-  if (opt === "--print-vars") {
-    console.log(JSON.stringify(flattenObj(parseVars(vars)), undefined, 2));
-    process.exit(0);
-  }
-
-  if (opt === "--print-env") {
-    console.log(JSON.stringify(flattenObj(env), undefined, 2));
-    process.exit(0);
-  }
-
-  if (opt === "--print-env-file") {
-    const flattenedParsedVars = flattenObj(parseVars(vars));
-    let envFile = "";
-    for (const key of Object.keys(flattenedParsedVars)) {
-      envFile += `${key}=${flattenedParsedVars[key]}\n`;
-    }
-    console.log(envFile);
-    process.exit(0);
-  }
-
-  if (opt === "--print-vars:self") {
-    console.log(JSON.stringify(flattenObj(parseVars(self.vars)), undefined, 
2));
-    process.exit(0);
-  }
-
-  if (opt === "--print-env:self") {
-    console.log(JSON.stringify(flattenObj(self.env), undefined, 2));
-    process.exit(0);
-  }
-
-  if (opt === "--print-env-file:self") {
-    const flattenedParsedVars = flattenObj(parseVars(self.vars));
-    let envFile = "";
-    for (const key of Object.keys(flattenedParsedVars)) {
-      envFile += `${key}=${flattenedParsedVars[key]}\n`;
-    }
-    console.log(envFile);
-    process.exit(0);
-  }
+  // This will exit the process if a special print case is requested using 
`opt`.
+  treatSpecialPrintCases({ opt, vars, self });
 
   const propertyPath = opt;
   if (!propertyPath) {
-    console.error(logs.pleaseProvideEnvPropertyPath());
-    console.error(logs.seeAllEnvProperties());
-    process.exit(1);
+    console.error(LOGS.error.pleaseProvideEnvPropertyPath());
+    console.error(LOGS.info.seeAllEnvProperties());
+    throw new Error(`[build-env] property-path-not-provided-error`);
   }
 
   let envPropertyValue: any = env;
   for (const p of propertyPath.split(".")) {
     envPropertyValue = envPropertyValue[p];
     if (envPropertyValue === undefined) {
-      console.error(logs.propertyNotFound(propertyPath));
-      console.error(logs.seeAllEnvProperties());
-      process.exit(1);
+      console.error(LOGS.error.propertyNotFound({ propertyPath }));
+      console.error(LOGS.info.seeAllEnvProperties());
+      throw new Error(`[build-env] property-not-found-error`);
     }
   }
 
@@ -89,23 +57,46 @@ async function main() {
     typeof envPropertyValue !== "boolean" &&
     typeof envPropertyValue !== "number"
   ) {
-    console.error(logs.cantReturnNonString(propertyPath, typeof 
envPropertyValue));
+    console.error(LOGS.error.cantReturnNonString({ propertyPath, propertyType: 
typeof envPropertyValue }));
     console.error(envPropertyValue);
-    process.exit(1);
+    throw new Error(`[build-env] cant-return-non-string-error`);
   }
 
-  if (flags === "--not") {
+  if (flag === "--not") {
     const isBoolean = `${envPropertyValue}` === "true" || 
`${envPropertyValue}` === "false";
-    if (isBoolean) {
-      console.log(!(`${envPropertyValue}` === "true"));
-      process.exit(0);
-    } else {
-      console.error(logs.cantNegateNonBoolean(envPropertyValue));
-      process.exit(1);
+    if (!isBoolean) {
+      console.error(LOGS.error.cantNegateNonBoolean({ envPropertyValue }));
+      throw new Error(`[build-env] cant-negate-non-boolean-error`);
     }
-  }
 
-  console.log(envPropertyValue);
+    console.log(!(`${envPropertyValue}` === "true"));
+  } else {
+    console.log(envPropertyValue);
+  }
 }
 
-main();
+main().catch((e) => {
+  const suppliedPath = 
process.env[ERROR_ACCESS_LOG_FILE_ABSOLUTE_PATH_ENV_VAR_NAME];
+  const defaultPath = path.join(os.tmpdir(), "build-env-access-errors.log");
+
+  let logFilePath;
+  if (!suppliedPath) {
+    logFilePath = defaultPath;
+    
console.error(LOGS.warn.defaultingAccessErrorsLogFileToTmpDirBecauseNotSupplied({
 logFilePath }));
+  } else if (!path.isAbsolute(suppliedPath)) {
+    logFilePath = defaultPath;
+    
console.error(LOGS.warn.defaultingAccessErrorsLogFileToTmpDirBecauseNotSupplied({
 logFilePath }));
+  } else {
+    logFilePath = suppliedPath;
+    console.error(LOGS.error.usingConfiguredAccessErrorLogFile({ logFilePath 
}));
+  }
+
+  try {
+    fs.appendFileSync(logFilePath, `${e.message} :: cwd:${path.resolve(".")} 
opt:${opt} flag:${flag}\n`, "utf-8");
+    console.error(LOGS.info.wroteAccessErrorLog({ logFilePath }));
+  } catch (e) {
+    console.error(LOGS.error.errorWritingAccessErrorLog({ logFilePath }));
+    console.error(e);
+    throw e;
+  }
+});
diff --git a/scripts/build-env/src/console_logs.ts 
b/scripts/build-env/src/console_logs.ts
new file mode 100644
index 00000000000..2ce7dcba018
--- /dev/null
+++ b/scripts/build-env/src/console_logs.ts
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { ERROR_ACCESS_LOG_FILE_ABSOLUTE_PATH_ENV_VAR_NAME } from "./lib";
+
+export const LOGS = {
+  error: {
+    foundConflictingVars() {
+      return `[build-env] ERROR: Found conflicting vars.`;
+    },
+    foundConflictingRootProps() {
+      return `[build-env] ERROR: Found conflicting root properties.`;
+    },
+    envNotFound(args: { envPath: string }) {
+      return `[build-env] ERROR: Env not found at '${args.envPath}'`;
+    },
+    envFileLoadingError(args: { envFilePath: string }) {
+      return `[build-env] ERROR: Error loading env at '${args.envFilePath}'`;
+    },
+    findEnvRecursionStopped(args: { startDir: string; curDir: string; 
envRecursionStopPath: string }) {
+      return `[build-env] ERROR: Couldn't load env from '${args.startDir}' to 
'${args.curDir}'. Stopped at '${args.envRecursionStopPath}'`;
+    },
+    cantNegateNonBoolean(args: { envPropertyValue: string | boolean | number 
}) {
+      return `[build-env] ERROR: Cannot negate non-boolean value 
'${args.envPropertyValue}'`;
+    },
+    cantReturnNonString(args: { propertyPath: string; propertyType: string }) {
+      return `[build-env] ERROR: Env property '${args.propertyPath}' is not of 
type "string", "number", or "boolean". Found "${args.propertyType}":`;
+    },
+    pleaseProvideEnvPropertyPath() {
+      return `[build-env] ERROR: Please provide an env property path.`;
+    },
+    propertyNotFound(args: { propertyPath: string }): string {
+      return `[build-env] ERROR: Env property '${args.propertyPath}' not 
found.`;
+    },
+    usingConfiguredAccessErrorLogFile({ logFilePath }: { logFilePath: string 
}) {
+      return `[build-env] ERROR: Env property access error. Using configured 
access errors log file '${logFilePath}'`;
+    },
+    errorWritingAccessErrorLog({ logFilePath }: { logFilePath: string }) {
+      return `[build-env] ERROR: Error writing access error log to 
'${logFilePath}'. Property access errors won't be detectable.`;
+    },
+  },
+  warn: {
+    defaultingAccessErrorsLogFileToTmpDirBecauseNotAbsolute(args: { 
suppliedPath: string; logFilePath: string }) {
+      return `[build-env] WARNING: Supplied path for access errors log file is 
not absolute ('${args.suppliedPath}'). Defaulting to '${args.logFilePath}'.`;
+    },
+    defaultingAccessErrorsLogFileToTmpDirBecauseNotSupplied(args: { 
logFilePath: string }) {
+      return `[build-env] WARNING: Access errors log file absolute path not 
supplied via env var ${ERROR_ACCESS_LOG_FILE_ABSOLUTE_PATH_ENV_VAR_NAME}. 
Defaulting to '${args.logFilePath}'.`;
+    },
+  },
+  info: {
+    seeAllEnvProperties() {
+      return `[build-env] See all env properties with 'build-env --print-env'`;
+    },
+    wroteAccessErrorLog(args: { logFilePath: string }) {
+      return `[build-env] Wrote access error to: '${args.logFilePath}'.`;
+    },
+  },
+  debug: {
+    envFound(args: { envPath: string }) {
+      return `[build-env] DEBUG: Found env at '${args.envPath}'`;
+    },
+  },
+};
diff --git a/scripts/build-env/src/index.ts b/scripts/build-env/src/index.ts
index 947fee2df20..5c4900fb319 100644
--- a/scripts/build-env/src/index.ts
+++ b/scripts/build-env/src/index.ts
@@ -17,19 +17,8 @@
  * under the License.
  */
 
-import * as fs from "fs";
-import * as path from "path";
-
-export type EnvAndVarsWithName<T> = { vars: { [K in keyof T]: VarWithName }; 
env: object; self: EnvAndVarsWithName<T> };
-
-export type Var = {
-  default: string | undefined;
-  description: string;
-};
-
-export type VarWithName = Var & { name: string };
-
-//
+import { LOGS } from "./console_logs";
+import { VarWithName, Var, EnvAndVarsWithName } from "./types";
 
 export function str2bool(str: string | undefined) {
   return str === "true";
@@ -51,23 +40,6 @@ export function varsWithName<T>(obj: { [K in keyof T]: Var 
}) {
   return obj as { [K in keyof T]: VarWithName };
 }
 
-export function treatVarToPrint<T>(varr: VarWithName) {
-  let value = getOrDefault(varr);
-  if (varr.default === undefined && value) {
-    value += " <- CHANGED 👀️ ";
-  } else if (value === undefined) {
-    value = "[unset] Default value may vary ⚠️ ";
-  } else if (value !== varr.default) {
-    value += " <- CHANGED 👀️ ";
-  }
-  return value;
-}
-
-function detectConflictingProps<T>(acc: object, d: object | 
EnvAndVarsWithName<T>) {
-  const accProps = new Set(Object.keys(acc));
-  return Object.keys(d).filter((a) => accProps.has(a));
-}
-
 export function composeEnv<T>(deps: EnvAndVarsWithName<any>[], self: 
EnvAndVarsWithName<T>) {
   // this avoids transitive dependencies coming from env deps
   // and respects the order of "import"
@@ -77,20 +49,18 @@ export function composeEnv<T>(deps: 
EnvAndVarsWithName<any>[], self: EnvAndVarsW
     vars: selfEnvs.reduce((acc, d) => {
       const conflictingProps = detectConflictingProps(acc, d.vars);
       if (conflictingProps.length > 0) {
-        console.error("[build-env] ERROR: Found conflicting vars.");
+        console.error(LOGS.error.foundConflictingVars());
         console.error(conflictingProps);
-        console.error("[build-env] Done.");
-        process.exit(1);
+        throw new Error("[build-env] conflicting-vars-error");
       }
       return { ...acc, ...d.vars };
     }, {}),
     env: selfEnvs.reduce((acc, d) => {
       const conflictingProps = detectConflictingProps(acc, d.env);
       if (conflictingProps.length > 0) {
-        console.error("[build-env] ERROR: Found conflicting root properties.");
+        console.error(LOGS.error.foundConflictingRootProps());
         console.error(conflictingProps);
-        console.error("[build-env] Done.");
-        process.exit(1);
+        throw new Error("[build-env] conflicting-root-props-error");
       }
 
       return { ...acc, ...d.env };
@@ -99,95 +69,7 @@ export function composeEnv<T>(deps: 
EnvAndVarsWithName<any>[], self: EnvAndVarsW
   };
 }
 
-const BUILD_ENV_RECURSION_STOP_FILE_NAME = ".build-env-root";
-
-export const logs = {
-  envNotFound: (envPath: string) => {
-    return `[build-env] env not found at '${envPath}'`;
-  },
-  envFound: (envPath: string) => {
-    return `[build-env] found env at '${envPath}'`;
-  },
-  envLoadingError: (envPath: string) => {
-    return `[build-env] error loading env at '${envPath}'`;
-  },
-  envRecursionStopped: (startDir: string, curDir: string, 
envRecursionStopPath: string) => {
-    return `[build-env] Couldn't load env from '${startDir}' to '${curDir}'. 
Stopped at '${envRecursionStopPath}'`;
-  },
-  cantNegateNonBoolean(envPropertyValue: string | boolean | number) {
-    return `[build-env] Cannot negate non-boolean value '${envPropertyValue}'`;
-  },
-  cantReturnNonString(propertyPath: string, propertyType: string) {
-    return `[build-env] Env property '${propertyPath}' is not of type 
"string", "number", or "boolean". Found "${propertyType}":`;
-  },
-  pleaseProvideEnvPropertyPath() {
-    return `[build-env] Please provide an env property path.`;
-  },
-  seeAllEnvProperties() {
-    return `[build-env] See all env properties with 'build-env --print-env'`;
-  },
-  propertyNotFound(propertyPath: string) {
-    return `[build-env] Env property '${propertyPath}' not found.`;
-  },
-};
-
-export async function requireEnv(curDir: string): 
Promise<EnvAndVarsWithName<any> | undefined> {
-  const envPathJS = path.resolve(curDir, "env", "index.js");
-  const envPathCJS = path.resolve(curDir, "env", "index.cjs");
-  const envPathJSExist = fs.existsSync(envPathJS);
-  const envPathCJSExist = fs.existsSync(envPathCJS);
-  const envPath = envPathJSExist ? envPathJS : envPathCJS;
-
-  if (!envPathJSExist && !envPathCJSExist) {
-    // console.debug(logs.envNotFound(envPath));
-    return undefined;
-  }
-
-  // console.debug(logs.envFound(envPath));
-
-  try {
-    return (await import(envPath)) as EnvAndVarsWithName<any>;
-  } catch (e) {
-    console.info(logs.envLoadingError(envPath));
-    throw e;
-  }
-}
-
-export async function findEnv(startDir: string, curDir: string): 
Promise<EnvAndVarsWithName<any>> {
-  const env = await requireEnv(curDir);
-  if (env) {
-    return env;
-  }
-
-  const envRecursionStopPath = path.resolve(curDir, 
BUILD_ENV_RECURSION_STOP_FILE_NAME);
-  if (fs.existsSync(envRecursionStopPath)) {
-    console.info(logs.envRecursionStopped(startDir, curDir, 
envRecursionStopPath));
-    process.exit(1);
-  }
-
-  return findEnv(startDir, path.dirname(curDir));
-}
-
-export function parseVars<T>(vars: { [K in keyof T]: VarWithName }) {
-  const result: Record<string, string | undefined> = {};
-  for (const v in vars) {
-    result[v] = treatVarToPrint(vars[v]);
-  }
-  return result;
-}
-
-export function flattenObj(
-  obj: Record<string, any>,
-  parent: any = undefined,
-  res: Record<string, any> = {}
-): Record<string, any> {
-  for (const key in obj) {
-    const propName = parent ? parent + "." + key : key;
-    if (typeof obj[key] == "object") {
-      flattenObj(obj[key], propName, res);
-    } else {
-      res[propName] = obj[key];
-    }
-  }
-  return res;
+function detectConflictingProps<T>(acc: object, d: object | 
EnvAndVarsWithName<T>) {
+  const accProps = new Set(Object.keys(acc));
+  return Object.keys(d).filter((a) => accProps.has(a));
 }
diff --git a/scripts/build-env/src/lib.ts b/scripts/build-env/src/lib.ts
new file mode 100644
index 00000000000..d432e040734
--- /dev/null
+++ b/scripts/build-env/src/lib.ts
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { EnvAndVarsWithName, VarWithName } from "./types";
+import { getOrDefault } from "./index";
+import { LOGS } from "./console_logs";
+
+import * as path from "path";
+import * as fs from "fs";
+
+export const ERROR_ACCESS_LOG_FILE_ABSOLUTE_PATH_ENV_VAR_NAME = 
"BUILD_ENV__accessErrorsLogFileAbsolutePath";
+export const BUILD_ENV_RECURSION_STOP_FILE_NAME = ".build-env-root";
+
+export async function requireEnv(curDir: string): 
Promise<EnvAndVarsWithName<any> | undefined> {
+  const envPathJs = path.resolve(curDir, "env", "index.js");
+  const envPathCjs = path.resolve(curDir, "env", "index.cjs");
+
+  const envPathJsExists = fs.existsSync(envPathJs);
+  const envPathCjsExists = fs.existsSync(envPathCjs);
+  if (!envPathJsExists && !envPathCjsExists) {
+    // console.debug(logs.error.envNotFound({envPath}));
+    return undefined;
+  }
+
+  const envFilePath = envPathJsExists ? envPathJs : envPathCjs;
+  // console.debug(logs.debug.envFound({envPath}));
+
+  try {
+    return (await import(envFilePath)) as EnvAndVarsWithName<any>;
+  } catch (e) {
+    console.error(LOGS.error.envFileLoadingError({ envFilePath }));
+    console.error(e);
+    throw new Error("[build-env] env-loading-error");
+  }
+}
+
+export async function findEnv(startDir: string, curDir: string): 
Promise<EnvAndVarsWithName<any>> {
+  const env = await requireEnv(curDir);
+  if (env) {
+    return env;
+  }
+
+  const envRecursionStopPath = path.resolve(curDir, 
BUILD_ENV_RECURSION_STOP_FILE_NAME);
+  if (fs.existsSync(envRecursionStopPath)) {
+    console.error(LOGS.error.findEnvRecursionStopped({ startDir, curDir, 
envRecursionStopPath }));
+    throw new Error("[build-env] env-loading-error");
+  }
+
+  return findEnv(startDir, path.dirname(curDir));
+}
+
+export function treatVarToPrint<T>(varr: VarWithName) {
+  let value = getOrDefault(varr);
+  if (varr.default === undefined && value) {
+    value += " <- CHANGED 👀️ ";
+  } else if (value === undefined) {
+    value = "[unset] Default value may vary ⚠️ ";
+  } else if (value !== varr.default) {
+    value += " <- CHANGED 👀️ ";
+  }
+  return value;
+}
+
+export function parseVars<T>(vars: { [K in keyof T]: VarWithName }) {
+  const result: Record<string, string | undefined> = {};
+  for (const v in vars) {
+    result[v] = treatVarToPrint(vars[v]);
+  }
+  return result;
+}
+
+export function flattenObj(
+  obj: Record<string, any>,
+  parent: any = undefined,
+  res: Record<string, any> = {}
+): Record<string, any> {
+  for (const key in obj) {
+    const propName = parent ? parent + "." + key : key;
+    if (typeof obj[key] == "object") {
+      flattenObj(obj[key], propName, res);
+    } else {
+      res[propName] = obj[key];
+    }
+  }
+  return res;
+}
diff --git a/scripts/build-env/src/bin.ts 
b/scripts/build-env/src/special_print_cases.ts
similarity index 57%
copy from scripts/build-env/src/bin.ts
copy to scripts/build-env/src/special_print_cases.ts
index ca1606c2b98..33d3c0f728d 100644
--- a/scripts/build-env/src/bin.ts
+++ b/scripts/build-env/src/special_print_cases.ts
@@ -17,16 +17,19 @@
  * under the License.
  */
 
-import * as path from "path";
-
-import { findEnv, flattenObj, logs, parseVars } from "./index";
-
-async function main() {
-  const { env, vars, self } = await findEnv(path.resolve("."), 
path.resolve("."));
-
-  const opt = process.argv[2];
-  const flags = process.argv[3];
-
+import { env } from "process";
+import { flattenObj, parseVars } from "./lib";
+import { EnvAndVarsWithName } from "./types";
+
+export function treatSpecialPrintCases({
+  opt,
+  vars,
+  self,
+}: {
+  opt: string;
+  vars: EnvAndVarsWithName<any>["vars"];
+  self: EnvAndVarsWithName<any>["self"];
+}) {
   if (opt === "--print-vars") {
     console.log(JSON.stringify(flattenObj(parseVars(vars)), undefined, 2));
     process.exit(0);
@@ -66,46 +69,4 @@ async function main() {
     console.log(envFile);
     process.exit(0);
   }
-
-  const propertyPath = opt;
-  if (!propertyPath) {
-    console.error(logs.pleaseProvideEnvPropertyPath());
-    console.error(logs.seeAllEnvProperties());
-    process.exit(1);
-  }
-
-  let envPropertyValue: any = env;
-  for (const p of propertyPath.split(".")) {
-    envPropertyValue = envPropertyValue[p];
-    if (envPropertyValue === undefined) {
-      console.error(logs.propertyNotFound(propertyPath));
-      console.error(logs.seeAllEnvProperties());
-      process.exit(1);
-    }
-  }
-
-  if (
-    typeof envPropertyValue !== "string" &&
-    typeof envPropertyValue !== "boolean" &&
-    typeof envPropertyValue !== "number"
-  ) {
-    console.error(logs.cantReturnNonString(propertyPath, typeof 
envPropertyValue));
-    console.error(envPropertyValue);
-    process.exit(1);
-  }
-
-  if (flags === "--not") {
-    const isBoolean = `${envPropertyValue}` === "true" || 
`${envPropertyValue}` === "false";
-    if (isBoolean) {
-      console.log(!(`${envPropertyValue}` === "true"));
-      process.exit(0);
-    } else {
-      console.error(logs.cantNegateNonBoolean(envPropertyValue));
-      process.exit(1);
-    }
-  }
-
-  console.log(envPropertyValue);
 }
-
-main();
diff --git a/scripts/build-env/src/types.ts b/scripts/build-env/src/types.ts
new file mode 100644
index 00000000000..3d7b87f2bd8
--- /dev/null
+++ b/scripts/build-env/src/types.ts
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+export type EnvAndVarsWithName<T> = {
+  vars: { [K in keyof T]: VarWithName };
+  env: object;
+  self: EnvAndVarsWithName<T>;
+};
+
+export type Var = {
+  default: string | undefined;
+  description: string;
+};
+
+export type VarWithName = Var & { name: string };


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to