Skip to content

Commit

Permalink
ci(github): add check to validate exported types being correct
Browse files Browse the repository at this point in the history
Primary Changes
---------------
1. Added get-all-tgz-path.ts to get all tgz files path
2. Added run-attw-on-tgz.ts to run attw on each tgz filepath
3. Added are-the-types-wrong as part of the custom-checks mechanism

Fixes: hyperledger-cacti#3140

Signed-off-by: ruzell22 <[email protected]>
  • Loading branch information
ruzell22 committed Nov 11, 2024
1 parent 7af9983 commit b1d5dd7
Show file tree
Hide file tree
Showing 6 changed files with 365 additions and 3 deletions.
1 change: 1 addition & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"approveformyorg",
"askar",
"Askar",
"attw",
"Authz",
"authzn",
"AWSSM",
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"tools:fix-pkg-npm-scope": "TS_NODE_PROJECT=tools/tsconfig.json node --experimental-json-modules --trace-deprecation --experimental-modules --abort-on-uncaught-exception --loader ts-node/esm --experimental-specifier-resolution=node ./tools/custom-checks/check-pkg-npm-scope.ts",
"tools:sort-package-json": "TS_NODE_PROJECT=tools/tsconfig.json node --experimental-json-modules --trace-deprecation --experimental-modules --abort-on-uncaught-exception --loader ts-node/esm --experimental-specifier-resolution=node ./tools/sort-package-json.ts",
"tools:check-missing-node-deps": "TS_NODE_PROJECT=tools/tsconfig.json node --experimental-json-modules --trace-deprecation --experimental-modules --abort-on-uncaught-exception --loader ts-node/esm --experimental-specifier-resolution=node ./tools/custom-checks/check-missing-node-deps.ts",
"tools:are-the-types-wrong": "TS_NODE_PROJECT=./tools/tsconfig.json node --trace-deprecation --experimental-modules --abort-on-uncaught-exception --loader ts-node/esm --experimental-specifier-resolution=node ./tools/custom-checks/run-attw-on-tgz.ts",
"generate-api-server-config": "node ./tools/generate-api-server-config.js",
"sync-ts-config": "TS_NODE_PROJECT=tools/tsconfig.json node --experimental-json-modules --loader ts-node/esm ./tools/sync-npm-deps-to-tsc-projects.ts",
"start:api-server": "node ./packages/cactus-cmd-api-server/dist/lib/main/typescript/cmd/cactus-api.js --config-file=.config.json",
Expand Down Expand Up @@ -121,6 +122,7 @@
"zod": ">=3.22.3"
},
"devDependencies": {
"@arethetypeswrong/cli": "0.16.4",
"@babel/parser": "7.24.7",
"@babel/types": "7.24.7",
"@bufbuild/buf": "1.30.0",
Expand Down
49 changes: 49 additions & 0 deletions tools/custom-checks/get-all-tgz-path.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import path from "path";
import { fileURLToPath } from "url";
import { globby, Options as GlobbyOptions } from "globby";
import lernaCfg from "../../lerna.json" assert { type: "json" };

/**
* Interface for the response of the getAllTgzPath function.
* @property {Array<string>} relativePaths - An array of relative paths to the
* package directories.
*/

export interface IGetAllTgzPathResponse {
readonly relativePaths: Readonly<Array<string>>;
}

/**
* Asynchronous function to get all tgz filepaths in a Lerna monorepo.
* @returns {Promise<IGetAllTgzPathResponse>} A promise that resolves to an
* object containing the arrays of relative paths to the all tgz files.
*/

export async function getAllTgzPath(): Promise<IGetAllTgzPathResponse> {
const TAG = "[tools/get-all-tgz-path.ts]";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const SCRIPT_DIR = __dirname;
const PROJECT_DIR = path.join(SCRIPT_DIR, "../../");

console.log(`${TAG} SCRIPT_DIR=${SCRIPT_DIR}`);
console.log(`${TAG} PROJECT_DIR=${PROJECT_DIR}`);

const globbyOpts: GlobbyOptions = {
cwd: PROJECT_DIR,
onlyFiles: true,
expandDirectories: false,
ignore: ["**/node_modules"],
};

const tgzFilesPattern = lernaCfg.packages.map(
(pkg: string) => `${pkg}/**/hyperledger-*.tgz`,
);

const tgzFilesRelative = await globby(tgzFilesPattern, globbyOpts);
console.log("%s Found %s tgz files.", TAG, tgzFilesRelative.length);

return {
relativePaths: tgzFilesRelative,
};
}
83 changes: 83 additions & 0 deletions tools/custom-checks/run-attw-on-tgz.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import esMain from "es-main";
import { getAllTgzPath } from "./get-all-tgz-path";
import { exec } from "child_process";
import { exit } from "process";
import { promisify } from "node:util";
import { rm } from "fs";

const execPromise = promisify(exec);

async function cleanUpTgzFiles(): Promise<void> {
const TAG = "[tools/custom-checks/run-attw-on-tgz.ts]";
console.log(`${TAG} Cleaning up existing .tgz files...`);

const { relativePaths: tgzFilesRelative } = await getAllTgzPath();

for (const filePath of tgzFilesRelative) {
await rm(filePath, { recursive: true, force: true }, () => {});
console.log(`${TAG} Deleted ${filePath}`);
}
}

export async function runAttwOnTgz(): Promise<[boolean, string[]]> {
await cleanUpTgzFiles();

const TAG = "[tools/custom-checks/run-attw-on-tgz.ts]";
await execCommand("yarn lerna exec 'npm pack'", true);
console.log(`${TAG} Packaging .tgz files`);

console.log(`${TAG} Fetching .tgz file paths.`);
const { relativePaths: tgzFilesRelative } = await getAllTgzPath();

const attwFailedPackages: string[] = [];

for (const filePath of tgzFilesRelative) {
try {
const output = await execCommand("attw", filePath);
console.log(output);
} catch (error: any) {
attwFailedPackages.push(
`ERROR ${filePath}: ${error.message} ${error.output}`,
);
}
}

const success = attwFailedPackages.length === 0;
return [success, attwFailedPackages];
}

async function execCommand(
binaryName: string,
argument: string | boolean,
): Promise<string> {
let command;
if (typeof argument === "boolean") {
command = binaryName;
} else if (typeof argument === "string") {
command = `${binaryName} ./${argument}`;
} else {
throw new Error("Invalid arguments for execCommand");
}

try {
const { stdout } = await execPromise(command);
return stdout;
} catch (error: any) {
const { stdout, stderr } = error;
const output =
(stdout ? `stdout:\n${stdout}` : "") +
(stderr ? `\nstderr:\n${stderr}` : "");
error.output = output;
throw error;
}
}

if (esMain(import.meta)) {
const [success, attwFailedPackages] = await runAttwOnTgz();
if (!success) {
console.log("Types are wrong for these packages:");
console.log(attwFailedPackages);
exit(1);
}
exit(0);
}
7 changes: 7 additions & 0 deletions tools/custom-checks/run-custom-checks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
checkMissingNodeDeps,
} from "./check-missing-node-deps";
import { getAllPkgDirs } from "./get-all-pkg-dirs";
import { runAttwOnTgz } from "./run-attw-on-tgz";

export async function runCustomChecks(
argv: string[],
Expand Down Expand Up @@ -73,6 +74,12 @@ export async function runCustomChecks(
overallSuccess = overallSuccess && success;
}

{
const [success, errors] = await runAttwOnTgz();
overallErrors = overallErrors.concat(errors);
overallSuccess = overallSuccess && success;
}

if (!overallSuccess) {
overallErrors.forEach((it) => console.error(it));
} else {
Expand Down
Loading

0 comments on commit b1d5dd7

Please sign in to comment.