Hubot with GitHub API to merge in Pull Request not working - github

I'm trying to use Hubot to merge a pull request for a specified repository, but I get a response object like this: { message: 'Not Found', documentation_url: 'https://developer.github.com/v3' }.
Here is my code, with the sha removed:
module.exports = (robot) ->
robot.respond /deploy pr (.*) in (.*)/i, (res) ->
prNumber = res.match[1]
repo = res.match[2]
owner = process.env.HUBOT_GITHUB_OWNER
base_url = process.env.HUBOT_GITHUB_API || 'https://api.github.com'
mergeUrl = "#{base_url}/repos/#{owner}/#{repo}/pulls/#{prNumber}/merge"
data =
commit_message: "Merged pull request #{prNumber} into #{repo}",
sha: "my-sha-here"
stringData = JSON.stringify data
res.http(mergeUrl)
.put(stringData) (err, response, body) ->
if err
res.send "Error: #{err}"
else
parsedBody = JSON.parse(body)
res.send parsedBody.message
Not sure what I'm doing wrong. I think my auth is set up correctly, as I'm able to make a call with the github api to list all open pull requests for a specified repository.

I realized I wasn't passing my auth token, as I was previously using a library that did it for me. You can do it in a header like this:
module.exports = (robot) ->
robot.respond /deploy pr (.*) in (.*)/i, (res) ->
prNumber = res.match[1]
repo = res.match[2]
owner = process.env.HUBOT_GITHUB_OWNER
base_url = process.env.HUBOT_GITHUB_API || 'https://api.github.com'
mergeUrl = "#{base_url}/repos/#{owner}/#{repo}/pulls/#{prNumber}/merge"
data =
commit_message: "Merged pull request #{prNumber} into #{repo}",
sha: "my-sha-here"
stringData = JSON.stringify data
res.http(mergeUrl)
.header("Authorization", "token #{your-auth-token}")
.put(stringData) (err, response, body) ->
if err
res.send "Error: #{err}"
else
parsedBody = JSON.parse(body)
res.send parsedBody.message

Related

Set hostname on HTTPRequest for testing

In writing tests for my Vapor 3 app, I've run into an issue where a certain framework is reliant on checking the incoming requests hostname
guard let peerHostName = request.http.remotePeer.hostname else {
throw Abort(
.forbidden,
reason: "Unable to verify peer"
)
}
It would seem that when testing a request like below
let emails = (0...10).map { "email#test.co"}
let responder = try app.make(Responder.self)
let request = HTTPRequest(method: .POST, url: URL(string: "\(usersURI)/create")!, headers: headers)
let wrappedRequest = Request(http: request, using: app)
try wrappedRequest.content.encode(createUserReq)
try responder.respond(to: wrappedRequest)
Then the requests hostname is empty and thus an error is thrown. Is there any way I can manually set the hostname of the request? The hostname property is get only, so I can't set it that way
The solution was to add a 'forwarded' header
var headers: HTTPHeaders = [
"Content-Type": "application/json",
"forwarded": "by=BY;for=127.0.0.1"
]

no_file_data error when using Slack API upload

I'm getting this error {"ok":false,"error":"no_file_data"} when I try to call the slack API to upload. I already have the specified file in ./log.
robot.respond /upload (.*)/i, (res) ->
app_name = res.match[1]
request = require("request")
fs = require("fs")
channel_name = res.message.room
data = {
channels: channel_name,
filename: "#{app_name}.txt",
file: fs.createReadStream("./log/#{app_name}.txt"),
}
robot.http("https://slack.com/api/files.upload")
.headers(Authorization: 'Bearer slack-token', 'Content-Type': 'application/json')
.post(data) (err, httpRes, body) ->
if err
res.send "#{err}"
return
res.send "#{body}"
This does not work, because the API method files.upload does not support the content type application/json posts.
For your case you need to post as multipart/form-data, with one part containing the file data and one part containing the API parameters including the token.

ionic 3 header not sending Authorizaqtion 'bearer "token"' to server

Im doing a login screen that takes a username and password.
if the login was successful the server will return a token.
then im trying to call another function to get user info but the authorization header is not being passed.
im trying my server method on postman and its working fine so i believe the problem is in the headers. May someone please advise me on what should be done?
let url = urlConst.Login;
let params1 = new HttpParams();
let loader = this.loadingcontroller.create({
content: stringEngConst.signinngin
});
let attributes = {
username: this.uname.value.toLowerCase(),
password: this.password.value,
grant_type: "password"
};
var headers = new HttpHeaders();
headers.append('Content-Type', 'application/x-www-form-urlencoded');
let body = 'username=' + this.uname.value.toLowerCase() + '&password=' + this.password.value + '&grant_type=password';
let data: Observable < any > = this.http.post(url, body, {
headers: headers
});
loader.present().then(() => {
data.subscribe(result => {
if (result.access_token != null) {
this.signintoken = result.access_token;
this.storage.set(storageConst.SIGN_IN_TOKEN, result.token_type + " " + result.access_token);
headers.append('Authorization', 'Bearer ' + this.signintoken);
let url1 = 'http://localhost:57940/API/Account/GetUserInfo/';
let info: Observable < any > = this.http.get(url1, {
headers: headers
});
info.subscribe(result => {
/*Do Something*/
});
}
Please Note that result.access_token != null is true. and i am successfully getting the token back. But it is not being passed again to the second url (info)
Looks like this SO post may solve things for you: https://stackoverflow.com/a/47805759/6599076
You may want to use:
headers = headers.append('Authorization', 'Bearer ' + this.signintoken);
You are using the same headers as for the first http request:
var headers = new HttpHeaders();
headers.append('Content-Type', 'application/x-www-form-urlencoded');
Depending on your end point for the subsequent call it might be that you need to set headers differently:
Try creating new headers with
var headers2 = new HttpHeaders();
headers.append('Content-Type', 'application/json');
Or get rid of Content-Type completely depending on what your end point expects.
Also if you are using Ionic 3 its worth to check which Http module you are using (HttpClient or the older one) as there are some differences in how these tend to handle request options.

Returning result from nested anonymous function in a hubot script

Having never worked with coffescript before, I'm trying to update the hubot script for jenkins integration. In a nutshell I want to call jenkins, get a result from that call and use it in a subsequent call. Based on the existing code in the hubot script I've added the following function:
jenkinsCrumb = (msg) ->
url = process.env.HUBOT_JENKINS_URL
path = "#{url}/crumbIssuer/api/json"
req = msg.http(path)
if process.env.HUBOT_JENKINS_AUTH
auth = new Buffer(process.env.HUBOT_JENKINS_AUTH).toString('base64')
req.headers Authorization: "Basic #{auth}"
req.get() (err, res, body) ->
if err
msg.reply "Jenkins says: #{err}"
else if 200 <= res.statusCode < 400 # Or, not an error code.
msg.reply "#{body}"
body
else if 404 == res.statusCode
msg.reply "Unable to fetch crumb from Jenkins..."
else
msg.reply "Jenkins says: Status #{res.statusCode} #{body}"
When this function is called, the value I want is reported in the variable body. The call to msg.reply properly displays the value in the hubot chat window.
What I would like to do, but can't figure out, is how to have this function return the value of body? I've tried explicitly returning the value of req.get() but it seems that it's returning the full request object.
You can do that by simply adding return body or just body (because of CoffeeScript) to the end of your anonymous function:
jenkinsCrumb = (msg, callback) ->
url = process.env.HUBOT_JENKINS_URL
path = "#{url}/crumbIssuer/api/json"
req = msg.http(path)
if process.env.HUBOT_JENKINS_AUTH
auth = new Buffer(process.env.HUBOT_JENKINS_AUTH).toString('base64')
req.headers Authorization: "Basic #{auth}"
req.get() (err, res, body) ->
if err
msg.reply "Jenkins says: #{err}"
else if 200 <= res.statusCode < 400 # Or, not an error code.
msg.reply "#{body}"
body
else if 404 == res.statusCode
msg.reply "Unable to fetch crumb from Jenkins..."
else
msg.reply "Jenkins says: Status #{res.statusCode} #{body}"
# critical part
callback(body)

calling 2 https requests simultaneously in hubot coffescript

module.exports = (robot) ->
robot.respond /log (.*)/i, (msg) ->
group = "test"
incident_message = msg.match[0]
service_key = keys[group]
curtime = new Date().getTime()
incident_key = "hubot/#{curtime}"
reporter = msg.message.user.name
query = {
"service_key": service_key,
"incident_key": incident_key,
"event_type": "trigger",
"description": "Change Log #{reporter}",
"details": "#{incident_message}"
}
string_query = JSON.stringify(query)
content_length = string_query.length
msg
.http("https://events.pagerduty.com/generic/2010-04-15/create_event.json")
.headers
"Content-type": "application/json",
"Content-length": content_length
.post(string_query) (err, res, body) ->
result = JSON.parse(body)
if result.status == "success"
msg.send "Your log has been sent"
else
msg.send "There was an error sending your log."
msg
.http("https://xyz.pagerduty.com/api/v1/incidents/#{incident_key}/acknowledge")
I am trying to auto acknowledge an event triggered in pagerduty. The first http request takes effect. But the second http request (last line of the code) never takes effect. I have tried varipus combinations. But it does not help. I am new to coffeescript and only use it for hubot.Can anyone help me ?
First, you don't specify what HTTP action you are doing:
msg.http("https://xyz.pagerduty.com/api/v1/incidents/#{incident_key}/acknowledge")
Should end with .get() or .post().
Also, possibly due to bad paste, your indentation if off a bit in the middle:
.post(string_query) (err, res, body) ->
result = JSON.parse(body)
if result.status == "success"
msg.send "Your log has been sent"
else
msg.send "There was an error sending your log."
Should be:
.post(string_query) (err, res, body) ->
result = JSON.parse(body)
if result.status == "success"
msg.send "Your log has been sent"
else
msg.send "There was an error sending your log."
Another thing, due to nature of NodeJS, these HTTP calls are made asynchronously, and there is a good chance that second call finishes before first one does. To avoid that, run the second request from callback of the first one:
msg
.http("https://events.pagerduty.com/generic/2010-04-15/create_event.json")
.headers
"Content-type": "application/json",
"Content-length": content_length
.post(string_query) (err, res, body) ->
result = JSON.parse(body)
if result.status == "success"
msg.send "Your log has been sent"
msg
.http("https://xyz.pagerduty.com/api/v1/incidents/#{incident_key}/acknowledge")
.get()
else
msg.send "There was an error sending your log."
You can find some examples of Hubot HTTP requests and other scripting tricks here.