Skip to content

Add support for @file:MavenCredentials() annotation #214

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ dependencies {
exclude("cglib", "cglib")
exclude("org.kuali.maven.wagons", "maven-s3-wagon")
}
// compile("com.jcabi:jcabi-aether:0.10.1:sources") //can be used for debugging, but somehow adds logging to dependency resolvement?
compile("org.apache.maven:maven-core:3.0.3")
compile("org.slf4j:slf4j-nop:1.7.25")

Expand Down Expand Up @@ -50,4 +51,4 @@ val jar by tasks.getting {
// Build shadowJar when
val assemble by tasks.getting {
dependsOn(shadowJar)
}
}
12 changes: 10 additions & 2 deletions src/main/kotlin/kscript/app/DependencyUtil.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package kscript.app
import com.jcabi.aether.Aether
import org.sonatype.aether.RepositoryException
import org.sonatype.aether.artifact.Artifact
import org.sonatype.aether.repository.Authentication
import org.sonatype.aether.repository.RemoteRepository
import org.sonatype.aether.util.artifact.DefaultArtifact
import org.sonatype.aether.util.artifact.JavaScopes.COMPILE
Expand Down Expand Up @@ -59,15 +60,22 @@ fun resolveDependencies(depIds: List<String>, customRepos: List<MavenRepo> = emp
// Print the classpath
return classPath
} catch (e: RepositoryException) {
errorMsg("Failed to lookup dependencies. Check dependency locators or file a bug on https://github.com/holgerbrandl/kscript")
// Probably a wrapped Nullpointer from 'DefaultRepositorySystem.resolveDependencies()', this however is probably a connection problem.
errorMsg("Failed while connecting to the server. Check the connection (http/https, port, proxy, credentials, etc.) of your maven dependency locators. If you suspect this is a bug, you can create an issue on https://github.com/holgerbrandl/kscript")
errorMsg("Exception: $e")
quit(1)
}
}

fun resolveDependenciesViaAether(depIds: List<String>, customRepos: List<MavenRepo>, loggingEnabled: Boolean): List<Artifact> {
val jcenter = RemoteRepository("jcenter", "default", "http://jcenter.bintray.com/")
val customRemoteRepos = customRepos.map { it -> RemoteRepository(it.id, "default", it.url) }
val customRemoteRepos = customRepos.map { mavenRepo ->
RemoteRepository(mavenRepo.id, "default", mavenRepo.url).apply {
if (!mavenRepo.user.isNullOrEmpty() && !mavenRepo.password.isNullOrEmpty()) {
authentication = Authentication(mavenRepo.user, mavenRepo.password)
}
}
}
val remoteRepos = customRemoteRepos + jcenter

val aether = Aether(remoteRepos, File(System.getProperty("user.home") + "/.m2/repository"))
Expand Down
14 changes: 9 additions & 5 deletions src/main/kotlin/kscript/app/Script.kt
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ fun Script.collectDependencies(): List<String> {

// if annotations are used add dependency on kscript-annotations
if (lines.any { isKscriptAnnotation(it) }) {
dependencies += "com.github.holgerbrandl:kscript-annotations:1.2"
dependencies += "com.github.holgerbrandl:kscript-annotations:1.4"
}

return dependencies.distinct()
Expand Down Expand Up @@ -182,7 +182,7 @@ private fun isDependDeclare(line: String) =
//


data class MavenRepo(val id: String, val url: String)
data class MavenRepo(val id: String, val url: String, val user: String = "", val password: String = "")

/**
* Collect custom artifact repos declared with @file:MavenRepository
Expand All @@ -192,12 +192,16 @@ fun Script.collectRepos(): List<MavenRepo> {
// only supported annotation format for now

// @file:MavenRepository("imagej", "http://maven.imagej.net/content/repositories/releases/")
// @file:MavenRepository("imagej", "http://maven.imagej.net/content/repositories/releases/", user="user", password="pass")
return lines
.filter { it.contains(dependsOnMavenPrefix) }
.map { it.replaceFirst(dependsOnMavenPrefix, "").substringBeforeLast(")") }
.map { it.split(",").map { it.trim(' ', '"', '(') }.let { MavenRepo(it[0], it[1]) } }

// todo add credential support https://stackoverflow.com/questions/36282168/how-to-add-custom-maven-repository-to-gradle
.map {
it.split(",").map { it.trim(' ', '"', '(') }.let { annotationParams ->
val namedArgs = annotationParams.filter { it.contains("=") }.map { item: String -> item.let { item.substringBefore("=") to item.substringAfter("=\"") } }.toMap()
MavenRepo(annotationParams[0], annotationParams[1], namedArgs.getOrDefault("user", ""), namedArgs.getOrDefault("password", ""))
}
}
}


Expand Down
33 changes: 30 additions & 3 deletions src/test/kotlin/Tests.kt
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class Tests {
val expected = listOf(
"something:dev-1.1.0-alpha3(T2):1.2.14",
"de.mpicbg.scicomp:kutils:0.7",
"com.github.holgerbrandl:kscript-annotations:1.2"
"com.github.holgerbrandl:kscript-annotations:1.4"
)

Script(lines).collectDependencies() shouldBe expected
Expand All @@ -58,7 +58,7 @@ class Tests {
"de.mpicbg.scicomp.joblist:joblist-kotlin:1.1",
"de.mpicbg.scicomp:kutils:0.7",
"log4j:log4j:1.2.14",
"com.github.holgerbrandl:kscript-annotations:1.2"
"com.github.holgerbrandl:kscript-annotations:1.4"
)

Script(lines).collectDependencies() shouldBe expected
Expand All @@ -83,12 +83,39 @@ class Tests {
collectDependencies() shouldBe listOf(
"net.clearvolume:cleargl:2.0.1",
"log4j:log4j:1.2.14",
"com.github.holgerbrandl:kscript-annotations:1.2"
"com.github.holgerbrandl:kscript-annotations:1.4"
)
}

}

@Test
fun customRepoWithCreds() {
val lines = listOf(
"""@file:MavenRepository("imagej-releases", "http://maven.imagej.net/content/repositories/releases", user="user", password="pass") """,
"""@file:MavenRepository("imagej-snapshots", "http://maven.imagej.net/content/repositories/snapshots", password="pass", user="user") """,
"""@file:DependsOnMaven("net.clearvolume:cleargl:2.0.1")""",
"""@file:DependsOn("log4j:log4j:1.2.14")""",
"""println("foo")"""
)

with(Script(lines)) {

collectRepos() shouldBe listOf(
MavenRepo("imagej-releases", "http://maven.imagej.net/content/repositories/releases", "user", "pass"),
MavenRepo("imagej-snapshots", "http://maven.imagej.net/content/repositories/snapshots", "user", "pass") //Provided with name in non-typical order
)

collectDependencies() shouldBe listOf(
"net.clearvolume:cleargl:2.0.1",
"log4j:log4j:1.2.14",
"com.github.holgerbrandl:kscript-annotations:1.4"
)
}

}



// combine kotlin opts spread over multiple lines
@Test
Expand Down
57 changes: 56 additions & 1 deletion test/TestsReadme.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,61 @@ which kscript
kscript --version
which resdeps.kts
kscript --clear-cache
kscript https://git.io/v1cG6 my argu ments
kscript https://git.io/v1cG6 my argu ments

```


## Manual testing

As of this writing, testing the credentials is only done manually with a dockerized Artifactory.

#### 1. Set up preconfigured artifactory with docker.

```
# 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
```

#### 2. Create and upload a downloadable archive.
```
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
```

#### 3. Then run the following kotlin script with the encrypted password
```
echo '
@file:MavenRepository("my-art", "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.
println("Hello, World!")
' | kscript -
```

### Additional info for manual testing

- Docker & container docu: https://www.jfrog.com/confluence/display/RTF/Installing+with+Docker
- Loading configs docu: https://www.jfrog.com/confluence/display/RTF/Configuration+Files

```
# get active security descriptor
curl -u admin:password -X GET -H "Accept: application/xml" http://localhost:8081/artifactory/api/system/security > ./test/resources/artifactory_config/security_descriptor.xml

# Also works with encrypted password instead of plaintext.
curl -u admin:password -X GET http://localhost:8081/artifactory/api/security/encryptedPassword
```
Loading