Skip to content

Instantly share code, notes, and snippets.

@totten
Last active June 13, 2019 18:39
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save totten/5d0fbbbb04c1bec67236d95390eb8fc3 to your computer and use it in GitHub Desktop.
Save totten/5d0fbbbb04c1bec67236d95390eb8fc3 to your computer and use it in GitHub Desktop.
Quick and Dirty Intro to Civi CI

Quick and Dirty Intro to Civi CI

Background

I find it easiest to consider the stack in three layers:

  • Host Environment or System Platform: Loosely, this is the collection of MySQL, Apache, PHP, NodeJS, and so on. These system-services and language-runtimes are provided in many distribution channels (e.g. Debian, Ubuntu, CentOS, RHEL, nix, MAMP, XAMPP, Bitnami, Docker, etc).

  • Buildkit or Toolchain: Loosely, this is the collection of composer, drush, cv, wp-cli, bower, civibuild, phpunit, and so on. These are mostly CLI tools written in PHP, NodeJS, or bash. They are usually not provided by an OS distributor (or, if they are, it can be hard to get the right versions), and they don't represent standalone network services.

  • Build or Site: Loosely, this is the collection of civicrm-core.git along with a CMS (Drupal, WordPress, etc) and related modules/extensions/integrations. It is a web-app. When setting up a site with Civi (et al), this is the main artifact. (For example, dmaster is the typical name for a build with Drupal 7 and the master version of Civi.)

Now-a-days, many teams in our industry are focused on a single design for their deployments; they will standardize the stack and define a single artifact or project which encompasses all these layers (e.g. one Dockerfile or one docker-compose.yml). However, Civi can be deployed in a range of environments. This has always been part of its appeal: that you can install it on top of an existing webserver running Drupal/Joomla/WordPress/etc. Each of those existing webservers has its own host-environment. Moreover, each developer who works with one of those existing webservers is likely to have a laptop with its own host-environment. As an ecosystem, we don't have the same degree of standardization that you'd find on a typical team.

The three tier analogy is not perfect, but it should help you get started by illustrating the design/scope of civicrm-buildkit.git: you can start with just about any host-environment (Debian, MAMP, et al), setup buildkit, and then produce a representative range of example sites (plain D7; D7+Civi master; D7+Civi 5.13; plain WP; WP+Civi master; etc).

Quick start on a test server

The official CI servers include a few host environments based on bknix, e.g.

  • bknix-min: This has the minimum versions of MySQL/PHP/NodeJS/etc supported by Civi.
  • bknix-max: This has the maxiumum versions of MySQL/PHP/NodeJS/etc supported by Civi.
  • bknix-dfl: This has middle-of-the-road versions of MySQL/PHP/NodeJS/etc.

Additionally, we have a copy of buildkit for each host-environment.

Let's do an example: we'll use the minimum host-environment to create a test site (Drupal 7 with Civi 5.13) and run all the test suites.

Connect to a test server. Login as Jenkins.

$ ssh myuser@35.246.100.181
myuser@test-gsoc19:~$ sudo -iu jenkins bash
jenkins@test-gsoc19:~$

At this point, the command line does not have access to PHP, MySQL, etc.

jenkins@test-gsoc19:~$ php --version
bash: php: command not found

jenkins@test-gsoc19:~$ node --version
bash: node: command not found

jenkins@test-gsoc19:~$ mysql --version
bash: mysql: command not found

We need to specify that we want to work with bknix-min:

jenkins@test-gsoc19$ eval $( use-bknix min )
[bknix-min:~]

Now, we have access all the minimum versions. Observe that the host-environment lives at /nix/var/nix/profiles/bknix-min.

[bknix-min:~] which php
/nix/var/nix/profiles/bknix-min/bin/php
[bknix-min:~] php --version
PHP 5.6.38 (cli) (built: Sep 11 2018 23:19:50)
Copyright (c) 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2016 Zend Technologies
    with Xdebug v2.3.1, Copyright (c) 2002-2015, by Derick Rethans

[bknix-min:~] which node
/nix/var/nix/profiles/bknix-min/bin/node

[bknix-min:~] node --version
v8.11.3

[bknix-min:~] which mysql
/nix/var/nix/profiles/bknix-min/bin/mysql

[bknix-min:~] mysql --version
mysql  Ver 14.14 Distrib 5.5.58, for Linux (x86_64) using readline 5.1

Additionally, this server also has buildkit. Observe that this lives in /home/jenkins/bknix-min/civicrm-buildkit:

[bknix-min:~] which cv
/home/jenkins/bknix-min/civicrm-buildkit/bin/cv

[bknix-min:~] cv --version
cv version v0.2.15

[bknix-min:~] which drush
/home/jenkins/bknix-min/civicrm-buildkit/bin/drush

[bknix-min:~] drush --version
 Drush Version   :  8.1.18

Create a site with Drupal 7 and CiviCRM 5.13. We'll use civibuild to setup the site:

[bknix-min:~] civibuild create mytest --type drupal-clean --civi-ver 5.13
[[Download mytest (type 'drupal-clean' in '/home/jenkins/bknix-min/build/mytest')]]
[[Update caches]]

...(skip a lot of text)...

[[Save CMS DB (mytestcms_umnfa) to file (/home/jenkins/bknix-min/civicrm-buildkit/app/snapshot/mytest/cms.sql.gz)]]
[[Save Civi DB (mytestcivi_ukibu) to file (/home/jenkins/bknix-min/civicrm-buildkit/app/snapshot/mytest/civi.sql.gz)]]
[[Setup MySQL for Test]]
[[Restore "/home/jenkins/bknix-min/build/mytest" DB (test) from file (/home/jenkins/bknix-min/civicrm-buildkit/app/snapshot/mytest/civi.sql.gz)]]
[[Show site summary (mytest/default)]]
 - CMS_ROOT: /home/jenkins/bknix-min/build/mytest
 - CMS_URL: http://mytest.35.246.100.181.nip.io:8002
 - CMS_DB_DSN: mysql://mytestcms_umnfa:knLQPCs76YhIqlhI@127.0.0.1:3308/mytestcms_umnfa?new_link=true
 - CIVI_DB_DSN: mysql://mytestcivi_ukibu:d1wHlS1fnmFJLyW7@127.0.0.1:3308/mytestcivi_ukibu?new_link=true
 - TEST_DB_DSN: mysql://mytesttest_304ck:rno6MPYARGlEUrxp@127.0.0.1:3308/mytesttest_304ck?new_link=true
 - ADMIN_USER: admin
 - ADMIN_PASS: wfJLUdcwvEIi
 - DEMO_USER: demo
 - DEMO_PASS: demo

Now, run the test suites. As a developer, it's usually better to call a specific tool (like phpunit5); but for CI purposes, we often use the wrapper script civi-test-run, as in:

[bknix-min:~] civi-test-run -b mytest -j /tmp/mytest-results all

The results will be recorded in JUnit XML format under /tmp/mytest-results.

Jenkins?

https://test.civicrm.org/ is the Jenkins master. Most of the important/relevant test jobs are based on some combination of civibuild and civi-test-run. For example:

  • CiviCRM-Core-PR: Uses civibuild to create a site with a proposed patch/PR, and then it calls civi-test-run.
  • CiviCRM-Core-Matrix: Uses civibuild to create a matrix of test sites (with different versions of Civi and different host-environments), and it calls civi-test-run for each.

These jobs should be fairly thin. For example, consider this snapshot of the CiviCRM-Core-PR job:

  • It doesn't call composer or cv or drush or wget -- it calls civibuild.
  • It doesn't call phpcs or jshint -- it calls civilint
  • It doesn't call phpunit5 or karma -- it calls civi-test-run.

This is no accident; it's an adaptation. Jenkins is a brilliant task-runner, but the stock Jenkinx 1.x experience encourages you to write jobs in a way which is difficult to test/reproduce/modify (i.e. all the configuration is done by clicking around the web UI). This makes it harder to copy/share/test revisions. Instead, we move most of the important logic+policy out Jenkins and into civicrm-buildkit.git. This way, one can clone the repo and patch/test the build scripts locally.

For more depth...

@prondubuisi
Copy link

Hello @totten I have been going through the remote server for some time trying to figure out how I can Integrate Psalm to Jenkins, I guess its time I ask some questions

  • Where Can I get the Jenkins Jobs on the server, I did come across a bash script I think works in this capacity but am not sure

  • When I do integrate Psalm to Jenkins is there away to see sample output on Github like is the case with tests and other outputs by the civibot

I have been able to get Psalm to analyse the entire repository without fail and I think this should be the next iteration

@eileenmcnaughton
Copy link

@prondubuisi - so I assume you mean you have jenkins running but not with psalm yet? If so can you schedule a simple bash script that (for example) touches a file on a schedule ?

@prondubuisi
Copy link

@prondubuisi - so I assume you mean you have jenkins running but not with psalm yet? If so can you schedule a simple bash script that (for example) touches a file on a schedule ?

Hello @eileenmcnaughton @jackgleeson has been able to set up an instance of Jenkins on the server, but we can't access the instance via a web interface due to server configurations. He is goin to send a message to @@totten in that regard

@totten
Copy link
Author

totten commented Jun 13, 2019

Where Can I get the Jenkins Jobs on the server, I did come across a bash script I think works in this capacity but am not sure

When I do integrate Psalm to Jenkins is there away to see sample output on Github like is the case with tests and other outputs by the civibot

@prondubuisi In https://lab.civicrm.org/infra/ops/tree/master/jenkins-examples , there are copies of some recent job configurations. The CiviCRM-Core-Matrix is probably the best example. Note that the *.bash file is easier to read (it's just the main script), and the *.config.xml is more complete

  • Fully simulating a PR test-run isn't needed -- the main deliverable is the update to civi-test-run. Any job that builds on civi-test-run (e.g. CiviCRM-Core-Matrix) should do for testing purposes.
  • It's easier to manually fire CiviCRM-Core-Matrix (in the jenkins web UI) than to fire CiviCRM-Core-PR (by creating PRs in the Github UI). Firing a PR job requires creating an actual PR in an actual Github project... which means you either tap-into the main civicrm/civicrm-core.git project (which means your test-system will get the full firehose of PRs -- and PR-reviewers will get confused about whether your PRs are meant to be reviewed)... or you have to setup extra/fake repos just for testing.

If you're looking for the experience of doing everything or if there's something about the test-run that really needs PR metadata, then I'd vote for creating some extra/fake/test repos on Github and creating a new job on the private instance of Jenkins. (I've done that before... it's a PITA...) However, I'd strongly recommend avoiding it if at all possible. It's usually more productive to focus on updatingbin/civi-test-run and evaluating it on an easier job (like CiviCRM-Core-Matrix).

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