Как загрузить GitHub Release из частного репо с помощью командной строки
Руководство GitHub объясняет два способа авторизации, но ни один из них не работает с файлами Release.
в результате:
curl -u 'username' -L -o a.tgz https://github.com/company/repository/releases/download/TAG-NAME/A.tgz
всегда есть что-то вроде
<!DOCTYPE html>
<!--
Hello future GitHubber! ...
Ответы
Ответ 1
Чтобы загрузить файл релиза из частного репозитория, вы можете использовать токен личного доступа, который можно сгенерировать в settings/tokens с полным контролем области личных репозиториев.
Затем загрузите ресурс с помощью команды curl
(измените ее на соответствующие значения):
curl -vLJO -H 'Accept: application/octet-stream' 'https://api.github.com/repos/:owner/:repo/releases/assets/:id?access_token=:token'
где:
:owner
- ваше имя пользователя или организации;
:repo
- это имя вашего хранилища;
:id
- это идентификатор вашего ресурса, его можно найти в URL-адресе выпуска тега, например:
https://api.github.com/repos/:owner/:repo/releases/tags/:tag
:token
- ваш личный токен доступа (может быть создан на /settings/tokens
;
Смотрите: API репозиториев v3 на 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 <<<[email protected]
# 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 'Accept: application/octet-stream' "$GH_ASSET?access_token=$GITHUB_API_TOKEN"
echo "$0 done." >&2
Перед запуском необходимо установить GITHUB_API_TOKEN
с помощью токена GitHub (см.: /settings/tokens
в 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
.
Ответ 2
Кажется, оба метода проверки подлинности работают только для конечных точек API.
Там есть конечная точка API для загрузки активов выпуска (document):
GET /repos/:owner/:repo/releases/assets/:id
Но для этого нужно знать идентификатор номера активов.
Я попросил их поддержки, могут ли они добавить конечную точку API для загрузки активов выпуска по имени (например, для архивов).
Обновление: ответ от поддержки Github:
Мы не предлагаем API, как вы предлагаете. Мы стараемся избегать хрупких URL-адресов, которые могут измениться, если тег или имя файла актива выпуска будут изменены. Я отвечу в команду, чтобы обсудить ее дальше.
Ответ 3
Нам приходилось довольно часто загружать ресурсы релизов из частных репозиториев GitHub, поэтому мы создали fetch, кроссплатформенный инструмент с открытым исходным кодом, который позволяет легко загружать исходные файлы и выпускать ресурсы из тега git, commit, или ветвь публичных и частных репозиториев GitHub.
Например, чтобы загрузить ресурс релиза foo.exe
из версии 0.1.3
частного репозитория GitHub в /tmp
, вы должны сделать следующее:
GITHUB_OAUTH_TOKEN="your token"
fetch --repo="https://github.com/foo/bar" --tag="0.1.3" --release-asset="foo.exe" /tmp
Ответ 4
Я узнал ответ в этом комментарии: https://github.com/request/request/pull/1058#issuecomment-55285276
curl
пересылает заголовок аутентификации в запросе в ведро AmazonS3, где хранятся активы релиза Github.
Ошибка ответа от 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 <token>" -H "Accept:application/octet-stream" https://<token>:@api.github.com/repos/:owner/:repo/releases/assets/:id
, для получения более подробной информации. Добавьте -L
, чтобы увидеть сообщение об ошибке S3.
Ответ 5
Вот один "лайнер" с использованием 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>
) устанавливает токен GitHub OAuth, который используется последующими командами wget
.
- Второй оператор состоит из двух частей:
-
wget -O - https://api.github.com/repos/<owner>/<repo>/releases/tags/<tag>?access_token=$AUTH_TOKEN
часть получает информацию о выпуске GitHub из имени тега и выводит ее на стандартный вывод.
- Часть
python -c 'import sys, json; print json.load(sys.stdin)["assets"][0]["id"]'
анализирует JSON из stdin и извлекает 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)
) получает один единственный релиз-ресурс GitHub по id и сохраняет его в файле.
- Внешние круглые скобки создают подоболочку и гарантируют, что экспортированные переменные среды будут отброшены впоследствии.
Ответ 6
Вот 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
перейдите на 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'"
Ответ 7
Более простым рабочим решением является использование .netrc для хранения учетных данных. Таким образом, curl не переводит учетные данные в Buzz 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