Skip to content

Commit

Permalink
Merge pull request #14 from weierophinney/feature/allow-object-jobs-i…
Browse files Browse the repository at this point in the history
…n-checks

Allow object jobs in the "checks" configuration array
  • Loading branch information
weierophinney authored Mar 4, 2021
2 parents 604ed10 + 83db619 commit fde2c44
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 9 deletions.
38 changes: 36 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,42 @@ The package can include a configuration file in its root, `.laminas-ci.json`, wh
}
```

The "checks" array should be in the same format as listed above for the outputs.
Please remember that the **job** element **MUST** be a JSON **string**
### Providing specific checks to run

If you do not want to autodiscover checks to run, you can provide the "checks" configuration.
Each element in that array should be in the same format as listed above for the outputs:

```json
{
"name": "(string) Name of the check being run",
"operatingSystem": "(string) Name of the OS the job should be run on (generally ubuntu-latest)",
"action": "(string) GHA to run the step on; currently ignored, as GHA does not support dynamic action selection",
"job": "(string) JSON object detailing the job (more on this later)",
}
```

The "job" element can either be a JSON string representing a job, or an object.
In each case, it MUST have the structure as noted above:

```json
{
"php": "(string; REQUIRED) PHP minor version to run against",
"extensions": [
"OPTIONAL array of strings",
"Each element represents an extension to install",
"Names are from the Sury PHP repository, minus the php{VERSION}- prefix",
],
"ini": [
"OPTIONAL array of strings",
"Each element respresents one php.ini directive",
"e.g. 'memory_limit=-1'",
],
"dependencies": "dependencies to test against; one of lowest, locked, latest",
"command": "command to run to perform the check",
}
```

The action validates each check and its job to ensure it is structured correctly, and will provide warnings if not, omitting any check that is malformed from the output.

### Providing additional checks

Expand Down
12 changes: 6 additions & 6 deletions src/additional-checks.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,25 @@ import {Job} from "./job.js";
const validateCheck = function (checkConfig) {
if (typeof checkConfig !== 'object' || checkConfig === null) {
// NOT AN OBJECT!
core.warning("Skipping additional check; not an object, or is null", checkConfig);
core.warning("Skipping additional check; not an object, or is null: " + JSON.stringify(checkConfig));
return false;
}

if (! ("name" in checkConfig) || ! ("job" in checkConfig)) {
// Missing one or more required elements
core.warning("Skipping additional check due to missing name or job keys", checkConfig);
core.warning("Skipping additional check due to missing name or job keys: " + JSON.stringify(checkConfig));
return false;
}

if (typeof checkConfig.job !== 'object' || checkConfig.job === null) {
// Job is malformed
core.warning("Invalid job provided for check; not an object, or is null", checkConfig.job);
core.warning("Invalid job provided for check; not an object, or is null: " + JSON.stringify(checkConfig.job));
return false;
}

if (! ("command" in checkConfig.job)) {
// Job is missing a command
core.warning("Invalid job provided for check; missing command property", checkConfig.job);
core.warning("Invalid job provided for check; missing command property: " + JSON.stringify(checkConfig.job));
return false;
}

Expand All @@ -53,7 +53,7 @@ const discoverPhpVersionsForCheck = function (job, config) {
return config.versions;
}

core.warning("Invalid PHP version specified for check job; must be a string version or '*'", job);
core.warning("Invalid PHP version specified for check job; must be a string version or '*': " + JSON.stringify(job));
return false;
};

Expand Down Expand Up @@ -101,7 +101,7 @@ const discoverDependencySetsForCheck = function (job, config) {
return config.dependencies;
}

core.warning("Invalid dependencies specified for check job; must be a string version or '*'", job);
core.warning("Invalid dependencies specified for check job; must be a string version or '*': " + JSON.stringify(job));
return false;
};

Expand Down
3 changes: 2 additions & 1 deletion src/create-jobs.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Command } from './command.js';
import { Config } from './config.js';
import { Job } from './job.js';
import create_additional_jobs from './additional-checks.js';
import validateAndNormalizeChecks from './validate-and-normalize-checks-from-config.js';

/**
* @param {String} filename
Expand Down Expand Up @@ -198,7 +199,7 @@ const excludeJob = function (job, exclusion) {
export default function (config) {
if (config.checks.length) {
core.info('Using checks found in configuration');
return config.checks;
return validateAndNormalizeChecks(config.checks);
}

/** @var {Array} jobs */
Expand Down
101 changes: 101 additions & 0 deletions src/validate-and-normalize-checks-from-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import core from '@actions/core';

const KNOWN_PHP_VERSIONS = [
'5.6',
'7.0',
'7.1',
'7.2',
'7.3',
'7.4',
'8.0',
];

/**
* @param {(Object|String)} job
* @return {(String|Boolean)} Returns false if job is invalid; otherwise, returns JSON representation of job
*/
const normalizeJob = function (job) {
if (typeof job === 'string') {
let parsedJob;
try {
parsedJob = JSON.parse(job);
} catch(error) {
core.warning("Unparseable JSON job provided: " + job);
return false;
}
job = parsedJob;
}

if (typeof job !== 'object' || job === null) {
core.warning("Invalid job provided; must be a JSON string or an object: " + JSON.stringify(job));
return false;
}

if (! "php" in job || ! KNOWN_PHP_VERSIONS.includes(job.php)) {
core.warning("Invalid job provided; no PHP version or unknown PHP version specified: " + JSON.stringify(job));
return false;
}

if (! "command" in job) {
core.warning("Invalid job provided; no command specified: " + JSON.stringify(job));
return false;
}

if ("extensions" in job && ! Array.isArray(job.extensions)) {
core.warning("Invalid job provided; extensions is not an Array: " + JSON.stringify(job));
return false;
}

if ("ini" in job && ! Array.isArray(job.ini)) {
core.warning("Invalid job provided; ini is not an Array: " + JSON.stringify(job));
return false;
}

if ("dependencies" in job && ! ["locked", "latest", "lowest"].includes(job.dependencies)) {
core.warning("Invalid job provided; invalid dependency set: " + JSON.stringify(job));
return false;
}

return JSON.stringify(job);
};

/**
* @param {Object} check
* @return {(null|Object)} null if invalid, object representing check otherwise
*/
const validateAndNormalizeCheck = function (check) {
if (! "name" in check) {
core.warning("Invalid check detected; missing name: " + JSON.stringify(check));
return null;
}

if (! "job" in check) {
core.warning("Invalid check detected; missing job: " + JSON.stringify(check));
return null;
}

let job = normalizeJob(check.job);
if (! job) {
return null;
}

check.job = job;

if (! "operatingSystem" in check) {
check.operatingSystem = 'ubuntu-latest';
}

return check;
};

/**
* @param {Array} checks
* @return {Array}
*/
export default function (checks) {
return checks
.map(validateAndNormalizeCheck)
.filter(function (check) {
return typeof check === 'object' && check !== null;
});
};

0 comments on commit fde2c44

Please sign in to comment.