Audit Pull Requests ... contd

January 08, 2024

In Azure DevOps, Pull requests provide a way to review the code before merging the changes to a branch. While submitting a PR for review it is possible to attach a work item to it. The attached work item can provide the complete background and context required for the reviewer. Also, for release management - from the work items, we can track back to the PRs

All these features are very handy,however,there is a caveat - Azure DevOps doesn't provide a way to query pull requests to find associated work items

So, in a previous article, we looked into a workaround to capture the information

today ,we will be auditing the information to perform a release management audit

Convert the PR information into Tabular format:

We used the api "Pull Requests - Get Pull Requests" to gather the PR-related information

GET https://dev.azure.com/{organization}/{project}/_apis/git/repositories/{repositoryId}/pullrequests?searchCriteria.creatorId={searchCriteria.creatorId}&searchCriteria.includeLinks={searchCriteria.includeLinks}&searchCriteria.maxTime={searchCriteria.maxTime}&searchCriteria.minTime={searchCriteria.minTime}&searchCriteria.queryTimeRangeType={searchCriteria.queryTimeRangeType}&searchCriteria.repositoryId={searchCriteria.repositoryId}&searchCriteria.reviewerId={searchCriteria.reviewerId}&searchCriteria.sourceRefName={searchCriteria.sourceRefName}&searchCriteria.sourceRepositoryId={searchCriteria.sourceRepositoryId}&searchCriteria.status={searchCriteria.status}&searchCriteria.targetRefName={searchCriteria.targetRefName}&maxCommentLength={maxCommentLength}&$skip={$skip}&$top={$top}&api-version=7.1-preview.1

in my case, the URL was like below, we are filtering only "completed" PRs on the target branch "main"

https://dev.azure.com/thillaimadhavan/Maddy_Test_Project/_apis/git/repositories/5731c60c-4dd0-4eaa-809a-b4a9c8c73435/pullrequests?searchCriteria.targetRefName=refs/heads/main&searchCriteria.status=completed&$top=100&api-version=7.1-preview.1

{
  "value": [
    {
      "repository": {
        "id": "5731c60c-4dd0-4eaa-809a-b4a9c8c73435",
        "name": "pipelines-java",
        "url": "https://dev.azure.com/thillaimadhavan/4e8d1831-0ff3-4269-8600-857bc0f39cb7/_apis/git/repositories/5731c60c-4dd0-4eaa-809a-b4a9c8c73435",
        "project": {
          "id": "4e8d1831-0ff3-4269-8600-857bc0f39cb7",
          "name": "Maddy_Test_Project",
          "state": "unchanged",
          "visibility": "unchanged",
          "lastUpdateTime": "0001-01-01T00:00:00"
        }
      },
      "pullRequestId": 16,
      "codeReviewId": 16,
      "status": "completed",
      "createdBy": {
        "displayName": "Thillai Madhavan Chelliah",
        "url": "https://spsprodcin1.vssps.visualstudio.com/Acea6439c-a370-4b66-99a5-037fe0f7735b/_apis/Identities/c755777f-833b-6701-b584-681f2bed96a2",
        "_links": {
          "avatar": {
            "href": "https://dev.azure.com/thillaimadhavan/_apis/GraphProfile/MemberAvatars/msa.Yzc1NTc3N2YtODMzYi03NzAxLWI1ODQtNjgxZjJiZWQ5NmEy"
          }
        },
        "id": "c755777f-833b-6701-b584-681f2bed96a2",
        "uniqueName": "dummy@gmail.com",
        "imageUrl": "https://dev.azure.com/thillaimadhavan/_api/_common/identityImage?id=c755777f-833b-6701-b584-681f2bed96a2",
        "descriptor": "msa.Yzc1NTc3N2YtODMzYi03NzAxLWI1ODQtNjgxZjJiZWQ5NmEy"
      },
      "creationDate": "2023-12-29T13:33:33.2166888Z",
      "closedDate": "2023-12-29T13:33:40.6854188Z",
      "title": "demo pr from another branch",
      "description": "demo pr to another branch",
      "sourceRefName": "refs/heads/demo_pr_branch_2",
      "targetRefName": "refs/heads/main",
      "mergeStatus": "succeeded",
      "isDraft": false,
      "mergeId": "21d0fcbb-f2e5-4c44-9ceb-ee391c467456",
      "lastMergeSourceCommit": {
        "commitId": "f52c10b3c4a42683f42ff2e08866718249814aa0",
        "url": "https://dev.azure.com/thillaimadhavan/4e8d1831-0ff3-4269-8600-857bc0f39cb7/_apis/git/repositories/5731c60c-4dd0-4eaa-809a-b4a9c8c73435/commits/f52c10b3c4a42683f42ff2e08866718249814aa0"
      },
      "lastMergeTargetCommit": {
        "commitId": "a1165e1b683c6aae95483c3e7a217c0c108f7f16",
        "url": "https://dev.azure.com/thillaimadhavan/4e8d1831-0ff3-4269-8600-857bc0f39cb7/_apis/git/repositories/5731c60c-4dd0-4eaa-809a-b4a9c8c73435/commits/a1165e1b683c6aae95483c3e7a217c0c108f7f16"
      },
      "lastMergeCommit": {
        "commitId": "a01c9e7d160c1276685ee84d54a0cc6faf1a5ccd",
        "url": "https://dev.azure.com/thillaimadhavan/4e8d1831-0ff3-4269-8600-857bc0f39cb7/_apis/git/repositories/5731c60c-4dd0-4eaa-809a-b4a9c8c73435/commits/a01c9e7d160c1276685ee84d54a0cc6faf1a5ccd"
      },
      "reviewers": [
        {
          "reviewerUrl": "https://dev.azure.com/thillaimadhavan/4e8d1831-0ff3-4269-8600-857bc0f39cb7/_apis/git/repositories/5731c60c-4dd0-4eaa-809a-b4a9c8c73435/pullRequests/16/reviewers/c755777f-833b-6701-b584-681f2bed96a2",
          "vote": 10,
          "hasDeclined": false,
          "isFlagged": false,
          "displayName": "Thillai Madhavan Chelliah",
          "url": "https://spsprodcin1.vssps.visualstudio.com/Acea6439c-a370-4b66-99a5-037fe0f7735b/_apis/Identities/c755777f-833b-6701-b584-681f2bed96a2",
          "_links": {
            "avatar": {
              "href": "https://dev.azure.com/thillaimadhavan/_apis/GraphProfile/MemberAvatars/msa.Yzc1NTc3N2YtODMzYi03NzAxLWI1ODQtNjgxZjJiZWQ5NmEy"
            }
          },
          "id": "c755777f-833b-6701-b584-681f2bed96a2",
          "uniqueName": "dummy@gmail.com",
          "imageUrl": "https://dev.azure.com/thillaimadhavan/_api/_common/identityImage?id=c755777f-833b-6701-b584-681f2bed96a2"
        }
      ],
      "url": "https://dev.azure.com/thillaimadhavan/4e8d1831-0ff3-4269-8600-857bc0f39cb7/_apis/git/repositories/5731c60c-4dd0-4eaa-809a-b4a9c8c73435/pullRequests/16",
      "completionOptions": {
        "mergeCommitMessage": "Merged PR 16: demo pr from another branch\n\ndemo pr to another branch\n\nRelated work items: #45",
        "squashMerge": true,
        "mergeStrategy": "squash",
        "autoCompleteIgnoreConfigIds": [
          
        ]
      },
      "supportsIterations": true,
      "completionQueueTime": "2023-12-29T13:33:40.1203155Z"
    },
    {
      "repository": {
        "id": "5731c60c-4dd0-4eaa-809a-b4a9c8c73435",
        "name": "pipelines-java",
        "url": "https://dev.azure.com/thillaimadhavan/4e8d1831-0ff3-4269-8600-857bc0f39cb7/_apis/git/repositories/5731c60c-4dd0-4eaa-809a-b4a9c8c73435",
        "project": {
          "id": "4e8d1831-0ff3-4269-8600-857bc0f39cb7",
          "name": "Maddy_Test_Project",
          "state": "unchanged",
          "visibility": "unchanged",
          "lastUpdateTime": "0001-01-01T00:00:00"
        }
      },
      "pullRequestId": 14,
      "codeReviewId": 14,
      "status": "completed",
      "createdBy": {
        "displayName": "Thillai Madhavan Chelliah",
        "url": "https://spsprodcin1.vssps.visualstudio.com/Acea6439c-a370-4b66-99a5-037fe0f7735b/_apis/Identities/c755777f-833b-6701-b584-681f2bed96a2",
        "_links": {
          "avatar": {
            "href": "https://dev.azure.com/thillaimadhavan/_apis/GraphProfile/MemberAvatars/msa.Yzc1NTc3N2YtODMzYi03NzAxLWI1ODQtNjgxZjJiZWQ5NmEy"
          }
        },
        "id": "c755777f-833b-6701-b584-681f2bed96a2",
        "uniqueName": "dummy@gmail.com",
        "imageUrl": "https://dev.azure.com/thillaimadhavan/_api/_common/identityImage?id=c755777f-833b-6701-b584-681f2bed96a2",
        "descriptor": "msa.Yzc1NTc3N2YtODMzYi03NzAxLWI1ODQtNjgxZjJiZWQ5NmEy"
      },
      "creationDate": "2023-12-29T13:28:20.4834833Z",
      "closedDate": "2023-12-29T13:28:28.9209163Z",
      "title": "demo pr commit 1",
      "description": "demo pr commit 1",
      "sourceRefName": "refs/heads/demo_query_pr_workitem",
      "targetRefName": "refs/heads/main",
      "mergeStatus": "succeeded",
      "isDraft": false,
      "mergeId": "9d4acc3a-99b8-4501-a2ae-b8687d23e812",
      "lastMergeSourceCommit": {
        "commitId": "e7fbc46758b7f19dc62dec314e1b2ff8568fdcce",
        "url": "https://dev.azure.com/thillaimadhavan/4e8d1831-0ff3-4269-8600-857bc0f39cb7/_apis/git/repositories/5731c60c-4dd0-4eaa-809a-b4a9c8c73435/commits/e7fbc46758b7f19dc62dec314e1b2ff8568fdcce"
      },
      "lastMergeTargetCommit": {
        "commitId": "b30700ed6277d536f520360d7791c8ef1938c1ea",
        "url": "https://dev.azure.com/thillaimadhavan/4e8d1831-0ff3-4269-8600-857bc0f39cb7/_apis/git/repositories/5731c60c-4dd0-4eaa-809a-b4a9c8c73435/commits/b30700ed6277d536f520360d7791c8ef1938c1ea"
      },
      "lastMergeCommit": {
        "commitId": "a1165e1b683c6aae95483c3e7a217c0c108f7f16",
        "url": "https://dev.azure.com/thillaimadhavan/4e8d1831-0ff3-4269-8600-857bc0f39cb7/_apis/git/repositories/5731c60c-4dd0-4eaa-809a-b4a9c8c73435/commits/a1165e1b683c6aae95483c3e7a217c0c108f7f16"
      },
      "reviewers": [
        {
          "reviewerUrl": "https://dev.azure.com/thillaimadhavan/4e8d1831-0ff3-4269-8600-857bc0f39cb7/_apis/git/repositories/5731c60c-4dd0-4eaa-809a-b4a9c8c73435/pullRequests/14/reviewers/c755777f-833b-6701-b584-681f2bed96a2",
          "vote": 10,
          "hasDeclined": false,
          "isFlagged": false,
          "displayName": "Thillai Madhavan Chelliah",
          "url": "https://spsprodcin1.vssps.visualstudio.com/Acea6439c-a370-4b66-99a5-037fe0f7735b/_apis/Identities/c755777f-833b-6701-b584-681f2bed96a2",
          "_links": {
            "avatar": {
              "href": "https://dev.azure.com/thillaimadhavan/_apis/GraphProfile/MemberAvatars/msa.Yzc1NTc3N2YtODMzYi03NzAxLWI1ODQtNjgxZjJiZWQ5NmEy"
            }
          },
          "id": "c755777f-833b-6701-b584-681f2bed96a2",
          "uniqueName": "dummy@gmail.com",
          "imageUrl": "https://dev.azure.com/thillaimadhavan/_api/_common/identityImage?id=c755777f-833b-6701-b584-681f2bed96a2"
        }
      ],
      "url": "https://dev.azure.com/thillaimadhavan/4e8d1831-0ff3-4269-8600-857bc0f39cb7/_apis/git/repositories/5731c60c-4dd0-4eaa-809a-b4a9c8c73435/pullRequests/14",
      "completionOptions": {
        "mergeCommitMessage": "Merged PR 14: demo pr commit 1\n\ndemo pr commit 1\n\nRelated work items: #44",
        "squashMerge": true,
        "mergeStrategy": "squash",
        "autoCompleteIgnoreConfigIds": [
          
        ]
      },
      "supportsIterations": true,
      "completionQueueTime": "2023-12-29T13:28:28.229145Z"
    }
  ],
  "count": 2
}

Let's use a JSON to Excel converter and the result will be like the below

PR tabulate

Plugin the work item ids:

Now that we have the pull request ids in a table we can add another column and capture the associated work item ids which we retrieved using the API response

The table will look like the one below

PR tabulate workitem id

Query the work items:

Now we can copy the values in the column workitemid to query the work items

to do so, click on "New Query" button under Boards → Queries

New query

Then use the ID column and IN clause to query all the pul request associated work items

Query results

Summary:

Now that we have tabulated the data it's easy to perform release management related audits on the following lines

  • Which release item requires attention based on the work item state?
  • Whether all the PRs been properly associated with the work item?
  • Whether the work item state reflect the appropriate state based on PR status?

Thanks for reading, Goodbye until next week!


Profile picture

Written by Thillai Madhavan who lives and works in India. Stay updated by following him on LinkedIn.

All the information on this website - OrganicDevops.com - is published in good faith and for general information purposes only. OrganicDevops.com does not make any warranties about the completeness, reliability and accuracy of this information. Any action you take upon the information you find on this website (OrganicDevops.com), is strictly at your own risk. OrganicDevops.com will not be liable for any losses and/or damages in connection with the use of our website. From our website, you can visit other websites by following hyperlinks to such external sites. While we strive to provide only quality links to useful and ethical websites, we have no control over the content and nature of these sites. These links to other websites do not imply a recommendation for all the content found on these sites. Site owners and content may change without notice and may occur before we have the opportunity to remove a link that may have gone 'bad'. Please be also aware that when you leave our website, other sites may have different privacy policies and terms which are beyond our control. Please be sure to check the Privacy Policies of these sites as well as their "Terms of Service" before engaging in any business or uploading any information. By using our website, you hereby consent to our disclaimer and agree to its terms. Should we update, amend or make any changes to this document, those changes will be prominently posted here
© 2024, OrganicDevOps