Space Automation: Using External Libraries

Alexey Totin


One of the best things about the Space Automation DSL is that it’s based on Kotlin script. This means not only that you can use pure Kotlin inside your build scripts but also that you can reference any external .jar libraries. For this purpose, Kotlin script provides the @file:DependsOn directive. Let’s see it in action!

How to reference an external library

We can start by looking in detail at the contents of a working example to clarify how this works. The script below gets a random joke from icanhazdadjoke.com using the OkHttp client and prints it to the job log.

@file:DependsOn("com.squareup.okhttp:okhttp:2.7.4", "org.json:json:20200518")

import com.squareup.okhttp.*
import org.json.JSONObject

job("Get random joke") {
    container("openjdk:11") {
        kotlinScript {
            val client = OkHttpClient()
            val request = Request.Builder()
                .url("http://icanhazdadjoke.com")
                .addHeader("Accept", "application/json")
                .build()
            val response = client.newCall(request).execute()
            val jData = response.body().string()
            val jObject = JSONObject(jData)
            val joke = jObject.get("joke").toString()
            println(joke)
        }
    }
}
  1. @file:DependsOn("com.squareup.okhtp:okhttp:2.7.4", "org.json:json:20200518") adds references to the OkHttp client and the standard library for working with JSON. Currently, you can reference only libraries hosted on Maven Central.
  2. import com.squareup.okhttp.* and import org.json.JSONObject: This is the standard syntax in Java and Kotlin for importing classes from libraries.
  3. container("openjdk:11"): If you already have a general understanding of Automation, you probably know that to run Kotlin code, you should use the kotlinScript block. When Automation runs your build script, it compiles the contents of kotlinScript into a .jar file. This imposes restrictions on the container image – it must include JRE/JDK v.9 or later. That’s why we use the openjdk:11 image.
  4. The contents of the kotlinScript block is pure Kotlin code that uses an OkHttpClient instance to get a JSON response from the server and then picks the joke contents out of the response.
  5. println(joke) prints the joke to the job log.
    Automation job log

Using Slack API to send messages from Automation scripts

Jokes from the internet are fun but let’s make something a little more useful. Let’s use @file:DependsOn to reference the Slack API and teach our Automation script to send messages to a Slack channel. As we need to authenticate our script in Slack, this will require some extra steps.

  1. Create a Slack application and install it to your Slack workspace. Note that to post messages to workspace channels, your application requires the calls:write permission.
  2. After you install the application, Slack will provide you its OAuth access token. You can also find this token in Slack on the application’s OAuth & Permissions page. Save the token, for example, by copying it to the clipboard.
  3. In Space, create a secret variable, for example, a slack-token, and specify your Slack OAuth token as its value.
    Small side note: Space has key-value storage that lets you securely store various service credentials:

    • To put a secret in the storage, open the required project and in the project Settings, go to Secrets & Parameters.
    • To get a secret value in a script, assign it to a container environment variable using the Secrets function:
      env["PSWRD"] = Secrets("password-key")
  4. In the project’s .space.kts file, add the code that will send messages to a particular channel:

    @file:DependsOn("com.slack.api:slack-api-client:1.1.1")
    import com.slack.api.Slack
    job("send to slack") {
        container("openjdk:11") {
            env["TOKEN"] = Secrets("slack-token")
    
            kotlinScript { api ->
                val slack = Slack.getInstance()
                val token = System.getenv("TOKEN")
                val response = slack.methods(token).chatPostMessage { req ->
                    req.channel("#automation").text("Hi there!")
                }
                println("$response")
            }
        }
    }
    

Now, every time you run the job, it will post the “Hello from Space!” message to the ‘automation’ channel.
Message sent from Automation to Slack

That’s all the basics for using external packages in your build scripts covered. Try it for yourself and, of course, feel free to share your experience in the comments below.

Subscribe

Subscribe for Space blog