Adding Pull Requests & Issues to a Project - github

Does the Github API provide an easy way to add a Pull Request or an Issue to a Project Board?
This is the programmatic equivalent of a user going to a pull request and selecting one more "Projects" from the sidebar menu
NOTE: The API does seem to provide a way to add cards to the Project, but I have to specify a specific project column. I'd love to just add the project blindly and let automation rules determine the column, similar to clicking on it through the UI.
Thanks!

I think the best way to associate an existing pull request with a project, in some kind of default column, would be to daisy-chain three separate pieces of the Github API, the Get a Single Pull Request method, the Create a Project Card method, and the List Project Columns method. The idea is as follows:
Use 'Get a Single Pull Request' to retrieve the ID
Use 'List Project Columns' to get a list of the columns
Do any conditional logic if you want to see if a certain column exists, or just use the first one, or create a certain column if it doesn't exist
Use "Create a Project Card" to add the card using the Pull request ID and Column you've selected.
Here is a simplified example in Python:
import requests, json
#get pull request
r = requests.get('https://api.github.com/repos/[myusername]/[myrepo]/pulls/2')
pull = json.loads(r.text)
#requires authentication ... create your token through Github.com
api_token = "mytoken"
#prepare dictionary of header data
h = {"Accept":"application/vnd.github.inertia-preview+json", "Authorization": "token %s" % api_token}
projects_r = requests.get('https://api.github.com/repos/[myusername]/[myrepo]/projects', headers=h)
#get projects data
projects = json.loads(projects_r.text)
#get columns url for the first project in the list projects
columns_url = projects[0]['columns_url']
columns_r = requests.get(columns_url, headers=h)
columns = json.loads(columns_r.text)
#get column url for the first column in the list of columns
column_url = columns[0]['cards_url']
#use retrieved data to build post
data = {"content_id":pull_id, "content_type":"PullRequest"}
#use post method with headers and data to create card in column
result = requests.post(column_url, headers=h, data=json.dumps(data))
#returns with status 201, created

Related

Power Query - Populate column through REST API

I have a list of IDs in Power Query and would like to call and API to return some information about each. As there is no direct API that allows me to pull the information for my entire list, I have to call the API for each row in my table.
The API requires a dynamic access token, which I already have a function that takes care of (GetToken()).
I have followed this guide. The guide adds a custom column for which I have written the following code:
Json.Document(
Web.Contents(
Text.Combine({"https://urlthatholdstheinfo.com/", [id]}), [Headers=[Authorization="Bearer "& GetToken()]]))
When I close the editor, I get this classic error:
"Expression.Error: The 'Authorization' header is only supported when connecting anonymously. These headers can be used with all authentication types: Accept, Accept-Charset, Accept-Encoding, Accept-Language, Cache-Control, Content-Type, If-Modified-Since, Prefer, Range, Referer
I have previously mitigated this in the Data Source Settings by setting the Permission to "Anonymous". However, I can not find this query in those settings, so I don't know where to change this.
I have unsuccessfully been looking for a way to parse a parameter to Web.Content, that tells the query to do this with Anonymous settings, but it does not seem to exist.
I have tried this variation as well, but I get the same error
Any thoughts on what I can do?
UPDATE:
The answer for this post works, with a small addition. After implementing the answer, the error still occurred. It was resolved by creating a blank query with a fixed id number instead of parsing the column as an argument to the function. This allowed me to go to "Data source settings" and change the permission for the query to Anonymous, which also fixed the problem for the function and the custom column.
let
Source =
Json.Document(
Web.Contents(
"https://https://urlthatholdstheinfo.com/id",
[Headers=[Authorization="Bearer "& GetToken()]])),
in
Source
Also, be sure to not have the curly brackets that are in the original code of the question.
If you have a list of IDs you can make a custom function that uses appropriate constructors for RelativePath like David suggests. Here is a function you can paste into a blank query, which you can specify using Invoke Custom Function on your list of IDs:
let
Source = (ID as text) =>
Json.Document(
Web.Contents(
"https://urlthatholdstheinfo.com/",
[
Headers=[Authorization="Bearer "& GetToken()] ,
RelativePath=ID
]
]
)
)
in
Source
Make sure your ID column is in text format - or change the custom function above to:
let
Source = (ID as number) =>
Json.Document(
Web.Contents(
"https://urlthatholdstheinfo.com/",
[
Headers=[Authorization="Bearer "& GetToken()] ,
RelativePath=Text.From(ID)
]
]
)
)
in
Source
I'm fairly sure this problem arises because of the way you're constructing your URL using Text.Combine. Can you rewrite your query to use the RelativePath header
https://learn.microsoft.com/en-us/powerquery-m/web-contents

Get hyperlink to sheet based on SheetID

I am importing a Smartsheet Report through Python, using an API. One of the columns in this report contains a hyperlink that works in Smartsheet, however when importing the report with Python I only receive the words of this column, and not the link behind them. Is it possible to get the URLs of the sheets that these hyperlinks are referring to in any other way? I was thinking maybe based on SheetID (which I can find using the title of the indepentent sheets), but all other suggestions are very welcome!
I've been unable to reproduce the problem you've described.
The report I'm testing with contains the following data. The Google link in the first row is a normal URL that points to https://www.google.com and the Contacts List link in the second row is a sheet hyperlink that points to another sheet in Smartsheet.
First, I use the Python SDK to get the report and then print out the contents of the second cell of the first row (i.e., the one that contains the Google hyperlink):
reportID = 6667768033503108
report = smartsheet_client.Reports.get_report(reportID)
print(report.rows[0].cells[1])
The result of this code showed the following output (JSON formatted here for readability):
{
"columnId": 5228827298293636,
"displayValue": "Google",
"hyperlink": {
"url": "https://www.google.com"
},
"value": "Google",
"virtualColumnId": 2581703205119876
}
So, accessing the URL of the hyperlink can be accomplished with the following code:
url = report.rows[0].cells[1].hyperlink.url
print(url) #shows output: https://www.google.com
The same approach works for getting the URL of the sheet hyperlink in the second row. i.e., running the following code:
reportID = 6667768033503108
report = smartsheet_client.Reports.get_report(reportID)
url = report.rows[1].cells[1].hyperlink.url
print(url) #shows output: https://app.smartsheet.com/sheets/[ID]
This approach should work for you, but if for some reason you're seeing that the cell object in the JSON response (when using the Python SDK) for the cell that contains the link doesn't actually contain a hyperlink object with a url property -- that might indicate a bug either with the Python SDK or with the underlying API. In that case, you might try getting the URL string by using a dictionary, as shown in the following code. (Note: you'll need to import json for this code to work).
reportID = 6667768033503108
# get the report
report = smartsheet_client.Reports.get_report(reportID)
# load the contents of the second cell in the first row
resp_dict = json.loads(str(report.rows[0].cells[1]))
# read the url property from the dictionary
url = resp_dict['hyperlink']['url']
print(url) #shows output: https://www.google.com

Is it possible to get all the pull requests made by a user on different repos using some API?

I am making an application where I need to get all the pull requests made by a particular user on various repositories.
I can get all the pull request on a particular repository but found no suitable API to get all the pull request by a user.
What kind of API call can I make to get those PR filtered by author?
The List Pull Request API has a head filter:
head string
Filter pulls by head user and branch name in the format of user:ref-name.
Example: github:new-script-format.
That wouldn't work in your case, as you don't know the branch names, only the author.
Use instead the search API for issues
GET /search/issues
It can filter by:
type: With this qualifier you can restrict the search to issues (issue) or pull request (pr) only.
author: Finds issues or pull requests created by a certain user.
Try using the following code
var d=2018-09-30T10%3A00%3A00%2B00%3A00 //start date
var f=2018-11-01T12%3A00%3A00%2B00%3A00 //end date
var t=iamshouvikmitra //username
$.getJSON("https://api.github.com/search/issues?q=-label:invalid+created:" + d + ".." + f + "+type:pr+is:public+author:" + t + "&per_page=300", function(e) {
}
Infact this is similar to the code that https://hacktoberfest.digitalocean.com Uses to count the number of pull request you have submitted during the month of october.

How can I get a list of all pull requests for a repo through the github API?

I want to obtain a list of all pull requests on a repo through the github API.
I've followed the instructions at http://developer.github.com/v3/pulls/ but when I query /repos/:owner/:repo/pulls it's consistently returning fewer pull requests than displayed on the website.
For example, when I query the torvalds/linux repo I get 9 open pull requests (there are 14 on the website). If I add ?state=closed I get a different set of 11 closed pull requests (the website shows around 20).
Does anyone know where this discrepancy arises, and if there's any way to get a complete list of pull requests for a repo through the API?
You can get all pull requests (closed, opened, merged) through the variable state.
Just set state=all in the GET query, like this->
https://api.github.com/repos/:owner/:repo/pulls?state=all
For more info: check the Parameters table at https://developer.github.com/v3/pulls/#list-pull-requests
Edit: As per Tomáš Votruba's comment:
the default value for, "per_page=30". The maximum is per_page=100. To get more than 100 results, you need to call it multiple itmes: "&page=1", "&page=2"...
PyGithub (https://github.com/PyGithub/PyGithub), a Python library to access the GitHub API v3, enables you to get paginated resources.
For example,
g = Github(login_or_token=$YOUR_TOKEN, per_page=100)
r = g.get_repo($REPO_NUMBER)
for pull in r.get_pulls('all'):
# You can access pulls
See the documentation (http://pygithub.readthedocs.io/en/latest/index.html).
With Github's new official CLI (command line interface):
gh pr list --repo OWNER/REPO
which would produce something like:
Showing 2 of 2 pull requests in OWNER/REPO
#62 Doing something that-weird-branch-name
#58 My PR title wasnt-inspired-branch
See additional details and options and installation instructions.
There is a way to get a complete list and you're doing it. What are you using to communicate with the API? I suspect you may not be doing something correctly. For example (there are only 13 open pull requests currently) using my API wrapper (github3.py) I get all of the open pull requests. An example of how to do it without my wrapper in python is:
import requests
r = requests.get('https://api.github.com/repos/torvalds/linux/pulls')
len(r.json()) == 13
and I can also get that result (vaguely) in cURL by counting the results myself: curl https://api.github.com/repos/torvalds/linux/pulls.
If you, however, run into a repository with more than 25 (or 30) pull requests that's an entirely different issue but most certainly it is not what you're encountering now.
If you want to retrieve all pull requests (commits, comments, issues etc) you have to use pagination.
https://developer.github.com/v3/#pagination
The GET request "pulls" will only return open pull-requests.
If you want to get all pull-requests either you do set the parameter state to all, or you use issues.
Extra information
If you need other data from Github, such as issues, then you can identify pull-requests from issues, and you can then retrieve each pull-request no matter if it is closed or open. It will also give you a couple of more attributes (mergeable, merged, merge-commit-sha, nr of commits etc)
If an issue is a pull-request, then it will contain that attribute. Otherwise, it is just an issue.
From the API: https://developer.github.com/v3/pulls/#labels-assignees-and-milestones
"Every pull request is an issue, but not every issue is a pull request. For this reason, “shared” actions for both features, like manipulating assignees, labels and milestones, are provided within the Issues API."
Edit I just found that issues behaves similar to pull-requests, so one would need to do retrieve all by setting the state parameter to all
You can also use GraphQL API v4 to request all pull requests for a repo. It requests all the pull requests by default if you don't specify the states field :
{
repository(name: "material-ui", owner: "mui-org") {
pullRequests(first: 100, orderBy: {field: CREATED_AT, direction: DESC}) {
totalCount
nodes {
title
state
author {
login
}
createdAt
}
}
}
}
Try it in the explorer
The search API shoul help: https://help.github.com/enterprise/2.2/user/articles/searching-issues/
q = repo:org/name is:pr ...
GitHub provides a "Link" header which specifies the previous, next and last URL to fetch the values.Eg, Link Header response,
<https://api.github.com/repos/:owner/:repo/pulls?state=all&page=2>; rel="next", <https://api.github.com/repos/:owner/:repo/pulls?state=all&page=15>; rel="last"
rel="next" suggests the next set of values.
Here's a snippet of Python code that retrieves information of all pull requests from a specific GitHub repository and parses it into a nice DataFrame:
import pandas as pd
organization = 'pvlib'
repository = 'pvlib-python'
state = 'all' # other options include 'closed' or 'open'
page = 1 # initialize page number to 1 (first page)
dfs = [] # create empty list to hold individual dataframes
# Note it is necessary to loop as each request retrieves maximum 30 entries
while True:
url = f"https://api.github.com/repos/{organization}/{repository}/pulls?" \
f"state={state}&page={page}"
dfi = pd.read_json(url)
if dfi.empty:
break
dfs.append(dfi) # add dataframe to list of dataframes
page += 1 # Advance onto the next page
df = pd.concat(dfs, axis='rows', ignore_index=True)
# Create a new column with usernames
df['username'] = pd.json_normalize(df['user'])['login']

How can I add parameters to the url as part of the path in a SOAP UI REST request?

I'm creating a test case for a REST API in soapUI 4.5 where I'm going to use the content from step X to make a new call in step Y.
Ideally I'd create the REST request with some parameters, say A and B, and say that these parameters should be used in the URL:
http://myapi.com/v1/stuff/A/B
Then I'd do a property transfer step and simply set values extracted from step X into A and B.
It looks as if soapUI only lets me create querystring parameters, like this:
http://myapi.com/v1/stuff?ParamA=A&ParamB=B
This works of course, but I'd like to be able to call it both ways, to verify they're both working.
Am I missing something?
I am not a soapui expert by any means, but have just worked through a very similar scenario, so this might help you out.
Part 1: Create a paramatized resource
In my service, I have a resource called stuff:
http://{host}/stuff
I create a child resource with the below values:
Resource Name: Get stuff by ID
Resource Path/Endpoint: {stuffId}
and before clicking ok, click Extract Params - this will populate the Parameters table with an entry like:
Name | Default value | Style | Location
stuffId | stuffId | TEMPLATE | RESOURCE
then click ok. You now have a resource that allows you to dynamically supply an id:
http://{host}/stuff/{id}
you would need to repeat this to create the B parameter above (or you could create A and B as two parameters to the single resource if you never call /stuff/A without also supplying B).
Part 2: Create the test case
Now in the test case, you need to retrieve A, transfer the property, and then send a request to the above resource using the property:
In the test case, create the request to retrieve the response containing A
Right click the testcase and add a Properties step. Add a property to store the value of A.
From the response in the Outline view, right click the value of A and select "Transfer to > Property", select the property you just created and hit ok
Create a new request, using the new paramatized resource created in the first part. In the place of the id, put a reference to the property which is holding the value of A in this format:
${propertyName}
I might have done something wrong, but my test initially fails on the property transfer with "Missing source property". In the Source are of the PropertyTransfer step, I needed to set the property to ResponseAsXml
Hope this helps!