Как выпустить актив артефакта сборки на GitHub с помощью скрипта? - PullRequest
27 голосов
/ 06 марта 2011

Я пытаюсь определить процесс с одной командой для создания сборки на GitHub.

То, что я ожидаю сделать, это запустить, скажем, какую-то команду-релиз релиза, и скрипт make release создаст артефакт релиза и затем каким-то образом загрузит его в GitHub.

Тем не менее, я не совсем понимаю, как получить артефакт релиза на GitHub. Исходный код потрясающий, но не каждый хочет делать свои собственные сборки. :-)

Ответы [ 7 ]

19 голосов
/ 06 марта 2011

Обновление сентября 2013 , вы можете автоматизировать выпуск ( API в режиме предварительного просмотра )

Обновление январь 2014 , есть неофициальное приложение командной строки, которое называется github-release от Николас Хиллиджер (aktau) , для создания выпусков и загрузки (двоичных) артефактов.
Он использует новый API Github Releases, упомянутый выше. Посмотрите на Makefile проекта, чтобы узнать, как еще автоматизировать его.

* * 1 022 Пример: * 1 023 *
# create a formal release
$ github-release release \
    --user aktau \
    --repo gofinance \
    --tag v0.1.0 \
    --name "the wolf of source street" \
    --description "Not a movie, contrary to popular opinion. Still, my first release!" \
    --pre-release

Этот API немного отличается из-за бинарных активов. Мы используем заголовок Accept для согласования содержимого при запросе ресурса релиза.
Передайте стандартный тип носителя API, чтобы получить представление API:

$ curl -i -H "Authorization: token TOKEN" \
     -H "Accept: application/vnd.github.manifold-preview" \
     "https://uploads.github.com/repos/hubot/singularity/releases/assets/123"

HTTP/1.1 200 OK

{
  "id": 123,
...
}

Передайте «application / octet-stream» для загрузки двоичного содержимого.

$ curl -i -H "Authorization: token TOKEN" \
     -H "Accept: application/octet-stream" \
     "https://uploads.github.com/repos/hubot/singularity/releases/assets/123"

HTTP/1.1 302 Found

Загрузка обрабатывается одним запросом к сопутствующей услуге «uploads.github.com».

$ curl -H "Authorization: token TOKEN" \
     -H "Accept: application/vnd.github.manifold-preview" \
     -H "Content-Type: application/zip" \
     --data-binary @build/mac/package.zip \
     "https://uploads.github.com/repos/hubot/singularity/releases/123/assets?name=1.0.0-mac.zip"

Обновление 2 июля 2013 г. , теперь вы можете определить выпуск .

release

  • Релизы сопровождаются примечаниями к выпуску и ссылками для загрузки программного обеспечения или исходного кода.
  • В соответствии с соглашениями многих проектов Git, релизы привязаны к тегам Git. Вы можете использовать существующий тег или разрешить релизам создавать тег при публикации.
  • Вы также можете присоединить двоичные ресурсы (например, скомпилированные исполняемые файлы, минимизированные сценарии, документацию) к выпуску . После публикации сведения о выпуске и ресурсы доступны любому, кто может просматривать репозиторий.

Это то, что заменяет старый бинарный сервис загрузки , который был удален в декабре 2012 года !


Сценарий make release создает артефакт выпуска и затем каким-то образом загружает его в github.

Это будет означать добавление его («оно» представляет собой доставку из одного или нескольких файлов, обычно включая двоичные файлы) к обычному локальному репо, а затем отправку этого репо в соответствующее репозиторий GitHub.

Тем не менее, причина, по которой GitHub не упоминается ни в одной из задач "релиза", заключается в том, что Git является исходной системой управления и не подходит для двоичных файлов.

Конечно, он может иметь эти файлы (двоичные файлы), но не предназначен для их регулярного использования из-за раздутого размера репо через некоторое время: каждое клонирование будет занимать все больше и больше времени.
См. Каковы ограничения Git , а также " git - должны ли исходные файлы и репозиторий находиться на одном компьютере? ".

8 голосов
/ 19 февраля 2014

Приготовление:

1) Загрузите github-release и поместите его исполняемый файл в ваш PATH.
2) Создайте токен на https://github.com/settings/applications#personal-access-tokens скажем, abc123

Загрузка артефакта:

1) Допустим, вы только что скомпилировали то, что решили назвать версией 3.1, и хотите загрузить его.
2) Убедитесь, что вы все совершили.
3) Запустите эти пять команд:

git tag v3.1
git push
git push --tags

github-release release --security-token abc123 --user <you> --repo <yourrepo> \
    --tag v3.1

github-release upload --security-token abc123 --user <you> --repo <yourrepo> \
    --tag v3.1 --name <thefile> --file <thefile>

Вы можете загрузить несколько файлов, например, для разных операционных систем.

(основываясь на ответе VonC, который, к сожалению, не описывает, как загрузить артефакт)

2 голосов
/ 10 июля 2012

Если вы используете Maven, вы можете добавить GitHub's Downloads Maven Plugin (https://github.com/github/maven-plugins/#downloads-plugin) и просто сделать:

$ mvn clean install ghDownloads:upload
1 голос

hub официальный инструмент GitHub CLI на основе Go

https://github.com/github/hub

Первая установка Go.В Ubuntu: https://askubuntu.com/questions/959932/installation-instructions-for-golang-1-9-into-ubuntu-16-04/1075726#1075726

Затем установите hub:

go get github.com/github/hub

Нет пакета Ubuntu: https://github.com/github/hub/issues/718

Затем из вашего репо:

hub release create -a prebuilt.zip -m 'release title' tag-name

Это:

  • запрашивает ваш пароль в первый раз, а затем автоматически создает и сохраняет токен API локально
  • создает неаннотированный тег на удаленномс именем tag-name
  • создает выпуск, связанный с этим тегом
  • загружает prebuilt.zip в виде вложения

Вы также можете предоставить свой существующий токен API с помощью GITHUB_TOKEN переменная окружения.

Для других операций release см .:

hub release --help

Проверено на hub de684cb613c47572cc9ec90d4fd73eef80aef09c .

Python APIv3 пример загрузкибез каких-либо внешних зависимостей

Использование:

GITHUB_TOKEN=<token> ./create-release username/reponame <tag-name> <path-to-upload>

Сценарий:

#!/usr/bin/env python3

import json
import os
import sys

from urllib.parse import urlencode
from urllib.request import Request, urlopen

repo = sys.argv[1]
tag = sys.argv[2]
upload_file = sys.argv[3]

token = os.environ['GITHUB_TOKEN']
url_template = 'https://{}.github.com/repos/' + repo + '/releases'

# Create.
_json = json.loads(urlopen(Request(
    url_template.format('api'),
    json.dumps({
        'tag_name': tag,
        'name': tag,
        'prerelease': True,
    }).encode(),
    headers={
        'Accept': 'application/vnd.github.v3+json',
        'Authorization': 'token ' + token,
    },
)).read().decode())
# This is not the tag, but rather some database integer identifier.
release_id = _json['id']

# Upload.
with open(upload_file, 'br') as myfile:
    content = myfile.read()
_json = json.loads(urlopen(Request(
    url_template.format('uploads') + '/' + str(release_id) + '/assets?' \
      + urlencode({'name': os.path.split(upload_file)[1]}),
    content,
    headers={
        'Accept': 'application/vnd.github.v3+json',
        'Authorization': 'token ' + token,
        'Content-Type': 'application/zip',
    },
)).read().decode())

И выпуск, и создание ресурса завершатся неудачно с 422, если они уже существуют.Обойти это, сначала удалив релиз или актив.Вот пример .

1 голос
/ 05 сентября 2012

У меня была такая же проблема, взломал маленький питон, чтобы сделать это для меня.Я должен сказать, что это было болью, s3 - полная чушь.

https://raw.github.com/reklis/utilityscripts/master/github-upload

#!/opt/local/bin/python2.7


import json
import requests
import sys
import argparse
import os
import mimetypes
import pycurl
import cStringIO
from xml.dom import minidom

github_api_root = "https://api.github.com/"

def parse_args():
    parser = argparse.ArgumentParser(description='post a file to github as a download')
    parser.add_argument('--user', dest='user', help='github username', required=True)
    parser.add_argument('--pass', dest='password', help='github password', required=True)
    parser.add_argument('--repo', dest='repo', help='the name of the github repo', required=True)
    parser.add_argument('--file', dest='filepath', help='path of the local file to upload', required=True)
    parser.add_argument('--desc', dest='description', help='descriptive text about this file', required=True)
    parser.add_argument('--owner', dest='owner', help='owner of the github repository', required=True)
    args = parser.parse_args()
    # print args
    return args

def make_dl_post_url(owner, repo):
    url = "%srepos/%s/%s/downloads" % (str(github_api_root), str(owner), str(repo))
    # print url
    return url

def make_dl_delete_url(owner, repo, dlid):
    url = "%srepos/%s/%s/downloads/%s" % (str(github_api_root), str(owner), str(repo), str(dlid))
    # print url
    return url

def add_github_reference(args):
    dl_post_url = make_dl_post_url(args.owner, args.repo)

    fp = args.filepath
    filename = os.path.basename(fp)
    filesize = os.path.getsize(fp)

    mtype, mdetails = mimetypes.guess_type(fp)

    file_description = {
        'name': filename,
        'size': filesize,
        'description': args.description,
        'content_type': mtype
    }
    # print json.dumps(file_description, indent=2)

    github = requests.post(dl_post_url, auth=(args.user, args.password), data=json.dumps(file_description))
    resp = github.json
    # print json.dumps(resp, indent=2)
    return resp

def remove_github_reference(args, dlid):
    dl_delete_url = make_dl_delete_url(args.owner, args.repo, dlid)

    github = requests.delete(dl_delete_url, auth=(args.user, args.password))
    delete_ok = (204 == github.status_code)
    return delete_ok

def post_file_to_s3(file_path, gh):
    # s3 is very particular with field ordering

    # curl \
    # -F "key=downloads/octocat/Hello-World/new_file.jpg" \
    # -F "acl=public-read" \
    # -F "success_action_status=201" \
    # -F "Filename=new_file.jpg" \
    # -F "AWSAccessKeyId=1ABCDEF..." \
    # -F "Policy=ewogIC..." \
    # -F "Signature=mwnF..." \
    # -F "Content-Type=image/jpeg" \
    # -F "file=@new_file.jpg" \
    # https://github.s3.amazonaws.com/

    s3_ok = 201
    xml_buffer = cStringIO.StringIO()

    try:
        post_fields = [
            ('key', str(gh['path'])),
            ('acl', str(gh['acl'])),
            ('success_action_status', str(s3_ok)),
            ('Filename', str(gh['name'])),
            ('AWSAccessKeyId', str(gh['accesskeyid'])),
            ('Policy', str(gh['policy'])),
            ('Signature', str(gh['signature'])),
            ('Content-Type', str(gh['mime_type'])),
          ('file', (pycurl.FORM_FILE, file_path))
        ]
        # print post_fields

        s3 = pycurl.Curl()
        s3.setopt(pycurl.SSL_VERIFYPEER, 0)   
        s3.setopt(pycurl.SSL_VERIFYHOST, 0)
        s3.setopt(pycurl.POST, 1)
        s3.setopt(pycurl.URL, str(gh['s3_url']))
        s3.setopt(pycurl.HTTPPOST, post_fields)
        # s3.setopt(pycurl.VERBOSE, 1)

        # accumulate string response
        s3.setopt(pycurl.WRITEFUNCTION, xml_buffer.write)

        s3.perform()

        file_upload_success = (s3_ok == s3.getinfo(pycurl.HTTP_CODE))
        xml_payload = minidom.parseString(xml_buffer.getvalue())

        if (file_upload_success):
            location_element = xml_payload.getElementsByTagName('Location')
            print location_element[0].firstChild.nodeValue
        else:
            print xml_payload.toprettyxml()


    except Exception, e:
        print e
        file_upload_success = False

    finally:
        s3.close()

    return file_upload_success


def main():
    mimetypes.init()
    args = parse_args()

    # step 1: tell github about the file
    gh = add_github_reference(args)

    # step 2: upload file to s3
    if ('errors' in gh):
        print json.dumps(gh, indent=2)
    else:
        file_upload_success = post_file_to_s3(args.filepath, gh)

        # cleanup if upload failed
        if (False == file_upload_success):
            removed_ok = remove_github_reference(args, gh['id'])
            if (removed_ok):
                print "removed github reference"
            else:
                print "failed to remove github reference"


if __name__ == '__main__':
    main()
1 голос
/ 21 июня 2012

Github имеет API для доступа к собственной системе загрузки файлов. Загрузки репо позволяют вам предоставлять двоичные файлы для пользователей - хотя могут быть ограничения по размеру и количеству. API обеспечивает доступ от автоматических агентов. Взгляни на: http://developer.github.com/v3/repos/downloads/ для информации об использовании.

Эта функция не очень часто используется, но, безусловно, работает. Вы можете перейти к любому репозиторию github, перейдите на вкладку «Загрузки», чтобы увидеть их.

Пример загружаемых файлов: http://github.com/dannystaple/emacs_cheat_sheets/downloads - предлагаемый там файл HTML на самом деле является встроенным артефактом, а не в источнике. Я пытаюсь найти лучший (бинарный) пример - но нет никаких причин, по которым нельзя предлагать исполняемые файлы, zips / tarballs и другие типы файлов.

Эти загрузки НЕ совпадают с исходными архивами для репо или его тегами. Любой произвольный файл может быть загружен таким образом.

0 голосов
/ 19 февраля 2016

Для тех, кто использует gradle, плагин gradle-github-plugin также позволяет создавать выпуски и прикреплять к ним файлы.

  1. Добавьте плагин к gradle.build:
plugins {
  id "co.riiid.gradle" version "X.Y.Z"
}
  1. Настройка загрузки. Пример:
github {
    owner = 'riiid'
    repo = 'gradle-github-plugin'
    token = 'XXXXXXXXXXXXXXXXXXXXX'
    tagName = '0.1.0'
    targetCommitish = 'master'
    name = 'v0.1.0'
    body = """# Project Name
Write `release note` here.
"""
    assets = [
            'app/build/outputs/apk/app-release.apk',
            'app/build/outputs/mapping/release/mapping.txt',
            'app/build/outputs',
            ...
    ]
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...