Using sdkman in github actions

Introduction Link to heading

I was experimenting with some Github Actions that needed to make use of Mandrel so, I thought that I should use sdkman. I run into some issues though and I thought I should document the experience

The main issue I encountered, is that no matter how I mixed sdkamn into the mix, my steps acted like it was not

The sdkamn action Link to heading

It seems that there is a Github Action for sdkman available, which should allow you to manage any `candidate`. I used it like this:

1
2
3
4
5
  - uses: sdkman/sdkman-action@master
    id: sdkman
    with:
      candidate: java
      version: 21.2.0.0-mandrel

But when I proceeded later on to make use of the `native-image` binary it was not there.

Using sdkman manually Link to heading

I decided that instead of troubleshooting the Github Action for sdkman, it might be simpler and quicker to manage https://sdkman.io/ myself.

It was not!

This is what I tried:

1
2
3
4
5
6
      - name: Setup sdkman
        run: |
          curl -s "https://get.sdkman.io" | bash
          source "$HOME/.sdkman/bin/sdkman-init.sh"
          sdkman_auto_answer=false
          sdkman_selfupdate_enable=false          

The effect was similar. The step seemed to work with no issue whatsoever, but when I tried to use later on `native-image` it was not there.

Trobleshooting Link to heading

When I started added debuging / troubleshooting command in my script, like:

1
2
     which java
     java --version

I realized that it was not using Mandrel at all, but instead a `jdk 11` binary that was found in the `PATH`. The path? Did I say the path?

Bingo! For sdkman to properly work I should find an entry like `$HOME/.sdkman/candidates/java/current/bin` in my `PATH`.

I didn’t!

Even worse, the `sdk` binary was also not found in the path !?

There is no such thing as an sdk binary! Link to heading

In case, you don’t already know, sdkman is not a binary but an alias that gets initialized by your shell. Usually, it should be initialized by a command like:

1
    [[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh"

found inside your `.bashrc` or `.zshrc`.

The weird part of the story is that after checking what’s inside those files, the sdkman initialization lines where present.

bashrc is not executed Link to heading

I searched online for `github actions bashrc not executed` The firs result that came back was pretty enlightening. According to https://github.community/t/self-hosted-not-using-bashrc/18358/2:

`In order for individual steps to make use of the .bashrc, one needs to explictly request it, by setting the default shell options:

1
2
3
4
name: use bashrc
defaults:
  run:
    shell: bash -ieo pipefail {0}

I added this to my action and things worked like a charm.

A full exmaple Link to heading

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
name: Build

env:
  MAVEN_ARGS: -B -e

# We need to set these defaults so that .bashrc is called for each step.
# This is needed so that sdkman can be properly intialized
defaults:
  run:
    shell: bash -ieo pipefail {0}

on:
  push:
    branches:
      - master
  pull_request:

jobs:
  build:
    name: Clojure on Mandrel ${{ matrix.java-version }} with Leiningen ${{ matrix.lein-version }}
    runs-on: ubuntu-latest
    strategy:
      matrix:
        java-version: [21.2.0.0-mandrel]
        lein-version: [2.9.7]
    steps:
      - name: Checkout
        uses: actions/checkout@v2.3.4
      - name: Setup sdkman
        run: |
          curl -s "https://get.sdkman.io" | bash
          source "$HOME/.sdkman/bin/sdkman-init.sh"
          sdkman_auto_answer=false
          sdkman_selfupdate_enable=false          
      - name: Setup java
        run: |
          sdk install java ${{matrix.java-version}}
          sdk default java ${{matrix.java-version}}          
      - name: Setup leiningen
        run: |
          sdk install leiningen ${{matrix.lein-version}}
          sdk default leiningen ${{matrix.lein-version}}          
      - name: Run tests
        run: lein test
      - name: Build native image
        run: |
          lein native-image          

The full project can be found at: https://github.com/iotemplates/clojure-cli. As always, I hope this was helpful. See ya!