rfennell / AzurePipelines

A single Repo to contain the source for ALL my Azure DevOps Build/Release Extensions. The packages can be found in the Azure DevOps Marketplace
https://marketplace.visualstudio.com/search?term=fenn&target=VSTS&sortBy=Relevance
MIT License
342 stars 429 forks source link

Error while generating Release Notes (TypeError: Cannot read properties of null (reading 'id')) #1471

Closed Froostx closed 9 months ago

Froostx commented 1 year ago

Azure DevOps Extensions

Generate Release Notes (Node Cross Platform)

Platform

Azure DevOps Services

Azure DevOps Server (TFS) Version

No response

Extension Version

4.2.2

Describe the bug

Hello,

We associate WIs of type Task to our PRs, and we want the only the WIs of type Parent, in this case "User Story" or "Feature" for the sections: "Whats new" and "Impact Analysis". Im getting an error, but not sure why...

The strange thing is, that with the template that i show down below, in the "Impact Analysis" apparently it works correctly, getting that "Custom.ImpactAnalysis" field. But the "Whats new" section is empty... I already checked the WIs that should be showing in there, and the Custom.ReleaseNotes contains text as normal...

Error:

Looking for parents and children of WI [175156]
The most common runtime reason for the task to fail is due API ECONNRESET issues. To avoid this failing the pipeline these will be treated as warnings and an attempt to generate any release notes possible
TypeError: Cannot read properties of null (reading 'id')
    at /home/vsts/work/_tasks/XplatGenerateReleaseNotes_7b0a5887-75c4-4ade-a915-f92a93c934cb/4.2.2/ReleaseNotesFunctions.js:754:67
    at Array.find (<anonymous>)
    at /home/vsts/work/_tasks/XplatGenerateReleaseNotes_7b0a5887-75c4-4ade-a915-f92a93c934cb/4.2.2/ReleaseNotesFunctions.js:754:43
    at Generator.next (<anonymous>)
    at fulfilled (/home/vsts/work/_tasks/XplatGenerateReleaseNotes_7b0a5887-75c4-4ade-a915-f92a93c934cb/4.2.2/ReleaseNotesFunctions.js:5:58)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)

This is my template:

### {{date}}
\
&nbsp;

## 🚨 What's New
{{#return_parents_only this.workItems this.relatedWorkItems}}
{{#if (or (contains (lookup this.fields 'System.WorkItemType') 'User Story') (contains (lookup this.fields 'System.WorkItemType') 'Feature'))}}
{{#if (not (eq (lookup this.fields 'Custom.IncludeinReleaseNotes') false))}}
{{#with fields}}
* **{{{get 'System.Title' this}}}:** {{{sanitize (get 'Custom.ReleaseNotes' this)}}}
  {{/with}}
  {{/if}}
  {{/if}}
  {{/return_parents_only}}

## 🐞 Bug Fixes
{{#forEach workItems}}
{{#with fields}}
{{#if (eq (get 'System.WorkItemType' this) 'Bug')}}
{{#if (not (eq (get 'Custom.IncludeinReleaseNotes' this) false))}}
* **{{{get 'System.Title' this}}}:** {{{sanitize (get 'Custom.ReleaseNotes' this)}}}
  {{/if}}
  {{/if}}
  {{/with}}
  {{/forEach}}

## 🚫 Vulnerabilties
{{#forEach this.workItems}}
{{#if (contains (lookup this.fields 'System.WorkItemType') 'Vulnerability')}}
{{#if (not (eq (lookup this.fields 'Custom.IncludeinReleaseNotes') false))}}
{{#with fields}}
* **{{{get 'System.Id' this}}}** **{{{get 'System.Title' this}}}:** {{{sanitize (get 'Custom.ReleaseNotes' this)}}}
  {{/with}}
  {{/if}}
  {{/if}}
  {{/forEach}}

## ❗Impact Analysis
{{#return_parents_only this.workItems this.relatedWorkItems}}
{{#if (or (contains (lookup this.fields 'System.WorkItemType') 'User Story') (contains (lookup this.fields 'System.WorkItemType') 'Feature'))}}
{{#if (not (eq (lookup this.fields 'Custom.IncludeinReleaseNotes') false))}}
{{#with fields}}
* {{{sanitize (get 'Custom.ImpactAnalysis' this)}}}
  {{/with}}
  {{/if}}
  {{/if}}
  {{/return_parents_only}}
  {{#forEach workItems}}
  {{#with fields}}
  {{#if (eq (get 'System.WorkItemType' this) 'Bug')}}
  {{#if (not (eq (get 'Custom.IncludeinReleaseNotes' this) false))}}
* {{{sanitize (get 'Custom.ImpactAnalysis' this)}}}
  {{/if}}
  {{/if}}
  {{/with}}
  {{/forEach}}
  {{#forEach this.workItems}}
  {{#if (contains (lookup this.fields 'System.WorkItemType') 'Vulnerability')}}
  {{#if (not (eq (get 'Custom.IncludeinReleaseNotes' this) false))}}
  {{#with fields}}
* {{{sanitize (get 'Custom.ImpactAnalysis' this)}}}
  {{/with}}
  {{/if}}
  {{/if}}
  {{/forEach}}  

And this is my yml:

  - task: XplatGenerateReleaseNotes@3
    inputs:
      outputfile: '$(Build.ArtifactStagingDirectory)/release-notes.md'
      templateLocation: 'File'
      templatefile: '.pipeline/release-notes.md'
      customHandlebarsExtensionCode: |
        module.exports = {
            return_parents_only(array, relatedWorkItems, block) {
                var ret = ''; 
                var foundList = [];
                for (var arrayCount = 0; arrayCount < array.length ; arrayCount++) {
                    for (var relationCount = 0; relationCount < array[arrayCount].relations.length; relationCount++) { 
                        if (array[arrayCount].relations[relationCount].attributes.name == 'Parent') { 
                            var urlParts = array[arrayCount].relations[relationCount].url.split("/");
                            var id = parseInt(urlParts[urlParts.length - 1]);
                            var parent = relatedWorkItems.find(element => element.id === id);
                            if (!foundList.includes(parent)) {
                                foundList.push(parent);
                                ret += block.fn(parent);
                            }
                        }
                    }
                }; 
                return ret;
            },
            stripHtml(fields, field) {
                return fields[field].replace(/(<([^>]+)>)/gi, "");
            }

        }
      dumpPayloadToConsole: false
      dumpPayloadToFile: false
      replaceFile: True
      getParentsAndChildren: True
      getAllParents: False
      getIndirectPullRequests: False
      stopOnError: False
      considerPartiallySuccessfulReleases: False
      checkForManuallyLinkedWI: False
      wiqlFromTarget: 'WorkItems'
      overrideActiveBuildReleaseId: '$(SOURCE_BUILD_ID)'

Repo Steps

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error ...

Expected Behavior

No response

Logging Information

Error:

Looking for parents and children of WI [175156]
The most common runtime reason for the task to fail is due API ECONNRESET issues. To avoid this failing the pipeline these will be treated as warnings and an attempt to generate any release notes possible
TypeError: Cannot read properties of null (reading 'id')
    at /home/vsts/work/_tasks/XplatGenerateReleaseNotes_7b0a5887-75c4-4ade-a915-f92a93c934cb/4.2.2/ReleaseNotesFunctions.js:754:67
    at Array.find (<anonymous>)
    at /home/vsts/work/_tasks/XplatGenerateReleaseNotes_7b0a5887-75c4-4ade-a915-f92a93c934cb/4.2.2/ReleaseNotesFunctions.js:754:43
    at Generator.next (<anonymous>)
    at fulfilled (/home/vsts/work/_tasks/XplatGenerateReleaseNotes_7b0a5887-75c4-4ade-a915-f92a93c934cb/4.2.2/ReleaseNotesFunctions.js:5:58)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
rfennell commented 1 year ago

The line it is failing on is if (!relatedWorkItems.find(element => element.id === id)) { on the follow block

var id = parseInt(urlParts[urlParts.length - 1]);
if (!relatedWorkItems.find(element => element.id === id)) {
    agentApi.logInfo(`Add ${relation.attributes.name} WI ${id}`);
    relatedWorkItems.push(yield (workItemTrackingApi.getWorkItem(id, null, null, WorkItemTrackingInterfaces_1.WorkItemExpand.All, null)));
 }

which suggest the element in the relatedWorkItems array null or not something with an id property.

I would suggest running the task locally with your extension, by doing this you can add more debugging logs to see what is present in the arrays at all points

Froostx commented 1 year ago

Im not sure why that line is failing tho... A few months ago it worked perfectly.

How can i debug this without using the testconsole?

And i dont know why im getting 0 Related WorkItems (Parent/Child). I checked my WIs of type task, and see if there was Parent relations, and yes, i dont see any problem there...

Looking for parents and children of WI [175073]
The most common runtime reason for the task to fail is due API ECONNRESET issues. To avoid this failing the pipeline these will be treated as warnings and an attempt to generate any release notes possible
TypeError: Cannot read property 'id' of null
    at relatedWorkItems.find.element (/home/vsts/work/_tasks/XplatGenerateReleaseNotes_7b0a5887-75c4-4ade-a915-f92a93c934cb/3.90.11/ReleaseNotesFunctions.js:754:67)
    at Array.find (<anonymous>)
    at /home/vsts/work/_tasks/XplatGenerateReleaseNotes_7b0a5887-75c4-4ade-a915-f92a93c934cb/3.90.11/ReleaseNotesFunctions.js:754:43
    at Generator.next (<anonymous>)
    at fulfilled (/home/vsts/work/_tasks/XplatGenerateReleaseNotes_7b0a5887-75c4-4ade-a915-f92a93c934cb/3.90.11/ReleaseNotesFunctions.js:5:58)
    at process._tickCallback (internal/process/next_tick.js:68:7)
Total Builds: [0]
Total Commits: [200]
Total Workitems: [118]
Total Related Workitems (Parent/Children): [0]
Total Release Tests: [0]
Total Tests: [984]
Total Manual Test Runs: [0]
Total Manual Test Configurations: [0]
Total Pull Requests: [0]
Total Indirect Pull Requests: [0]
Total Associated Test WI: [0]
Total Consumed Artifacts: [0]
Total WIQL Workitems: [0]
rfennell commented 1 year ago

There is no way to debug beyond the logs you have shown without using the test console. That is why I build the test console so I could run and re-run the task against a build.

What is the issue with using the test console?

If you can tell me the version of the task that was working we can compare the code changes in GitHub

Froostx commented 1 year ago

Found that some relations come with this format:

"relations": [
    {
        "rel": "System.LinkTypes.Hierarchy-Reverse",
        "url": "https://dev.azure.com/.../aeb79ad6-...-b7a4e76586c5/_apis/wit/workItems/152412",
        "attributes": {
            "isLocked": false,
            "name": "Parent"
        }
    },
    {
        "rel": "ArtifactLink",
        "url": "vstfs:///Git/PullRequestId/aeb79ad6-...-605c-42d0-b24a-9194c22d47a4%2F16424",
        "attributes": {
            "authorizedDate": "2023-01-31T17:59:40.007Z",
            "id": 9533611,
            "resourceCreatedDate": "2023-01-31T17:59:40.007Z",
            "resourceModifiedDate": "2023-01-31T17:59:40.007Z",
            "revisedDate": "9999-01-01T00:00:00Z",
            "name": "Pull Request"
        }
    },
    {
        "rel": "ArtifactLink",
        "url": "vstfs:///Git/PullRequestId/aeb79ad6-...-605c-42d0-b24a-9194c22d47a4%2F16427",
        "attributes": {
            "authorizedDate": "2023-01-31T18:38:13.43Z",
            "id": 9535561,
            "resourceCreatedDate": "2023-01-31T18:38:13.43Z",
            "resourceModifiedDate": "2023-01-31T18:38:13.43Z",
            "revisedDate": "9999-01-01T00:00:00Z",
            "name": "Pull Request"
        }
    },   
 ...
]

The first relation (an EPIC wi), "System.LinkTypes.Hierarchy-Reverse" has no id property.

rfennell commented 1 year ago

I assume that is because an Epic WI can have no parent.

I guess I could alter the code

 var id = parseInt(urlParts[urlParts.length - 1]);
 if (!relatedWorkItems.find(element => element.id === id)) {
      agentApi.logInfo(`Add ${relation.attributes.name} WI ${id}`);
     relatedWorkItems.push(yield (workItemTrackingApi.getWorkItem(id, null, null, 
        WorkItemTrackingInterfaces_1.WorkItemExpand.All, null)));
 }

to something like

 var id = parseInt(urlParts[urlParts.length - 1]);
 if (!relatedWorkItems.find(element => element instanceof id && element.id === id)) {
      agentApi.logInfo(`Add ${relation.attributes.name} WI ${id}`);
     relatedWorkItems.push(yield (workItemTrackingApi.getWorkItem(id, null, null, 
        WorkItemTrackingInterfaces_1.WorkItemExpand.All, null)));
 }
github-actions[bot] commented 1 year ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days

Stan-Stani commented 10 months ago

This should also be added to Known Issues if possible. I am running into it. 🙏

rfennell commented 10 months ago

This went stale and was closed as I got no feedback on the proposed fix, but does sound like it is an ongoing issue and needs to be fixed. So re-added it to the backlog, but am away on business for a while so not sure when it will get done

Stan-Stani commented 10 months ago

Just a note:, for me, the issue presents itself in the test console when "getAllParents": "true" is set.