使用httr在本地和Travis-CI上进行Github身份验证(本地工作正常,远程无法工作)

7

我有一个 Rmd 文件,它使用 httr 访问 Github-API。在本地,如果我在渲染 Rmd 之前在 R 控制台上运行以下命令就可以正常通过 Github 进行身份验证:

myapp <- oauth_app("APP", key = "xyz", secret = "pqr")
github_token <- oauth2.0_token(oauth_endpoints("github"), myapp)

关键字和密钥是在Github上创建的,并存在于我的工作空间中。因此,当我渲染时,会自动获取github_token,这样我就可以在本地渲染时访问Github-API,而不必担心超出访问限制。
现在,相同的Rmd也会在Travis-CI上自动构建,然后在我推送主分支时部署到gh-pages。虽然我已经实现了无需身份验证的功能,但这将限制我的Github-API请求次数为每小时60次。我需要更高的请求次数,因此我在Github上设置了个人访问令牌(PAT)。设置PAT的页面上写着:“个人访问令牌的功能与普通OAuth访问令牌相同。它们可以用来替代Git over HTTPS的密码,或者用于通过基本认证对API进行认证”。
以下是我的Rmd的一部分,我尝试检测渲染是本地还是远程,并获取适当的令牌。但是,在Travis-CI上运行时,似乎没有识别到令牌,因此我认为我没有正确使用它。
# Figure out the build location, and get the needed token
at_home <- FALSE
at_TCI <- FALSE
token_found <- FALSE
token_OK <- FALSE # not used now/yet

# Check to see if we are at TRAVIS-CI
# This next variable is in the Travis build environment & is a character string
token_value <- Sys.getenv("TRAVIS_CI") 
if (token_value != "") {
  token_found <- TRUE
  at_TCI <- TRUE
}

# Check to see if we are on the local/home machine
# This token is generated interactively via "Web Application Flow",
# and is deposited in the local workspace
# See developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/#web-application-flow
# This token has classes 'Token2.0', 'Token', 'R6' <Token2.0>
if (!at_TCI) {
  token_found <- exists("github_token")
  if (token_found) {
    token_value <- github_token
    at_home <- TRUE
  }
}

# See where we stand and act accordingly
if (!token_found) {
  message("Could not retrieve token - GET calls will be rate-limited by Github")
  # TEMPORARY: just use a few lines for faster testing & not blasting GH limits
  DF <- DF[1:5,]
}
if (token_found) {
  set_config(config(token = token_value)) # applies to all GET requests below
}

我认为当我在Travis-CI上时,set_config调用没有正常工作,因为我会在稍后发生的GET调用中遇到错误(在T-CI上进行故障排除非常困难,但本地的Rmd运行良好)。以下是一个样例GET调用,在运行上述代码片段后远程失败,但本地工作正常:

repoOK[i] <- identical(status_code(GET(DF$repo[i])), 200L)

DF$repo[i] 是一个URL。

我对httr和Github-API还不熟悉,但我已经花了很多时间在SO上尝试各种方法,并查阅了Github的文档,但远程构建一直失败。因此,我请求SO社区的帮助!

编辑:GH repo 带有完整的代码。

编辑2:悬赏期间没有人回答(!)。所以我将在主分支上工作。此分支在本地运行良好,但在Travis-CI上失败。此外,该分支已经消除了所有Python方面的问题,以保持代码整洁。该分支在Travis-CI上出现以下错误:

Error in getGHdates(DF$repo[i], "commits") : Github access rate exceeded, try again later

1个回答

1
答案似乎是,当在本地工作时,不能使用与Travis-CI远程使用所需的相同身份验证方法。为了使Rmd在两个位置都正确渲染,我不得不编写比我希望的更复杂的代码。特别是,在本地工作时,只需要进行以下身份验证即可。
首先,在R控制台中运行(如上所述);
myapp <- oauth_app("APP", key = "xyz", secret = "pqr")
github_token <- oauth2.0_token(oauth_endpoints("github"), myapp)

然后在 Rmd 代码中需要:
# Figure out the build location, and get the needed token
at_home <- FALSE
at_TCI <- FALSE
token_found <- FALSE
where <- NULL

# Check to see if we are at TRAVIS-CI
# This token has class character
token_value <- Sys.getenv("TRAVIS_CI")
if (token_value != "") {
  token_found <- TRUE
  at_TCI <- TRUE
}

# Check to see if we are on the local/home machine
# This token is generated interactively via "Web Application Flow",
# and is deposited in the local workspace with the name github_token before rendering
# See developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/#web-application-flow
# This token has classes 'Token2.0', 'Token', 'R6' <Token2.0>
if (!at_TCI) {
  token_found <- exists("github_token")
  if (token_found) {
    token_value <- github_token
    at_home <- TRUE
  }
}

# See where we stand and act accordingly
if (!token_found) {
  message("Could not retrieve token - GET calls will be rate-limited by Github")
  # TEMPORARY: just use a few lines for faster testing & not blasting GH limits
  DF <- DF[1:5,]
}
if (token_found) {
  if (at_home) set_config(config(token = token_value))
  # This is sufficient for at_home and the GET calls elsewhere have a simple form
  if (at_home) where <- "home"
  if (at_TCI) where <- "TCI"
}

if (is.null(where)) stop("I'm lost")

# Report for troubleshooting
# cat("at_home = ", at_home, "\n")
# cat("at_TCI = ", at_TCI, "\n")
# cat("token_found = ", token_found, "\n")

使用这种安排,使用GET调用Github API没有问题。
然而,在Travis-CI远程工作时,这种方法不起作用。对于这种情况,需要按照以下方式操作:
for (i in 1:ne) {
  if (!is.na(DF$web[i])) {
    if (at_home) access_string <- DF$web[i]
    if (at_TCI) {
      GH <- grepl("github\\.com", DF$web[i])
      if (!GH) access_string <- DF$web[i] # local access
      if (GH) access_string <- paste0(DF$web[i], "?access_token=",
        token_value) # remote access from Travis-CI
    }
    webOK[i] <- identical(status_code(GET(access_string)), 200L)
    webLink[i] <- TRUE
    if (webLink[i] != webOK[i]) badWeb[i] <- TRUE
  }
}

我发现建议是将令牌嵌入到GET调用这里中。
如果你已经读到这里,祝你的项目好运!完整代码在GH repo中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接