r-lib / remotes

Install R packages from GitHub, GitLab, Bitbucket, git, svn repositories, URLs
https://remotes.r-lib.org/
Other
336 stars 153 forks source link

[Feature Request] Default to `install_git` when access token can't use Gitlab repository/ API endpoint #604

Open dgkf opened 3 years ago

dgkf commented 3 years ago

A bit of a goofy behavior, but Gitlab's CI_JOB_TOKEN (the access token created for the execution of each CI job), has very selective access to the Gitlab API.

Errors using install_gitlab in private gitlab CI

Notably, it does not have access to the projects/:id/repository/files endpoint or projects/:id/repository/archive endpoint used to fetch the remote DESCRIPTION and download the package archive. These are accessible on public Gitlab because these endpoints are accessible without authentication. However, any private instance which requires authentication will fail using this token. Users would have to embed personal tokens with a CI job in order to use install_gitlab - feasible, but a poor practice as personal tokens would be exposed to co-maintainers/owners.

Oddly enough, the CI_JOB_TOKEN does have full ability to git clone any unrestricted private repo using basic auth (git clone https://gitlab-ci-token:$CI_JOB_TOKEN@example.com/<namespace>/<project>.git). This can be used in any CI job after setting

options(remotes.git_credentials = git2r::cred_user_pass("gitlab-ci-token", Sys.getenv("CI_JOB_TOKEN"))`)

Suggested fallback

When the projects/:id/repository/files endpoint returns a 401 response, it would be wonderful if remotes would fall back to using install_git in its place. This would allow use of install_gitlab within CI jobs without having to embed personal access tokens within the repo's env vars.

PR Considerations

I'd be happy to help put together a PR, but I would appreciate some feedback about approach. As is, the first failed request isn't hit until remote_package_name, but I don't think that's the right point to handle the fallback. Alternatively, this endpoint could get hit even before returning a remote object from install_gitlab, allowing an easy point to fallback, but possibly duplicating a request.

If you'd be interested in accepting this functionality, I would greatly appreciate some thoughts on the design before starting to put something together.