如何使用命令行从私有回购下载 GitHub 发布

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! ...
72483 次浏览

似乎两种身份验证方法都只适用于 API 端点。 有一个用于下载发行版资产(文件)的 API 端点:

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

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


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

我们没有你说的 API。我们尽量避免脆弱的 URL,如果发布资产的标签或文件名发生变化,这些 URL 就会发生变化。我会把你的反馈给团队进一步讨论。

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

curl正在将请求中的身份验证标头转发到 AmazonS3存储桶,Github 发布资产就存储在这个存储桶中。 中三的错误回应:

<?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 <token>" -H "Accept:application/octet-stream" https://<token>:@api.github.com/repos/:owner/:repo/releases/assets/:id,了解更多细节。添加 -L以查看 S3错误消息。

一个更简单的工作解决方案是使用。用于存储凭据的 netrc。这样,curl 就不会将凭证转发到 AmazonS3Bucket

~/.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

下面是使用 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)

要使用它,只需用适当的值替换 <oauth-token><owner><repo><tag><download-name>

说明:

  • 第一条语句(export AUTH_TOKEN=<oauth-token>)设置后续 wget命令使用的 GitHub OAuth 令牌
  • 第二项声明包括两个部分:
    1. wget -O - https://api.github.com/repos/<owner>/<repo>/releases/tags/<tag>?access_token=$AUTH_TOKEN部分 从标记名获取 GitHub 发布信息并在 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 <tarball-name>.tar.gz https://api.github.com/repos/<owner>/<repo>/releases/assets/$ASSET_ID?access_token=$AUTH_TOKEN)) 通过 id 获取单个 GitHub 发布资产并将其存储到一个文件中。
  • 外部括号创建一个子 shell 并确保随后丢弃导出的环境变量。

要从私人回购下载释放文件,您可以使用个人访问令牌,可以在 设置/标记完全控制私有存储库范围生成。

然后使用 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 is your personal access token (can be created at /settings/tokens;

Note: Using access_token as a query param is deprecated.

See: Repositories API v3 at GitHub


Here is the Bash script which can download asset file given specific name of file:

#!/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 <token>)

而且由于 GitHub 从资产页面重定向您(当请求 application/octet-stream时) ,它会自动在查询字符串中填充凭据,而且由于 curl在请求头部传递相同的凭据(您已经指定了) ,因此它们是冲突的。因此,作为解决方案,您可以使用 access_token代替。

我们经常需要从私有的 GitHub 回购协议下载发布资产,所以我们创建了 捡回来,这是一个开源的跨平台工具,可以很容易地从 GitHub 回购协议的 git 标签、提交或分支下载源文件和发布资产。

例如,要将发行版资产 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

这里是 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'"

用您的数据更改 <>包围的部分。 要生成 auth_token,请访问 < a href = “ https://github.com/sets/tokens”rel = “ norefrer”> 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'"

使用 Gh 版本下载轻松脚本下载。 登录首先授权。

因此,要下载示例 URL https://github.com/company/repository/releases/download/TAG-NAME/A.tgz,请使用:

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

像@dwayne 一样,我用 ghCLI 解决了这个问题,你也需要安装这个命令。当我在一个 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