Подтвердить что ты не робот

Как загрузить 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! ...

4b9b3361

Ответ 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