Skip to content

Instantly share code, notes, and snippets.

@BenMorel
Last active October 20, 2020 18:20
Show Gist options
  • Save BenMorel/67e5d94c864af9b9ae1d3a1db8010b98 to your computer and use it in GitHub Desktop.
Save BenMorel/67e5d94c864af9b9ae1d3a1db8010b98 to your computer and use it in GitHub Desktop.
Builds the Travis CI job matrix for Doctrine DBAL - See doctrine/dbal#3347
<?php
/**
* This script builds the .travis.yml build matrix, around these variables:
*
* - PHP versions
* - database drivers
* - platform versions
*
* With the following requirements:
*
* - the latest stable PHP version is tested against all drivers and platform versions
* - other PHP versions are tested against the latest version of the platform for each driver
*/
/* -----------------------------------------------------------------------------
* BEGIN CONFIGURATION
* -----------------------------------------------------------------------------
*/
/**
* The PHP versions to test.
*/
$phpVersions = ['7.2', '7.3', 'nightly'];
/**
* The latest stable PHP version.
* All drivers and platform versions will be tested against this PHP version.
* All other PHP versions will only test each driver with the latest version of the platform.
*/
$latestStablePhpVersion = '7.2';
/**
* The PHP version used for code coverage analysis.
*/
$coveragePhpVersion = '7.2';
/**
* The travis config file name.
*/
$travisConfigFileName = '.travis.yml';
/**
* The database drivers.
*
* The key is the driver name ("DB" environment variable).
* The value is an array mapping an optional *_VERSION environment variable name to a list of versions.
* If one of these versions is NULL, then the environment variable will be skipped in the output.
*
* This version environment variable array MAY BE EMPTY, and MAY CONTAIN AT MOST ONE environment variable.
* THE LATEST PLATFORM VERSION MUST BE THE LAST ENTRY IN THE ARRAY.
* This point is extremely important to respect the premises of this script.
*/
$dbs = [
'mysql' => [
'MYSQL_VERSION' => [
null,
'5.7',
'8.0'
]
],
'mysqli' => [
'MYSQL_VERSION' => [
null,
'5.7',
'8.0'
]
],
'mariadb' => [
'MARIADB_VERSION' => [
'10.0',
'10.1',
'10.2',
'10.3',
]
],
'mariadb.mysqli' => [
'MARIADB_VERSION' => [
'10.0',
'10.1',
'10.2',
'10.3',
]
],
'pgsql' => [
'POSTGRESQL_VERSION' => [
'9.2',
'9.3',
'9.4',
'9.5',
'9.6',
'10.0',
'11.0'
]
],
'sqlite' => [],
'sqlsrv' => [],
'pdo_sqlsrv' => [],
'ibm_db2' => [],
];
/**
* The additional Travis job parameters for specific environment variables.
* The keys are expected to be single KEY=VALUE pair to be matched against the env string built in the matrix.
*/
$additionalJobParams = [
'MYSQL_VERSION=5.7' => [
'sudo' => 'required',
'before_script' => ['bash ./tests/travis/install-mysql-5.7.sh']
],
'MYSQL_VERSION=8.0' => [
'dist' => 'xenial',
'sudo' => 'required',
'before_script' => ['bash ./tests/travis/install-mysql-8.0.sh']
],
'POSTGRESQL_VERSION=10.0' => [
'sudo' => 'required',
'services' => ['postgresql'],
'addons' => ['postgresql' => '"9.6"'],
'before_script' => ['bash ./tests/travis/install-postgres-10.sh']
],
'POSTGRESQL_VERSION=11.0' => [
'sudo' => 'required',
'services' => ['docker'],
'before_script' => ['bash ./tests/travis/install-postgres-11.sh']
],
'DB=sqlsrv' => [
'sudo' => 'required',
'services' => ['docker'],
'before_script' => [
'bash ./tests/travis/install-mssql-sqlsrv.sh',
'bash ./tests/travis/install-mssql.sh'
]
],
'DB=pdo_sqlsrv' => [
'sudo' => 'required',
'services' => ['docker'],
'before_script' => [
'bash ./tests/travis/install-mssql-pdo_sqlsrv.sh',
'bash ./tests/travis/install-mssql.sh'
]
],
'DB=ibm_db2' => [
'sudo' => 'required',
'services' => ['docker'],
'before_script' => [
'bash ./tests/travis/install-db2.sh',
'bash ./tests/travis/install-db2-ibm_db2.sh'
]
]
];
foreach (['10.0', '10.1', '10.2', '10.3'] as $mariadbVersion) {
$additionalJobParams['MARIADB_VERSION=' . $mariadbVersion] = [
'addons' => ['mariadb' => $mariadbVersion],
];
}
foreach (['9.2', '9.3', '9.4', '9.5', '9.6'] as $pgsqlVersion) {
$additionalJobParams['POSTGRESQL_VERSION=' . $pgsqlVersion] = [
'services' => ['postgresql'],
'addons' => ['postgresql' => '"' . $pgsqlVersion . '"'],
];
}
/**
* The excluded jobs.
*
* This is a numeric array where each element is a numeric array with 2 values:
* - the target PHP version
* - a single KEY=VALUE pair to be matched against the env string built in the matrix
*
* Example:
* ['7.3', 'DB=ibm_db2'],
* ['nightly', 'MYSQL_VERSION=5.7']
*/
$excludedJobs = [
['7.3', 'DB=ibm_db2'], // DB2 currently fails on PHP 7.3
['nightly', 'DB=ibm_db2'], // DB2 currently fails on PHP nightly
];
/* -----------------------------------------------------------------------------
* END CONFIGURATION
* -----------------------------------------------------------------------------
*/
/* Generate jobs */
$jobs = [];
foreach ($phpVersions as $phpVersion) {
foreach ($dbs as $db => $versions) {
if (empty($versions)) {
$baseEnvs = [[]];
} elseif (count($versions) === 1) {
$baseEnvs = [];
foreach ($versions as $versionEnvName => $versionValues) { // single iteration
foreach ($versionValues as $versionValue) {
if ($versionValue === null) {
$baseEnvs[] = [];
} else {
$baseEnvs[] = [$versionEnvName => $versionValue];
}
}
}
} else {
echo "Error: this script does not currently support multiple environment variables per database driver.\n";
exit(1);
}
foreach ($baseEnvs as $baseEnvKey => $baseEnv) {
$env = ['DB' => $db];
$isLatestVersion = ($baseEnvKey === count($baseEnvs) - 1);
foreach ($baseEnv as $envName => $envValue) { // at most one iteration
$env[$envName] = $envValue;
}
if ($phpVersion !== $latestStablePhpVersion && ! $isLatestVersion) {
// not the latest stable PHP version: only test the latest platform version
continue;
}
if ($phpVersion === $coveragePhpVersion) {
$env['COVERAGE'] = 'yes';
}
$env = envArrayToString($env);
foreach ($excludedJobs as [$excludedPhpVersion, $excludedEnvKeyValuePair]) {
if ($excludedPhpVersion === $phpVersion && strpos($env, $excludedEnvKeyValuePair) !== false) {
continue 2;
}
}
$job = [
'stage' => 'Test',
'php' => $phpVersion,
'env' => $env
];
foreach ($additionalJobParams as $jobEnvKeyValuePair => $jobParams) {
if (strpos($env, $jobEnvKeyValuePair) !== false) {
$job += $jobParams;
}
}
$jobs[] = $job;
}
}
}
echo arrayToYAML($jobs, 2);
/* Utility functions */
function envArrayToString(array $env) : string
{
$result = [];
foreach ($env as $key => $value) {
$result[] = "$key=$value";
}
return implode(' ', $result);
}
function arrayToYAML(array $array, int $level = 0, $indentFirst = true) : string
{
$result = '';
$first = true;
foreach ($array as $key => $value) {
if (! ($first && ! $indentFirst)) {
$result .= str_repeat(' ', $level * 2);
}
if (is_int($key)) {
$result .= '- ';
} else {
$result .= $key . ':';
if (! is_array($value)) {
$result .= ' ';
}
}
if (is_array($value)) {
if (! is_int($key)) {
$result .= "\n";
}
$result .= arrayToYAML($value, $level + 1, ! is_int($key));
} else {
$result .= $value . "\n";
}
$first = false;
}
return $result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment