Как скачать 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
команды. - Второе утверждение состоит из двух частей:
wget -O - https://api.github.com/repos/<owner>/<repo>/releases/tags/<tag>?access_token=$AUTH_TOKEN
part получает информацию о выпуске GitHub из имени тега и печатает его на стандартный вывод.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
, то
gh
CLI, а затем загрузите выпуск, как показано ниже. Также показано, как пройти аутентификацию с помощью личного токена в 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
Объяснение:
- Inner , используя ваш токен, извлекает метаданные с github.com, которые включают подписанный URL-адрес, содержащий фактический контент для получения.
- Метаданные анализируются для получения строки, которая начинается с
-
location:
префикс и окончание\r
суффикс удален, поэтому у нас остается только URL-адрес - Внешний
curl
извлекает ресурс, используя