Skip to content

Unit Tests

Unit Tests #1764

Workflow file for this run

name: Unit Tests
on:
pull_request:
branches:
- main
workflow_dispatch:
inputs:
matrix:
description: matrix in json format
required: true
default: '{"include":[{"php-versions":"8.1","drupal":"~10.1.1","civicrm":"dev-master"}]}'
prurl:
description: PR Url
required: false
repourl:
description: Repo Url
required: false
repobranch:
description: Target Branch
required: false
notifyemail:
description: Notification email
required: false
contactid:
description: Civi contact id
required: false
coreprurl:
description: Core PR Url
required: false
jobs:
phpunit:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix: ${{ fromJson(github.event.inputs.matrix) }}
name: D${{ matrix.drupal }} | Civi ${{ matrix.civicrm }} | ${{ github.event.inputs.repourl }}
services:
mysql:
image: mysql:5.7
env:
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: db
ports:
- 3306
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
extensions: dom, curl, libxml, mbstring, zip, pdo, mysql, pdo_mysql, bcmath, soap, intl, gd, exif, iconv
coverage: none
tools: composer:v2
- name: starttimer
run: |
cd $GITHUB_WORKSPACE
date +%s > carrottimerfile
echo "EXITEARLY=n" >> $GITHUB_ENV
- name: Get composer cache directory
id: composercache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- uses: actions/cache@v4
with:
path: ${{ steps.composercache.outputs.dir }}
key: ${{ runner.os }}-${{ matrix.drupal }}-composer-${{ hashFiles('**/composer.json') }}
restore-keys: ${{ runner.os }}-composer-
- name: Setup problem matchers for PHPUnit
run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json"
- name: Download cv
run: |
cd $GITHUB_WORKSPACE
git clone https://github.com/civicrm/cv.git civicrm-cv
cd civicrm-cv
# downloads-plugin is locked at 2.1 but that doesn't work with composer v2
rm composer.lock
composer config --no-interaction --no-plugins allow-plugins.composer/installers true
composer config --no-interaction --no-plugins allow-plugins.drupal/core-composer-scaffold true
composer config --no-interaction --no-plugins allow-plugins.drupal/core-project-message true
composer config --no-interaction --no-plugins allow-plugins.civicrm/composer-compile-plugin true
composer config --no-interaction --no-plugins allow-plugins.civicrm/composer-downloads-plugin true
composer config --no-interaction --no-plugins allow-plugins.civicrm/civicrm-asset-plugin true
composer config --no-interaction --no-plugins allow-plugins.cweagans/composer-patches true
COMPOSER_MEMORY_LIMIT=-1 composer install
- name: Download Drupal
run: |
COMPOSER_MEMORY_LIMIT=-1 composer create-project drupal/recommended-project:${{ matrix.drupal }} ~/drupal --no-interaction --no-install
cd ~/drupal
composer config extra.enable-patching true
composer config extra.compile-mode all
composer config minimum-stability dev
composer config --no-interaction --no-plugins allow-plugins.composer/installers true
composer config --no-interaction --no-plugins allow-plugins.drupal/core-composer-scaffold true
composer config --no-interaction --no-plugins allow-plugins.drupal/core-project-message true
composer config --no-interaction --no-plugins allow-plugins.civicrm/composer-compile-plugin true
composer config --no-interaction --no-plugins allow-plugins.civicrm/composer-downloads-plugin true
composer config --no-interaction --no-plugins allow-plugins.civicrm/civicrm-asset-plugin true
composer config --no-interaction --no-plugins allow-plugins.cweagans/composer-patches true
composer config --no-interaction --no-plugins allow-plugins.dealerdirect/phpcodesniffer-composer-installer true
composer install --no-interaction
- name: Download CiviCRM ${{ matrix.civicrm }}
run: |
cd ~/drupal
COMPOSER_MEMORY_LIMIT=-1 composer require civicrm/civicrm-asset-plugin:'~1.1' civicrm/civicrm-{core,packages,drupal-8}:${{ matrix.civicrm }}
CANUSE95=`php -r 'echo version_compare("${{ matrix.civicrm }}", "5.65");'`
if [ "${{ matrix.civicrm }}" != "dev-master" -a "$CANUSE95" != "1" ]; then
COMPOSER_MEMORY_LIMIT=-1 composer require phpunit/phpunit:'^8.5' drush/drush
else
COMPOSER_MEMORY_LIMIT=-1 composer require phpunit/phpunit:'^9.5' drush/drush
fi
- name: Install Drupal
run: |
cd ~/drupal
./vendor/drush/drush/drush -y -l http://civi.localhost site-install standard --db-url='mysql://root:@127.0.0.1:${{ job.services.mysql.ports[3306] }}/db' --site-name=TestCivi --account-pass=admin
chmod +w web/sites/default
- name: Install CiviCRM
run: |
cd ~/drupal
$GITHUB_WORKSPACE/civicrm-cv/bin/cv core:install --cms-base-url=http://civi.localhost -m loadGenerated=1
cd web/sites/default
sed -i -e 's#if (!defined('"'"'CIVICRM_SMARTY3_AUTOLOAD_PATH'"'"')) {#if (FALSE) {#' civicrm.settings.php
- name: Get some code to test
if: ${{ github.event.inputs.repourl != 0 }}
run: |
mkdir -p ~/drupal/web/sites/default/files/civicrm/ext
cd ~/drupal/web/sites/default/files/civicrm/ext
if [ "${{ github.event.inputs.repobranch }}" != "" ]; then
git clone -b ${{ github.event.inputs.repobranch }} ${{ github.event.inputs.repourl }} thingtotest
else
git clone ${{ github.event.inputs.repourl }} thingtotest
fi
- name: Set identity
# Needed for `git am`
run: |
git config --global user.email "civicarrot@gmail.com"
git config --global user.name "CiviCARROT"
- name: Check if PR has closed early
if: ${{ github.event.inputs.prurl != 0 }}
run: |
# Check if the PR is still open since the process started, e.g. a rebase just before merge.
prurl=${{ github.event.inputs.prurl }}
temp1=${prurl%/-/merge_requests/*}
projectname=${temp1#https://*/}
# close enough?
urlencoded=${projectname//\//%2F}
domain=${temp1%/$projectname}
mrid=${prurl##*/}
mrstate=`curl -H "Authorization: Bearer ${{secrets.LABCO_API_KEY}}" ${domain}/api/v4/projects/${urlencoded}/merge_requests/${mrid} | jq -r .state`
if [ "$mrstate" != "opened" ]; then
echo "EXITEARLY=y" >> $GITHUB_ENV
fi
- name: Apply PR
if: ${{ (github.event.inputs.prurl != 0) && (env.EXITEARLY != 'y') }}
run: |
cd ~/drupal/web/sites/default/files/civicrm/ext/thingtotest
curl -L -o thingtopatch.patch ${{ github.event.inputs.prurl }}.patch
git am thingtopatch.patch
- name: Apply Core PR
if: ${{ (github.event.inputs.coreprurl != 0) && (env.EXITEARLY != 'y') }}
run: |
cd ~/drupal/vendor/civicrm/civicrm-core
curl -L -o thingtopatch.diff ${{ github.event.inputs.coreprurl }}.diff
git apply thingtopatch.diff
- name: Download extension dependencies
if: ${{ (github.event.inputs.repourl != 0) && (env.EXITEARLY != 'y') }}
run: |
cd ~/drupal/web/sites/default/files/civicrm/ext
# Allow "unapproved" extensions
$GITHUB_WORKSPACE/civicrm-cv/bin/cv ev '\Civi::settings()->set("ext_repo_url", "https://civicrm.org/extdir/ver={ver}|cms={uf}|ready=");'
$GITHUB_WORKSPACE/civicrm-cv/bin/cv ev '\Civi::settings()->set("http_timeout", 60);'
DEPS=`php -r '$xml = simplexml_load_file("thingtotest/info.xml"); $deps = array(); foreach ($xml->requires as $req) { foreach ($req->ext as $ext) { $deps[] = $ext; } } echo implode(" ", $deps);'`
if [ -n "$DEPS" ]; then
for e in $DEPS; do
# Might need to be tolerant of failure here since it's possible to have dependencies that
# aren't in universe and that could still get installed by the tests themselves. But this
# whole system is really only designed for publicly reachable repos at the moment. Also
# if you declare a dependency on a core extension, there's nothing to "download".
# By adding the `||` the exit code is the exit code of `echo`, which will be success.
$GITHUB_WORKSPACE/civicrm-cv/bin/cv api3 Extension.download install=0 key=$e || echo 'ignoring failure'
done
fi
- name: Run PHPUnit
if: ${{ env.EXITEARLY != 'y' }}
run: |
export PATH=$PATH:$GITHUB_WORKSPACE/civicrm-cv/bin
cd ~/drupal
cv vars:fill
sed -i -e 's#dbUser:dbPass@dbHost/dbName#root:@127.0.0.1:${{ job.services.mysql.ports[3306] }}/db#' ~/.cv.json
export CIVICRM_UF=UnitTests
# export CIVICRM_SETTINGS=~/drupal/web/sites/default/civicrm.settings.php
cd ~/drupal/web/sites/default/files/civicrm/ext/thingtotest
# TODO: We could do something like glob and iterate through any folders that are not Mink? But these are the only ones that typically autoload anyway.
# This will use either phpunit.xml.dist or phpunit.xml depending on what they have, and hopefully that file points to a good bootstrap file
if [ -d tests/phpunit/CRM ]; then ~/drupal/vendor/bin/phpunit tests/phpunit/CRM; fi
if [ -d tests/phpunit/Civi ]; then ~/drupal/vendor/bin/phpunit tests/phpunit/Civi; fi
if [ -d tests/phpunit/api ]; then ~/drupal/vendor/bin/phpunit tests/phpunit/api; fi
env:
COMPOSER_MEMORY_LIMIT: -1
- name: send notification email
if: ${{ failure() && (github.event.inputs.notifyemail != 0) && (github.event.inputs.notifyemail != '[REDACTED]') && (env.EXITEARLY != 'y') }}
uses: dawidd6/action-send-mail@v3
with:
server_address: smtp.gmail.com
server_port: 465
secure: true
username: ${{secrets.MAIL_USERNAME}}
# This can be a temporary app password, not the real password
password: ${{secrets.MAIL_PASSWORD}}
subject: CiviCARROT Unit tests ${{ github.event.inputs.repourl }}
body: Visit https://github.com/semperit/CiviCARROT/actions/runs/${{ github.run_id }} to view logs and artifacts.
to: ${{ github.event.inputs.notifyemail }}
from: civicarrot@gmail.com
- name: record stats
if: ${{ (success() || failure()) && (github.event.inputs.contactid != 0) }}
run: |
cd $GITHUB_WORKSPACE
STARTTIME=`cat carrottimerfile`
TIMEUSED=$(( `date +%s` - $STARTTIME ))
# TODO: SPACEUSED=`cat carrotspacefile`
SPACEUSED=00
echo "{\"type\":\"plain\",\"id\":${{ github.event.inputs.contactid }},\"bytes\":\"$SPACEUSED\",\"seconds\":$TIMEUSED,\"repo\":\"${{ github.event.inputs.repourl }}\",\"pr\":\"${{ github.event.inputs.prurl }}\",\"run_id\":\"${{ github.run_id }}\"}"
curl --user ${{secrets.REST_USER}}:${{secrets.REST_PASS}} -X POST -H "Content-type: application/json" -d "{\"type\":\"plain\",\"id\":${{ github.event.inputs.contactid }},\"bytes\":\"$SPACEUSED\",\"seconds\":$TIMEUSED,\"repo\":\"${{ github.event.inputs.repourl }}\",\"pr\":\"${{ github.event.inputs.prurl }}\",\"run_id\":\"${{ github.run_id }}\"}" https://civicrm.io/githubaction/${{ github.event.inputs.contactid }}
# It seems like there should be shorthand for this instead of 8 lines
- name: checkstatus1
if: ${{ success() && (github.event.inputs.prurl != 0) }}
run: |
echo "RUNSTATUS=%E2%9C%94%EF%B8%8F+PASS" >> $GITHUB_ENV
- name: checkstatus2
if: ${{ failure() && (github.event.inputs.prurl != 0) }}
run: |
echo "RUNSTATUS=%E2%9D%8C+FAIL" >> $GITHUB_ENV
- name: create comment on PR
if: ${{ (success() || failure()) && (github.event.inputs.prurl != 0) && (env.EXITEARLY != 'y') }}
run: |
prurl=${{ github.event.inputs.prurl }}
temp1=${prurl%/-/merge_requests/*}
projectname=${temp1#https://*/}
# close enough?
urlencoded=${projectname//\//%2F}
domain=${temp1%/$projectname}
mrid=${prurl##*/}
echo ${domain}/api/v4/projects/${urlencoded}/merge_requests/${mrid}/notes
curl -H "Authorization: Bearer ${{secrets.LABCO_API_KEY}}" -X POST ${domain}/api/v4/projects/${urlencoded}/merge_requests/${mrid}/notes?body=${{ env.RUNSTATUS }}:+Unit+Tests:+https:%2F%2Fgithub.com%2Fsemperit%2FCiviCARROT%2Factions%2Fruns%2F${{ github.run_id }}