github-script icon indicating copy to clipboard operation
github-script copied to clipboard

Setting mediaType doesn't work

Open T3rm1 opened this issue 2 years ago • 6 comments

What version of octokit is used in this action? I'm trying to get the contents of a file in a repository with:

github.rest.repos.getContent({
  owner,
  repo,
  path,
  mediaType: {
    format: "raw+json"
  }
});

but it doesn't work. I always get the default response as if mediaType isn't set. Maybe this is not yet supported in the octokit client used in this action?

I looked at the debug information of the request and the headers don't include an Accept header. I expect the Accept header to be set to application/vnd.github.v3.raw+json

T3rm1 avatar Mar 03 '22 17:03 T3rm1

What version of octokit is used in this action?

If you're on the latest version of this action, we're using Octokit 3.5.1 https://github.com/actions/github-script/blob/main/package.json#L39

joshmgross avatar Mar 03 '22 17:03 joshmgross

I see, thanks for the response. I figured out what I misunderstood. I thought that setting the media type to raw+json would be the same as doing the request with the header Accept; application/vnd.github.v3.raw+json. Apparently that is not the case. The only thing that changes is the data key in the returned json object.

Example: https://api.github.com/repos/actions/github-script/contents/README.md If you open the link in the browser you get json object. If you open the link in the browser and set the header Accept; application/vnd.github.v3.raw you only get the contents of the file. If you use octokit to request the conent with

await octokit.request("GET /repos/{owner}/{repo}/contents/{path}", {
    owner: "actions",
    repo: "github-script",
    path: "README.md",
    mediaType: {
      format: "raw"
    }
})

you get a different json object although the requested url is the same. That's totally confusing and I haven't found anything about this in the octokit documentation.

T3rm1 avatar Mar 03 '22 19:03 T3rm1

Ok I have to reopen this. I did the above test directly with node and not in the context of the GitHub script action.

This morning I tested it again with this action and it doesn't work, although the mediaType is set. I still get the base64 encoded data as a response.

I also noticed that the User-Agent is set to actions/github-script. Maybe this is the issue or maybe even more fields are changed by this action so that it won't pass on the mediaType.

T3rm1 avatar Mar 04 '22 07:03 T3rm1

@joshmgross I set up a reproducible test case here: https://github.com/T3rm1/github-script-bug/runs/5419408653?check_suite_focus=true#step:2:57

As you can see, the content is encoded as base64 although the mediaType format is set to raw. As I don't get this error when I run this with the latest octokit in node directly, I assume this must be a bug of this action.

Can you have a look, please?

T3rm1 avatar Mar 04 '22 08:03 T3rm1

I ran into the same issue and was able to work around it like this:

      - name: install npm packages
        run: |
          npm install @octokit/rest @actions/github

      - uses: actions/github-script@v6
        with:
          script: |
            const { Octokit } = require("@octokit/rest");
            const { getOctokitOptions } = require('@actions/github/lib/utils');

            const github2 = new Octokit(getOctokitOptions(process.env.GITHUB_TOKEN));

Of course this is suboptimal, but at least it behaves the same as when run directly via node locally, or from within custom JS actions.

avonengel avatar Apr 27 '22 08:04 avonengel

bug level is on march 3 not updating

starsagar21 avatar May 25 '22 13:05 starsagar21

I've traced this down to how the action handles getInput() responses for missing settings; it assumes that if you don't set an option, that core.getInput() returns null. This is incorrect, but the error then leads to mediaType handling being broken by mediaType.previews being set to an array with an empty string.

You can see this by running the following script:

const endpoint = github.request.endpoint;
core.info(JSON.stringify(endpoint.DEFAULTS.mediaType));
core.info(endpoint({}).headers.accept);
core.info(endpoint({ mediaType: { format: 'diff' } }).headers.accept);

This outputs:

{"format":"","previews":[""]}
application/vnd.github.-preview.json
application/vnd.github.-preview.diff

Note the -preview strings in the Accept headers there; these are invalid and GitHub then falls back to the default media type for a given endpoint. The correct output would look like:

{"format":"","previews":[]}
application/vnd.github.v3+json
application/vnd.github.v3.diff

The issue is this line:

https://github.com/actions/github-script/blob/98814c53be79b1d30f795b907e553d8679345975/src/main.ts#L43

previews != null is always true, because at the very least, it'll be the empty string, see the implementation for core.getInput():

  const val: string =
    process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || ''

Inputs are read from environment variables and when the variable is missing or empty, the empty string is used. Splitting an empty string results in an array with a single empty string.

The work-around is to pop that empty string off the defaults:

const DEFAULTS = github.request.endpoint.DEFAULTS;
if (DEFAULTS.mediaType.previews.length === 1 && DEFAULTS.mediaType.previews[0] === '') {
    DEFAULTS.mediaType.previews.pop();
}

I'll create a PR to fix the input handling (it also affects setting the user agent, and the debug flag should really use core.getBooleanInput()).

mjpieters avatar Mar 30 '23 09:03 mjpieters