Skip to content

Instantly share code, notes, and snippets.

@tomac4t
Last active January 17, 2023 01:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomac4t/16dc1e91d95c94f60251e586672b6314 to your computer and use it in GitHub Desktop.
Save tomac4t/16dc1e91d95c94f60251e586672b6314 to your computer and use it in GitHub Desktop.
A python script to upload the release assets via the GitHub Release API.
#!/usr/bin/python3
# A python script to upload the release assets via the GitHub Release API.
import mimetypes
import os
import requests
import sys
# Written for Github actions when release created event is triggered.
# It must set the env variables in the GitHub actions file:
# env:
# GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# GH_REPO: ${{ github.repository }}
# GH_REF: ${{ github.ref }}
# Or replace the variables by yourself.
GithubToken = os.environ["GH_TOKEN"]
GithubRepository = os.environ["GH_REPO"]
GithubRef = os.environ["GH_REF"]
GithubTagname = GithubRef.replace(u'refs/tags/','')
# List releases for a repository:
# https://developer.github.com/v3/repos/releases/#list-releases-for-a-repository
releasesAPI = "https://api.github.com/repos/" + GithubRepository + "/releases"
# The hardcoded path of assets, eg. "out/".
outputFilePath = "out/"
def get_uploadurl():
global uploadURL
print("Releases API: " + releasesAPI)
headers = {
'Authorization': 'token ' + GithubToken,
}
response = requests.get(releasesAPI, headers=headers)
print("API status code: " + str(response.status_code))
releases = response.json()
releasesLength = len(releases)
for i in range (0, releasesLength):
if releases[i]["tag_name"] == GithubTagname:
releasesNumber = i
break
try:
print("Found the target tagname, continue... " + str(releasesNumber))
# In case the tag was deleted before this python script running.
except Exception:
print("Can't found the target tagname, exit.")
sys.exit(1)
uploadURL = releases[releasesNumber]["upload_url"].split(u"{")[0]
print("Upload URL: " + uploadURL)
def upload_assets():
outputFiles = os.listdir(outputFilePath)
outputFilesNumber = len(outputFiles)
print("Assets: " + str(outputFiles) + "\nAssets number: " + str(outputFilesNumber))
ifFailure = False;
for i in range (0, outputFilesNumber):
filename = outputFiles[i]
print("Current asset: " + filename)
# Upload a release asset:
# https://developer.github.com/v3/repos/releases/#upload-a-release-asset
# `Content-Type` is required, use `mimetypes` to guess the file's mimetype.
mimetype = mimetypes.guess_type(outputFilePath + filename)[0]
# Use `application/octet-stream` for an unknown filetype.
if mimetype is None:
mimetype = "application/octet-stream"
print("Mimetype: " + mimetype)
headers = {
'Authorization': 'token ' + GithubToken,
'Content-Type': mimetype,
}
params = (('name', filename),)
data = open(outputFilePath + filename, 'rb').read();
response = requests.post(uploadURL, headers=headers, params=params, data=data)
# For debugging.
print("API status code: " + str(response.status_code))
#print("API response:\n" + str(response.text))
# Response for successful upload: 201 Created
# https://developer.github.com/v3/repos/releases/#response-for-successful-upload
if response.status_code == 201:
print("Asset download url: " + response.json()["browser_download_url"])
print(
"\033[1;32;40m["
+ str(i + 1)
+ "/"
+ str(outputFilesNumber)
+ "]"
+ filename
+ ": success. "
+ "\033[0m"
)
else:
print(
"\033[1;31;40m["
+ str(i + 1)
+ "/"
+ str(outputFilesNumber)
+ "]"
+ filename
+ ": fail. "
+ "\033[0m"
)
ifFailure = True
if ifFailure == True:
sys.exit(1)
elif ifFailure == False:
sys.exit(0)
if __name__ == '__main__':
get_uploadurl()
upload_assets()
@tomac4t
Copy link
Author

tomac4t commented Apr 18, 2020

An example Github workflow file:

name: release assets
on:
  release:
    types: [created]
jobs:
  debian-bullseye:
    runs-on: ubuntu-latest
    container: debian:bullseye
    env:
      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      GH_REPO: ${{ github.repository }}
      GH_REF: ${{ github.ref }}
    steps:
    - name: upgrade the packages
      run: apt-get update && apt-get upgrade -y && apt-get install -y git
    - uses: actions/checkout@v2
    - name: build
      run: .github/workflows/pack-debian.sh
    - name: upload the assets
      run: /usr/bin/python3 .github/workflows/release-assets-upload.py

@tomac4t
Copy link
Author

tomac4t commented Apr 21, 2020

Success output:

Releases API: https://api.github.com/repos/tomac4t/srain/releases
API status code: 200
Found the target tagname, continue... 0
Upload URL: https://uploads.github.com/repos/tomac4t/srain/releases/77458193/assets
Assets: ['srain_1.4.1-4_amd64.deb']
Assets number: 1
Current asset: srain_1.4.1-4_amd64.deb
Mimetype: application/vnd.debian.binary-package
API status code: 201
Asset download url: https://github.com/tomac4t/srain/releases/download/1.4.1-4/srain_1.4.1-4_amd64.deb
[1/1]srain_1.4.1-4_amd64.deb: success.

@chadulous
Copy link

Python doesn't need semicolons

@tomac4t
Copy link
Author

tomac4t commented Jul 4, 2021

@maverick-dev-55 Thanks, sorry for the late reply.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment