Coding with Titans

so breaking things happens constantly, but never on purpose

Docker image for Android CI

And the day has finally came. Turned out my docker image for Continuous Integration to build Android native apps doesn’t work anymore. Honestly, it wasn’t even my fault. At first glance the OS was OK, Android SDK was also OK, but then fastlane installation was not happy about something. And that little something turned out to be a real PAIN … in my arm! Ruby ta-da-da-tam! But how was that?

So let’s first rewind to the beginning. How am I building Android app? Application itself is written natively in Kotlin language and consists of bunch of Gradle configurations and source files to come up with AAB (Android Application Bundle). This is all nicely handled by Android Studio and underlying toolset. Later however, immediately after the successful build, I want to automatically distribute the outcomes to my team-mates and testers. This requires the AAB package to be signed and submitted to the beta channel of Android Play Store. This part is actually handled by mentioned fastlane tool (written in Ruby). Beside simple binary submission, it also uploads screenshots and change-log, so there are few things it simplifies and lots and lots of other dependencies it relies on.

To always have the latest fastlane the build script of the app utilizes bundler to install everything (every gem) for the current Ruby version:

# update fastlane
gem install bundler
bundle update --ruby

However for the first time it ended with the following error:

Fetching signet 0.12.0
Installing signet 0.12.0
Gem::InstallError: signet requires Ruby version >= 2.4.0.
An error occurred while installing signet (0.12.0), and Bundler cannot continue.
Make sure that `gem install signet -v '0.12.0' --source 'https://rubygems.org/'`
succeeds before bundling.
In Gemfile:
  fastlane was resolved to 2.137.0, which depends on
    google-cloud-storage was resolved to 1.16.0, which depends on
      google-api-client was resolved to 0.23.9, which depends on
        googleauth was resolved to 0.6.7, which depends on
          signet

Quick look and installed version of Ruby:

ruby -v

Yeap, it was 2.3.1. So it was for sure older one than required 2.4 and caused a failure.

Funny thing comes true, as this is the version mentioned in Ruby installation docs in polish translation. And I used simplest possible command to get Ruby installed into my docker image.

sudo apt install ruby

Unfortunately, it also turned out this is the last version released this way and as of today (December 2019) and it’s not even maintained anymore (EOL!). Which seemed pretty bad too, forcing me to find another way of installing newer Ruby edition.

Side note: Just for filling gaps for this post I looked again at the documentation site. I didn’t know it’s much more worthful to look at the English version of the installation page, since this one suggests performing installation of totally different package to bring more up-to-date Ruby environment:

sudo apt-get install ruby-full

Maybe, if I know it before it could save me some time. Please go ahead and try it. Instead, I went the more rough road and installed everything to build Ruby 2.6.5 and other dependencies purely from sources. Whole docker script can be found in my GitHub repository.

The procedure to manually build from scratch might seem complex, but looking closely to following steps, reveals it’s actually not:

  1. Clone rbenv repository and build the tool (to manage Ruby environments).
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
cd ~/.rbenv && src/configure && make -C src
  1. Update PATH variable for current and next shell runs (bash here), so it’s possible to run rbenv (also rbenv-doctor will complain about it later, if not done).

    echo 'export PATH="~/.rbenv/bin:$PATH"' >> ~/.bashrc
    export PATH="~/.rbenv/bin:$PATH"
    
  2. Then initialize it.

    ~/.rbenv/bin/rbenv init; exit 0
    
  3. Install ruby-build plugin to easily compile Ruby at designated version.

    mkdir -p "$(rbenv root)"/plugins
    git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build
    
  4. Verify current setup.

    curl -fsSL https://github.com/rbenv/rbenv-installer/raw/master/bin/rbenv-doctor | bash; eval exit 0
    
  5. Finally trigger compilation.

    rbenv install '2.6.5'
    
    export PATH="~/.rbenv/versions/2.6.5/bin:$PATH"
    

    If you need any other version - list them all first, choose the proper one and replace it in the snipped above:

    rbenv install -l
    

Finished! Bravo.

Anyway, if you don’t want to do this yourself, simply put import into your .gitlab-ci.yaml and it will reuse my pre-build system:

image: phofman/gitlab-ci-android

Done!