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

Getting an "Invalid request payload" error with addNewIssue and an Atlassian Document Format payload #361

Open
adamk72 opened this issue Mar 12, 2023 · 4 comments

Comments

@adamk72
Copy link

adamk72 commented Mar 12, 2023

Hey, there!

I'm working on syncing GitHub issues over to Jira using GH actions. At a basic level, I have this working just fine; authentication and such aren't the problem.

What I'd like to do is to format the descriptions I'm passing to Jira with bold, headers, etc. Passing raw Markdown syntax doesn't behave as expected (such as ## Title for a header), so I've been trying to pass in an Atlassian Document Format payload.

The error I'm getting is:

✖  fatal  {"errorMessages":["Invalid request payload. Refer to the REST API documentation and try again."]}

My payload looks like this (this is the log result right after the object has been JSON.stringify()'d):

{"fields":{"project":{"key":"SYNTST"},"summary":"Jira Sync #43","description":{"content":[{"type":"paragraph","content":[{"type":"text","text":"Test"}]},{"type":"rule"},{"type":"heading","attrs":{"level":6},"content":[{"type":"text","text":"Test footer"}]}],"type":"doc","version":1},"issuetype":{"name":"Task"}}}

When I pass that payload to the Postman app (with a POST command to '{{jiraUrl}}/rest/api/3/issue/') this works fine. My Jira instance updates with no trouble and with the expected formatting.

This is what the client setup looks like:

const jira = new JiraApi({
   protocol: 'https',
   host: core.getInput('jiraHost', { required: true }),
   username: core.getInput('jiraUsername', { required: true }),
   password: core.getInput('jiraPassword', { required: true }),
   apiVersion: '3',
   strictSSL: true
});

At first I had the wrong apiVersion (using 2 instead of 3) in the code, but I corrected that as well, and am not seeing a way to get deeper into the error (I'm assuming it's from Atlassian, but since I don't see it when using Postman, I can't see what I might be doing wrong). I see that the underlying code is using postman-request so I'd think there isn't a major difference in implementations. Looking for a suggestion to see if there's a way to further debug this, or if you know why this might be happening.

Thanks for your time in advance. I'm going to keep trying things to see what arises.

@adamk72
Copy link
Author

adamk72 commented Mar 12, 2023

I pulled this code down and tinkered with things to find that with apiVersion 2 and a non-stringified options payload, all works well. Either stringifying or apiVersion 3 (which requires a stringified payload, so same thing) causes an error to happen.

I saw that one could customize the request function, so I replaced it with this:

function internalRequest(options) {
  return new Promise((resolve, reject) => {
    _request(options.uri, options, (err, httpResponse) => {
      if (err) {
        reject(err);
      } else {
        if (httpResponse.statusCode >= 400) {
          reject(httpResponse.body);
        }

        // for compatibility with request-promise
        resolve(httpResponse.body);
      }
    });
  });
}

An almost exact copy of the default request function expect for it only takes in a single option argument instead of a (uri, options) tuple and I pull the uri off of the options object. This, I'm glad to say, worked. While I have some speculation on why the default function doesn't work when passed a stringified object, I'm satisfied that it works.

Because, I have other things to now debug. Unfortunately, when I copy and paste that new working function over into my own code... it doesn't work. But I do see a delightfully new set of console log output that I'm not sure where it came from... so, that at least is something different.

@Seth10001
Copy link
Contributor

Hey @adamk72, thank you for the detailed description. If you get it working the way you expect then feel free to open an MR or post the solution here! I wouldn't expect that modifying request in that way would do anything, but maybe I'm missing something

@adamk72
Copy link
Author

adamk72 commented Mar 13, 2023

Success!

I'm not clear on what I was doing wrong in the past that originally prompted me to make this post, but I suspect it had to do with a combination of the apiVersions being mixed up with the content type I was trying to deliver, in conjunction with stringifying things.

However, in the most recent testing, I noticed that I had not applied JSON.stringify in the jira-test.js file for node-jira-client and things worked fine. That was the last bit to get it working on my side, removing my original JSON.stringify. It was actually in writing a followup post here that I noticed the discrepancy. One log showed me one thing, another something different. Enough for that a-ha moment! 💡

Really, it was just a question of sorting through the different error types Atlassian was throwing back my way. 🙄

So it appears all is hunky-dory.

@adamk72
Copy link
Author

adamk72 commented Mar 13, 2023

I know this asking a bit beyond what is expected of an open source project, but since it was a red herring in my search. perhaps you can clear something up for for me. No worries if you can't/don't want to. In any case, Thanks for letting me rubber duck this problem out here! 🐣

So here's the ask:

doRequest only passes an options object, but it passes it to the uri argument of the request function (which takes a uri and options argument in that order), so it appears to me that:

  1. uri is populated by options.
  2. 'options` is undefined.

A console log reveals that as being true:

{
    auth: {
      user: '***',
      pass: '***'
    },
    rejectUnauthorized: true,
    method: 'POST',
    uri: 'https://***/rest/api/3/issue',
    json: true,
    followAllRedirects: true,
    body: { fields: [Object] }
  }
} { options: undefined }

Am I reading that right? What am I missing that this works? I'd expect uri to be a string, and not an object in this case. I consider myself decent at TS, but am free to admit I get lost without my types to help guide me in JS. 😄

Screen Shot 2023-03-13 at 12 23 34

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants