Как скачать GitHub Release из частного репозитория с помощью командной строки

Руководство GitHub объясняет 2 способа авторизации, но ни одна из них не работает с файлами Release.

как результат:

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

всегда есть что-то вроде

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

10 ответов

Чтобы загрузить файл релиза из частного репозитория, вы можете использовать токен личного доступа, который может быть сгенерирован в настройках / токенах с Полным контролем области личных репозиториев.

Затем загрузите ресурс с 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://stackru.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 '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 вместо.

Нам приходилось довольно часто загружать ресурсы релизов из частных репозиториев GitHub, поэтому мы создали fetch, который является кроссплатформенным инструментом с открытым исходным кодом, который позволяет легко загружать исходные файлы и освобождать ресурсы из тегов git, коммитов или открытых веток и частные репозитории 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

Используйте загрузку релиза gh, чтобы легко загружать скрипты. сначала gh authвойдите, чтобы авторизоваться.

Итак, чтобы скачать URL-адрес примеров https://github.com/company/repository/releases/download/TAG-NAME/A.tgz использовать:

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

Кажется, что оба метода аутентификации работают только для конечных точек API. Существует конечная точка API для загрузки ресурсов релиза ( документ):

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

Но для этого нужно знать числовой идентификатор актива. Я спросил их поддержку, могут ли они добавить конечную точку API для загрузки ресурсов релиза по имени (как они это делают для тарболлов).


Обновление: Ответ от поддержки Github:

Мы не предлагаем API, как вы предлагаете. Мы стараемся избегать хрупких URL-адресов, которые могли бы измениться при изменении тега или имени файла релиза. Я передам ваш отзыв команде для дальнейшего обсуждения.

Вот 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 перейдите на https://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'"

Я узнал ответ в этом комментарии: https://github.com/request/request/pull/1058

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.

Вот "одна строка", используя 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 команды.
  • Второе утверждение состоит из двух частей:
    1. wget -O - https://api.github.com/repos/<owner>/<repo>/releases/tags/<tag>?access_token=$AUTH_TOKEN part получает информацию о выпуске GitHub из имени тега и печатает его на стандартный вывод.
    2. python -c 'import sys, json; print json.load(sys.stdin)["assets"][0]["id"]' часть анализирует 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)) получает один актив GitHub Release по идентификатору и сохраняет его в файле.
  • Внешние скобки создают подоболочку и гарантируют, что экспортированные переменные среды впоследствии будут отброшены.

Более простое решение - использовать.netrc для хранения учетных данных. Таким образом, curl не передает учетные данные в Amazon S3 Bucket

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

Как и @dwayne, я решил это с помощью gh CLI, который вам также необходимо установить. Поскольку я был внутри контейнера докеров, мне нужно было установить curl, dirmngr, то ghCLI, а затем загрузите выпуск, как показано ниже. Также показано, как пройти аутентификацию с помощью личного токена в gh cli и распаковать файлы выпуска (в моем случае это архив).

      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

Однострочный способ сделать это, используя только завиток, где:

      # YOUR_TOKEN = your access token e.g. ghp_xxxxxxxxxxxxx
# YOUR_GITHUBCOM_URL = the portion of the URL that comes after https://github.com/ e.g. myuser/myrepo/assets/127345322/d0ad7915-a6a3-4aef-adf7-369c95e13316
# YOUR_DESTINATION = the location on your local drive to save the result to e.g. /tmp/x.png

curl "$(TOKEN=YOUR_TOKEN GITHUBCOM_URL=YOUR_GITHUBCOM_URL && curl -i -H "Authorization: token $TOKEN" https://github.com/$GITHUBCOM_URL | grep '^location: ' | sed 's/location: //' | tr -d '\r' )" > YOUR_DESTINATION

Протестировано на MacOS

Объяснение:

  1. Inner , используя ваш токен, извлекает метаданные с github.com, которые включают подписанный URL-адрес, содержащий фактический контент для получения.
  2. Метаданные анализируются для получения строки, которая начинается с
  3. location: префикс и окончание\rсуффикс удален, поэтому у нас остается только URL-адрес
  4. Внешнийcurlизвлекает ресурс, используя
Другие вопросы по тегам