Running Moodle CI tests in GitLab

I maintain about a dozen plugins in the Moodle plugins repository. I use Moodlerooms’ moodle-plugin-ci project to test all of them on Travis CI. It’s a fantastic tool and rely heavily on it.

This fall I’ve been working on a plugin which, because of various hooks into Lafayette’s internal infrastructure, I’m not releasing publicly. I’d still like to test it in the usual way, so I decided to run the tests on our internal GitLab infrastructure.

Building a container

Dagefoerde pitched a usable .gitlab-ci.yml some time ago. This could be run on our existing docker-based CI infrastructure with basically no tweaks. Adding those packages on each run took several minutes, so I crafted a custom container (based on PHP 5.6, which is what we’re running) to eliminate the overhead. The package part is pretty simple:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
RUN apt-get clean
RUN apt-get update
RUN apt-get install -y \
git \
libfreetype6-dev \
libjpeg62-turbo-dev \
libmcrypt-dev \
libpng12-dev \
libicu-dev \
g++ \
mysql-client \
php5-mysql \
npm
RUN ln -s "$(which nodejs)" /usr/bin/node
RUN docker-php-ext-install -j$(nproc) iconv mcrypt intl zip mysqli
RUN docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/
RUN docker-php-ext-install -j$(nproc) gd

A few lines add the PHPUnit and Composer support:

1
2
3
4
5
6
ADD https://phar.phpunit.de/phpunit.phar /usr/local/bin/phpunit
RUN chmod +x /usr/local/bin/phpunit

RUN curl -sS https://getcomposer.org/installer | php
RUN mv composer.phar /usr/local/bin/composer
RUN chmod +x /usr/local/bin/composer

Confident, I deployed this container instead of the stock php:7.0 and it promptly died:

1
2
3
4
5
6
7
8
9
[Symfony\Component\Process\Exception\ProcessFailedException]                
The command "phpenv config-add /builds/ci/res/template/moodle.ini" failed.
Exit Code: 127(Command not found)
Working directory: /builds
Output:
================
Error Output:
================
sh: 1: phpenv: not found

Huh?

phpenv

Getting this working was tricky. There are several different phpenv projects floating around. Travis CI uses CHH/phpenv. The installation notes are a bit sparse, and didn’t spell out that you needed to install php-build as well to use the phpenv config-add and phpenv config-rm commands. I adapted most of this block from jolicode/phpenv, with some tweaks to reflect that I was running everything under root:

1
2
3
4
5
6
7
8
RUN git clone https://github.com/CHH/phpenv.git /tmp/phpenv && \
/tmp/phpenv/bin/phpenv-install.sh && \
/bin/bash -c "echo 'eval \"\$(phpenv init -)\"' >> /etc/profile.d/phpenv.sh" && \
echo 'eval "$(phpenv init -)"' >> /root/.bashrc
ENV PATH /root/.phpenv/bin:$PATH
RUN git clone https://github.com/CHH/php-build /root/.phpenv/plugins/php-build && \
cp /tmp/phpenv/extensions/rbenv-config-* /root/.phpenv/plugins/php-build/bin/
RUN mkdir -p /root/.phpenv/versions/system/etc/conf.d

Directory collisions

Our internal Moodle projects in GitLab are organized into a “Moodle” group. When GitLab clones a project during a CI run it puts it into the /builds/moodle/<project name> directory. This causes a problem, because by default moodle-plugin-ci will try cloning core Moodle into /builds/moodle. The directory isn’t empty in our case, so this clone fails.

The first way I solved this was by proposing a feature request to moodle-plugin-ci: allow a customized installation path for Moodle. A second way, I realized later, was to create such a directory myself in the .gitlab-ci.yml file, and then create the ci project and core installation one level deep. The build path for the project ($CI_PROJECT_DIR) is absolute anyway. It looks a little clunkier than the default, but it works:

1
2
3
4
5
6
- mkdir moodle-ci
- cd moodle-ci
- composer create-project -n --no-dev moodlerooms/moodle-plugin-ci ci ^1
- export PATH="$(cd ci/bin; pwd):$(cd ci/vendor/bin; pwd):$PATH"
- chmod u+x /builds/moodle-ci/ci/bin/moodle-plugin-ci
- chmod u+x /builds/moodle-ci/ci/bin/*

In this revised setup, builds looks like this:

1
2
3
4
5
builds/
moodle-ci/
ci/
moodle/
your-moodle-plugin/

Multiple versions

GitLab doesn’t have the same concept of the Travis build matrix, but you can approximate it using a job template:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
.job_template: &job_definition
script:
- moodle-plugin-ci phplint
- moodle-plugin-ci phpcpd
- moodle-plugin-ci phpmd
- moodle-plugin-ci codechecker
- moodle-plugin-ci csslint
- moodle-plugin-ci shifter
- moodle-plugin-ci jshint
- moodle-plugin-ci validate
- moodle-plugin-ci phpunit
- moodle-plugin-ci behat

job1:
<<: *job_definition
image: lafayette/php56-moodle:latest
variables:
MOODLE_BRANCH: "MOODLE_33_STABLE"

job2:
<<: *job_definition
image: lafayette/php70-moodle:latest
variables:
MOODLE_BRANCH: "MOODLE_33_STABLE"

This works well enough for my purposes. For an internal project, I’m only interested in testing my current environment, and the next likely environment. I don’t need to test postgresql, or myriad Moodle versions that we don’t run.