【问题标题】:How to download GitHub Release from private repo using command line如何使用命令行从私有仓库下载 GitHub Release
【发布时间】:2013-12-22 04:14:46
【问题描述】:

GitHub guide 解释了两种授权方式,但看起来这些都不适用于发布文件。

由于:

curl -u 'username' -L -o a.tgz https://github.com/company/repository/releases/download/TAG-NAME/A.tgz

总会有类似的东西

<!DOCTYPE html> <!-- Hello future GitHubber! ...

【问题讨论】:

标签: command-line github


【解决方案1】:

要从私有仓库下载发布文件,您可以使用个人访问令牌,该令牌可以在settings/tokens 生成,完全控制私有仓库范围。

然后使用curl 命令下载资产(更改为适当的值):

curl -vLJO -H 'Authorization: token my_access_token' 'https://api.github.com/repos/:owner/:repo/releases/assets/:id'

或者,如果您使用的是 OAuth 应用,请使用:

curl -u my_client_id:my_client_secret https://api.github.com/repos/:owner/:repo/releases/assets/:id

地点:

  • :owner 是您的用户或组织用户名;
  • :repo 是您的存储库名称;
  • :id是你的资产ID,可以在标签发布URL中找到,比如:

    https://api.github.com/repos/:owner/:repo/releases/tags/:tag 
    
  • :token 是您的个人访问令牌(可以在/settings/tokens 创建;

注意:使用access_token 作为查询参数是deprecated

见:Repositories API v3 at GitHub


这里是 Bash 脚本,它可以根据文件的特定名称下载资产文件:

#!/usr/bin/env bash
# Script to download asset file from tag release using GitHub API v3.
# See: http://stackoverflow.com/a/35688093/55075    
CWD="$(cd -P -- "$(dirname -- "$0")" && pwd -P)"

# Check dependencies.
set -e
type curl grep sed tr >&2
xargs=$(which gxargs || which xargs)

# Validate settings.
[ -f ~/.secrets ] && source ~/.secrets
[ "$GITHUB_API_TOKEN" ] || { echo "Error: Please define GITHUB_API_TOKEN variable." >&2; exit 1; }
[ $# -ne 4 ] && { echo "Usage: $0 [owner] [repo] [tag] [name]"; exit 1; }
[ "$TRACE" ] && set -x
read owner repo tag name <<<$@

# Define variables.
GH_API="https://api.github.com"
GH_REPO="$GH_API/repos/$owner/$repo"
GH_TAGS="$GH_REPO/releases/tags/$tag"
AUTH="Authorization: token $GITHUB_API_TOKEN"
WGET_ARGS="--content-disposition --auth-no-challenge --no-cookie"
CURL_ARGS="-LJO#"

# Validate token.
curl -o /dev/null -sH "$AUTH" $GH_REPO || { echo "Error: Invalid repo, token or network issue!";  exit 1; }

# Read asset tags.
response=$(curl -sH "$AUTH" $GH_TAGS)
# Get ID of the asset based on given name.
eval $(echo "$response" | grep -C3 "name.:.\+$name" | grep -w id | tr : = | tr -cd '[[:alnum:]]=')
#id=$(echo "$response" | jq --arg name "$name" '.assets[] | select(.name == $name).id') # If jq is installed, this can be used instead. 
[ "$id" ] || { echo "Error: Failed to get asset id, response: $response" | awk 'length($0)<100' >&2; exit 1; }
GH_ASSET="$GH_REPO/releases/assets/$id"

# Download asset file.
echo "Downloading asset..." >&2
curl $CURL_ARGS -H "Authorization: token $GITHUB_API_TOKEN" -H 'Accept: application/octet-stream' "$GH_ASSET"
echo "$0 done." >&2

在运行之前,您需要使用您的 GitHub 令牌设置您的 GITHUB_API_TOKEN(请参阅:/settings/tokens at GH)。这可以放在您的~/.secrets 文件中,例如:

GITHUB_API_TOKEN=XXX

示例脚本用法:

./get_gh_asset.sh :owner :repo :tag :name

其中 name 是您的文件名(或部分文件名)。使用 TRACE=1 前缀的脚本来调试它。


如果您想知道为什么 curl 有时会失败(如其他答案中所述):

只允许一种身份验证机制;只应指定X-Amz-Algorithm 查询参数、签名查询字符串参数或Authorization 标头。

当运行时:

curl -vLJ -H 'Authorization: token <token>' -H 'Accept: application/octet-stream' https://api.github.com/repos/:owner/:repo/releases/assets/<id>

这是因为你同时指定了多种机制,所以S3服务器不知道使用哪一种,所以只能选择一种,比如:

  • X-Amz-Algorithm查询参数
  • 签名查询字符串参数(X-Amz-Signature)
  • 授权标头 (Authorization: token &lt;token&gt;)

并且由于 GitHub 将您从资产页面重定向(在请求 application/octet-stream 时),它会在查询字符串中自动填充凭据,并且由于 curl 在请求标头(您已指定)中传递相同的凭据,因此他们是矛盾的。因此,对于解决方法,您可以改用access_token

【讨论】:

  • 感谢 @kenorb 脚本,我将使用它来允许我的 ansible playbook 从私人仓库获取发布的 .deb 文件。非常感谢。
  • 感谢脚本。如果安装了jq JSON 实用程序,则可以使用ASSET_ID=$(echo "$response" | jq --arg name "$name" '.assets[] | select(.name == $name).id') 等大大简化提取资产ID。
  • 注意:不推荐使用 access_token 作为查询参数:developer.github.com/changes/…
  • @joonas.fi 感谢您的建议,我已经更新了我的答案。
  • Full control of private repositories scope 仅获取发布数据?有没有我可以使用的其他范围,因为我只是不想授权除了only releases
【解决方案2】:

我们不得不经常从私有 GitHub 存储库下载发布资产,因此我们创建了 fetch,这是一个开源、跨平台的工具,可以轻松地从 git 标签下载源文件和发布资产,提交,或公共和私有 GitHub 存储库的分支。

例如,要将发布资产 foo.exe 从私有 GitHub 存储库的版本 0.1.3 下载到 /tmp,您需要执行以下操作:

GITHUB_OAUTH_TOKEN="your token"
fetch --repo="https://github.com/foo/bar" --tag="0.1.3" --release-asset="foo.exe" /tmp

【讨论】:

  • 只需在此处添加一条评论,即 fetch 是一个独立的可执行文件,并且完全符合原始发布者的要求。我也将它纳入了我团队的构建过程。
  • 唯一对我有用的答案。试图从私人仓库的 github 版本中获取一项特定资产,但只有这一项成功了。
【解决方案3】:

似乎这两种身份验证方法仅适用于 API 端点。 有一个用于下载发布资产的 API 端点 (docu):

GET /repos/:owner/:repo/releases/assets/:id

但是需要知道资产的数字 ID。 我询问他们是否可以添加 API 端点以按名称下载发布资产(就像他们对 tarball 所做的那样)。


更新:来自 Github 支持的回复:

我们不提供您建议的任何 API。如果发布资产的标签或文件名发生变化,我们会尽量避免脆弱的 URL。我会将您的反馈反馈给团队以进一步讨论。

【讨论】:

【解决方案4】:

这里是curl & jq 一个;)班轮:

CURL="curl -H 'Authorization: token <auth_token>' \
      https://api.github.com/repos/<owner>/<repo>/releases"; \
ASSET_ID=$(eval "$CURL/tags/<tag>" | jq .assets[0].id); \
eval "$CURL/assets/$ASSET_ID -LJOH 'Accept: application/octet-stream'"

用您的数据更改用&lt;&gt; 包围的部分。 要生成auth_token,请转到github.com/settings/tokens

如果你想用密码登录,请使用这个(注意它会要求输入两次密码):

CURL="curl -u <github_user> https://api.github.com/repos/<owner>/<repo>/releases"; \
ASSET_ID=$(eval "$CURL/tags/<tag>" | jq .assets[0].id); \
eval "$CURL/assets/$ASSET_ID -LJOH 'Accept: application/octet-stream'"

【讨论】:

  • 您可以将tags/&lt;tag&gt; 替换为latest 以获取最新版本。
  • 最新版本现在似乎只需要/latest,即"$CURL/latest"
  • 新的 Github 令牌系统似乎需要 -u 方法,即-u username:token
【解决方案5】:

我在这条评论中找到了答案:https://github.com/request/request/pull/1058#issuecomment-55285276

curl 将请求中的身份验证标头转发到存储 Github 发布资产的 AmazonS3 存储桶。 来自 S3 的错误响应:

<?xml version="1.0" encoding="UTF-8"?>
<Error>
 <Code>InvalidArgument</Code>
 <Message>
   Only one auth mechanism allowed; only the X-Amz-Algorithm query parameter, Signature query string parameter or the Authorization header should be specified
 </Message>
 <ArgumentName>Authorization</ArgumentName>
 <ArgumentValue>token <yourtoken> </ArgumentValue><RequestId>4BEDDBA630688865</RequestId> <HostId>SXLsRKgKM6tPa/K7g7tSOWmQEqowG/4kf6cwOmnpObXrSzUt4bzOFuihmzxK6+gx</HostId>
</Error>

一行wget解决方案:

wget --auth-no-challenge --header='Accept:application/octet-stream' https://<token>:@api.github.com/repos/:owner/:repo/releases/assets/:id -O app.zip

试试:curl -i -H "Authorization: token &lt;token&gt;" -H "Accept:application/octet-stream" https://&lt;token&gt;:@api.github.com/repos/:owner/:repo/releases/assets/:id,了解更多详情。加-L查看S3错误信息。

【讨论】:

  • 您能解释一下如何在您的解决方案中生成&lt;token&gt; 吗?对不起,如果这是一个愚蠢的问题。
  • 认为我已经回答了我自己的问题。 Github API 身份验证记录在这里:developer.github.com/v3/#authentication
  • 如果您使用 curl,解决方法是将身份验证放在其他地方而不是作为标头。就像查询字符串参数方法一样(根据 API 文档,“URL?access_token=TOKEN”)。你也可以用 curl 做“TOKEN:@api.github.com...”吗?
【解决方案6】:

这是使用wget 发出HTTP 请求和python 进行JSON 解析的“单线”:

(export AUTH_TOKEN=<oauth-token>; \
 export ASSET_ID=$(wget -O - https://api.github.com/repos/<owner>/<repo>/releases/tags/<tag>?access_token=$AUTH_TOKEN | python -c 'import sys, json; print json.load(sys.stdin)["assets"][0]["id"]'); \
 wget --header='Accept:application/octet-stream' -O <download-name> https://api.github.com/repos/<owner>/<repo>/releases/assets/$ASSET_ID?access_token=$AUTH_TOKEN)

要使用它,只需将&lt;oauth-token&gt;&lt;owner&gt;&lt;repo&gt;&lt;tag&gt;&lt;download-name&gt; 替换为适当的值。

解释:

  • 第一条语句 (export AUTH_TOKEN=&lt;oauth-token&gt;) 设置 GitHub OAuth token,供后续的 wget 命令使用。
  • 第二条语句有两部分:
    1. wget -O - https://api.github.com/repos/&lt;owner&gt;/&lt;repo&gt;/releases/tags/&lt;tag&gt;?access_token=$AUTH_TOKEN 部分 gets GitHub release information from a tag name 并将其打印在 stdout 上。
    2. python -c 'import sys, json; print json.load(sys.stdin)["assets"][0]["id"]' 部分从 stdin 解析 JSON 并提取(第一个)发布资产的 id
  • 第三条语句 (wget --header='Accept:application/octet-stream' -O &lt;tarball-name&gt;.tar.gz https://api.github.com/repos/&lt;owner&gt;/&lt;repo&gt;/releases/assets/$ASSET_ID?access_token=$AUTH_TOKEN)) gets a single GitHub release asset by id 并将其存储到文件中。
  • 外括号创建一个子shell,并确保导出的环境变量在之后被丢弃。

【讨论】:

    【解决方案7】:

    更简单的解决方案是使用 .netrc 来存储凭据。这样,curl 不会将凭证转发到 Amazon S3 存储桶

    ~/.netrc文件中(应使用0600文件权限创建):

    machine api.github.com
    login yourusername
    password yourpassword
    

    然后使用 curl -n 选项来使用 .netrc:

    curl -L -O -J -n -H "Accept:application/octet-stream" https://api.github.com/repos/:owner/:repo/releases/assets/:id
    

    【讨论】:

    • 太糟糕了,当您在默认情况下没有 .netrc 文件的动态主机/配置上运行时,此选项有点麻烦,例如您无法定义的新生成的虚拟机/环境预配置的图像。我认为就像 CircleCI 一样。
    • @David 好吧,您也可以在脚本头部以编程方式将 3 行写入 .netrc 文件,这仍然是最简单的解决方案。
    • 它也适用于 windows,但 netrc 文件可能被命名为 ~/_netrc 而不是 ~/.netrc
    【解决方案8】:

    使用gh release download 轻松下载脚本。 gh auth login先授权。

    所以要下载示例 URL https://github.com/company/repository/releases/download/TAG-NAME/A.tgz 使用:

    gh release download --repo company/repository TAG-NAME -p 'A.tgz'

    【讨论】:

      【解决方案9】:

      像 @dwayne 一样,我使用 gh CLI 解决了这个问题,您还需要安装它。当我在一个 docker 容器中时,我需要安装 curldirmngr,然后是 gh CLI,然后下载如下所示的版本。还展示了如何使用个人令牌对 gh cli 进行身份验证,并解压缩发布文件(在我的例子中是一个 tarball)。

      FROM debian:10.9 as base
      RUN apt update \
       # Install package dependencies
       && apt install -y \
          build-essential \
          wget \
          dirmngr \
          curl
      
      # Install GH CLI - see https://github.com/cli/cli/blob/trunk/docs/install_linux.md
      RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | gpg --dearmor -o /usr/share/keyrings/githubcli-archive-keyring.gpg && \
         echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | tee /etc/apt/sources.list.d/github-cli.list > /dev/null && \
         apt update && \
         apt install -y gh
      
      # auth to github with PAT and download release
      ARG RELEASE_TOKEN
      RUN echo $RELEASE_TOKEN | gh auth login --with-token && \
         cd /opt && \
         gh release download YOUR_TAG_HERE --repo https://github.com/SOME_ORG/SOME-REPO && \
         tar -xjf SOME-RELEASE-FILES.tar.bz2 -C /opt && \
         rm SOME-RELEASE-FILES.tar.bz2
      

      【讨论】:

        猜你喜欢
        • 2017-06-24
        • 1970-01-01
        • 1970-01-01
        • 2013-08-10
        • 2022-10-13
        • 2022-06-21
        • 2020-04-27
        • 2019-02-07
        • 1970-01-01
        相关资源
        最近更新 更多