Skip to content
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

Feature: Using SDKMAN in a CI pipeline #1270

Open
lbruun opened this issue Jan 13, 2024 · 0 comments
Open

Feature: Using SDKMAN in a CI pipeline #1270

lbruun opened this issue Jan 13, 2024 · 0 comments

Comments

@lbruun
Copy link

lbruun commented Jan 13, 2024

Clearly, SDKMAN was (originally) designed for interactive and personal use by a developer.
It can be used in a CI pipeline, but such use case under-documented. This is sad as SDKMAN is a great tool.

This ticket explores how SDKMAN can be used in such context and also what might be improved in SDKMAN (in code or documentation) to make such adoption easier.

CI docker image with SDKMAN

Many CI systems use Docker for execution and therefore require that you put your tools (e.g. SDKMAN) into a docker image. SDKMAN is both useful at build time (for installing software that we want included the image) as well as at execution time (to allow a CI pipeline to install additional software).

Putting SDKMAN into a Docker image for such purpose is in fact not that simple as there as many things to remember. Below is an example of how it might be done:

FROM ubuntu:22.04

# (1)
SHELL ["/bin/bash", "-c"]

# (2) 
# Install needed packages
RUN apt-get update && apt-get install -y \
  curl \
  unzip \
&& rm -rf /var/lib/apt/lists/*

# (3)
# Install SDKMAN  
RUN curl -s -S -o ./get-sdkman.sh "https://get.sdkman.io?rcupdate=false" \
  && chmod +x ./get-sdkman.sh \
  && ./get-sdkman.sh \
  && rm ./get-sdkman.sh \
  # Change SDKMAN's config to be suitable for a CI pipeline execution
  && sed -i 's/sdkman_auto_answer=false/sdkman_auto_answer=true/g'                $HOME/.sdkman/etc/config \
  && sed -i 's/sdkman_selfupdate_feature=true/sdkman_selfupdate_feature=false/g'  $HOME/.sdkman/etc/config \
  && sed -i 's/sdkman_colour_enable=true/sdkman_colour_enable=false/g'            $HOME/.sdkman/etc/config 

# (4)
ENV BASH_ENV="\$HOME/.sdkman/bin/sdkman-init.sh"

# (5)
ENTRYPOINT ["/bin/bash", "-c"]

Comments to Dockerfile:

  1. SDKMAN requires Bash. The SHELL statement governs the shell used for subsequent RUN commands in the Dockerfile, not the shell used in the finished image.
  2. I'm a bit uncertain about what packages SDKMAN requires. It is not documented, AFAIK. This is my guess.
  3. Installing SDKMAN:
    • We use rcupdate=false as having SDKMAN manipulate .bashrc file is pointless for our use case. It wouldn't hurt, it would just be pointless.
    • There is no CI friendly install of SDKMAN so we have to manipulate the SDKMAN config file post installation.
  4. SDKMAN needs to be in path and so on. This is taken care of by the sdkman-init-sh script. So far, so good. You can get SDKMAN to add this to .bashrc file but that file is only sourced for interactive logins. So for non-interactive logins you have to take care of this yourself. Using the BASH_ENV variable is one way to solve this problem. Notice the escaped $ character. This is important as we want the HOME variable to be resolved when the image is executed, not when it is built.
  5. Make sure Bash is used.

You can of course use SDKMAN to install software in the docker image. The Dockerfile snippet can for example look like this (example installs Java 21):

RUN sdk install java 21.0.1-tem  \
  && sdk flush 

Notice how we execute sdk flush after the installation. This is in order to keep the size of the image as low as possible. It is crucial that the BASH_ENV variable is defined in the Dockerfile prior to attempting to use the sdk command in RUN statements. The Dockerfile ENV statement has effect both at build time and run time.

What might be improved in SDKMAN?

Here are some suggestions:

Suggestion 1

Have an install feature which creates a CI friendly config file, e.g. with

sdkman_auto_answer=true
sdkman_selfupdate_feature=false
sdkman_colour_enable=false

Suggestion 2

Document what packages (e.g. curl, etc) that SDKMAN requires for its execution.

Suggestion 3

Document how SDKMAN might be used in a Dockerfile. Have some examples in the documentation. This ticket is hopefully a good starting point.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant