Skip to content

Commit

Permalink
refactor: reduce code duplication
Browse files Browse the repository at this point in the history
Extracted some named types and helpers.
  • Loading branch information
vvagaytsev committed Jun 22, 2023
1 parent f10490d commit 8d89f6f
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 230 deletions.
98 changes: 98 additions & 0 deletions plugins/jib/build-tool-base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* Copyright (C) 2018-2023 Garden Technologies, Inc. <[email protected]>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import { Log, PluginContext } from "@garden-io/sdk/types"
import { Writable } from "node:stream"
import execa from "execa"
import { RuntimeError } from "@garden-io/core/build/src/exceptions"

export interface CheckVersionParams {
binaryPath: string
toolName: string
configFieldName: string
}

export function baseErrorMessage({ binaryPath, configFieldName }: CheckVersionParams): string {
return `Gradle binary path "${binaryPath}" is incorrect! Please check the \`${configFieldName}\` configuration option.`
}

export async function getBuildToolVersion(params: CheckVersionParams) {
const { binaryPath, toolName } = params
try {
const res = await execa(binaryPath, ["--version"])
return res.stdout
} catch (error) {
const composeErrorMessage = (err: any): string => {
if (err.code === "EACCES") {
return `${baseErrorMessage(
params
)} It looks like the ${toolName} path defined in the config is not an executable binary.`
} else if (err.code === "ENOENT") {
return `${baseErrorMessage(params)} The ${toolName} path defined in the configuration does not exist.`
} else {
return baseErrorMessage(params)
}
}
throw new RuntimeError(composeErrorMessage(error), { binaryPath })
}
}

export interface VerifyBinaryParams extends CheckVersionParams {
outputVerificationString: string
}

export async function verifyBinaryPath(params: VerifyBinaryParams) {
const { binaryPath, toolName, outputVerificationString } = params
const versionOutput = await getBuildToolVersion(params)
const isMaven = versionOutput.toLowerCase().includes(outputVerificationString)
if (!isMaven) {
throw new RuntimeError(
`${baseErrorMessage(params)} It looks like the ${toolName} path points to a wrong executable binary.`,
{ binaryPath }
)
}
}

export interface BuildToolParams {
ctx: PluginContext
args: string[]
cwd: string
log: Log
openJdkPath: string
binaryPath?: string
outputStream?: Writable
concurrentMavenBuilds?: boolean
}

export function runBuildTool({
binaryPath,
args,
cwd,
openJdkPath,
outputStream,
}: {
binaryPath: string
args: string[]
cwd: string
openJdkPath: string
outputStream?: Writable
}) {
const res = execa(binaryPath, args, {
cwd,
env: {
JAVA_HOME: openJdkPath,
},
})

if (outputStream) {
res.stdout?.pipe(outputStream)
res.stderr?.pipe(outputStream)
}

return res
}
87 changes: 16 additions & 71 deletions plugins/jib/gradle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,12 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import execa from "execa"
import { find } from "lodash"
import { Log, PluginContext, PluginToolSpec } from "@garden-io/sdk/types"
import { PluginError, RuntimeError } from "@garden-io/core/build/src/exceptions"
import { PluginContext, PluginToolSpec } from "@garden-io/sdk/types"
import { PluginError } from "@garden-io/core/build/src/exceptions"
import { resolve } from "path"
import { pathExists } from "fs-extra"
import { Writable } from "stream"
import { runBuildTool, BuildToolParams, verifyBinaryPath, VerifyBinaryParams } from "./build-tool-base"

export const gradleVersion = "7.5.1"

Expand Down Expand Up @@ -68,44 +67,13 @@ export function getGradleTool(ctx: PluginContext) {
return tool
}

const baseErrorMessage = (gradlePath: string): string =>
`Gradle binary path "${gradlePath}" is incorrect! Please check the \`gradlePath\` configuration option.`

async function checkGradleVersion(gradlePath: string) {
try {
const res = await execa(gradlePath, ["--version"])
return res.stdout
} catch (error) {
const composeErrorMessage = (err: any): string => {
if (err.code === "EACCES") {
return `${baseErrorMessage(
gradlePath
)} It looks like the Gradle path defined in the config is not an executable binary.`
} else if (err.code === "ENOENT") {
return `${baseErrorMessage(gradlePath)} The Gradle path defined in the configuration does not exist.`
} else {
return baseErrorMessage(gradlePath)
}
}
throw new RuntimeError(composeErrorMessage(error), { gradlePath })
}
}

let gradlePathValid = false

async function verifyGradlePath(gradlePath: string) {
async function verifyGradlePath(params: VerifyBinaryParams) {
if (gradlePathValid) {
return
}

const versionOutput = await checkGradleVersion(gradlePath)
const isGradle = versionOutput.toLowerCase().includes("gradle")
if (!isGradle) {
throw new RuntimeError(
`${baseErrorMessage(gradlePath)} It looks like the Gradle path points to a non-Gradle executable binary.`,
{ gradlePath }
)
}
await verifyBinaryPath(params)
gradlePathValid = true
}

Expand All @@ -116,29 +84,17 @@ async function verifyGradlePath(gradlePath: string) {
* If no explicit binary specific, then a `./gradlew` script will be used if it's available in the specified directory.
* Otherwise, the Gradle distribution will be downloaded and used.
*/
export async function gradle({
ctx,
args,
cwd,
log,
openJdkPath,
gradlePath,
outputStream,
}: {
ctx: PluginContext
args: string[]
cwd: string
log: Log
openJdkPath: string
gradlePath?: string
outputStream: Writable
}) {
export async function gradle({ ctx, args, cwd, log, openJdkPath, binaryPath, outputStream }: BuildToolParams) {
let effectiveGradlePath: string

if (!!gradlePath) {
log.verbose(`Using explicitly specified Gradle binary from ${gradlePath}`)
effectiveGradlePath = gradlePath
await verifyGradlePath(effectiveGradlePath)
if (!!binaryPath) {
log.verbose(`Using explicitly specified Gradle binary from ${binaryPath}`)
effectiveGradlePath = binaryPath
await verifyGradlePath({
binaryPath,
toolName: "Gradle",
configFieldName: "gradlePath",
outputVerificationString: "gradle",
})
} else {
const gradlewPath = resolve(cwd, process.platform === "win32" ? "gradlew.bat" : "gradlew")
if (await pathExists(gradlewPath)) {
Expand All @@ -156,16 +112,5 @@ export async function gradle({
}

log.debug(`Execing ${effectiveGradlePath} ${args.join(" ")}`)

const res = execa(effectiveGradlePath, args, {
cwd,
env: {
JAVA_HOME: openJdkPath,
},
})

res.stdout?.pipe(outputStream)
res.stderr?.pipe(outputStream)

return res
return runBuildTool({ binaryPath: effectiveGradlePath, args, cwd, openJdkPath, outputStream })
}
6 changes: 3 additions & 3 deletions plugins/jib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ export const gardenPlugin = () =>
cwd: action.basePath(),
args: [...mavenPhases, ...args],
openJdkPath,
mavenPath,
binaryPath: mavenPath,
concurrentMavenBuilds,
outputStream,
})
Expand All @@ -247,7 +247,7 @@ export const gardenPlugin = () =>
cwd: action.basePath(),
args: [...mavenPhases, ...args],
openJdkPath,
mavendPath,
binaryPath: mavendPath,
concurrentMavenBuilds,
outputStream,
})
Expand All @@ -258,7 +258,7 @@ export const gardenPlugin = () =>
cwd: action.basePath(),
args,
openJdkPath,
gradlePath,
binaryPath: gradlePath,
outputStream,
})
}
Expand Down
97 changes: 19 additions & 78 deletions plugins/jib/maven.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@
*/

import AsyncLock from "async-lock"
import { Log, PluginContext, PluginToolSpec } from "@garden-io/sdk/types"
import { PluginContext, PluginToolSpec } from "@garden-io/sdk/types"
import { find } from "lodash"
import { PluginError, RuntimeError } from "@garden-io/core/build/src/exceptions"
import { Writable } from "node:stream"
import execa from "execa"
import { PluginError } from "@garden-io/core/build/src/exceptions"
import { BuildToolParams, runBuildTool, verifyBinaryPath, VerifyBinaryParams } from "./build-tool-base"

const buildLock = new AsyncLock()

Expand Down Expand Up @@ -71,44 +70,13 @@ export function getMvnTool(ctx: PluginContext) {
return tool
}

const baseErrorMessage = (mvnPath: string): string =>
`Maven binary path "${mvnPath}" is incorrect! Please check the \`mavenPath\` configuration option.`

async function checkMavenVersion(mvnPath: string) {
try {
const res = await execa(mvnPath, ["--version"])
return res.stdout
} catch (error) {
const composeErrorMessage = (err: any): string => {
if (err.code === "EACCES") {
return `${baseErrorMessage(
mvnPath
)} It looks like the Maven path defined in the config is not an executable binary.`
} else if (err.code === "ENOENT") {
return `${baseErrorMessage(mvnPath)} The Maven path defined in the configuration does not exist.`
} else {
return baseErrorMessage(mvnPath)
}
}
throw new RuntimeError(composeErrorMessage(error), { mvnPath })
}
}

let mavenPathValid = false

async function verifyMavenPath(mvnPath: string) {
async function verifyMavenPath(params: VerifyBinaryParams) {
if (mavenPathValid) {
return
}

const versionOutput = await checkMavenVersion(mvnPath)
const isMaven = versionOutput.toLowerCase().includes("maven")
if (!isMaven) {
throw new RuntimeError(
`${baseErrorMessage(mvnPath)} It looks like the Maven path points to a non-Maven executable binary.`,
{ mvnPath }
)
}
await verifyBinaryPath(params)
mavenPathValid = true
}

Expand All @@ -121,62 +89,35 @@ export async function mvn({
cwd,
log,
openJdkPath,
mavenPath,
binaryPath,
outputStream,
concurrentMavenBuilds,
}: {
ctx: PluginContext
args: string[]
cwd: string
log: Log
openJdkPath: string
mavenPath?: string
outputStream?: Writable
concurrentMavenBuilds?: boolean
}) {
}: BuildToolParams) {
let mvnPath: string
if (!!mavenPath) {
log.verbose(`Using explicitly specified Maven binary from ${mavenPath}`)
mvnPath = mavenPath
await verifyMavenPath(mvnPath)
if (!!binaryPath) {
log.verbose(`Using explicitly specified Maven binary from ${binaryPath}`)
mvnPath = binaryPath
await verifyMavenPath({
binaryPath,
toolName: "Maven",
configFieldName: "mavenPath",
outputVerificationString: "maven",
})
} else {
log.verbose(`The Maven binary hasn't been specified explicitly. Maven ${mvnVersion} will be used by default.`)
const tool = getMvnTool(ctx)
mvnPath = await tool.ensurePath(log)
}

log.debug(`Execing ${mvnPath} ${args.join(" ")}`)
const params = { binaryPath: mvnPath, args, cwd, openJdkPath, outputStream }
if (concurrentMavenBuilds) {
const res = execa(mvnPath, args, {
cwd,
env: {
JAVA_HOME: openJdkPath,
},
})

if (outputStream) {
res.stdout?.pipe(outputStream)
res.stderr?.pipe(outputStream)
}

return res
return runBuildTool(params)
} else {
// Maven has issues when running concurrent processes, so we're working around that with a lock.
// TODO: http://takari.io/book/30-team-maven.html would be a more robust solution.
return buildLock.acquire("mvn", async () => {
const res = execa(mvnPath, args, {
cwd,
env: {
JAVA_HOME: openJdkPath,
},
})

if (outputStream) {
res.stdout?.pipe(outputStream)
res.stderr?.pipe(outputStream)
}

return res
return runBuildTool(params)
})
}
}
Loading

0 comments on commit 8d89f6f

Please sign in to comment.