For the second day of the 2022 December CI Challenge I wanted to have a Perl module. Partially because I have working on adding CI to Perl modules for a while.

I looked at CPAN Digger where some Perl script collects and analyses the most recent uploads to CPAN, the central web site of of the Perl packages and MetaCPAN is the user-friendly place to view the content of all the packages.

When I looked at CPAN::Digger the first package that had a link to its GitHub repository but did not have CI was the Net-Async-Redis-XS distribution.

I thought that could be a nice challenge as it will probably require having Redis installed on the CI server.

Background work

Before I could start working on this project I wanted to create an example GitHub Action configuration where we have a Redis server and it is being access by curl. I wasted a lot of time on this and thought I should try to do something simpler that I can experiment with on my own computer and I don't need to send it to GitHub and wait for it do run my code.

So I started to work on a Docker Compose configuration where I had two containers. One is a Redis service and the other one is a simple client. Here to I failed to use curl as the client. However, I could make it work using the official Redis client called redis-cli. I added the example to my Docker slides.

Once I managed to create the Docker Compose configuration, creating the one running on GitHub Actions was easier. You can find my example in this repository.

I 08 2-3 hours on the preparations, but I also created the examples so people will be able to base their work on these examples.

Creating the GitHub Action using Redis

Once I had the Redis configuration the work on the Perl module was not that hard. I made a few typos and missed the fact that the repository has a Makefile.PL so at first I tried to use Dist::Zilla.

I also had to include the installation of a few Perl modules in the GitHub Action configuration. I am not sure why is that. Are they really missing from the list of dependencies of the module? If yes, how does it even get installed by users? Did I miss a step that would have installed them?

I'll leave the discussion about this for later, after the initial version of the CI is enabled.

Supported versions of Redis and Perl

I added 3 versions of Redis to the matrix and tried a number of versions of Perl, but it worked only with Perl 5.36.

Also I only tried this inside a Linux-based Docker container. Not on Windows and not on Mac OSX. I don't know if the module is even intended to support those platforms.

Adding a test

After sending the Pull-reques I went for a long walk. That helped me realize that I never told the tests what is the hostname of the Redis servers. So I guess the tests of the module never actually tried to access the server.

When I got back in-front of the computer I looked at the tests and indeed they were very shallow never trying to execute any operation that would need a server. So I created one, basically copying the example in the documentation of the module and put it in the t directory where it belongs. The test will received the name of the Redis host via an environment variable called REDIS_HOST. If this variable is not set these tests will be skipped. You can see the test-file here:

examples/Net-Async-Redis-XS/set_get.t

use strict;
use warnings;

use Test::More;
use Future::AsyncAwait;
use IO::Async::Loop;
use Net::Async::Redis::XS;

my $key = 'some-key';
my $value = 'some-value';

my $host = $ENV{REDIS_HOST};

plan skip_all => 'Set REDIS_HOST to run this test' if not $host;

my $loop = IO::Async::Loop->new;
$loop->add(my $redis = Net::Async::Redis::XS->new);
$redis->configure(host => $host);
await $redis->connect;
await $redis->set($key, $value);
my $result = await $redis->get($key);
is $result, $value;

done_testing();

I've also update the GitHub Action configuration file so it will set the REDIS_HOST environment variable to redis, the name of redis service that was included in the configuration file.

GitHub Actions configuration file

I've included here the configuration file for future reference as the one in the project, if it even gets accepted, will probably change.

examples/Net-Async-Redis-XS/ci.yml

name: CI

on:
  push:
  pull_request:
  workflow_dispatch:
  schedule:
    - cron: '42 5 * * *'

jobs:
  test:
    strategy:
      fail-fast: false
      matrix:
        # Perl 5.30, 5.32., 5.34 all failed with all 3 versions of Redis
        perl: [ '5.36' ]
        redis: ['6.0', '7.0', 'latest']
        #redis: ['latest']

    services:
      redis:
        image: redis:${{matrix.redis}}

    runs-on: ubuntu-latest
    name: Perl ${{matrix.perl}} Redis ${{matrix.redis}}
    container: perl:${{matrix.perl}}

    steps:
    - name: Checkout
      uses: actions/checkout@v3

    - name: Show Perl Version
      run: |
        perl -v

    - name: Install Modules
      run: |
        cpanm --installdeps .
        cpanm --verbose Test::Fatal
        cpanm Net::Async::Redis
        cpanm Test::MemoryGrowth

    - name: Show Errors on Ubuntu
      if:  ${{ failure() && matrix.runner == 'ubuntu-latest' }}
      run: |
         cat /home/runner/.cpanm/work/*/build.log

    - name: Run tests
      env:
        AUTHOR_TESTING: 1
        RELEASE_TESTING: 1
        REDIS_HOST: redis
      run: |
        perl Makefile.PL
        make
        make test
        prove -b xt/

Pull-Request

I sent the Pull-Request. Let's see if it gets commented on or accepted.