diff --git a/NEWS.adoc b/NEWS.adoc index 09148c36a..bdda9e528 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -1,5 +1,12 @@ = Changes +== [Future] - ? + +=== Fixed + +* (*Breaking*) Since migrating to a Kotlin Scripting backend, environment variables for repository authentication now use the `$FOO` syntax vs the `{{FOO}}` syntax. This has been broken since 4.2.0. (fixed thanks to https://github.com/rocketraman[rocketraman]) +* Packaging scripts via `--package` did not work with repository authentication (thanks to https://github.com/rocketraman[rocketraman]) + == [4.2.2] - 2023-04-29 === Added diff --git a/README.adoc b/README.adoc index 73377af00..2d5a0100f 100644 --- a/README.adoc +++ b/README.adoc @@ -139,7 +139,7 @@ Two workarounds for ArchLinux exists, which can be used to make 'kscript' workin [source,bash] ---- sudo mkdir /usr/share/kotlin/bin -sudo ln -s /usr/bin/kotlin /usr/share/kotlin/bin/kotlin +sudo ln -s /usr/bin/kotlin /usr/share/kotlin/bin/kotlin sudo ln -s /usr/bin/kotlinc /usr/share/kotlin/bin/kotlinc ---- @@ -243,7 +243,7 @@ EOF [source,bash] ---- -kscript <(echo 'println("k-onliner")') arg1 arg2 arg3 +kscript <(echo 'println("k-onliner")') arg1 arg2 arg3 ---- Inlined _kscripts_ are also cached based on `md5` checksum, so running the same snippet again will use a cached jar ( @@ -259,7 +259,7 @@ script for better readability) [source,bash] ---- -kscript https://git.io/v1cG6 my argu ments +kscript https://git.io/v1cG6 my argu ments ---- To streamline the usage, the first part could be even aliased: @@ -414,12 +414,12 @@ The latter is the default for `kt` files and could be omitted @file:DependsOnMaven("net.clearvolume:cleargl:2.0.1") // Note that for compatibility reasons, only one locator argument is allowed for @DependsOnMaven -// also protected artifact repositories are supported, see +// also protected repositories are supported, see // @file:Repository("my-art", "http://localhost:8081/artifactory/authenticated_repo", user="auth_user", password="password") -// You can use environment variables for user and password when string surrounded by double {} brackets -// @file:Repository("my-art", "http://localhost:8081/artifactory/authenticated_repo", user="{{ARTIFACTORY_USER}}", password="{{ARTIFACTORY_PASSWORD}}") +// You can use environment variables for user and password +// @file:Repository("my-art", "http://localhost:8081/artifactory/authenticated_repo", user="$ARTIFACTORY_USER", password="$ARTIFACTORY_PASSWORD") // will be use 'ARTIFACTORY_USER' and 'ARTIFACTORY_PASSWORD' environment variables -// if the value doesn't found in the script environment will fail +// if a referenced environment variable is not found, the script will fail // Include helper scripts without deployment or prior compilation @file:Import("util.kt") @@ -516,7 +516,7 @@ which will bring up the classpath-enhanced REPL: Creating REPL from CountRecords.kts Welcome to Kotlin version 1.1.51 (JRE 1.8.0_151-b12) >>> import de.mpicbg.scicomp.bioinfo.openFasta ->>> +>>> ---- == Boostrap IDEA from a scriptlet @@ -582,7 +582,7 @@ KScript follows XDG directory standard, so the file should be created in (paths existing path is used): |=== -|OS |PATH +|OS |PATH |*Windows* | %LOCALAPPDATA%\kscript\kscript.properties; %USERPROFILE%.config\kscript\kscript.properties |*MacOs* | ~/Library/Application Support/kscript/kscript.properties; @@ -623,6 +623,43 @@ scripting.repository.user=user scripting.repository.password=password ---- +Various environment variables, if set, may override these properties or configure other behavior. See +https://github.com/kscripting/kscript/blob/1c97c2197ddd08382834c014096ffe8b26727a4f/src/main/kotlin/io/github/kscripting/kscript/model/ConfigBuilder.kt#L42[ConfigBuilder] +for all the possible environment overrides. The most common ones corresponding to the properties above will likely be: + +* `KSCRIPT_KOTLIN_OPTS` +* `KSCRIPT_REPOSITORY_URL` +* `KSCRIPT_REPOSITORY_USER` +* `KSCRIPT_REPOSITORY_PASSWORD` + +In addition, environment lookups may be made dynamically in a script specifically for repository url, username, and +password by prefixing the lookup with a literal `$`. + +NOTE: Unlike in Kotlin code, the '$' in a kscript is not escaped. + +In addition, ``KSCRIPT_REPOSITORY_*` values may be included in an override by using the double-brace syntax +`{{KSCRIPT_REPOSITORY_URL}}`. For example, a repository declaration like: + +[source,kotlin] +---- +#!/usr/bin/env kscript +@file:Repository("$REPO", user="$USER", password="$PASS") +---- + +would obtain the user from the `USER` environment variable. +If the `USER` environment variable contained a value like `foo-{{KSCRIPT_REPOSITORY_URL}}` and the value of +`KSCRIPT_REPOSITORY_URL` (either also from the environment or from the kscript properties), was `bar`, then the resolved +value for `user` would be `foo-bar`. + +The placeholder values `{{KSCRIPT_REPOSITORY_URL}}`, `{{KSCRIPT_REPOSITORY_USER}}`, and +`{{KSCRIPT_REPOSITORY_PASSWORD}}` may also be used directly with optional prefixes or suffixes. For example: + +[source,kotlin] +---- +#!/usr/bin/env kscript +@file:Repository("{{KSCRIPT_REPOSITORY_URL}}", user="prefix-{{KSCRIPT_REPOSITORY_USER}}", password="{{KSCRIPT_REPOSITORY_PASSWORD}}-postfix") +---- + == FAQ === How to edit kscript in VS Code? diff --git a/src/main/kotlin/io/github/kscripting/kscript/KscriptHandler.kt b/src/main/kotlin/io/github/kscripting/kscript/KscriptHandler.kt index bcadedb46..564b0c2ad 100644 --- a/src/main/kotlin/io/github/kscripting/kscript/KscriptHandler.kt +++ b/src/main/kotlin/io/github/kscripting/kscript/KscriptHandler.kt @@ -50,7 +50,7 @@ class KscriptHandler( } val inputOutputResolver = InputOutputResolver(config.osConfig, cache) - val sectionResolver = SectionResolver(inputOutputResolver, Parser(), config.scriptingConfig) + val sectionResolver = SectionResolver(inputOutputResolver, Parser(), config.scriptingConfig, config.osConfig) val scriptResolver = ScriptResolver(inputOutputResolver, sectionResolver, config.scriptingConfig) if (options.containsKey("add-bootstrap-header")) { diff --git a/src/main/kotlin/io/github/kscripting/kscript/code/GradleTemplates.kt b/src/main/kotlin/io/github/kscripting/kscript/code/GradleTemplates.kt index 56ad00a42..fd7eee49d 100644 --- a/src/main/kotlin/io/github/kscripting/kscript/code/GradleTemplates.kt +++ b/src/main/kotlin/io/github/kscripting/kscript/code/GradleTemplates.kt @@ -61,9 +61,9 @@ object GradleTemplates { |} | |repositories { - | mavenLocal() - | mavenCentral() |${createGradleRepositoriesSection(script.repositories).prependIndent()} + | mavenCentral() + | mavenLocal() |} | |tasks.jar { @@ -124,6 +124,7 @@ object GradleTemplates { private fun createGradleRepositoriesSection(repositories: Set) = repositories.joinToString("\n") { """|maven { | url = uri("${it.url}") + | isAllowInsecureProtocol = true |${createGradleRepositoryCredentials(it).prependIndent()} |} """.trimMargin() diff --git a/src/main/kotlin/io/github/kscripting/kscript/model/Config.kt b/src/main/kotlin/io/github/kscripting/kscript/model/Config.kt index 4593b128c..cd68ba55f 100644 --- a/src/main/kotlin/io/github/kscripting/kscript/model/Config.kt +++ b/src/main/kotlin/io/github/kscripting/kscript/model/Config.kt @@ -33,6 +33,7 @@ data class OsConfig( val configFile: OsPath, val cacheDir: OsPath, val kotlinHomeDir: OsPath, + val environment: ProcessEnvironment, ) { override fun toString(): String { return """|OsConfig { @@ -44,6 +45,7 @@ data class OsConfig( | configFile: $configFile | cacheDir: $cacheDir | kotlinHomeDir: $kotlinHomeDir + | environment: ${environment.size} entries |} """.trimMargin() } diff --git a/src/main/kotlin/io/github/kscripting/kscript/model/ConfigBuilder.kt b/src/main/kotlin/io/github/kscripting/kscript/model/ConfigBuilder.kt index a94689774..ac4669fc7 100644 --- a/src/main/kotlin/io/github/kscripting/kscript/model/ConfigBuilder.kt +++ b/src/main/kotlin/io/github/kscripting/kscript/model/ConfigBuilder.kt @@ -87,6 +87,7 @@ class ConfigBuilder( configFile, cacheDir, kotlinHomeDir, + environment, ) val configProperties = Properties().apply { diff --git a/src/main/kotlin/io/github/kscripting/kscript/model/ProcessEnvironment.kt b/src/main/kotlin/io/github/kscripting/kscript/model/ProcessEnvironment.kt new file mode 100644 index 000000000..3ac8d6919 --- /dev/null +++ b/src/main/kotlin/io/github/kscripting/kscript/model/ProcessEnvironment.kt @@ -0,0 +1,3 @@ +package io.github.kscripting.kscript.model + +typealias ProcessEnvironment = Map diff --git a/src/main/kotlin/io/github/kscripting/kscript/resolver/SectionResolver.kt b/src/main/kotlin/io/github/kscripting/kscript/resolver/SectionResolver.kt index 088111621..7687665d9 100644 --- a/src/main/kotlin/io/github/kscripting/kscript/resolver/SectionResolver.kt +++ b/src/main/kotlin/io/github/kscripting/kscript/resolver/SectionResolver.kt @@ -2,6 +2,7 @@ package io.github.kscripting.kscript.resolver import io.github.kscripting.kscript.model.* import io.github.kscripting.kscript.parser.Parser +import io.github.kscripting.kscript.util.ScriptUtils.resolveRepositoryOption import io.github.kscripting.kscript.util.UriUtils import io.github.kscripting.shell.model.ScriptLocation import io.github.kscripting.shell.model.ScriptSource @@ -10,14 +11,15 @@ import java.net.URI class SectionResolver( private val inputOutputResolver: InputOutputResolver, private val parser: Parser, - private val scriptingConfig: ScriptingConfig + private val scriptingConfig: ScriptingConfig, + private val osConfig: OsConfig, ) { fun resolve( scriptLocation: ScriptLocation, scriptText: String, allowLocalReferences: Boolean, maxResolutionLevel: Int, - resolutionContext: ResolutionContext + resolutionContext: ResolutionContext, ): List
{ val sections = parser.parse(scriptLocation, scriptText) val resultingSections = mutableListOf
() @@ -32,7 +34,7 @@ class SectionResolver( allowLocalReferences, scriptLocation.level, maxResolutionLevel, - resolutionContext + resolutionContext, ) } @@ -48,7 +50,7 @@ class SectionResolver( allowLocalReferences: Boolean, currentLevel: Int, maxResolutionLevel: Int, - resolutionContext: ResolutionContext + resolutionContext: ResolutionContext, ): List { val resolvedScriptAnnotations = mutableListOf() @@ -82,7 +84,7 @@ class SectionResolver( content.text, allowLocalReferences && scriptSource == ScriptSource.FILE, maxResolutionLevel, - resolutionContext + resolutionContext, ) val scriptNode = ScriptNode(scriptLocation, newSections) @@ -132,14 +134,30 @@ class SectionResolver( } is Repository -> { + val environment = osConfig.environment val repository = Repository( - scriptAnnotation.id, scriptAnnotation.url.replace( - "{{KSCRIPT_REPOSITORY_URL}}", scriptingConfig.providedRepositoryUrl - ), scriptAnnotation.user.replace( - "{{KSCRIPT_REPOSITORY_USER}}", scriptingConfig.providedRepositoryUser - ), scriptAnnotation.password.replace( - "{{KSCRIPT_REPOSITORY_PASSWORD}}", scriptingConfig.providedRepositoryPassword - ) + id = scriptAnnotation.id, + url = resolveRepositoryOption( + scriptAnnotation.url, + "url", + "{{KSCRIPT_REPOSITORY_URL}}", + scriptingConfig.providedRepositoryUrl, + environment, + ), + user = resolveRepositoryOption( + scriptAnnotation.user, + "user", + "{{KSCRIPT_REPOSITORY_USER}}", + scriptingConfig.providedRepositoryUser, + environment, + ), + password = resolveRepositoryOption( + scriptAnnotation.password, + "password", + "{{KSCRIPT_REPOSITORY_PASSWORD}}", + scriptingConfig.providedRepositoryPassword, + environment, + ), ) resolutionContext.repositories.add(repository) diff --git a/src/main/kotlin/io/github/kscripting/kscript/util/ScriptUtils.kt b/src/main/kotlin/io/github/kscripting/kscript/util/ScriptUtils.kt index 93a8b25ee..7511d3c3a 100644 --- a/src/main/kotlin/io/github/kscripting/kscript/util/ScriptUtils.kt +++ b/src/main/kotlin/io/github/kscripting/kscript/util/ScriptUtils.kt @@ -3,6 +3,7 @@ package io.github.kscripting.kscript.util import io.github.kscripting.kscript.model.Code import io.github.kscripting.kscript.model.ImportName import io.github.kscripting.kscript.model.PackageName +import io.github.kscripting.kscript.model.ProcessEnvironment import io.github.kscripting.kscript.model.ScriptNode import io.github.kscripting.kscript.resolver.ResolutionContext import io.github.kscripting.shell.model.ScriptType @@ -57,6 +58,35 @@ object ScriptUtils { return sb.toString() } + fun resolveRepositoryOption( + str: String?, + optionName: String, + placeholder: String, + property: String, + environment: ProcessEnvironment, + ): String = tryResolveEnvironmentVariable(str, optionName, environment) + ?.replace(placeholder, property) + ?: error("Failed to resolve value for option '$optionName'") + + /** + * This is a variant of [kotlin.script.experimental.dependencies.maven.MavenDependenciesResolver.tryResolveEnvironmentVariable]. + */ + private fun tryResolveEnvironmentVariable( + str: String?, + optionName: String, + environment: ProcessEnvironment, + ): String? { + if (str == null) return null + if (!str.startsWith("$")) return str + val envName = str.substring(1) + val envValue: String? = environment[envName] + if (envValue.isNullOrEmpty()) { + Logger.errorMsg("Environment variable '$envName' is not defined for option '$optionName'") + return null + } + return envValue + } + private fun resolveSimpleCode(sb: StringBuilder, scriptNode: ScriptNode, lastLineIsEmpty: Boolean = false) { var isLastLineEmpty = lastLineIsEmpty diff --git a/src/test/kotlin/io/github/kscripting/kscript/code/GradleTemplatesTest.kt b/src/test/kotlin/io/github/kscripting/kscript/code/GradleTemplatesTest.kt index 2f3ca6969..f1b0e8994 100644 --- a/src/test/kotlin/io/github/kscripting/kscript/code/GradleTemplatesTest.kt +++ b/src/test/kotlin/io/github/kscripting/kscript/code/GradleTemplatesTest.kt @@ -95,6 +95,7 @@ class GradleTemplatesTest { | mavenCentral() | maven { | url = uri("https://url1") + | isAllowInsecureProtocol = true | credentials { | username = "user1" | password = "pass1" @@ -102,6 +103,7 @@ class GradleTemplatesTest { | } | maven { | url = uri("https://url2") + | isAllowInsecureProtocol = true | credentials { | username = "user2" | password = "pass2" diff --git a/src/test/kotlin/io/github/kscripting/kscript/resolver/CommandResolverTest.kt b/src/test/kotlin/io/github/kscripting/kscript/resolver/CommandResolverTest.kt index d96eddfe3..15db8f684 100644 --- a/src/test/kotlin/io/github/kscripting/kscript/resolver/CommandResolverTest.kt +++ b/src/test/kotlin/io/github/kscripting/kscript/resolver/CommandResolverTest.kt @@ -106,6 +106,7 @@ class CommandResolverTest { homeDir.resolve("./.config/"), homeDir.resolve("./.cache/"), kotlinDir, + emptyMap(), ) val scriptingConfig = ScriptingConfig("", "", "", "", "", null) diff --git a/src/test/kotlin/io/github/kscripting/kscript/resolver/ScriptResolverTest.kt b/src/test/kotlin/io/github/kscripting/kscript/resolver/ScriptResolverTest.kt index 85da32048..032887b03 100644 --- a/src/test/kotlin/io/github/kscripting/kscript/resolver/ScriptResolverTest.kt +++ b/src/test/kotlin/io/github/kscripting/kscript/resolver/ScriptResolverTest.kt @@ -1,10 +1,7 @@ package io.github.kscripting.kscript.resolver import assertk.assertThat -import assertk.assertions.endsWith -import assertk.assertions.isEmpty -import assertk.assertions.isEqualTo -import assertk.assertions.prop +import assertk.assertions.* import io.github.kscripting.kscript.cache.Cache import io.github.kscripting.kscript.model.* import io.github.kscripting.kscript.parser.Parser @@ -28,7 +25,7 @@ class ScriptResolverTest { private val cache = Cache(testHome.resolve("cache")) private val inputOutputResolver = InputOutputResolver(config.osConfig, cache) private val scriptingConfig = ScriptingConfig("", "", "", "", "", null) - private val sectionResolver = SectionResolver(inputOutputResolver, Parser(), scriptingConfig) + private val sectionResolver = SectionResolver(inputOutputResolver, Parser(), scriptingConfig, config.osConfig) private val scriptResolver = ScriptResolver(inputOutputResolver, sectionResolver, scriptingConfig) private val defaultPackageName = PackageName("kscript.scriplet") @@ -163,5 +160,83 @@ class ScriptResolverTest { } } + @Test + fun `Should resolve environment variables in repository declarations`() { + val input = "test/resources/depends_on_env.kts" + + val osConfig = config.osConfig.copy(environment = mapOf( + "REPO" to "http://foo/bar", + "USER" to "u", + "PASS" to "p", + )) + + val sectionResolver = SectionResolver(inputOutputResolver, Parser(), scriptingConfig, osConfig) + val scriptResolver = ScriptResolver(inputOutputResolver, sectionResolver, scriptingConfig) + + val script = scriptResolver.resolve(input) + + assertThat(script).apply { + prop(Script::repositories).isEqualTo( + setOf( + Repository("", "http://foo/bar","u", "p") + ) + ) + } + } + + @Test + fun `Should resolve KSCRIPT_REPOSITORY placeholders in repository declarations`() { + val input = "test/resources/depends_on_repo_placeholders.kts" + + val scriptingConfig = ScriptingConfig("", "", "http://foo/bar", "u", "p", null) + val sectionResolver = SectionResolver(inputOutputResolver, Parser(), scriptingConfig, config.osConfig) + val scriptResolver = ScriptResolver(inputOutputResolver, sectionResolver, scriptingConfig) + + val script = scriptResolver.resolve(input) + + assertThat(script).apply { + prop(Script::repositories).isEqualTo( + setOf( + Repository("", "http://foo/bar","u-suffix", "prefix-p") + ) + ) + } + } + + @Test + fun `Should resolve KSCRIPT_REPOSITORY placeholders in repository declarations after resolving environment variables`() { + val input = "test/resources/depends_on_env.kts" + + val scriptingConfig = ScriptingConfig("", "", "http://foo/bar", "u", "p", null) + val osConfig = config.osConfig.copy(environment = mapOf( + "REPO" to "{{KSCRIPT_REPOSITORY_URL}}", + "USER" to "{{KSCRIPT_REPOSITORY_USER}}-suffix", + "PASS" to "prefix-{{KSCRIPT_REPOSITORY_PASSWORD}}", + )) + val sectionResolver = SectionResolver(inputOutputResolver, Parser(), scriptingConfig, osConfig) + val scriptResolver = ScriptResolver(inputOutputResolver, sectionResolver, scriptingConfig) + + // this allows configuration to come from both the properties file and allows the environment to override + // properties by composing from it + val script = scriptResolver.resolve(input) + + assertThat(script).apply { + prop(Script::repositories).isEqualTo( + setOf( + Repository("", "http://foo/bar","u-suffix", "prefix-p") + ) + ) + } + } + + @Test + fun `Unresolved environment variables in repository declarations result in an error`() { + val input = "test/resources/depends_on_env.kts" + + assertThat { + scriptResolver.resolve(input) + }.isFailure() + } + private fun String.discardEmptyLines(): String = this.lines().filterNot { it.isEmpty() }.joinToString("\n") } diff --git a/src/test/kotlin/io/github/kscripting/kscript/util/ScriptUtilsTest.kt b/src/test/kotlin/io/github/kscripting/kscript/util/ScriptUtilsTest.kt new file mode 100644 index 000000000..55a1abcab --- /dev/null +++ b/src/test/kotlin/io/github/kscripting/kscript/util/ScriptUtilsTest.kt @@ -0,0 +1,100 @@ +package io.github.kscripting.kscript.util + +import assertk.assertThat +import assertk.assertions.isEqualTo +import assertk.assertions.isFailure +import org.junit.jupiter.api.Test + +class ScriptUtilsTest { + @Test + fun `Test resolve repository option literal`() { + val option = ScriptUtils.resolveRepositoryOption( + "literal-value", + "optionName", + "{{PLACEHOLDER}}", + "placeholder-value", + emptyMap(), + ) + + assertThat(option).isEqualTo("literal-value") + } + + @Test + fun `Test resolve repository option placeholder`() { + val option = ScriptUtils.resolveRepositoryOption( + "{{FOO}}", + "optionName", + "{{FOO}}", + "placeholder-value", + emptyMap(), + ) + + assertThat(option).isEqualTo("placeholder-value") + } + + @Test + fun `Test resolve repository option placeholder with prefix and suffix`() { + assertThat( + ScriptUtils.resolveRepositoryOption( + "{{FOO}}-bar", + "optionName", + "{{FOO}}", + "placeholder-value", + emptyMap(), + ) + ).isEqualTo("placeholder-value-bar") + + assertThat( + ScriptUtils.resolveRepositoryOption( + "bar-{{FOO}}", + "optionName", + "{{FOO}}", + "placeholder-value", + emptyMap(), + ) + ).isEqualTo("bar-placeholder-value") + } + + @Test + fun `Test resolve repository option environment`() { + val option = ScriptUtils.resolveRepositoryOption( + "\$FOO", + "optionName", + "{{FOO}}", + "placeholder-value", + mapOf( + "FOO" to "env-value", + ), + ) + + assertThat(option).isEqualTo("env-value") + } + + @Test + fun `Test resolve repository option environment with placeholder`() { + assertThat( + ScriptUtils.resolveRepositoryOption( + "\$FOO", + "optionName", + "{{BAR}}", + "placeholder-value", + mapOf( + "FOO" to "env-value-{{BAR}}", + ), + ) + ).isEqualTo("env-value-placeholder-value") + } + + @Test + fun `Test repository option resolution failure, no environment value`() { + assertThat { + ScriptUtils.resolveRepositoryOption( + "\$FOO", + "optionName", + "{{BAR}}", + "placeholder-value", + emptyMap(), + ) + }.isFailure() + } +} diff --git a/test/TestsReadme.md b/test/TestsReadme.md index bdaa493a0..4e0b4b618 100644 --- a/test/TestsReadme.md +++ b/test/TestsReadme.md @@ -157,28 +157,16 @@ As of this writing, testing the credentials is only done manually with a dockeri ```bash # download and start artifactory container -docker run --name artifactory -d -p 8081:8081 docker.bintray.io/jfrog/artifactory-oss:latest - -# Copy preconfigured gloabl config (with custom repo) and security config (with credentials user) into container. -docker cp ./test/resources/artifactory_config/artifactory.config.xml artifactory:/var/opt/jfrog/artifactory/etc/artifactory.config.import.xml -docker cp ./test/resources/artifactory_config/security_descriptor.xml artifactory:/var/opt/jfrog/artifactory/etc/security.import.xml - -# Make the configs accessable -docker exec -u 0 -it artifactory sh -c 'chmod 777 $ARTIFACTORY_HOME/etc/*.import.xml' - -# Restart docker after is done with initial booting (otherwise restart breaks the container). -echo "sleeping for 15..." && sleep 15 -docker restart artifactory +modified_image=$(DOCKER_BUILDKIT=1 docker build -q \ + -f test/resources/artifactory_config/Dockerfile \ + test/resources/artifactory_config) +docker run --name artifactory -d -p 8081:8081 $modified_image ``` #### 2. Create and upload a downloadable archive. ```bash -tmpClass=$(mktemp --suffix ".class") -tmpZipDir=$(mktemp -d) -echo "public class something() {}" > $tmpClass -zip $tmpZipDir/tmp.zip $tmpClass -curl --request PUT -u admin:password -T $tmpZipDir/tmp.zip http://localhost:8081/artifactory/authenticated_repo/group/somejar/1.0/somejar-1.0.jar +gradle --project-dir test/resources/jar_dependency publishAllPublicationsToMavenRepository ``` #### 3. Then run the following kotlin script with the encrypted password @@ -187,9 +175,43 @@ curl --request PUT -u admin:password -T $tmpZipDir/tmp.zip http://localhost:8081 echo ' @file:Repository("http://localhost:8081/artifactory/authenticated_repo", user="auth_user", password="password") @file:DependsOn("com.jcabi:jcabi-aether:0.10.1") // If unencrypted works via jcenter -@file:DependsOnMaven("group:somejar:1.0") // If encrypted works. +@file:DependsOnMaven("com.github.holgerbrandl.kscript.test:jartester:1.0-SNAPSHOT") // If encrypted works. +println("Hello, World!") +' | kscript -c - +``` + +#### 4. Test environment variable substitution + +```bash +export auth_user="auth_user" +export auth_password="password" + +echo ' +@file:Repository("http://localhost:8081/artifactory/authenticated_repo", user="$auth_user", password="$auth_password") +@file:DependsOn("com.jcabi:jcabi-aether:0.10.1") // If unencrypted works via jcenter +@file:DependsOnMaven("com.github.holgerbrandl.kscript.test:jartester:1.0-SNAPSHOT") // If encrypted works. println("Hello, World!") -' | kscript - +' | kscript -c - +``` + +#### 5. Test environment variable substitution with packaging + +```bash +export auth_user="auth_user" +export auth_password="password" + +echo ' +@file:Repository("http://localhost:8081/artifactory/authenticated_repo", user="$auth_user", password="$auth_password") +@file:DependsOn("com.jcabi:jcabi-aether:0.10.1") // If unencrypted works via jcenter +@file:DependsOnMaven("com.github.holgerbrandl.kscript.test:jartester:1.0-SNAPSHOT") // If encrypted works. +println("Hello, World!") +' | kscript -c --package - +``` + +#### 6. (Optional) Cleanup Local Maven Cache + +```bash +rm -fr ~/.m2/repository/com/github/holgerbrandl/kscript/test/ ``` ### Additional info for manual testing diff --git a/test/resources/artifactory_config/Dockerfile b/test/resources/artifactory_config/Dockerfile new file mode 100644 index 000000000..1864735e9 --- /dev/null +++ b/test/resources/artifactory_config/Dockerfile @@ -0,0 +1,3 @@ +FROM docker.bintray.io/jfrog/artifactory-oss:latest +COPY ./artifactory.config.xml /var/opt/jfrog/artifactory/etc/artifactory/artifactory.config.import.xml +COPY --chmod=777 ./security_descriptor.xml /var/opt/jfrog/artifactory/etc/artifactory/security.import.xml diff --git a/test/resources/depends_on_env.kts b/test/resources/depends_on_env.kts new file mode 100755 index 000000000..97647ef5a --- /dev/null +++ b/test/resources/depends_on_env.kts @@ -0,0 +1,7 @@ +#!/usr/bin/env kscript + +@file:Repository("$REPO", user="$USER", password="$PASS") +@file:DependsOn("com.eclipsesource.minimal-json:minimal-json:0.9.4") +@file:DependsOn("log4j:log4j:1.2.14") + +println("Hello, World!") diff --git a/test/resources/depends_on_repo_placeholders.kts b/test/resources/depends_on_repo_placeholders.kts new file mode 100755 index 000000000..5e75119b7 --- /dev/null +++ b/test/resources/depends_on_repo_placeholders.kts @@ -0,0 +1,7 @@ +#!/usr/bin/env kscript + +@file:Repository("{{KSCRIPT_REPOSITORY_URL}}", user="{{KSCRIPT_REPOSITORY_USER}}-suffix", password="prefix-{{KSCRIPT_REPOSITORY_PASSWORD}}") +@file:DependsOn("com.eclipsesource.minimal-json:minimal-json:0.9.4") +@file:DependsOn("log4j:log4j:1.2.14") + +println("Hello, World!") diff --git a/test/resources/jar_dependency/build.gradle b/test/resources/jar_dependency/build.gradle index d633d136e..33bb852d8 100644 --- a/test/resources/jar_dependency/build.gradle +++ b/test/resources/jar_dependency/build.gradle @@ -1,6 +1,7 @@ plugins { id 'java' - id 'org.jetbrains.kotlin.jvm' version '1.3.41' + id 'org.jetbrains.kotlin.jvm' version '1.8.20' + id 'maven-publish' } group 'com.github.holgerbrandl.kscript.test' @@ -10,11 +11,21 @@ sourceCompatibility = 1.8 repositories { mavenCentral() + // for use with local artifactory for testing auth repo access, see artifactory_config and + // TestsReadme.md (Manual testing) + maven { + url "http://localhost:8081/artifactory/authenticated_repo" + allowInsecureProtocol = true + credentials { + username 'auth_user' + password 'password' + } + } } dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8" - testCompile group: 'junit', name: 'junit', version: '4.12' + testImplementation group: 'junit', name: 'junit', version: '4.12' } compileKotlin { @@ -22,4 +33,22 @@ compileKotlin { } compileTestKotlin { kotlinOptions.jvmTarget = "1.8" -} \ No newline at end of file +} + +publishing { + publications { + mavenJava(MavenPublication) { + from components.java + } + } + repositories { + maven { + url "http://localhost:8081/artifactory/authenticated_repo" + allowInsecureProtocol = true + credentials { + username 'auth_user' + password 'password' + } + } + } +} diff --git a/test/resources/jar_dependency/settings.gradle.kts b/test/resources/jar_dependency/settings.gradle.kts new file mode 100644 index 000000000..36510d5f2 --- /dev/null +++ b/test/resources/jar_dependency/settings.gradle.kts @@ -0,0 +1 @@ +rootProject.name = "jartester"