2011-03-05 34 views
16

我想弄清楚在github上生成构建的一个命令过程。在github上发布构建工件

我想要做的是运行某种命令发布版本,并且make release脚本构建发布工件,然后以某种方式将其上传到github。

但是,我对如何在github上实际获得发行工件感到困惑。源代码很棒,但不是每个人都想做自己的构建。 :-)

+0

看一看GitHub的新 “版本” 功能:看我的[编辑答案如下(http://stackoverflow.com/a/5207352/6309)。 – VonC

+0

@VonC:已更新。谢谢。 –

回答

15

Update September 2013,你可以自动释放API in preview mode

Update January 2014,有一个非官方的命令行应用程序,叫做github-release通过Nicolas Hillegeer (aktau),用于创建发布和上传(二进制)文物。
它使用上面提到的新的github发布API。看项目的Makefile,看看如何更自动化它。

实施例:

# 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, 
... 
} 

通“应用程序/八位字节流”下载的二进制内容。

$ 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" 

Update 2d July 2013,你现在可以定义释放

release

  • 发布都伴随着发行说明和链接,下载该软件或源代码。
  • 遵循许多Git项目的约定,发布与Git标签绑定。您可以使用现有标签,也可以让版本在发布时创建标签。
  • 您还可以将二进制资源(如编译的可执行文件,缩小的脚本,文档)附加到版本。一旦发布,任何可以查看存储库的人都可以获得发布细节和资产。

这是什么取代old binary upload service,这是removed in December 2012


化妆释放脚本积聚释放神器,然后上传它以某种方式github上。

这将意味着增加它(“它”正在传送由一个或多个文件,大致包括:二进制文件)到正规的本地回购,然后推动该回购其匹配GitHub库。

这就是说,GitHub没有在任何“发布”任务中提及的原因是因为Git是一个源代码控制管理系统,并且不适合二进制文件。

它当然可以有这些文件(二进制文件),但由于一段时间后回购数据的臃肿大小,它们并没有定期生成它们:每次克隆需要的时间越来越长。
What are the Git limits,还有“git - should source files and repository be on the same machine ?”。

+0

嗯。这是一个痛苦。我想在那里有一个滚动的“当前构建”。 (我也希望能够获得构建的点数发布)。 –

+1

@Paul:但是VCS并不是你想要发布的版本(有点像http://stackoverflow.com/questions/3863964/tracking-deployed-applications-files/3864134#3864134)。像Nexus这样的工件存储库更合适,如http://stackoverflow.com/questions/4983060/should-generated-documentation-go-into-source-control/4983530#4983530或http://stackoverflow.com/questions/4968745/many-binary-files-synchronization/4968834#4968834 – VonC

+0

我认为GitHub有一个文件上传机制(下载)可以与一个项目一起使用。有没有办法使这个脚本? –

0

我会建议使用一个附带的开源托管站点,并将文件放在那里。

我更喜欢这个 - http://www.cloudbees.com/foss/foss-dev.cb - 你得到一个jenkins设置来建立你的项目,测试你的项目,然后可以分发这些存档的工件。

这样,所有的bug报告/讨论/ wiki可以保存在github上。

1

Github上有一个API来访问他们自己的文件下载系统。 通过Repo下载,您可以为用户提供二进制文件 - 尽管可能会限制大小和数量。该API允许从自动代理进行访问。 看看: http://developer.github.com/v3/repos/downloads/的使用信息。

该功能没有多大用处,但绝对有效。你可以去任何github回购,点击“下载”标签来查看它们。

有关可下载文件的示例: http://github.com/dannystaple/emacs_cheat_sheets/downloads - 提供的HTML文件实际上是一个内置的制造品,而不是源代码。我正在尝试创建一个更好的(二进制)示例 - 但没有理由不能提供可执行文件,zip文件/ tarball文件和其他文件类型。

这些下载与repo或其代码的源代码tarball不同。任何任意文件都可以通过这种方式上传。

1

我有同样的问题,设计了一个简单的小蟒蛇做到这一点对我来说。我必须说这是一个痛苦,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 "[email protected]_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() 
5

准备:

1)下载github-releases,并把其可执行文件路径中。
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的答案,不幸的是没有详细说明如何上传一个神器)

+0

好的除了我的答案。 +1 – VonC

0

对于使用这些的gradle,该插件还gradle-github-plugin允许创建发布和附加文件给他们。

  1. 插件添加到gradle.build
plugins { 
    id "co.riiid.gradle" version "X.Y.Z" 
} 
  • 配置的上载。例如:
  • 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', 
          ... 
        ] 
    }