[skip ci] refactor ClojureScript.kt, NpmByNvm.kt & tests

This commit is contained in:
ansgarz 2025-02-02 18:25:23 +01:00
parent c884bc8c6e
commit cec1b0f23e
8 changed files with 126 additions and 71 deletions
doc/dev
src
main/kotlin/org/domaindrivenarchitecture/provs
desktop/infrastructure
framework
core
ubuntu/install/base
test/kotlin/org/domaindrivenarchitecture/provs/desktop/infrastructure

View file

@ -1,11 +1,15 @@
Should be added in dev_circumstances for single unit tests to get repeatable results ('fresh container'):
ContainerStartMode.CREATE_NEW_KILL_EXISTING
# Container Tests
like this way:
+import org.domaindrivenarchitecture.provs.test.tags.ContainerTest
The method `defaultTestContainer()` provides a prov instance in a container for integration-tests.
//annotate to ContainerTest
+@ContainerTest
Container-tests should be annotated by tag: `@ContainerTest` and if long-lasting (ca. > 10 - 20 sec) with @ExtensiveContainerTest
For performance reasons the test container is re-used among the tests.
In case you want a fresh container for your test, add the following option:
`ContainerStartMode.CREATE_NEW_KILL_EXISTING`
example: `val container = defaultTestContainer(ContainerStartMode.CREATE_NEW_KILL_EXISTING)`
//and configured Testcontainer
+val container = defaultTestContainer(ContainerStartMode.CREATE_NEW_KILL_EXISTING)

View file

@ -2,14 +2,17 @@ package org.domaindrivenarchitecture.provs.desktop.infrastructure
import org.domaindrivenarchitecture.provs.framework.core.Prov
import org.domaindrivenarchitecture.provs.framework.core.ProvResult
import org.domaindrivenarchitecture.provs.framework.ubuntu.install.base.isPackageInstalled
/**
* Installs ShadowCljs. Prerequisite: NVM and NPM are installed, otherwise fails.
*/
fun Prov.installShadowCljs(): ProvResult = task {
if (!isPackageInstalled("shadow-cljs")) {
cmd(". .nvm/nvm.sh && npm install -g shadow-cljs")
cmd(". .nvm/nvm.sh && shadow-cljs --help")
if (!chk(". .nvm/nvm.sh")) {
addProvResult(false, err = "nvm not installed!")
} else {
ProvResult(true, out = "shadow-cljs already installed")
if (!chk("npm list -g --depth=0 | grep shadow-cljs")) {
cmd(". .nvm/nvm.sh && npm install -g shadow-cljs")
}
}
}

View file

@ -3,16 +3,16 @@ package org.domaindrivenarchitecture.provs.desktop.infrastructure
import org.domaindrivenarchitecture.provs.framework.core.Prov
import org.domaindrivenarchitecture.provs.framework.core.ProvResult
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.*
import org.domaindrivenarchitecture.provs.framework.ubuntu.install.base.isPackageInstalledCheckCommand
import org.domaindrivenarchitecture.provs.framework.ubuntu.install.base.checkCommand
import org.domaindrivenarchitecture.provs.framework.ubuntu.web.base.downloadFromURL
//from https://go.dev/dl/
fun Prov.installGo(
//from https://go.dev/dl/
version: String = "1.23.5",
enforceVersion: Boolean = false,
sha256sum: String = "cbcad4a6482107c7c7926df1608106c189417163428200ce357695cc7e01d091"
) = taskWithResult {
if (isPackageInstalledCheckCommand("go") && !enforceVersion) {
if (checkCommand("go") && !enforceVersion) {
return@taskWithResult ProvResult(true)
}

View file

@ -2,39 +2,34 @@ package org.domaindrivenarchitecture.provs.desktop.infrastructure
import org.domaindrivenarchitecture.provs.framework.core.Prov
import org.domaindrivenarchitecture.provs.framework.core.ProvResult
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.checkFile
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.createFile
import org.domaindrivenarchitecture.provs.framework.ubuntu.filesystem.base.userHome
import org.domaindrivenarchitecture.provs.framework.ubuntu.install.base.isPackageInstalledCheckCommand
fun Prov.installNpmByNvm(): ProvResult = task {
/**
* Installs Node.js and NPM (Node Package Manager) by using NVM (Node Version Manager), if NVM not already installed
*/
fun Prov.installNpmByNvm(version: String = "0.40.1"): ProvResult = task {
if (!isPackageInstalledCheckCommand("npm")) {
//Node-Version-Manager from https://github.com/nvm-sh/nvm
val version = "0.40.1"
//see Node-Version-Manager at https://github.com/nvm-sh/nvm
val bashConfigFile = "~/.bashrc.d/npmbynvm.sh"
if (!checkFile(".nvm/nvm.sh") && !checkFile(bashConfigFile)) {
// install NVM
cmd("sudo curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v$version/install.sh | bash")
cmd("chmod 755 .nvm/nvm.sh")
// configure bash - create file ".bashrc.d/npmbynvm.sh" with settings
configureBashForUser()
createFile("~/.bashrc.d/npmbynvm.sh", """export NVM_DIR="${userHome()}.nvm" """ + "\n"
+ """[ -s "${"\$NVM_DIR/nvm.sh"}" ] && \. "${"\$NVM_DIR/nvm.sh"}" """ + "\n")
val content = """
export NVM_DIR="${userHome()}.nvm"
[ -s "${"\$NVM_DIR/nvm.sh"}" ] && \. "${"\$NVM_DIR/nvm.sh"}"
""".trimIndent()
createFile(bashConfigFile, content)
// install Node.js and NPM
cmd(". .nvm/nvm.sh && nvm install --lts")
val nvmRes = cmd(". .nvm/nvm.sh && nvm --version").toString()
if (version == nvmRes) {
println("NVM version $version")
addResultToEval(ProvResult(true, out = "SUCCESS: NVM version $version installed !!"))
} else {
println("FAIL: NVM version $version is not installed !!")
addResultToEval(ProvResult(true, out = "FAIL: NVM version $version is not installed !!"))
}
cmd(". .nvm/nvm.sh && node -v")
cmd(". .nvm/nvm.sh && npm --version")
} else {
addResultToEval(ProvResult(true, out = "npm already installed"))
}
}

View file

@ -217,11 +217,12 @@ open class Prov protected constructor(
fun getSecret(command: String, removeNewlineSuffix: Boolean = false): Secret? {
val result = cmdNoLog(command)
return if (result.success && result.out != null) {
addResultToEval(ProvResult(true, getCallingMethodName()))
val plainSecret = if (removeNewlineSuffix && result.out.takeLast(1) == "\n") result.out.dropLast(1) else result.out
addProvResult(true, getCallingMethodName())
val plainSecret =
if (removeNewlineSuffix && result.out.takeLast(1) == "\n") result.out.dropLast(1) else result.out
Secret(plainSecret)
} else {
addResultToEval(ProvResult(false, getCallingMethodName(), err = result.err, exception = result.exception))
addProvResult(false, getCallingMethodName(), err = result.err, exception = result.exception)
null
}
}
@ -231,10 +232,26 @@ open class Prov protected constructor(
* Adds a ProvResult to the overall success evaluation.
* Intended for use in methods which do not automatically add results.
*/
@Deprecated("since 0.39.7", replaceWith = ReplaceWith("addProvResult", ))
fun addResultToEval(result: ProvResult) = taskWithResult {
result
}
/**
* Adds a ProvResult to the overall success evaluation.
* Intended for use in methods which do not automatically add results.
*/
fun addProvResult(
success: Boolean,
cmd: String? = null,
out: String? = null,
err: String? = null,
exception: Exception? = null,
exit: String? = null
) = taskWithResult {
ProvResult(success, cmd, out, err, exception, exit)
}
/**
* Executes multiple shell commands. Each command must be in its own line.
* Multi-line commands within the script are not supported.

View file

@ -16,9 +16,9 @@ private var aptInit = false
@Suppress("UNUSED_PARAMETER") // ignoreAlreadyInstalled is added for external usage
fun Prov.aptInstall(packages: String, ignoreAlreadyInstalled: Boolean = true): ProvResult = taskWithResult {
val packageList = packages.split(" ")
val allInstalled: Boolean = packageList.map { isPackageInstalled(it) }.fold(true, { a, b -> a && b })
val allInstalled: Boolean = packageList.map { checkPackage(it) }.fold(true, { a, b -> a && b })
if (!allInstalled) {
if (!isPackageInstalled(packages)) {
if (!checkPackage(packages)) {
if (!aptInit) {
optional {
// may fail for some packages, but this should in general not be an issue
@ -31,8 +31,7 @@ fun Prov.aptInstall(packages: String, ignoreAlreadyInstalled: Boolean = true): P
for (packg in packageList) {
// see https://superuser.com/questions/164553/automatically-answer-yes-when-using-apt-get-install
cmd("sudo apt-get install -q=2 $packg")
//DEBIAN_FRONTEND=noninteractive
cmd("sudo DEBIAN_FRONTEND=noninteractive apt-get install -q=2 $packg")
}
ProvResult(true) // dummy
} else {
@ -71,20 +70,36 @@ fun Prov.aptInstallFromPpa(launchPadUser: String, ppaName: String, packageName:
/**
* Returns true if a package is installed else false
*/
@Deprecated("since 0.39.7", replaceWith = ReplaceWith("checkPackage"))
fun Prov.isPackageInstalled(packageName: String): Boolean {
return chk("dpkg -s $packageName")
}
/**
* Returns true if a package is installed else false
*/
fun Prov.checkPackage(packageName: String): Boolean {
return chk("dpkg -s $packageName")
}
/**
* Returns true if a package is installed else false
*/
@Deprecated("since 0.39.7", replaceWith = ReplaceWith("checkPackage"))
fun Prov.checkPackageInstalled(packageName: String): ProvResult = taskWithResult {
cmd("dpkg -s $packageName")
}
fun Prov.isPackageInstalledCheckCommand(packageName: String): Boolean {
return chk("command -v $packageName")
/**
* Returns true if a command is available else false.
* Can be used e.g. to check if software is installed in case it is not installed as debian package.
* ATTENTION:
* * checks only commands which are available in the shell
* * does NOT find commands which are defined in .bashrc when running in a non-interactive shell (which is the case with: `bash -c "command -v mycommand"`),
*/
fun Prov.checkCommand(commandName: String): Boolean {
return chk("command -v $commandName")
}
/**

View file

@ -1,7 +1,11 @@
package org.domaindrivenarchitecture.provs.desktop.infrastructure
import org.domaindrivenarchitecture.provs.framework.core.processors.ContainerStartMode
import org.domaindrivenarchitecture.provs.framework.ubuntu.install.base.aptInstall
import org.domaindrivenarchitecture.provs.test.defaultTestContainer
import org.domaindrivenarchitecture.provs.test.tags.ContainerTest
import org.domaindrivenarchitecture.provs.test.tags.ExtensiveContainerTest
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
internal class ClojureScriptKtTest {
@ -10,19 +14,30 @@ internal class ClojureScriptKtTest {
fun installShadowCljs() {
// given
val prov = defaultTestContainer()
//Todo:
// To be discussed, should init container, but not available for prov.installShadowCljs() !!
// Howto work in addition prov.a() + prov.b()?
prov.installNpmByNvm()
prov.task {
aptInstall("curl")
installNpmByNvm()
}
// when
// check if it can be run twice successfully
val res01 = prov.installShadowCljs()
val res02 = prov.installShadowCljs()
val res = prov.task {
installShadowCljs()
installShadowCljs() // check repeatability
}
// then
assertTrue(res01.success)
assertTrue(res02.success)
assertTrue(res.success)
}
@ExtensiveContainerTest // extensive test, as it kills the existing container and creates a new one
fun installShadowCljs_fails_if_nvm_missing() {
// given
val prov = defaultTestContainer(ContainerStartMode.CREATE_NEW_KILL_EXISTING)
// when
val res = prov.installShadowCljs()
// then
assertFalse(res.success)
}
}

View file

@ -7,16 +7,22 @@ import org.junit.jupiter.api.Assertions.assertTrue
internal class NpmByNvmKtTest {
@ContainerTest
fun installNVMnpm() {
// given
val container = defaultTestContainer()
container.aptInstall("curl")
// when
val res01 = container.installNpmByNvm()
val res02 = container.installNpmByNvm()
// then
assertTrue(res01.success)
assertTrue(res02.success)
}
@ContainerTest
fun installNVMnpm() {
// given
val prov = defaultTestContainer()
prov.aptInstall("curl")
// when
val res = prov.task {
installNpmByNvm()
installNpmByNvm() // check repeatability
// check if node and npm are installed and can be called in a shell (with sourcing nvm.sh)
cmd(". .nvm/nvm.sh && node -v")
cmd(". .nvm/nvm.sh && npm --version")
}
// then
assertTrue(res.success)
}
}