r-lib / devtools

Tools to make an R developer's life easier
https://devtools.r-lib.org
Other
2.37k stars 755 forks source link

`source_gist` should support GHE URLs #2494

Closed hutch3232 closed 8 months ago

hutch3232 commented 1 year ago

Is your feature request related to a problem? Please describe. I would like to use devtools::source_gist but it is not working for gists on my GitHub Enterprise instance. That is because the regex in the function is setup for non-Enterprise GH: https://github.com/r-lib/devtools/blob/e8f5585fcd901fba894be411b338aad15f1e77fe/R/run-source.R#L114

Whereas GHE formats the URL differently: https://docs.github.com/en/enterprise-server@3.7/get-started/writing-on-github/editing-and-sharing-content-with-gists/creating-gists

http(s)://[hostname]/gist/discover or http(s)://gist.[hostname]/discover if subdomains are enabled

Describe the solution you'd like The url_match pattern to be revised to also support GHE.

Describe alternatives you've considered I have been using source_url, which works, but it is less elegant because I need to manually go to the RAW view to get the full URL. Additionally, if there are multiple R scripts in a gist, I lose the nice functionality provided by filename in source_gist.

Additional context NA

Thanks for the excellent package!

jennybc commented 1 year ago

This is the first time I've looked at the source_gist() family of functions. And the first question I have: how does this interact with auth and GHE? Since you have more first-hand experience with and easier access to gists + GHE that I do, do you have any quick thoughts about that?

Basically I'm a bit surprised to see a simple httr::GET() here in source_url(), which source_gist() ultimately calls:

https://github.com/r-lib/devtools/blob/aa3f88bc693d049e1b524ca1a86b300e2c954765/R/run-source.R#L38

In your workaround workflow where you use source_url() directly, does a token end up getting baked into the URL?

hutch3232 commented 1 year ago

Thanks for taking a look! I'm happy to do any testing for you, since I have easy access to gist/GHE.

One thing I have to do to get source_url to work is to navigate to the raw view of the gist. Here is an example from my non-GHE account:

https://gist.github.com/hutch3232/01546dd3f3741906644c7eca01ec2e07

image

image *Note I added .R to the gist name after taking the screenshots

devtools::source_url("https://gist.githubusercontent.com/hutch3232/01546dd3f3741906644c7eca01ec2e07/raw/1e7e3406dd1960a414fd8eb3c565052c47914b85/test_devtools_source.R")
# ℹ SHA-1 hash of file is "8dc0972db2b8be3707cefdfa33fb270bc57dcf9c"
# [1] "source worked!"

It looks like the source_gist version is basically a shortcut to the raw URL I created above. https://github.com/r-lib/devtools/blob/aa3f88bc693d049e1b524ca1a86b300e2c954765/R/run-source.R#L162

As far as authentication goes for GHE-based gists, that is kind of interesting. GHE is an on-premises instance (I think) so my colleagues on the network are able to source my gist even if they don't have GitHub access. I think it's doing that via a special token embedded in the URL.

My GHE URL looks something like this:

https://[hostname]/raw/gist/[username]/b2b7207fee02170d973ecde02170d071e/raw/ec1d7eca987806a3fed32c3ce4ad31e6691d9029/test.R?token=A9AH3BLKYLV56WZCH3BLVUA3D4TH3BLW
jennybc commented 1 year ago

Docs re: gists on GHE: https://docs.github.com/en/enterprise-server@3.7/get-started/writing-on-github/editing-and-sharing-content-with-gists/creating-gists

jennybc commented 1 year ago

Summary of what I've learned so far:

source_gist() eventually calls source_url() which eventually uses plain old httr::GET() to get the gist's (generally, file's) content. The GET() call does no auth.

Therefore source_gist() really only works for gists on github.com and it's not just a matter of the regular expression we're using to check and parse the URL. This is really about auth.

I could make source_gist() work for GHE, if I don't call source_url(). Instead I would get the gist file's content via the GitHub API, using the gh package. We get a lot of auth "for free" with gh. I've done a little experimentation (I do have some access to GHE) and I'm pretty convinced this would work.

However, note I think this results in an overall higher level of friction and friction for the wrong person. This last method I just described would require that the person calling source_gist() for a GHE gist has an account on that GHE instance and they also have to have a personal access token. This will add considerable friction for the GHE user calling source_gist().

For your use case, I'm not sure it gets any better than what you're already doing, which is to call source_url() on a manually-obtained raw URL which has a token baked in. You do some annoying work, but your non-GHE-using colleagues have an easy time.

The raw URL I get for a GHE gist via the API does not include such a token. I don't see a programmatic way to emulate what you're doing in the browser to get the raw URL that embeds a token.

hutch3232 commented 1 year ago

Thank you for this info, really appreciate it! I think I better understand what's happening now and I agree with your conclusion (about friction for other users compared to how easy it is for me to do some copy/pasting of the URL with a token).

For curiosities sake I might look to see if the token can be generated somehow, but even if I can, it wouldn't really help my use-case too much, but might be useful to other users who are more "power users" by having PATs.

jennybc commented 1 year ago

I stored my research in a local branch, because yes, for people who have configured PATs, we could make source_gist() play nicely with GHE. But it's not going to streamline the workflow where you make a gist available on GHE for non-Git(Hub)-, non-GHE-using colleagues.

jennybc commented 8 months ago

I'm going to close this because I don't plan to act on it soon, but the research is preserved in case we revisit this.