jenkinsapi icon indicating copy to clipboard operation
jenkinsapi copied to clipboard

Build.get_actions() munges together dictionaries so that some items are missing from the result

Open ben-g- opened this issue 8 years ago • 10 comments

The variable 'build' here is a jenkinsapi.build.Build object.

Here's what I get when I call build.get_actions():

>>> build.get_actions()
{'failCount': 0, 'totalCount': 0, 'skipCount': 0, 'parameters': [{'name': 'DESCRIPTION_SETTER_DESCRIPTION', 'value': 'sandbox'}], 'tags': [], 'urlName': 'aggregatedTestReport', 'causes': [{'userName': 'ben', 'userId': 'ben', 'shortDescription': 'Started by user ben'}]}

That's the result of merging multiple dictionaries, and some information got lost in the merger, as you can see from this:

>>> build._data["actions"]
[{'parameters': [{'name': 'CUSTOMER', 'value': 'sandbox'}, {'name': UPSTREAM_ARTIFACTS_DIRECTORY', 'value': 'upstream-artifacts'}, {'name': 'MAKE_WINDOWS_INSTALLER', 'value': False}, {'name': 'CREATE_SVN_TAG', 'value': True}]},
 {'causes': [{'userName': 'ben', 'userId': 'ben', 'shortDescription': 'Started by user ben'}]},
 {},
 {'tags': []},
 {},
 {'failCount': 0, 'totalCount': 0, 'skipCount': 0, 'urlName': 'aggregatedTestReport'},
 {},
 {},
 {'parameters': [{'name': 'DESCRIPTION_SETTER_DESCRIPTION', 'value': 'sandbox'}]},
 {},
 {},
 {}]

Specifically, more than one of the merged dictionaries has a 'parameters' key, so one of the corresponding values gets dropped.

ben-g- avatar Jun 01 '16 16:06 ben-g-

Where is this DESCRIPTION_SETTER_DESCRIPTION is coming from? Is that a plugin or you have such parameter defined in job?

lechat avatar Jun 02 '16 13:06 lechat

DESCRIPTION_SETTER_DESCRIPTION comes from the 'Set build description' post-build action, which comes from the Description Setter Plugin.

ben-g- avatar Jun 02 '16 14:06 ben-g-

Please submit pull request if you managed to fix this.

lechat avatar Aug 16 '16 12:08 lechat

I initially had the idea that this could be solved simply by merging duplicated keys from the actions list. But I also realize that there may be dictionaries that aren't straight forward to merge.

Could a good enough solution be to use the old dictionary update for everything that isn't parameters and merge the parameters lists into one?

mett avatar Mar 22 '17 06:03 mett

Based on the one example in the original post, I agree that that looks like a reasonable solution. It depends on the value of 'parameters' always being a list, which seems likely to be the case, but I have no idea if it is.

ben-g- avatar Mar 23 '17 13:03 ben-g-

Your right. My assumption was that parameters would always be a list. If that assumption is incorrect the complexity increases a bit.

mett avatar Mar 24 '17 12:03 mett

I'm running into the same thing. I'm seeing get_upstream_build failing on aborted jobs because I have two dictionaries with 'causes" as the key. The other one shown looks like it could cause problems as well because of the double 'name' keys. [ {'_class': 'com.tikal.jenkins.plugins.multijob.MultiJobParametersAction', 'parameters': [ {'_class': 'org.jvnet.jenkins.plugins.nodelabelparameter.LabelParameterValue', 'name': 'Where_To_Run', 'value': 'Everywhere'}, {'_class': 'hudson.model.StringParameterValue', 'name': 'TEST_OPTIONS', 'value': '-f=IP_Over_Carrier_Pigeon'}, {'_class': 'hudson.model.StringParameterValue', 'name': 'MULTI_JOB_OPTION', 'value': '--dryrun'} ] }, {'_class': 'hudson.model.CauseAction', 'causes': [{'upstreamBuild': 47, '_class': 'hudson.model.Cause$UpstreamCause', 'shortDescription': 'Started by upstream project "System_Tests/__Nightly Run" build number 47', 'upstreamProject': 'System_Tests/__Nightly Run', 'upstreamUrl': 'job/System_Tests/job/__Nightly%20Run/'} ] }, {'_class': 'jenkins.model.InterruptedBuildAction', 'causes': [{'_class': 'jenkins.model.CauseOfInterruption$UserInterruption'}]}, ]

mjarmstr avatar Sep 05 '18 18:09 mjarmstr

I've run into the same issue as @mjarmstr. The causes section of one dictionary clobbers previous ones, which leads to missing data. I've been able to work around that particular problem with a quick auxiliary function

def get_upstream_build(
    *, jenkins: jenkinsapi.jenkins.Jenkins, build: jenkinsapi.build.Build
) -> Optional[jenkinsapi.build.Build]:
    """ Fetch the upstream build for a given build, if any. """
    for cause in build.get_causes():
        if "upstreamProject" in cause:
            upstream_job = jenkins.get_job(jobname=cause["upstreamProject"])
            return upstream_job.get_build(buildnumber=cause["upstreamBuild"])

, but this definitely isn't ideal. Has anyone else attempted to fix this?

reillysiemens avatar Sep 24 '19 18:09 reillysiemens

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Nov 23 '19 19:11 stale[bot]

This issue might be stale because no one has attempted to fix it yet, but I don't think it should be closed until it's resolved.

reillysiemens avatar Nov 27 '19 06:11 reillysiemens