From c4ab72fe11fc20d34f53ea1c67c7628437e90adb Mon Sep 17 00:00:00 2001 From: hainenber Date: Fri, 29 Nov 2024 22:58:43 +0700 Subject: [PATCH] feat(scripts): convert all service initialization script to Typescript Signed-off-by: hainenber --- package-lock.json | 109 ++++++++++++++++++ package.json | 7 +- .../{start-jenkins.js => start-jenkins.ts} | 59 ++++++---- scripts/start-nexus.js | 92 --------------- scripts/start-nexus.ts | 98 ++++++++++++++++ scripts/utils/common.js | 30 ----- scripts/utils/common.ts | 34 ++++++ scripts/utils/index.js | 3 - scripts/utils/index.ts | 3 + scripts/utils/{jenkins.js => jenkins.ts} | 32 +++-- .../{sonatype_nexus.js => sonatype_nexus.ts} | 21 ++-- 11 files changed, 321 insertions(+), 167 deletions(-) rename scripts/{start-jenkins.js => start-jenkins.ts} (81%) delete mode 100644 scripts/start-nexus.js create mode 100644 scripts/start-nexus.ts delete mode 100644 scripts/utils/common.js create mode 100644 scripts/utils/common.ts delete mode 100644 scripts/utils/index.js create mode 100644 scripts/utils/index.ts rename scripts/utils/{jenkins.js => jenkins.ts} (58%) rename scripts/utils/{sonatype_nexus.js => sonatype_nexus.ts} (93%) diff --git a/package-lock.json b/package-lock.json index 5caa88e..829440c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,14 +11,17 @@ "dependencies": { "@logtape/logtape": "^0.8.0", "@octokit/types": "^13.6.2", + "axios": "^1.7.8", "dotenv": "^16.4.5", "es-toolkit": "^1.27.0", "execa": "^9.5.1", + "glob": "^11.0.0", "mustache": "^4.2.0", "octokit": "^4.0.2", "rimraf": "^6.0.1" }, "devDependencies": { + "@types/mustache": "^4.2.5", "@types/node": "^22.10.0" } }, @@ -361,6 +364,13 @@ "version": "8.10.145", "license": "MIT" }, + "node_modules/@types/mustache": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@types/mustache/-/mustache-4.2.5.tgz", + "integrity": "sha512-PLwiVvTBg59tGFL/8VpcGvqOu3L4OuveNvPi0EYbWchRdEVP++yRUXJPFl+CApKEq13017/4Nf7aQ5lTtHUNsA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { "version": "22.10.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.0.tgz", @@ -395,6 +405,23 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.8.tgz", + "integrity": "sha512-Uu0wb7KNqK2t5K+YQyVCLM76prD5sRFjKHbJYCP1J7JFGEQ6nN7HWn9+04LAeiJ3ji54lgS/gZCH1oxyrf1SPw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -436,6 +463,18 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/cross-spawn": { "version": "7.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.5.tgz", @@ -450,6 +489,15 @@ "node": ">= 8" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/dotenv": { "version": "16.4.5", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", @@ -525,6 +573,26 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/foreground-child": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", @@ -541,6 +609,20 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/get-stream": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz", @@ -663,6 +745,27 @@ "node": "18 >=18.20 || 20 || >=22" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/minimatch": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz", @@ -810,6 +913,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/rimraf": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz", diff --git a/package.json b/package.json index 9ada084..ab3cf8b 100644 --- a/package.json +++ b/package.json @@ -8,22 +8,25 @@ "type": "module", "license": "MIT", "scripts": { - "start-nexus": "node scripts/start-nexus.js", - "start-jenkins": "node scripts/start-jenkins.js", + "start-nexus": "deno --allow-env --allow-read --allow-sys --allow-write --allow-run --allow-net scripts/start-nexus.ts", + "start-jenkins": "deno --allow-env --allow-read --allow-run --allow-write scripts/start-jenkins.ts", "lint-fix": "deno fmt", "sync_forked_repos": "deno run --allow-net --allow-env scripts/sync_forked_repos.ts" }, "dependencies": { "@logtape/logtape": "^0.8.0", "@octokit/types": "^13.6.2", + "axios": "^1.7.8", "dotenv": "^16.4.5", "es-toolkit": "^1.27.0", "execa": "^9.5.1", + "glob": "^11.0.0", "mustache": "^4.2.0", "octokit": "^4.0.2", "rimraf": "^6.0.1" }, "devDependencies": { + "@types/mustache": "^4.2.5", "@types/node": "^22.10.0" } } diff --git a/scripts/start-jenkins.js b/scripts/start-jenkins.ts similarity index 81% rename from scripts/start-jenkins.js rename to scripts/start-jenkins.ts index d5b545e..808232c 100644 --- a/scripts/start-jenkins.js +++ b/scripts/start-jenkins.ts @@ -1,9 +1,14 @@ import { execa } from "execa"; -import { join as pathJoin } from "path"; -import { writeFile } from "fs/promises"; -import { cpSync, globSync, mkdirSync, readdirSync } from "fs"; +import { join as pathJoin } from "node:path"; +import { + cpSync, + mkdirSync, + readdirSync, + writeFileSync, +} from "node:fs"; +import { globSync } from "glob"; import { drop, head, isNil, isNotNil } from "es-toolkit"; -import { cwd } from "process"; +import { cwd } from "node:process"; import { configureLogger, fileExists, @@ -12,9 +17,9 @@ import { getArtifactVersionData, PROJECT_NAME, VERSION_LIMIT, -} from "./utils/index.js"; -import { Readable } from "stream"; +} from "./utils/index.ts"; import { rimrafSync } from "rimraf"; +import axios from "axios"; // Constants const SERVICE = "jenkins"; @@ -43,15 +48,16 @@ const jenkinsProjectPath = pathJoin(ROOT_DIR, SERVICE); logger.info( `Not found ${SERVICE}-${version}. Downloading ${artifact_name} from ${download_url}`, ); - const response = await fetch(download_url); - if (!response.ok) { + const response = await axios.get(download_url, { + responseType: "arraybuffer", + }); + if (response.status >= 200 && response.status < 300) { logger.fatal( `Failed to fetch ${artifact_name} from ${download_url}: ${response.statusText}`, ); process.exit(1); } - const stream = Readable.fromWeb(response.body); - await writeFile(artifactPath, stream); + writeFileSync(artifactPath, response.data); } else { logger.info(`${artifact_name} exists. Skip download`); } @@ -91,12 +97,12 @@ const jenkinsProjectPath = pathJoin(ROOT_DIR, SERVICE); ); process.exit(1); } else { - const javaVersion = head(javaVersionData).split(/\s+/).at(1); - const javaVersionComponents = javaVersion.split("."); - const javaMajorVersion = head(javaVersionComponents) === "1" - ? javaVersionComponents.at(1) - : head(javaVersionComponents); - if (parseInt(javaMajorVersion, 10) < JENKINS_MINIMAL_JAVA_VERSION) { + const javaVersion = head(javaVersionData)?.split(/\s+/).at(1); + const javaVersionComponents = javaVersion?.split("."); + const javaMajorVersion = head(javaVersionComponents ?? []) === "1" + ? javaVersionComponents?.at(1) + : head(javaVersionComponents ?? []); + if (parseInt(javaMajorVersion ?? '8', 10) < JENKINS_MINIMAL_JAVA_VERSION) { logger.fatal( `Current machine has Java version that is less than required 17 (version: ${javaMajorVersion})`, ); @@ -133,13 +139,20 @@ const jenkinsProjectPath = pathJoin(ROOT_DIR, SERVICE); const jenkinsBinary = head( globSync(pathJoin(jenkinsProjectPath, "jenkins-*.war")), ); - await execa({ - timeout: 60000, - stdout: ["inherit"], - stderr: ["inherit"], - })`java -jar ${jenkinsPluginManager} --war ${jenkinsBinary} --verbose --plugin-download-directory ${ - pathJoin(jenkinsProjectPath, "data", "plugins") - } --plugin-file ${jenkinsPluginConfigPath}`; + if (jenkinsPluginManager && jenkinsBinary) { + await execa({ + timeout: 60000, + stdout: ["inherit"], + stderr: ["inherit"], + })`java -jar ${jenkinsPluginManager} --war ${jenkinsBinary} --verbose --plugin-download-directory ${ + pathJoin(jenkinsProjectPath, "data", "plugins") + } --plugin-file ${jenkinsPluginConfigPath}`; + } else { + logger.fatal( + `Not finding neither Jenkins Plugin Manager JAR nor Jenkins WAR`, + ); + process.exit(1); + } } else { logger.warn( "Configuration file for Jenkins plugins are not found. Handle plugins manually.", diff --git a/scripts/start-nexus.js b/scripts/start-nexus.js deleted file mode 100644 index 18bcff1..0000000 --- a/scripts/start-nexus.js +++ /dev/null @@ -1,92 +0,0 @@ -import { execa } from "execa"; -import { basename as pathBasename, join as pathJoin } from "path"; -import { lstatSync, mkdirSync, readdirSync } from "fs"; -import { head } from "es-toolkit"; -import { homedir } from "os"; -import { cwd } from "process"; -import { - configureLogger, - configureSonatypeNexus, - generateLogFilenameWithTimestamp, - healthcheckSonatypeNexus, - PROJECT_NAME, - VERSION_LIMIT, -} from "./utils/index.js"; - -// Constants -const SERVICE = "nexus"; -const NEXUS_COMPATIBLE_JAVA_MAJOR_VERSION = "17"; - -(async () => { - // Configure logger - const logger = await configureLogger(PROJECT_NAME, SERVICE); - - // Find Nexus directory - const sonatypeFolderPath = pathJoin(cwd(), "sonatype"); - const sonatypeBinaryPaths = readdirSync(sonatypeFolderPath) - .map((fileName) => pathJoin(sonatypeFolderPath, fileName)) - .filter((fileName) => - lstatSync(fileName).isDirectory() && fileName.includes(`${SERVICE}-`) - ); - - // Validating presence of Nexus binary path(s) - if (sonatypeBinaryPaths.length == 0) { - logger.fatal("Not found any Nexus directory"); - process.exit(1); - } else if (sonatypeBinaryPaths.length > 3) { - logger.warn( - `Found multiple Nexus directory ${sonatypeBinaryPaths}. Please keep them to minimal ${VERSION_LIMIT}`, - ); - } - - const sonatypeBinaryPath = head(sonatypeBinaryPaths); - - // Find suitable JVM directory in $HOME/.sdk/candidates directory. - // Prequisites is that `sdkman` is installed and Java 17 has been installed previously. - const jvmCandidatesPath = pathJoin( - homedir(), - ".sdkman", - "candidates", - "java", - ); - if (!lstatSync(jvmCandidatesPath)) { - logger.fatal("Not found the path used by sdkman to install Java."); - process.exit(1); - } - const jvmCandidates = readdirSync(jvmCandidatesPath) - .map((fileName) => pathJoin(jvmCandidatesPath, fileName)) - .filter( - (fileName) => - lstatSync(fileName).isDirectory() && - pathBasename(fileName).startsWith(NEXUS_COMPATIBLE_JAVA_MAJOR_VERSION), - ); - - // Validating presence of suitable JVM - if (jvmCandidates.length == 0) { - logger.fatal( - `Not found any Java ${NEXUS_COMPATIBLE_JAVA_MAJOR_VERSION} candidate`, - ); - process.exit(1); - } - - // Creating directory for Nexus logs - const sonatypeLogPath = pathJoin(sonatypeFolderPath, "logs"); - mkdirSync(sonatypeLogPath, { recursive: true }); - - // Start Nexus - const jvmCandidate = head(jvmCandidates); - const nexusLogFilename = generateLogFilenameWithTimestamp(SERVICE); - const nexusProcess = execa({ - cwd: sonatypeBinaryPath, - env: { INSTALL4J_JAVA_HOME: jvmCandidate }, - stdout: ["inherit", { file: pathJoin(sonatypeLogPath, nexusLogFilename) }], - })`${sonatypeBinaryPath}/bin/nexus run`; - - // Check Sonatype health before configuring - const sonatypeIsAvailable = await healthcheckSonatypeNexus(logger); - if (sonatypeIsAvailable) { - await configureSonatypeNexus(logger); - } - - await nexusProcess; -})(); diff --git a/scripts/start-nexus.ts b/scripts/start-nexus.ts new file mode 100644 index 0000000..12218a4 --- /dev/null +++ b/scripts/start-nexus.ts @@ -0,0 +1,98 @@ +import { execa, ExecaMethod } from "execa"; +import { basename as pathBasename, join as pathJoin } from "node:path"; +import { lstatSync, mkdirSync, readdirSync } from "node:fs"; +import { head } from "es-toolkit"; +import { homedir } from "node:os"; +import { cwd } from "node:process"; +import { + configureLogger, + configureSonatypeNexus, + generateLogFilenameWithTimestamp, + healthcheckSonatypeNexus, + PROJECT_NAME, + VERSION_LIMIT, +} from "./utils/index.js"; +import { Logger } from "@logtape/logtape"; + +// Constants +const SERVICE = "nexus"; +const NEXUS_COMPATIBLE_JAVA_MAJOR_VERSION = "17"; + +// Configure logger +const logger: Logger = await configureLogger(PROJECT_NAME, SERVICE); + +// Find Nexus directory +const sonatypeFolderPath: string = pathJoin(cwd(), "sonatype"); +const sonatypeBinaryPaths: string[] = readdirSync(sonatypeFolderPath) + .map((fileName) => pathJoin(sonatypeFolderPath, fileName)) + .filter((fileName) => + lstatSync(fileName).isDirectory() && fileName.includes(`${SERVICE}-`) + ); + +// Validating presence of Nexus binary path(s) +if (sonatypeBinaryPaths.length == 0) { + logger.fatal("Not found any Nexus directory"); + process.exit(1); +} else if (sonatypeBinaryPaths.length > 3) { + logger.warn( + `Found multiple Nexus directory ${sonatypeBinaryPaths}. Please keep them to minimal ${VERSION_LIMIT}`, + ); +} + +const sonatypeBinaryPath: string | undefined = head(sonatypeBinaryPaths); + +// Find suitable JVM directory in $HOME/.sdk/candidates directory. +// Prequisites is that `sdkman` is installed and Java 17 has been installed previously. +const jvmCandidatesPath: string = pathJoin( + homedir(), + ".sdkman", + "candidates", + "java", +); +if (!lstatSync(jvmCandidatesPath)) { + logger.fatal("Not found the path used by sdkman to install Java."); + process.exit(1); +} +const jvmCandidates: string[] = readdirSync(jvmCandidatesPath) + .map((fileName) => pathJoin(jvmCandidatesPath, fileName)) + .filter( + (fileName) => + lstatSync(fileName).isDirectory() && + pathBasename(fileName).startsWith(NEXUS_COMPATIBLE_JAVA_MAJOR_VERSION), + ); + +// Validating presence of suitable JVM +if (jvmCandidates.length == 0) { + logger.fatal( + `Not found any Java ${NEXUS_COMPATIBLE_JAVA_MAJOR_VERSION} candidate`, + ); + process.exit(1); +} + +// Creating directory for Nexus logs +const sonatypeLogPath: string = pathJoin(sonatypeFolderPath, "logs"); +mkdirSync(sonatypeLogPath, { recursive: true }); + +const jvmCandidate: string | undefined = head(jvmCandidates); +const nexusLogFilename: string = generateLogFilenameWithTimestamp(SERVICE); + +// Start Nexus +if (sonatypeBinaryPath && jvmCandidate) { + const nexusProcess = execa({ + cwd: sonatypeBinaryPath, + env: { INSTALL4J_JAVA_HOME: jvmCandidate }, + stdout: ["inherit", { file: pathJoin(sonatypeLogPath, nexusLogFilename) }], + })`${sonatypeBinaryPath}/bin/nexus run`; + + // Check Sonatype health before configuring + const sonatypeIsAvailable = await healthcheckSonatypeNexus(logger); + if (sonatypeIsAvailable) { + await configureSonatypeNexus(logger); + } + + await nexusProcess; +} else { + logger.fatal( + `Sonatype Nexus cannot be started due to missing binary path (${sonatypeBinaryPath}) and/or missing JVM directory path (${jvmCandidate})`, + ); +} diff --git a/scripts/utils/common.js b/scripts/utils/common.js deleted file mode 100644 index c098fd6..0000000 --- a/scripts/utils/common.js +++ /dev/null @@ -1,30 +0,0 @@ -import { statSync } from "fs"; -import { configure, getConsoleSink, getLogger } from "@logtape/logtape"; - -export const VERSION_LIMIT = 3; -export const PROJECT_NAME = "auto-infra"; -export const SONATYPE_BASE_URL = "http://localhost:8081"; - -export const configureLogger = async (PROJECT_NAME, SERVICE) => { - await configure({ - sinks: { console: getConsoleSink() }, - loggers: [{ - category: PROJECT_NAME, - lowestLevel: "debug", - sinks: ["console"], - }], - }); - return getLogger([PROJECT_NAME, SERVICE]); -}; - -export const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); - -export const generateLogFilenameWithTimestamp = (service) => { - const currentDate = new Date(); - return `${service}-${currentDate.getFullYear()}-${currentDate.getMonth()}-${currentDate.getDay()}.log`; -}; - -// File utils -export const fileExists = (path) => statSync(path, { throwIfNoEntry: false }); -export const folderExists = (path) => - statSync(path, { throwIfNoEntry: false }).isDirectory(); diff --git a/scripts/utils/common.ts b/scripts/utils/common.ts new file mode 100644 index 0000000..5dd40e5 --- /dev/null +++ b/scripts/utils/common.ts @@ -0,0 +1,34 @@ +import { statSync } from "node:fs"; +import { configure, getConsoleSink, getLogger, Logger } from "@logtape/logtape"; + +export const VERSION_LIMIT = 3; +export const PROJECT_NAME = "auto-infra"; +export const SONATYPE_BASE_URL = "http://localhost:8081"; + +export const configureLogger = async ( + PROJECT_NAME: string, + SERVICE: string, +): Promise => { + await configure({ + sinks: { console: getConsoleSink() }, + loggers: [{ + category: PROJECT_NAME, + lowestLevel: "debug", + sinks: ["console"], + }], + }); + return getLogger([PROJECT_NAME, SERVICE]); +}; + +export const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms)); + +export const generateLogFilenameWithTimestamp = (service: string): string => { + const currentDate = new Date(); + return `${service}-${currentDate.getFullYear()}-${currentDate.getMonth()}-${currentDate.getDay()}.log`; +}; + +// File utils +export const fileExists = (path: string): boolean => + Boolean(statSync(path, { throwIfNoEntry: false })); +export const folderExists = (path: string): boolean => + Boolean(statSync(path, { throwIfNoEntry: false })?.isDirectory()); diff --git a/scripts/utils/index.js b/scripts/utils/index.js deleted file mode 100644 index f2f01d2..0000000 --- a/scripts/utils/index.js +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./common.js"; -export * from "./jenkins.js"; -export * from "./sonatype_nexus.js"; diff --git a/scripts/utils/index.ts b/scripts/utils/index.ts new file mode 100644 index 0000000..dc94ea8 --- /dev/null +++ b/scripts/utils/index.ts @@ -0,0 +1,3 @@ +export * from "./common.ts"; +export * from "./jenkins.ts"; +export * from "./sonatype_nexus.ts"; diff --git a/scripts/utils/jenkins.js b/scripts/utils/jenkins.ts similarity index 58% rename from scripts/utils/jenkins.js rename to scripts/utils/jenkins.ts index d5a0a78..9e88fcb 100644 --- a/scripts/utils/jenkins.js +++ b/scripts/utils/jenkins.ts @@ -1,10 +1,22 @@ import Mustache from "mustache"; -import { readFileSync } from "fs"; -import { join as pathJoin } from "path"; -import { cwd } from "process"; +import { readFileSync } from "node:fs"; +import { join as pathJoin } from "node:path"; +import { cwd } from "node:process"; import { fromPairs } from "es-toolkit/compat"; -export const getArtifactVersionData = (service) => { +interface ArtifactVersionSchema { + artifact_name: string; + download_url: string; + version: string; +} +interface ArtifactVersionData { + versionData: ArtifactVersionSchema | null; + error: Error | null; +} + +export const getArtifactVersionData = ( + service: string, +): ArtifactVersionData => { const artifactVersionFolderPath = cwd(); try { // Read the .version.json file and extract the version. @@ -15,13 +27,15 @@ export const getArtifactVersionData = (service) => { `${service}.version.json`, ); const artifactVersionDataString = readFileSync(artifactVersionFilePath); - const rawArtifactVersionData = JSON.parse(artifactVersionDataString); - const ARTIFACT_VERSION = rawArtifactVersionData["version"]; + const rawArtifactVersionData = JSON.parse( + artifactVersionDataString.toString(), + ) as ArtifactVersionSchema; + const ARTIFACT_VERSION = rawArtifactVersionData.version; if (ARTIFACT_VERSION === null) { return { versionData: null, - error: new Error(`No artifact version for ${version}`), + error: new Error(`No artifact version for ${service}`), }; } @@ -34,9 +48,9 @@ export const getArtifactVersionData = (service) => { }); return [key, rendered]; }), - ); + ) as ArtifactVersionSchema; - versionData["version"] = ARTIFACT_VERSION; + versionData.version = ARTIFACT_VERSION; return { versionData: versionData, diff --git a/scripts/utils/sonatype_nexus.js b/scripts/utils/sonatype_nexus.ts similarity index 93% rename from scripts/utils/sonatype_nexus.js rename to scripts/utils/sonatype_nexus.ts index 6fd4412..9da9c11 100644 --- a/scripts/utils/sonatype_nexus.js +++ b/scripts/utils/sonatype_nexus.ts @@ -1,17 +1,22 @@ import "dotenv/config"; import { cloneDeep, isEqual } from "es-toolkit"; import { unset } from "es-toolkit/compat"; -import { SONATYPE_BASE_URL } from "./common.js"; +import { sleep, SONATYPE_BASE_URL } from "./common.ts"; +import { Logger } from "@logtape/logtape"; + +interface SonatypeNexusRepoResponse { + online: boolean; +} // Check if local Sonatype Nexus server is up and running. export const healthcheckSonatypeNexus = async (logger) => { const read_healthcheck_url = `${SONATYPE_BASE_URL}/service/rest/v1/status`; - const retryLimit = 20; + const retryLimit = 30; let retryCount = 0; let sonatypeIsAvailable = false; - while (!sonatypeIsAvailable || retryCount <= retryLimit) { + while (retryCount <= retryLimit) { try { const response = await fetch(read_healthcheck_url, { headers: { "Content-Type": "application/json" }, @@ -26,7 +31,7 @@ export const healthcheckSonatypeNexus = async (logger) => { `[${retryCount}/${retryLimit} retries] Sonatype Nexus is not yet available. Retrying healthcheck after 1 second...`, ); retryCount += 1; - sleep(1000); + await sleep(1000); } } } @@ -43,7 +48,7 @@ export const healthcheckSonatypeNexus = async (logger) => { return true; }; -const getRepoAPIMapping = (repoType) => { +const getRepoAPIMapping = (repoType: string): string => { if (String(repoType).includes("maven")) { return "maven"; } @@ -51,7 +56,7 @@ const getRepoAPIMapping = (repoType) => { }; // Configuration -export const configureSonatypeNexus = async (logger) => { +export const configureSonatypeNexus = async (logger: Logger): Promise => { const proxiesToBeMade = [ { name: "jenkins-public", @@ -225,14 +230,14 @@ export const configureSonatypeNexus = async (logger) => { } // Enable them online afterwards if they are offline. - const proxyRepoData = ( + const proxyRepoData = await ( await fetch( `${SONATYPE_BASE_URL}/service/rest/v1/repositories/${repoAPI}/${proxyToBeMade.type}/${proxyToBeMade.name}`, { headers: authorizationHeader, }, ) - ).json(); + ).json() as SonatypeNexusRepoResponse; if (!Boolean(proxyRepoData.online)) { logger.info(