Problem:

After upgrading the Jenkins Active Choices Plugin from version 2.6.1 to 2.8.1, the client’s Jenkins instance began exhibiting critical malfunctions in jobs that utilized multi-level reactive reference parameters. These parameters, implemented via Active Choices Reactive Reference Parameter fields, rely on Groovy scripts to dynamically populate choices based on the values of one or more parent parameters.

The regression manifested in several ways:

  • Incorrect or stale values in deeply nested parameters (i.e., 2 or more levels of dependency).
  • Parameters rendering before parent values were available, resulting in empty or broken dropdowns.
  • Some parameters failed to render entirely, causing job start forms to remain incomplete or invalid.
  • No error messages were displayed to the user—failures occurred silently in the UI.

Affected fields included:

  • Product → Branch → Artifact_Name_Param → Artifact_Name
  • Build_Type, which also depended indirectly on Product

This effectively broke the user’s CI/CD workflow for jobs like CCM-Build, where these chains are essential to selecting the correct artifact version and environment.

Process:

Step 1 – Initial Analysis

  • Identified plugin version change as the only variable: Jenkins core version remained constant.
  • Verified plugin versions:
    • Working: Active Choices Plugin v2.6.1
    • Broken: Active Choices Plugin v2.8.1
  • Searched Jenkins JIRA and GitHub for related issues:
    • JENKINS-71909 – parameter not updating
    • JENKINS-73118 – stale parameter values
    • JENKINS-73215 – nested parameter failure
    • JENKINS-73239 – multi-level dependency bug
  • Concluded issue is likely caused by reordering of reactive parameter rendering or script execution timing.

Step 2 – Reproduction and Reverse Engineering

  • Attempted to reproduce in isolated test job using Groovy script:
    return ['alpha', 'beta', 'gamma']
  • Could reproduce 2-level dependency reliably, but 3rd level (Artifact_Name) failed to pick up selected Branch or Artifact_Name_Param.
  • Observed XHR requests for parameter scripts were firing too early, using null or outdated upstream values.
  • No backend Groovy errors in logs; scripts executed but with invalid inputs.
  • Reviewed client’s job script CCM/Build/CCM-Build.groovy:
    def product = Product
    def branch = Branch
    def builds = getBuildsFromArtifactory(product, branch)
    return builds

    Assumed upstream values would be present at execution time.

Step 3 – Plugin Source Code Diff Review

  • Compared v2.6.1 to v2.8.1:
    • Significant refactor of UnoChoiceParameter rendering logic
    • Changes to GroovyScriptEngineImpl.java, ReactiveReferenceParameter.groovy
    • New executeReactiveScript() via AJAX, now Promise-based
    • UnoChoice.js no longer chains rendering synchronously
  • Old version: Product → Branch → Artifact_Name_Param → Artifact_Name
  • New version: parameters may fire concurrently
  • No topological sort of dependencies → race conditions:
    • Grandchild renders before parent
    • Groovy sees outdated parameter map
  • v2.8.1 → v2.8.3 mostly had logging changes and minor fixes—not addressing the core issue

Step 4 – JavaScript-Based Hotfix Implementation

  • Unpacked .hpi file:
    unzip uno-choice.hpi -d uno-choice-patched
  • Edited uno-choice.js in the js/ folder, adding:
    window.setTimeout(() => {
      document.querySelectorAll('.reactive-reference-parameter').forEach(el => {
        el.dispatchEvent(new Event('change'));
      });
    }, 500);

    (Forcing re-rendering in dependency order)

  • Optional: wrap in MutationObserver to dynamically handle DOM changes
  • Repacked plugin:
    cd uno-choice-patched
    zip -r ../uno-choice-patched.hpi *
  • Delivered to client for upload via Jenkins Plugin Manager

Step 5 – Validation and Client Feedback

  • Client installed patch and confirmed:
    • Initial rendering time slightly improved
    • Multi-level fields (Artifact_Name, Build_Type) now display correctly
  • Remaining issue:
    • Artifact_Name sometimes used stale Artifact_Name_Param
    • Requested full HTTP dump of page + endpoint responses for further debugging

Solution:

A JavaScript-level hotfix was implemented that delays and re-triggers all reactive parameter renderings, ensuring a proper top-down initialization sequence. This avoids plugin-level rebuilds and provides a quick, low-intrusion fix.

Details:

  • Uses setTimeout to ensure initial async calls complete
  • Manually dispatches change events on .reactive-reference-parameter elements
  • Simulates a topological refresh pass over all parameters
  • Fully reversible; no Groovy or Jenkins core changes
  • Only requires patching one file in the .hpi archive (UnoChoice.js)

Conclusion:

The regression was caused by the shift from synchronous to asynchronous rendering of reactive parameters without managing dependency order. Multi-level parameters failed because their scripts executed before parents were resolved, violating the assumptions of existing pipelines.

The delivered fix:

  • Restored multi-level parameter correctness without reverting plugin version or rewriting Groovy logic
  • Demonstrated feasibility of deeper plugin fixes (dependency graph, event queue, etc.)
  • Opened the door for:
    • A production-grade plugin fork with dependency-aware execution
    • A pull request to upstream Active Choices Plugin with generalized fix logic
  • Client was satisfied with the fix and requested a polished .hpi along with ATP and deployment documentation