Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add pullrequests/:id route to fetch PRs of a given id of user using GitHub API #90

Merged
merged 12 commits into from
Dec 3, 2020

Conversation

swarajpure
Copy link
Contributor

@swarajpure swarajpure commented Nov 26, 2020

Added pullrequests/:id API route
Fixes #89

To do

  • [ JSDoc ]
  • [ Swagger Annotations ]

Please suggest changes, if any.

Thank you!

Subsequent PRs:

@swarajpure swarajpure added the feature task Feature that has to be built label Nov 26, 2020
@swarajpure swarajpure self-assigned this Nov 26, 2020
Copy link
Contributor

@whyDontI whyDontI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work @swarajpure ,
Please make changes as requested.

Comment on lines 4 to 13
const getGithubId = async (id) => {
try {
const details = await userQuery.fetchUser(id)
return (details.user.github_id)
} catch (err) {
logger.error(`Error while fetching user: ${err}`)
throw err
}
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to write this function.
You can directly use already existing getUser function from userController

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@swarajpure @whyDontI Maybe that function should be moved into utils for better visibility for reusability

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ankushdharkar there are more functions related to users in userController, do we need to move all of them in that case?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not required. The user data is already fetched and can be accessed with req.userdata.
Refer: https://github.com/Real-Dev-Squad/website-backend/blob/develop/middlewares/authenticate.js#L38

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UserController is separate because all the user related functions are there. We should import functions from there to where ever we need to use it.
I don't think we should to create a separate function just to access one key (github_id).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ankurnarkhede That is only true for logged in user, here we need user details with ID

Comment on lines 12 to 22
data.items.forEach((res) => {
allPRs.push({
title: res.title,
url: res.url,
state: res.state,
created_at: res.created_at,
updated_at: res.updated_at,
ready_for_review: res.state === 'closed' ? false : !res.draft,
labels: res.labels,
assignees: res.assignees
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can destructure the res object.
Use shorthand syntax.

const pullRequests = async (req, res) => {
try {
const githubId = await getGithubId(req.params.id)
const url = `https://api.github.com/search/issues?q=org:Real-Dev-Squad+author:${githubId}+type:pr`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set BASE_URL= https://api.github.com at the starting of the code and reuse the BASE_URL variable whenever you please to generate the full path.


const pullRequests = async (req, res) => {
try {
const githubId = await getGithubId(req.params.id)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Directly use already existing getUser function from userController

Comment on lines 4 to 13
const getGithubId = async (id) => {
try {
const details = await userQuery.fetchUser(id)
return (details.user.github_id)
} catch (err) {
logger.error(`Error while fetching user: ${err}`)
throw err
}
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not required. The user data is already fetched and can be accessed with req.userdata.
Refer: https://github.com/Real-Dev-Squad/website-backend/blob/develop/middlewares/authenticate.js#L38

})
return res.send(allPRs)
}
return res.send('No pull requests found!')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need a JSON response.

const pullRequests = async (req, res) => {
try {
const githubId = await getGithubId(req.params.id)
const url = `https://api.github.com/search/issues?q=org:Real-Dev-Squad+author:${githubId}+type:pr`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add the github API URL in the config: https://github.com/Real-Dev-Squad/website-backend/blob/develop/config/default.js#L18

The org name also should be added in the config.

return res.send('No pull requests found!')
} catch (err) {
logger.error(`Error while fetching pull requests: ${err}`)
return res.boom.serverUnavailable('Something went wrong please contact admin')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Return 500.

@@ -10,6 +10,11 @@ module.exports = {
enableFileLogs: false,
enableConsoleLogs: true,

githubApi: {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We dont need to add this to development and test config unless the values are changing.

try {
const BASE_URL = 'https://api.github.com'
const { user } = await fetchUser(req.params.id)
const url = `${BASE_URL}/search/issues?q=org:Real-Dev-Squad+author:${user.github_id}+type:pr`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will be using the github API functionality at multiple places in the code.
We better move the PRs fetch logic to a file, say services/githubService.js where we can add all other logic around fetching data from github.

Also the getNames function at https://github.com/Real-Dev-Squad/website-backend/pull/90/files#diff-3c24610be60a29530abbeabee1a488714820262747d9542ecd1f39e29d89139aR8 does not necessarily be defined in a separate file unless that's going to be used multiple times in the repo. It can be added in the service function.

@@ -0,0 +1,47 @@
const logger = require('../utils/logger')
const fetch = require('../lib/fetch')
const config = require('../config')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the library 'config', do not read from the file. Refer in other files.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should solve the failing CI problem

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool

const pullRequests = async (req, res) => {
try {
const { user } = await fetchUser(req.params.id)
const url = `${config.baseUrl}/search/issues?q=org:${config.org}+author:${user.github_id}+type:pr`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use check the rate limit rules and also pass the client secret and client Id.
https://developer.github.com/v3/search/#rate-limit

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added authorization via personal access token
https://docs.github.com/en/free-pro-team@latest/rest/guides/getting-started-with-the-rest-api#authentication

They have not mentioned how to authorize using client id and client secret

const getPullRequests = async (req, res) => {
try {
const { user } = await fetchUser(req.params.id)
const url = `${config.githubApi.baseUrl}/search/issues?q=org:${config.githubApi.org}+author:${user.github_id}+type:pr`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As used elsewhere, use config.get('')

try {
const { user } = await fetchUser(req.params.id)
const url = `${config.githubApi.baseUrl}/search/issues?q=org:${config.githubApi.org}+author:${user.github_id}+type:pr`
const { data } = await githubService.fetch(url)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the fetch function moved to githubService?
As per we discussed, we were to move it to /utils directory.

Also, the API call should be made from githubService file as per mentioned in the comment: #90 (comment)

The controller should handle any response modifications and error handling.

})
return res.json(allPRs)
}
return res.json('No pull requests found!')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should send an empty array in this case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done with requested changes

@swarajpure swarajpure changed the title [WIP] Added pullrequests/:id API route Added pullrequests/:id API route Nov 29, 2020
Copy link
Contributor

@whyDontI whyDontI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small changes requested, Rest all looks great 👍🏽

Comment on lines 17 to 18
const { data } = await fetch(url)
return data
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: What if we directly return fetch call, and destructure the data at call site?
@ankurnarkhede @swarajpure

Anyway TailCallOptimization will be there, but at call site we are using await, which is not required because we are returning data directly, not a promise.
What's ideal in this case ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have returned fetch call and destructured the data at function call

And about your second question, we need to use await at function call, otherwise data.total_count is undefined because data is not returned yet.

Comment on lines 32 to 41
data.items.forEach(({ title, html_url: htmlUrl, state, created_at: createdAt, updated_at: updatedAt, draft, labels, assignees }) => {
const allAssignees = getNames(assignees, 'login')
const allLabels = getNames(labels, 'name')
allPRs.push({
title: title,
url: htmlUrl,
state: state,
created_at: createdAt,
updated_at: updatedAt,
ready_for_review: state === 'closed' ? false : !draft,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

snake_case -> camelCase -> snake_case conversion detected.
Any particular reason?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. Fixed it.

whyDontI
whyDontI previously approved these changes Dec 2, 2020
Copy link
Contributor

@whyDontI whyDontI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work Swaraj. 🥳
Once you are done with the GitHub Auth changes, we can merge this PR. 👍🏽

githubOauth: {
clientId: 'GITHUB_CLIENT_ID',
clientSecret: 'GITHUB_CLIENT_SECRET'
clientSecret: 'GITHUB_CLIENT_SECRET',
accessToken: '<accessToken>'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WHat is the access token? And how do we get it? Aren't we using client Id and client secret for making requests?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please refer my reply to your earlier review
Posted on discord as well

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Authorizing now using clientId and clientSecret. Please check

Copy link
Contributor

@ankurnarkhede ankurnarkhede left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good work @swarajpure !

@ankurnarkhede ankurnarkhede merged commit 68fe6e6 into Real-Dev-Squad:develop Dec 3, 2020
@swarajpure swarajpure deleted the pullrequests branch March 16, 2021 18:22
@swarajpure swarajpure changed the title Added pullrequests/:id API route Add pullrequests/:id route Apr 24, 2021
@swarajpure swarajpure changed the title Add pullrequests/:id route Add pullrequests/:id route to fetch PRs of a given id of user using GitHub API Apr 24, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request feature task Feature that has to be built
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add pullrequests/:id route
4 participants