Deploying a Kotlin app to Railway (a Slack bot)

We will deploy a “Hello world” Slack bot to Railway, sourced from GitHub (written in Kotlin).

Luís Soares
CodeX
Published in
3 min readNov 22, 2022

--

Photo by Eric Krull on Unsplash

Now that Heroku has no free plan anymore, it’s time to find a new home for our experimental JVM apps. Railway does the job.

1. Codebase

  1. Create a new Kotlin project.
  2. If you haven’t yet made git init, you should do it now.
  3. Make sure you have a .gitignore file at the root with:
/.gradle
/.idea
/build

4. We will use GitHub as the source of the app codebase; Railway will access it and deploy the app from there. Create a new GitHub repository (can be private or public) naming it slack-hello-bot or similar.

5. Commit and push to your new repository:

git remote add origin GITHUB_REPOSITORY_LINK
git push -u origin main

2. Railway project

We need to set up a Railway project which will serve our Kotlin app created before.

  1. Go to Railway ▶ register/login ▶ click “New Project” ▶ “Deploy from GitHub repo” ▶ provide access to GitHub ▶ pick the created project (slack-hello-bot).
  2. On the Kotlin app’s root folder, create a file named Procfile with the following content:
    web: java -jar build/libs/PROJ_ID-1.0-SNAPSHOT-all.jar
    (to get thePROJ_ID, check settings.gradle.kts).
    This represents the command that Railway runs to launch the web app.
  3. Railway requires a stage target.
    At the end of build.gradle.kts, add:
task("stage") {
dependsOn("shadowJar")
}

3. Slack Bolt app

  1. Add the following dependencies to build.gradle.kts:
dependencies {
implementation("org.slf4j:slf4j-simple:1.+")
implementation("com.slack.api:bolt:1.+")
implementation("com.slack.api:bolt-servlet:1.+")
implementation("com.slack.api:bolt-jetty:1.+")
}

2. Add Gradle Shadow build.gradle.kts. This will enable the creation of a single fat jar that can be run later in Railway.

plugins {
id("com.github.johnrengelman.shadow") version "7.+"
application
}
// at the bottom:
application {
mainClass.set("SlackMainKt")
}

📝 You may need to click the buttons to refresh Gradle, in the top-right corner of the file in the IDE.

3. At src/main/kotlin/SlackMain.kt, put:

fun main() {
val app = App()
app.command("/hello") { _, _ ->
Response.ok("world")
}
SlackAppServer(app, getenv("PORT")?.toInt() ?: 8080)
.start()
}

📝 PORT is an environment variable provided by Railway. It represents the port that Railway exposes. Therefore, we need to serve our app from that port.

4. Commit and push all the local Git changes. The push will automatically trigger a Railway deployment. You can check the deploy status and logs on Railway dashboard.

4. Slack app configuration

Based on the official docs: Building an app with Bolt for Java and Getting Started with Bolt.

  1. Go to Slack Apps ▶ click “Create New App”.
  2. Pick “From scratch” ▶ click “Next” ▶ name the app ▶ assign it to a workspace.
  3. On the left-side menu, go to “OAuth & Permissions” ▶ scroll to “Scopes” ▶ add chat:write.
  4. On the menu, click “Slash Commands” ▶ “Create New Command”.
  5. Fill in the details with:
    Command: hello
    Request URL: BASE_APP_URL/slack/events
    To get BASE_APP_URL, go to Railway dashboard ▶ pick the app ▶ “web” ▶ “Settings” ▶ “Domains”.
    Short Description: hello world
    Save the changes.
  6. We need to copy the Slack environment variables from Slack UI to Railway:
    Go to “Basic Information” ▶ “App Credentials” ▶ “Signing Secret” ▶ click “Show” ▶ copy it. Go to Railway dashboard ▶ pick the created app ▶ “web” ▶ “Variables” ▶ “New Variable” named SLACK_SIGNING_SECRET with the copied value from before.
  7. Going back to the Slack UI ▶ go to “OAuth & Permissions” ▶ click the button “Install to Workspace” ▶ copy the value at “Bot User OAuth Token”. Go back to the Railway ▶ create another env var named SLACK_BOT_TOKEN ▶ paste the copied value.
  8. Time to test the app! Go to Slack ▶ type /hello in any channel ▶ press Enter. You should get world as reply.

--

--

Luís Soares
CodeX
Writer for

I write about automated testing, Lean, TDD, CI/CD, trunk-based dev., user-centric dev, DDD, coding good practices,