How do we know a pull request is approved or rejected using API in github? - github

I would like to know if there is an function in the Github API which would return the status of a pull request whether its accepted or rejected. Does such a function exist?

I was stymied by this problem, too. I had a hard time finding relevant info in the docs.
Option A
The tactic I've landed on is to use the issues search endpoint with the review qualifier in the q param.
So, in my case, when I want to see all PRs assigned to me that have not yet been reviewed, I'd hit this endpoint: https://github.com/api/v3/search/issues?q=is:open+is:pr+review-requested:jordan-bonitatis+review:none
Other review qualifiers include approved and changes_requested as explained here: https://docs.github.com/en/github/searching-for-information-on-github/searching-issues-and-pull-requests#search-by-pull-request-review-status-and-reviewer
Option B
If you want to see the review status for a given PR, instead of getting a list filtered by status like in my example above, you can hit the pull requests reviews endpoint: /repos/:owner/:repo/pulls/:number/reviews
This will return a list of reviews for the PR, each of which have a state key.
Note that a given PR may have multiple reviews with conflicting states. Like, if teamMemberA approved it but teamMemberB requested changes. You'll have to traverse the entire list and decide how you want to treat it based on all the states.

Depending on the repo configuration you can get the answer one way or another. The examples below use the GraphQL API.
Case 1: PR reviews are required before merging
You can query reviewDecision on the pullRequest field for a given repository.
reviewDecision is of type PullRequestReviewDecision, an enum with values of APPROVED, CHANGES_REQUESTED, and REVIEW_REQUIRED.
Example query:
{
repository(name: "gatsby", owner: "gatsbyjs") {
pullRequest(number: 30371) {
title
reviewDecision
url
}
}
}
Response:
{
"data": {
"repository": {
"pullRequest": {
"title": "chore(gatsby): don't terminate dev server if graphql wasn't imported from gatsby",
"reviewDecision": "APPROVED",
"url": "https://github.com/gatsbyjs/gatsby/pull/30371"
}
}
}
}
Case 2: PR reviews are not required before merging
If the repository settings don't specify that reviews are required, reviewDecision will be null regardless of approvals.
In this case you could iterate over the reviews and check the states. state is of type PullRequestReviewState, an enum with values of APPROVED, CHANGES_REQUESTED, COMMENTED, DISMISSED, and PENDING.
Example query:
{
repository(name: "create-react-app", owner: "facebook") {
pullRequest(number: 10003) {
title
reviewDecision
url
reviews(first: 100) {
nodes {
state
author {
login
}
}
}
}
}
}
Response:
{
"data": {
"repository": {
"pullRequest": {
"title": "Update postcss packages",
"reviewDecision": null,
"url": "https://github.com/facebook/create-react-app/pull/10003",
"reviews": {
"nodes": [
{
"state": "APPROVED",
"author": {
"login": "jasonwilliams"
}
}
]
}
}
}
}
}
It's possible to filter reviews for approvals: reviews(first: 100, states: APPROVED).
Note that two reviews will be returned if a reviewer gives his approval and subsequently requests changes.
Checking the PR state (of type PullRequestState) could be misleading: an admin user may have bypassed the required review process to merge changes.

You can get a single PR and check its state and merged properties. If it's merged, then it's accepted. If it's closed and not merged it may be rejected.
In fact it may be not rejected but closed by a creator. I'm not sure if it's possible to check if it was closed by another user (rejected) or by it's creator (denied).

I had a similar requirement - to know if a PR has been approved or not before merging it to master. I added a rule on the repo to ensure that every PR must be approved prior to merging. Then on using the API to get details about the branch there was one field which stated if the branch was clean to merge or blocked . I used this as a way to mange things in my app.
mergeable_state

This is now possible using GraphQL.
Specifically if the mergeStateStatus enum is BLOCKED then the pull request hasn't been approved and for any other status it would have been approved.
This enum is present in the PullRequest object. Do note that at the time of posting this is a preview feature and so must have the appropriate header to work. It will also not work using the GraphQL Explorer while it's in preview.

In the official Github API Documentation it shows that there is a GET request you can make that has the field merged_at if it has already been merged. Edit: theres also a merged field as well.
Snippet:
...
"merge_commit_sha": "e5bd3914e2e596debea16f433f57875b5b90bcd6",
"merged": false,
"mergeable": true,
"merged_by": {
"login": "octocat",
"id": 1,
"avatar_url": "https://github.com/images/error/octocat_happy.gif",
"gravatar_id": "",
"url": "https://api.github.com/users/octocat",
"html_url": "https://github.com/octocat",
"followers_url": "https://api.github.com/users/octocat/followers",
"following_url": "https://api.github.com/users/octocat/following{/other_user}",
"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
"organizations_url": "https://api.github.com/users/octocat/orgs",
"repos_url": "https://api.github.com/users/octocat/repos",
"events_url": "https://api.github.com/users/octocat/events{/privacy}",
"received_events_url": "https://api.github.com/users/octocat/received_events",
"type": "User",
"site_admin": false
},

Related

In TeamCity, trigger build with 2 VCS roots with 2 custom revisions using REST API

looking for collective wisdom on this problem I am tackling.
I need to trigger build using REST API on TeamCity. The build configuration has 2 VCS roots and I need to pass specific revision for both of them. In documentation, I found example for single VCS, but I am stuck on setting revisions for both of them.
I am trying to set up something like this:
{
"buildType": {
"id": "ExampleConfiguration"
},
"defaultBranch": "false",
"lastChanges": {
"change": [
{
"locator": "combination of locators that will set VCS 1 - branch + revision"
},
{
"locator": "combination of locators that will set VCS 2 - branch + revision"
}
]
}
}
In principle, I am simulating execution of the build, where both revisions are manually set - this is possible in the UI.
https://www.jetbrains.com/help/teamcity/rest/start-and-cancel-builds.html#Advanced+Build+Run
TC version: 2022.04.3 (build 108706)
Edit:
I was able to detect the changes and resolve their id on both VCS roots. For the changes field in the body I can now use locator of the form {"id": 123456}. But another obstacle on the road, if I specify pair of these changes:
"lastChanges": { "change": [ {"id": 1}, {"id": 2} ] }
I get error
Responding with error, status code: 400 (Bad Request).
Details: jetbrains.buildServer.server.rest.errors.BadRequestException: Several non-personal changes are submitted, only one can be present
Invalid request. Please check the request URL and data are correct.
Same build with the exact revisions is possible to trigger manually from TC UI.
Finally resolved it. The way to go is to use revisions instead of lastChanges. To pass revisions for 2 VCS roots together with branch names, use this:
"revisions": {
"revision": [
{
"vcs-root-instance": {
"id": "111"
},
"vcsBranchName": "branch-name-111",
"version": "rev_on_vcs_111"
},
{
"vcs-root-instance": {
"id": "222"
},
"vcsBranchName": "branch-name-222",
"version": "rev_on_vcs_222"
}
]
}
To resolve VCS root instance id, use API call /app/rest/vcs-root-instances/vcsRoot:(id:(Project_Vcs_Root))"

How to make child-card Discussion notes rollup to parent card?

How to make child-card Discussion notes rollup to parent card in Azure DevOps?
The way we use ADO is like this:
User Story -> Task 1
-> Task 2
-> Task 3
Both User Story cards and Task cards contain Discussion fields, and we have hit a quandary as to "which cards' discussion fields should we use to enter ongoing notes and discussions"? The Parent (user story)? Or the child (task)? It makes more sense for devs to enter discussion notes in the tasks, but our Support people and managers like to just look at the parent User Story card where they hope to see all discussion notes.
For now I am double-entering discussion notes in both tasks and their parent user story cards, which is not only an inefficient pain, but also violates DRY.
Then it occurred to me that the ideal solution would be for user story cards to be able to display (within the Discussion section) all discussion notes from all child cards. So if I enter a note in a Task (child) card and save it, automatically it would appear as a discussion note within its parent user story card. Ideally I could still enter user-story-specific discussion notes on occasion, but all child cards' notes would be automatically pulled in and displayed (maybe readonly? editable only in the child?) in the parent card, in all cases.
Is there an easy way to make this happen?
If the answer to #1 above is no, then is there a difficult way to make it happen? Maybe via customizations or custom API calls? What would be the best way to achieve my desired result?
This is not possible out of the box in Azure DevOps (at least not to my knowledge).
However I can think of a few ways to get this done, but it requires some custom scripting, and have some drawbacks that may of may not affect your use case.
Option 1. Create a custom extension that aggregates the comments on the parent
This option gives you complete freedom of how to visually design the feature. It is also completely DRY
You can develop your own custom extension for Azure DevOps and create a dynamic section on the User Story card that pulls in the comments from all tasks.
Option 2. Setup a Web Hook for the event "Workitem commented on"
This option does is not completely DRY, but it will at least automate the copying of comments across work items.
By configuring a web hook in Azure Devops to post a json object containing information about the new comment to a REST endpoint of your choice. The payload posted looks like below.
{
"subscriptionId": "5be97cbc-ee4b-4c21-91ea-866a61d624c4",
"notificationId": 4,
"id": "fb2617ed-60df-4518-81fa-749faa6c5cd6",
"eventType": "workitem.commented",
"publisherId": "tfs",
"message": {
"markdown": "[Bug #5](http://fabrikam-fiber-inc.visualstudio.com/web/wi.aspx?pcguid=74e918bf-3376-436d-bd20-8e8c1287f465&id=5) (Some great new idea!) commented on by Jamal Hartnett."
},
"detailedMessage": {
"markdown": "[Bug #5](http://fabrikam-fiber-inc.visualstudio.com/web/wi.aspx?pcguid=74e918bf-3376-436d-bd20-8e8c1287f465&id=5) (Some great new idea!) commented on by Jamal Hartnett.\r\nThis is a great new idea"
},
"resource": {
"id": 5,
"rev": 4,
"fields": {
"System.AreaPath": "FabrikamCloud",
"System.TeamProject": "FabrikamCloud",
"System.IterationPath": "FabrikamCloud\\Release 1\\Sprint 1",
"System.WorkItemType": "Bug",
"System.State": "New",
"System.Reason": "New defect reported",
"System.CreatedDate": "2014-07-15T17:42:44.663Z",
"System.CreatedBy": {
"displayName": "Jamal Hartnett",
"url": "https://vssps.dev.azure.com/fabrikam/_apis/Identities/e5a5f7f8-6507-4c34-b397-6c4818e002f4",
"_links": {
"avatar": {
"href": "https://dev.azure.com/mseng/_apis/GraphProfile/MemberAvatars/aad.YTkzODFkODYtNTYxYS03ZDdiLWJjM2QtZDUzMjllMjM5OTAz"
}
},
"id": "e5a5f7f8-6507-4c34-b397-6c4818e002f4",
"uniqueName": "Jamal Hartnett",
"imageUrl": "https://dev.azure.com/fabrikam/_api/_common/identityImage?id=e5a5f7f8-6507-4c34-b397-6c4818e002f4",
"descriptor": "ukn.VXkweExUVXRNakV0TWpFME5qYzNNekE0TlMwNU1ETXpOak15T0RVdE56RTVNelEwTnpBM0xURXpPRGswTlRN"
},
"System.ChangedDate": "2014-07-15T17:42:44.663Z",
"System.ChangedBy": {
"displayName": "Jamal Hartnett",
"url": "https://vssps.dev.azure.com/fabrikam/_apis/Identities/e5a5f7f8-6507-4c34-b397-6c4818e002f4",
"_links": {
"avatar": {
"href": "https://dev.azure.com/mseng/_apis/GraphProfile/MemberAvatars/aad.YTkzODFkODYtNTYxYS03ZDdiLWJjM2QtZDUzMjllMjM5OTAz"
}
},
"id": "e5a5f7f8-6507-4c34-b397-6c4818e002f4",
"uniqueName": "Jamal Hartnett",
"imageUrl": "https://dev.azure.com/fabrikam/_api/_common/identityImage?id=e5a5f7f8-6507-4c34-b397-6c4818e002f4",
"descriptor": "ukn.VXkweExUVXRNakV0TWpFME5qYzNNekE0TlMwNU1ETXpOak15T0RVdE56RTVNelEwTnpBM0xURXpPRGswTlRN"
},
"System.Title": "Some great new idea!",
"System.Parent": 26
"Microsoft.VSTS.Common.Severity": "3 - Medium",
"WEF_EB329F44FE5F4A94ACB1DA153FDF38BA_Kanban.Column": "New",
"System.History": "This is a great new idea"
},
"_links": {
"self": {
"href": "http://fabrikam-fiber-inc.visualstudio.com/DefaultCollection/_apis/wit/workItems/5"
},
"workItemUpdates": {
"href": "http://fabrikam-fiber-inc.visualstudio.com/DefaultCollection/_apis/wit/workItems/5/updates"
},
"workItemRevisions": {
"href": "http://fabrikam-fiber-inc.visualstudio.com/DefaultCollection/_apis/wit/workItems/5/revisions"
},
"workItemType": {
"href": "http://fabrikam-fiber-inc.visualstudio.com/DefaultCollection/_apis/wit/ea830882-2a3c-4095-a53f-972f9a376f6e/workItemTypes/Bug"
},
"fields": {
"href": "http://fabrikam-fiber-inc.visualstudio.com/DefaultCollection/_apis/wit/fields"
}
},
"url": "http://fabrikam-fiber-inc.visualstudio.com/DefaultCollection/_apis/wit/workItems/5"
},
"resourceVersion": "1.0",
"resourceContainers": {
"collection": {
"id": "c12d0eb8-e382-443b-9f9c-c52cba5014c2"
},
"account": {
"id": "f844ec47-a9db-4511-8281-8b63f4eaf94e"
},
"project": {
"id": "be9b3917-87e6-42a4-a549-2bc06a7a878f"
}
},
"createdDate": "2022-07-03T12:30:03.0691717Z"
}
In particular you have the comment message under message, the author of the message under fields.System.ChangedBy, the date of the comment in fields.System.ChangedDate and the parent workitem id in System.Parent
Using this information your REST service that receives the json object can create a comment on the parent work item using the Comments Rest API or post an update to the workitem where you set the System.History field to the value of the comment. This also allows you to set the original comment time and author, given that the user account you use in your automation has the permission Bypass rules on work item updates granted.
Drawbacks
If tasks can be moved from one user story to another, then the task comments on the user stories need to be moved. The same idea as above can be applied to solve this. By configuring a webhook for WorkItem updated you can listen for all updates to tasks.
By fetching the previous revision (Revision is found in resource.rev) from the Revision Rest API and comparing the field System.Parent you can determine whether the task has been moved or not and add the comments to the new parent and remove them from the old.
Similarly if you want to propagate comment updates and reactions, you would need to extend the webhook functionality even further.

Linking multiple existing work items to queued build (from Azure Devops SDK)

In Azure Devops REST API, I want to link a task\bug\story (that already exists) when triggering a build. How do I do that?
checkInTicket might be a solution, but it is not documented.
Payload based on Merlin's response worked:
var payload = new object[] {
new {
op = "add",
path = "/relations/-",
value =
new {
rel = "ArtifactLink",
url = $"vstfs:///Build/Build/{buildId}",
attributes = new
{
name = "Build"
}
}
}
};
1. Approach 1
Same with the UI operation, to link the exists work item to build, just need to update one option in build definition:
This is the api:
https://dev.azure.com/{org name}/{project name}/_apis/build/definitions/{definition id}?api-version=5.0-preview.6
In its request body, please focus on below script part:
"options": [
{
"enabled": true,
"inputs": {
"branchFilters": "[\"+refs/heads/*\"]",
"additionalFields": "{}"
},
"definition": {
"id": "5d58cc01-7c75-450c-be18-a388ddb129ec"
}
}
]
The enabled represent whether it will create links to work items which linked to associated changes after the build completed. To achieve what you want, here, please set the enabled value as true. The id value is fixed and represent this option, so here do not worry about this id value.
When you updating the build definition by this method, do not forget increment the revision in request body. revision increment means update the definition as a new revision. or the update action would not actually succeed.
But, what you should concerned is this update should finished before the build triggered. Thus it will create link to the exists WIT automatically after the build finished.
Also, this would only add this build link to work item which associate with the changes.
2. Approach 2
If the above is not what you want, and you just want to link work item to build while the build is triggered. Afraid to say, there's no such direct API could finish that.
You may need to use 2 APIs: one of it is queue build, and another API is add this build link to work item.
The request body sample of add build link to work item:
[
{
"op": "test",
"path": "/rev",
"value": "2"
},
{
"op": "add",
"path": "/relations/-",
"value":
{
"rel": "ArtifactLink",
"url": "vstfs:///Build/Build/{the build id that you just queued}"
}
}
]
This method need you get the generated BuildId after you queue the build, and then pass it to the workitem API. Different with the approach 1, in this method, you can customize the work item id which you want to add the build link to.

MS Graph REST API checkout user

I've managed to successfully checkout a file using the https://graph.microsoft.com/beta/drives/{driveId}/items/{itemId}/checkout
Now, I'd like to get the information about the user, who actually perform the checkout operation.
It's possible to check if the item is locked:
https://graph.microsoft.com/beta/drives/{driveId}/items/{itemId}?select=*,publication
However, according to DOCs, publication doesn't provide information about the checked user. Without information who locked the file is the whole checkin/checkout logic is useless.
This kind of information could be retrieved via the metadata for an item in a list as demonstrated below:
https://graph.microsoft.com/beta/sites/{site-id}/lists/{list-id}/items/{item-id}?expand=fields(select=CheckoutUserLookupId)
Once you get checkout user id (CheckoutUserLookupId field) , user details could be determined via the following endpoint:
https://graph.microsoft.com/v1.0/sites/{site-id}/lists('User Information List')/items/{CheckoutUserLookupId}
where CheckoutUserLookupId is the user id from the previous request
https://graph.microsoft.com/beta/sites/{site-id}/lists/{list-id}/items/{item-id} can't work with folders.
Anyway, drive endpoint "Allows access to the list as a drive" (according to MS Graph Docs). It works with folders as expected.
So I have
get the drive-id: /sites/${siteId}/drives
list root folder: /drives/{drive-id}/items/root/children?select=name,publication
if an item is locked, it's possible to list the activity on the item:
/drives/${idObj.driveId}/items/${idObj.fileId}?select=id&expand=activities
return list of actions:
"activities": [
{
"#odata.type": "#oneDrive.activityEntity",
"#odata.id": "https://xxxxxxxxxx/v2.0/oneDrive.activityEntity2a3649d6-2xxxxx",
"#odata.editLink": "oneDrive.activityEntity2a3649d6xxxxxx",
"#sharePoint.localizedRelativeTime": "0|July 30",
"action": {
"checkout": {}
},
"actor": {
"user": {
"email": "XXX#XXX",
"displayName": "vladimir",
"self": {},
"userPrincipalName": "XXX#XXX
}
},
"id": "XXXXXXXXXXXXXX",
"times": {
"recordedTime": "2018-07-31T04:59:03Z"
}
},
although no user ID at least a have the email....

GitHub API: List a users teams within an organization

In GitHub when viewing my organization's user list I'm able to see how many teams a user is a member of.
Clicking on this count shows me which teams a user is in, putting me on the following page:
https://github.com/orgs/my-org/teams?query=%40username
However, I'm trying to achieve the same functionality via the GitHub API, but I've been unable to find an endpoint that lists what teams (within an organization) a user is currently a member of.
One workaround is to loop through all the teams in an organization and get their members list, but this can quickly go through my rate limit, so to be able to do this in one request would be useful.
You can do this with GraphQL API v4 filtering users in teams within an organization with userLogins :
{
organization(login: "my-org") {
teams(first: 100, userLogins: ["johndoe"]) {
totalCount
edges {
node {
name
description
}
}
}
}
}
which gives for instance :
{
"data": {
"organization": {
"teams": {
"totalCount": 2,
"edges": [
{
"node": {
"name": "Employees",
"description": "org employees"
}
},
{
"node": {
"name": "Developers",
"description": "active developers"
}
}
]
}
}
}
}
Source : platform.github.community forum
Unfortunately, GitHub does not yet provide a way to do this.
At the moment, like you suggested, you would have to loop through each team in the organization to get all members within each one, then you would need to loop through all users, and check if the users are members of those teams.
You can increase your rate limit if you use an API token, but the solution is still lousy if you have a large organization.
Heads up!
Providing an invalid/unknown "userLogin" sometimes results in all teams being returned.
Perhaps me doing something wrong, but I opened a ticket with GH about this, so lets see:
https://github.community/t/teams-userlogins-filter-is-not-working-as-expected/206251