jenkinsci / jenkinsci/matrix-project-plugin

[JENKINS-49350] Matrix Job Combination Filter causes builds to be kept forever if it's random

Open
#698 0 comments 0 reactions 0 assignees View on GitHub
component:matrix-project-plugin imported-jira-issue priority:minor resolution:unresolved
Dominant language
Java
Stars
17
Forks
85
Avg merge
4h 27m
Merged PRs (30d)
5

Description

Summary

When sparsing out the matrix in any randomized way, builds are kept forever, disregarding the job's Build Discarder settings.  All sparse builds are marked "Keep This Build Forever" because newer builds depend on older builds.  


Rationale

I need to run random subsets of a lot of possible combinations because running all combinations every time would require a lot of resources.  I suspect that this is not an unusual scenario.


Steps to reproduce:

Create a matrix job:



  • Add some axis combinations (more than 2 total combinations).

  • Set build discarder to keep 3 builds (for example)

  • Add a String parameter named MATRIX_SPARSE_FACTOR to control sparse execution

  • Set a Combination Filter to something like this:

    (new java.util.Random()).nextInt(MATRIX_SPARSE_FACTOR.toInteger()) == 0

  • Run this job several times (more than the number of builds to keep) with a parameter value >1 (eg 2). 

  • Old builds are not discarded, ever, growing infinitely.

  • Run the job 3+ times with a parameter value of 1

  • Old builds are discarded once there are 3 "complete" builds (all combinations).

Note: the same issue is seen when using the Matrix Groovy Execution Strategy Plugin with a Groovy Execution Strategy that returns random results (changes between executions).

Screenshot of the tested configuration:


Correct Behavior:

When using a non-random matrix combination filter string instead, things work, for example:

index%3!=0 

 This produces the same execution (one of three combinations execute), but old builds with this configuration are correctly discarded.  However, this is not random, so successive builds run the same combinations.


Screenshot

This is what a job configured to keep 5 builds looks like: (it has >100 builds right now)

 


Additional Troubleshooting

Experimenting with consistent sparse matrix (same subsets chosen in each build), with a build discarder set to keep 3 builds:

index%(MATRIX_SPARSE_FACTOR.toInteger()) == 0


  • 10 builds with all combinations:

         3 are kept.

  • 10 builds with all combinations followed by 10 builds with every 3rd combination:

         1 kept from first 10, and 3 from the second.

  • 10 "all", then 10 "1/3", then 10 "1/2":

         1 kept from "all", 1 kept from "1/3", 3 kept from "1/2"

  • 10 "all", then 10 "1/3", then 10 "1/2", then 10 "1/4":

         1 kept from "all", 1 kept from "1/3", 1 kept from "1/2", 3 kept from "1/4"

In other words, at least one is always kept from each different combination, and the build discarder only applies to the repetition of the latest variant, unless it is "run all", in which case all prior builds are finally removed once we have N successive builds with "all".

 

---
Originally reported by akom, imported from: Matrix Job Combination Filter causes builds to be kept forever if it's random


  • status: Open
  • priority: Minor
  • component(s): matrix-project-plugin
  • resolution: Unresolved
  • votes: 1
  • watchers: 2
  • imported: 2025-12-06

Raw content of original issue

Summary

When sparsing out the matrix in any randomized way, builds are kept forever, disregarding the job's Build Discarder settings.  All sparse builds are marked "Keep This Build Forever" because newer builds depend on older builds.  


Rationale

I need to run random subsets of a lot of possible combinations because running all combinations every time would require a lot of resources.  I suspect that this is not an unusual scenario.


Steps to reproduce:

Create a matrix job:



  • Add some axis combinations (more than 2 total combinations).

  • Set build discarder to keep 3 builds (for example)

  • Add a String parameter named MATRIX_SPARSE_FACTOR to control sparse execution

  • Set a Combination Filter to something like this:
    (new java.util.Random()).nextInt(MATRIX_SPARSE_FACTOR.toInteger()) == 0

  • Run this job several times (more than the number of builds to keep) with a parameter value >1 (eg 2). 

  • Old builds are not discarded, ever, growing infinitely.

  • Run the job 3+ times with a parameter value of 1

  • Old builds are discarded once there are 3 "complete" builds (all combinations).

Note: the same issue is seen when using the Matrix Groovy Execution Strategy Plugin with a Groovy Execution Strategy that returns random results (changes between executions).

Screenshot of the tested configuration:


Correct Behavior:

When using a non-random matrix combination filter string instead, things work, for example:



index%3!=0 


 This produces the same execution (one of three combinations execute), but old builds with this configuration are correctly discarded.  However, this is not random, so successive builds run the same combinations.


Screenshot

This is what a job configured to keep 5 builds looks like: (it has >100 builds right now)

 


Additional Troubleshooting

Experimenting with consistent sparse matrix (same subsets chosen in each build), with a build discarder set to keep 3 builds:



index%(MATRIX_SPARSE_FACTOR.toInteger()) == 0



  • 10 builds with all combinations:
         3 are kept.

  • 10 builds with all combinations followed by 10 builds with every 3rd combination:
         1 kept from first 10, and 3 from the second.

  • 10 "all", then 10 "1/3", then 10 "1/2":
         1 kept from "all", 1 kept from "1/3", 3 kept from "1/2"

  • 10 "all", then 10 "1/3", then 10 "1/2", then 10 "1/4":
         1 kept from "all", 1 kept from "1/3", 1 kept from "1/2", 3 kept from "1/4"

In other words, at least one is always kept from each different combination, and the build discarder only applies to the repetition of the latest variant, unless it is "run all", in which case all prior builds are finally removed once we have N successive builds with "all".

 

environment

```
Jenkins 2.98

Matrix Plugin: 1.12

Matrix Groovy Execution Strategy Plugin: 1.0.7
```

2 attachments

- [Screenshot_2018-03-07_08-24-33.png](https://issues.jenkins.io/secure/attachment/41760/Screenshot_2018-03-07_08-24-33.png)
> ![Screenshot_2018-03-07_08-24-33.png](https://issues.jenkins.io/secure/attachment/41760/Screenshot_2018-03-07_08-24-33.png)
- [build-keep-forever.png](https://issues.jenkins.io/secure/attachment/41323/build-keep-forever.png)
> ![build-keep-forever.png](https://issues.jenkins.io/secure/attachment/41323/build-keep-forever.png)

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the randomized Combination Filter behavior with the matrix-project-plugin configuration described, using MATRIX_SPARSE_FACTOR and a Build Discarder. Compare it with the deterministic index%3!=0 filter and the Matrix Groovy Execution Strategy Plugin case. Done means randomized sparse builds are discarded according to the configured retention count without being kept forever.

Written by the indexing model from the issue text.

Assessment

Tech stack
groovy, java
Domain
build-system
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.