SW 개발

[git] github release api 사용 자동업로드 하기 (python 예제)

. . . 2020. 9. 17. 17:10
반응형

사용자 경험

다음의 경우를 위해서 github release page 를 사용하였다.

  • 내부에서 jenkins 자동화 빌드후, github release 페이지에 자동으로 업로드

사실은말이지...

외부업체에 보드이미지를 제공해야할일이 있었다. jenkins 뿐만아니라, 모든 사내서버가..내부 ip 로만구성되어있으며 보안정책상 포트등도 못뚫는 상황. 하지만.. 외부 업체에 이미지를 매번 보내야하는 이슈발생.

  • 매번 이미지를 압축하여 메일로 보낼것인가?
    • 난 이짓은 도저히 못하겠다.

그래서 github private 로 프로젝트를 만들고, 해당 릴리즈 페이지를 이용하기로 하였다. jenkins 자동화 빌드후에 이미지를 github private 로 자동 업로드 되도록 python 으로 구성하였다.

준비 : api key 발급받기

일단, web api 로 이미지를 업로드하기위해서 다음의 링크를 참고하여 github 의 api key 를 발급받는다.

python 예제소스

코드의 공통부분

각 함수에서 api 를 사용하기위한 다음의 내용을 상단에 코드를 작성 한다.

from pathlib import Path
import sys, os
import requests

import os.path
import pathlib
import json

GITHUB_API_TOKEN='your token'
OWNER='your name'
REPO='your target repo'

# -----------------------------------------
# Define variables.
# -----------------------------------------
GH_API='https://api.github.com'
GH_REPO='%s/repos/%s/%s'%(GH_API, OWNER, REPO)
  • GITHUB_API_TOKEN : 발급받은 토큰
  • OWNER : repo 소유자의 id
  • REPO : 올리고자 하는 target repo

release tag 만들기

일단, github release page 에 파일을 업로드하기 위해서는 해당 프로젝트의 release tag 를 찍어야한다.



def creat_relelase_info(tag_name, description) :
  GH_TAGS='%s/releases'%(GH_REPO)

  description = description.replace('\r', '')
  description = description.replace('\n', '\\n')

  params = (
      ('access_token', '%s'%(GITHUB_API_TOKEN)),
  )
  data = ''
  data += '{'
  data += '"target_commitish": "master",'
  data += '"draft": false,'
  data += '"prerelease": false, '
  data += '"tag_name": "%s",'%(tag_name)
  data += '"name": "%s",'%(tag_name)
  data += '"body" : "%s"'%(description)
  data += '}'

  response = requests.post('%s'%(GH_TAGS), params=params, data=data)

  if response.status_code != 201 :
      print(response.text)
      return False

  return True

위와 함수와같이 release tag 를 찍어준다.

  • tag_name : 만들 테그의 이름
  • description : 릴리즈 페이지의 상세 내용을 마크다운형식으로 넘긴다, 이때 멀티라인 스트링의 경우 \n 의 처리를 따로 해줘야 request 를 정상으로 할수있다.

타겟 release tag 에 파일업로드하기

creat_relelase_info() 를 이용하여 tag 를 만든후에 해당 타겟 tag 에 파일을 업로드한다.

def get_github_target_tag_hash_id(tag_name) : 
  GH_TAGS='%s/releases/tags/%s'%(GH_REPO, tag_name)

  headers = {
    'Authorization': 'token %s'%(GITHUB_API_TOKEN),
  }

  response = requests.get('%s'%(GH_TAGS), headers=headers)
  response = response.json()
  return response['id']


def upload_release_file(tag_name, target_file_pull_path) :
  path = Path(target_file_pull_path)
  taget_file_name = path.name

  # convert tag to id
  tag_name = get_github_target_tag_hash_id(tag_name)

  headers = {
      'Authorization': 'token %s'%(GITHUB_API_TOKEN),
      'Content-Type': 'application/octet-stream',
  }

  files = open(target_file_pull_path, 'rb')
  upload_files = {'file': files}

  GH_ASSET='https://uploads.github.com/repos/%s/%s/releases/%s/assets?name=%s'%(OWNER, REPO, tag_name, taget_file_name)

  response = requests.post(GH_ASSET, headers=headers, files=upload_files)

  if response.status_code != 200 :
      print(response.text)

특이사항은 https://uploads.github.com/repos 를 이용하여 github 에 파일을 업로드할때 tag 쪽 아규먼트는 tag 이름이 아니라 해당 tag 의 id 가 필요하다. get_github_target_tag_hash_id() 에서 tag 명을 tag id 를 얻어온후에, 파일업로드에 사용하도록한다.

full source code

그냥 위의 함수들을 다음과 같이 만들어서 사용한다.


from pathlib import Path
import sys, os
import requests

import os.path
import pathlib
import json

GITHUB_API_TOKEN='your token'
OWNER='your name'
REPO='your target repo'

# -----------------------------------------
# Define variables.
# -----------------------------------------
GH_API='https://api.github.com'
GH_REPO='%s/repos/%s/%s'%(GH_API, OWNER, REPO)

def creat_relelase_info(tag_name, description) :
  GH_TAGS='%s/releases'%(GH_REPO)

  description = description.replace('\r', '')
  description = description.replace('\n', '\\n')

  params = (
      ('access_token', '%s'%(GITHUB_API_TOKEN)),
  )
  data = ''
  data += '{'
  data += '"target_commitish": "master",'
  data += '"draft": false,'
  data += '"prerelease": false, '
  data += '"tag_name": "%s",'%(tag_name)
  data += '"name": "%s",'%(tag_name)
  data += '"body" : "%s"'%(description)
  data += '}'

  response = requests.post('%s'%(GH_TAGS), params=params, data=data)

  if response.status_code != 201 :
      print(response.text)
      return False

  return True

def get_github_target_tag_hash_id(tag_name) : 
  GH_TAGS='%s/releases/tags/%s'%(GH_REPO, tag_name)

  headers = {
    'Authorization': 'token %s'%(GITHUB_API_TOKEN),
  }

  response = requests.get('%s'%(GH_TAGS), headers=headers)
  response = response.json()
  return response['id']


def upload_release_file(tag_name, target_file_pull_path) :
  path = Path(target_file_pull_path)
  taget_file_name = path.name

  # convert tag to id
  tag_name = get_github_target_tag_hash_id(tag_name)

  headers = {
      'Authorization': 'token %s'%(GITHUB_API_TOKEN),
      'Content-Type': 'application/octet-stream',
  }

  files = open(target_file_pull_path, 'rb')
  upload_files = {'file': files}

  GH_ASSET='https://uploads.github.com/repos/%s/%s/releases/%s/assets?name=%s'%(OWNER, REPO, tag_name, taget_file_name)

  response = requests.post(GH_ASSET, headers=headers, files=upload_files)

  if response.status_code != 200 :
      print(response.text)



version_str='1.0'
upload_target='./uploadfile.zip'
release_msg='''
# this is test version

hello world
'''

creat_relelase_info('v.%s'%(version_str), release_msg)
upload_release_file('v.%s'%(version_str), upload_target)

잘되더라~

땡큐 github~

반응형