Using optional needs causes rendering error in pipeline view
Summary
Using a pipeline with optional needs causes rendering errors in the pipeline view.
Steps to reproduce
- Create a pipeline with optional needs like this for example:
stages:
- stage1
- stage2
job1:
stage: stage1
script:
- echo "job1"
rules:
- if: $CI_COMMIT_REF_NAME != "master"
job2:
stage: stage2
needs:
- job: job1
optional: true
script:
- echo "job2"
- Go into the pipeline view of that run and click "Group jobs by Job dependencies"
Example Project
https://gitlab.com/WIStudent/needs-optional-gitlab-ui-issue-demo/-/pipelines/300869103
What is the current bug behavior?
The ui shows an indefinte loading animation. "Group jobs by" buttons also might not be rendered at all if you already switched to "Job dependencies" in a previous pipeline run where the optional needs did not exist or the optional job was included.
What is the expected correct behavior?
Job dependency graph should be rendered.
Relevant logs and/or screenshots
instrument.js:109 TypeError: Cannot read property 'needs' of undefined
at parsing_utils.js:79
at Array.map (<anonymous>)
at t (parsing_utils.js:78)
at parsing_utils.js:108
at Array.filter (<anonymous>)
at h (parsing_utils.js:92)
at g (parsing_utils.js:115)
at b (parsing_utils.js:158)
at a.getPipelineLayers (graph_component_wrapper.vue:190)
at a.<anonymous> (graph_component_wrapper.vue?c440:1)
at a.t._render (vue.esm.js:3557)
at a.r (vue.esm.js:4075)
at mn.get (vue.esm.js:4488)
at mn.run (vue.esm.js:4563)
at pn (vue.esm.js:4319)
at Array.<anonymous> (vue.esm.js:1989)
at Jt (vue.esm.js:1915)
Different private project where view was switched to "Job dependencies" in a previous pipeline run:
Output of checks
This bug happens on GitLab.com
Possible fixes
Probably caused by this part: https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/pipelines/components/parsing_utils.js#L79
export const getAllAncestors = (nodes, nodeDict) => {
const needs = nodes
.map((node) => {
return nodeDict[node].needs || '';
})
.flat()
.filter(Boolean);
if (needs.length) {
return [...needs, ...getAllAncestors(needs, nodeDict)];
}
return [];
};
nodeDict
does not contain job1 because of its rule but needs
still contains job1 even if optional is set to true. So nodeDict[node]
is undefined causing Cannot read property 'needs' of undefined
when trying to access nodeDict[node].needs
.