To clarify ... While this looks like I'm just proposing a chains pre-requisite here, there are multiple reasons to pursue this:

- Eliminate the hardcoded build steps in worker, and thus extraneous build-step function calls during processing
- Eliminates the need to specify empty array() properties for extraneous build steps,
- Provides more compartmentalization of code; making it easier for newcomers to digest and understand worker's processing flow
- Eliminates confusion over whether things like scan or syntax are "setup tasks" or "jobs", as all are treated as equal citizen 'tasks' from a worker perspective
- Improves consistency by using the same approach invoking all worker actions (whether setup or job)
- Makes it perfectly clear what 'setup' tasks are involved in a particular task - there are no 'hidden' operations known only to someone who's studied the code

All of this contributes to the bottom line with regards to simplifying worker operation, reducing the 'noise' factor in the properties array, and removing some of the 'magic' operations that I got hung up on when first learning the existing code. Making things easier for a testing infra newbie to understand improves the 'community maintainability' factor and makes it easier for folks to troubleshoot their own testing problems and/or build their own extensions and plugins.

ORIGINAL POST
Currently, the build steps are hard-wired to perform certain setup tasks, in a specific order, and once per cycle. There are some job types which straddle the grey area between 'independent job' and 'job setup task', with scan being one such example.

This structure leads to two different approaches for 'actions' executed by the worker ... those that are hardcoded into the worker code as 'build' steps, and those that are written as job plugins. For consistency, we could define new plugins for each of these build steps ... simplifying the worker code, and providing a single consistent method for defining all of the different 'actions' a worker is capable of performing.

With this done, I can see the potential for jobs to be defined as a combination of 1) a 'job tasks' parameter which defines the build steps (i.e. jobs) to be executed for that job, and 2) a property for each element of the job_tasks stack, using the value of that particular item in the stack as the property key'. For example:

array(
  'job_tasks' => array(
    '0' => 'setup',
    '2' => 'vcs',
    '3' => 'patch',
    '4' => 'build',
  ),
  'setup' => array(...),
  'vcs' => array(...),
  'patch' => array(...),
   ...

The worker execution could then loop over each element in the job task list, and execute the associated plugin logic (and might even only pass the properties which are relevant to that particular plugin).

While the current logic works well for the existing defined plugins and job types, the above approach does increase the overall flexibility of the platform; breaking job tasks down into their base building blocks. This in turn opens up future possibilities for re-assembling these building blocks in different combinations, while avoiding the need for code duplication between jobs which perform similar types of functionality but require slightly different processing at any particular step.

This also opens up the potential in the long term for exposing things like job chaining and 'build your own test' or 'macro' capabilities on drupal.org.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

jthorson’s picture

One concern with the above structure is that it doesn't accommodate multiple invocations of the same job type, as this would lead to conflicts on the properties array keys. Creating seperate 'setup', 'build', and 'execute' plugins doesn't make much sense, if all three of these perform the same action.

An alternative approach:

array(
  'job_tasks' => array(
    '0' => array(
      // Setup Commands
      'plugin' => 'execute',
      'properties' => array(...),
    ),
    '1' => array(
      // Git Checkout
      'plugin' => 'vcs',
      'properties' => array(...),
    ),
    '2' => array(
      // Apply Patch
      'plugin' => 'patch',
      'properties' => array(...),
    ),
    '3' => array(
      // Post-build steps
      'plugin' => 'execute',
      'properties' => array(...),
    ),
  ),
)
jthorson’s picture

Disadvantage to #1 is that it requires duplication of properties for tasks which use the same property definitions ... another option is to keep the properties seperate from the job stack, as per #1 ... but allow a mechanism for overriding the array key associated with a particular item in the job stack.

array(
  'job_tasks' => array(
    '0' => array(
      'plugin' => 'execute',
      'properties' => 'execute1',
    ),
    '1' => array(
      'plugin' => 'vcs',
    ),
    '2' => array(
      'plugin' => 'patch',
    ),
    '3' => array(
      'plugin' => 'execute',
      'properties' => 'execute2',
    ),
  ),
  'execute1' => array(...),
  'execute2' => array(...),
  'vcs' => array(...),
  'patch' => array(...),
   ...

Admittedly, the extra array() in the job tasks is a bit annoying ... but this could be made optional; cleaning up the array (but adding complexity to the processing code).

array(
  'job_tasks' => array(
    '0' => array(
      'plugin' => 'execute',
      'properties' => 'execute1',
    ),
    '1' => 'vcs',
    '2' => 'patch',
    '3' => array(
      'plugin' => 'execute',
      'properties' => 'execute2',
    ),
  ),
  'execute1' => array(...),
  'execute2' => array(...),
  'vcs' => array(...),
  'patch' => array(...),
   ...
jthorson’s picture

The property name 'task' makes more sense than 'job_task', as 'job' has a certain context in the current build.

Next challenge is how to handle those build steps or plugins which depend on other properties as well. For example, the 'patch' processing also contains a dependency on the 'vcs' property.

One proposed approach is related to #1649986: Allow each plugin to define the complete set of 'allowed' properties it accepts. Adding a capability for each plugin to define the complete set of properties that it depends on would allow us to simply iterate over that list, look for any keys in the properties array which match, and forward those along to the plugin.

This could conflict with the second structure defined in #2 above, as you would not be able to match a 'user-named' property against the property named in the plugin definition. This combination of 'multiple plugin invocations' combined with a patch dependency could be considered a bit of an edge case ... but would still need to be accomodated. An option here is to map the 'plugin' defined property name to the 'user' defined property name in the task array.

array(
  'job_tasks' => array(
    '0' => 'setup',
    '1' => array(
      'plugin' => 'vcs',
      'properties' => 'vcs1',
    ),
    '2' => array(
      'plugin' => 'vcs',
      'properties' => 'vcs2',
    ),
    '3' => array(
      'plugin' => 'patch',
      'vcs' => 'vcs2',
    ),
    '4' => 'build',
  ),
  'setup' => array(...),
  'vcs1' => array(...),
  'vcs2' => array(...),
  'patch' => array(...),
  'build' => array(...),
   ...
jthorson’s picture

Status: Active » Needs review
FileSize
23.19 KB

First cut on the worker side.

jthorson’s picture

Project: Worker (Sandbox) » Worker
Issue summary: View changes

Updated issue summary.

jthorson’s picture

Project: Worker » Worker (Sandbox)
FileSize
405 bytes
25.2 KB

Second iteration. Includes a one-line patch to default properties on the conduit side.

jthorson’s picture

Status: Needs review » Needs work

Missing required argument 'status'.

jthorson’s picture

Status: Needs work » Needs review
FileSize
25.51 KB

Minor fix.

This patch isn't compatible with the existing conduit_drupal plugins, as they would need to add their own default 'tasks' entry into the properties array.

jthorson’s picture

Project: Worker (Sandbox) » Worker
Version: » 7.x-1.x-dev
jthorson’s picture

Issue summary: View changes

Updated issue summary.