Co-authored-by: Erik Grinaker <erik@interchain.berlin> Co-authored-by: Alessio Treglia <alessio@tendermint.com>pull/5585/head
@ -0,0 +1,30 @@ | |||
name: "Release" | |||
on: | |||
push: | |||
tags: | |||
- "v[0-9]+.[0-9]+.[0-9]+" # Push events to matching v*, i.e. v1.0, v20.15.10 | |||
jobs: | |||
goreleaser: | |||
runs-on: ubuntu-latest | |||
steps: | |||
- name: Checkout | |||
uses: actions/checkout@v2 | |||
with: | |||
fetch-depth: 0 | |||
- name: Set up Go | |||
uses: actions/setup-go@v2 | |||
with: | |||
go-version: 1.15 | |||
- run: echo https://github.com/tendermint/tendermint/blob/${GITHUB_REF#refs/tags/}/CHANGELOG.md#${GITHUB_REF#refs/tags/} > ../release_notes.md | |||
- name: Run GoReleaser | |||
uses: goreleaser/goreleaser-action@v2 | |||
with: | |||
version: latest | |||
args: release --rm-dist --release-notes=../release_notes.md | |||
env: | |||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
@ -0,0 +1,27 @@ | |||
project_name: Tendermint | |||
env: | |||
# Require use of Go modules. | |||
- GO111MODULE=on | |||
builds: | |||
- id: "Tendermint" | |||
main: ./cmd/tendermint/main.go | |||
ldflags: | |||
- -s -w -X github.com/tendermint/tendermint/version.TMCoreSemVer={{ .Version }} | |||
env: | |||
- CGO_ENABLED=0 | |||
goos: | |||
- darwin | |||
- linux | |||
goarch: | |||
- amd64 | |||
- arm | |||
- arm64 | |||
checksum: | |||
name_template: SHA256SUMS-{{.Version}}.txt | |||
algorithm: sha256 | |||
release: | |||
name_template: "{{.Version}} (WARNING: BETA SOFTWARE)" |
@ -0,0 +1 @@ | |||
<!-- TODO: add in release notes prior to release. --> |
@ -1,20 +0,0 @@ | |||
#!/usr/bin/env bash | |||
set -e | |||
VERSION=$1 | |||
DIST_DIR=./build/dist | |||
# Get the version from the environment, or try to figure it out. | |||
if [ -z $VERSION ]; then | |||
VERSION=$(awk -F\" 'TMCoreSemVer =/ { print $2; exit }' < version/version.go) | |||
fi | |||
if [ -z "$VERSION" ]; then | |||
echo "Please specify a version." | |||
exit 1 | |||
fi | |||
echo "==> Copying ${DIST_DIR} to S3..." | |||
# copy to s3 | |||
aws s3 cp --recursive ${DIST_DIR} s3://tendermint/binaries/tendermint/v${VERSION} --acl public-read | |||
exit 0 |
@ -1,53 +0,0 @@ | |||
#!/usr/bin/env bash | |||
set -e | |||
# Get the version from the environment, or try to figure it out. | |||
if [ -z $VERSION ]; then | |||
VERSION=$(awk -F\" 'TMCoreSemVer =/ { print $2; exit }' < version/version.go) | |||
fi | |||
if [ -z "$VERSION" ]; then | |||
echo "Please specify a version." | |||
exit 1 | |||
fi | |||
echo "==> Releasing version $VERSION..." | |||
# Get the parent directory of where this script is. | |||
SOURCE="${BASH_SOURCE[0]}" | |||
while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done | |||
DIR="$( cd -P "$( dirname "$SOURCE" )/.." && pwd )" | |||
# Change into that dir because we expect that. | |||
cd "$DIR" | |||
# Building binaries | |||
sh -c "'$DIR/scripts/dist.sh'" | |||
# Pushing binaries to S3 | |||
sh -c "'$DIR/scripts/publish.sh'" | |||
# echo "==> Crafting a Github release" | |||
# today=$(date +"%B-%d-%Y") | |||
# ghr -b "https://github.com/tendermint/tendermint/blob/master/CHANGELOG.md#${VERSION//.}-${today,}" "v$VERSION" "$DIR/build/dist" | |||
# Build and push Docker image | |||
## Get SHA256SUM of the linux archive | |||
SHA256SUM=$(shasum -a256 "${DIR}/build/dist/tendermint_${VERSION}_linux_amd64.zip" | awk '{print $1;}') | |||
## Replace TM_VERSION and TM_SHA256SUM with the new values | |||
sed -i -e "s/TM_VERSION .*/TM_VERSION $VERSION/g" "$DIR/DOCKER/Dockerfile" | |||
sed -i -e "s/TM_SHA256SUM .*/TM_SHA256SUM $SHA256SUM/g" "$DIR/DOCKER/Dockerfile" | |||
git commit -m "update Dockerfile" -a "$DIR/DOCKER/Dockerfile" | |||
echo "==> TODO: update DOCKER/README.md (latest Dockerfile's hash is $(git rev-parse HEAD)) and copy it's content to https://store.docker.com/community/images/tendermint/tendermint" | |||
pushd "$DIR/DOCKER" | |||
## Build Docker image | |||
TAG=$VERSION sh -c "'./build.sh'" | |||
## Push Docker image | |||
TAG=$VERSION sh -c "'./push.sh'" | |||
popd | |||
exit 0 |
@ -1,64 +0,0 @@ | |||
# Release management scripts | |||
## Overview | |||
The scripts in this folder are used for release management in CircleCI. Although the scripts are fully configurable using input parameters, | |||
the default settings were modified to accommodate CircleCI execution. | |||
# Build scripts | |||
These scripts help during the build process. They prepare the release files. | |||
## bump-semver.py | |||
Bumps the semantic version of the input `--version`. Versions are expected in vMAJOR.MINOR.PATCH format or vMAJOR.MINOR format. | |||
In vMAJOR.MINOR format, the result will be patch version 0 of that version, for example `v1.2 -> v1.2.0`. | |||
In vMAJOR.MINOR.PATCH format, the result will be a bumped PATCH version, for example `v1.2.3 -> v1.2.4`. | |||
If the PATCH number contains letters, it is considered a development version, in which case, the result is the non-development version of that number. | |||
The patch number will not be bumped, only the "-dev" or similar additional text will be removed. For example: `v1.2.6-rc1 -> v1.2.6`. | |||
## zip-file.py | |||
Specialized ZIP command for release management. Special features: | |||
1. Uses Python ZIP libaries, so the `zip` command does not need to be installed. | |||
1. Can only zip one file. | |||
1. Optionally gets file version, Go OS and architecture. | |||
1. By default all inputs and output is formatted exactly how CircleCI needs it. | |||
By default, the command will try to ZIP the file at `build/tendermint_${GOOS}_${GOARCH}`. | |||
This can be changed with the `--file` input parameter. | |||
By default, the command will output the ZIP file to `build/tendermint_${CIRCLE_TAG}_${GOOS}_${GOARCH}.zip`. | |||
This can be changed with the `--destination` (folder), `--version`, `--goos` and `--goarch` input parameters respectively. | |||
## sha-files.py | |||
Specialized `shasum` command for release management. Special features: | |||
1. Reads all ZIP files in the given folder. | |||
1. By default all inputs and output is formatted exactly how CircleCI needs it. | |||
By default, the command will look up all ZIP files in the `build/` folder. | |||
By default, the command will output results into the `build/SHA256SUMS` file. | |||
# GitHub management | |||
Uploading build results to GitHub requires at least these steps: | |||
1. Create a new release on GitHub with content | |||
2. Upload all binaries to the release | |||
3. Publish the release | |||
The below scripts help with these steps. | |||
## github-draft.py | |||
Creates a GitHub release and fills the content with the CHANGELOG.md link. The version number can be changed by the `--version` parameter. | |||
By default, the command will use the tendermint/tendermint organization/repo, which can be changed using the `--org` and `--repo` parameters. | |||
By default, the command will get the version number from the `${CIRCLE_TAG}` variable. | |||
Returns the GitHub release ID. | |||
## github-upload.py | |||
Upload a file to a GitHub release. The release is defined by the mandatory `--id` (release ID) input parameter. | |||
By default, the command will upload the file `/tmp/workspace/tendermint_${CIRCLE_TAG}_${GOOS}_${GOARCH}.zip`. This can be changed by the `--file` input parameter. | |||
## github-publish.py | |||
Publish a GitHub release. The release is defined by the mandatory `--id` (release ID) input parameter. |
@ -1,62 +0,0 @@ | |||
#!/usr/bin/env python | |||
# Bump the release number of a semantic version number and print it. --version is required. | |||
# Version is | |||
# - vA.B.C, in which case vA.B.C+1 will be returned | |||
# - vA.B.C-devorwhatnot in which case vA.B.C will be returned | |||
# - vA.B in which case vA.B.0 will be returned | |||
import re | |||
import argparse | |||
import sys | |||
def semver(ver): | |||
if re.match('v[0-9]+\.[0-9]+',ver) is None: | |||
ver="v0.0" | |||
#raise argparse.ArgumentTypeError('--version must be a semantic version number with major, minor and patch numbers') | |||
return ver | |||
def get_tendermint_version(): | |||
"""Extracts the current Tendermint version from version/version.go""" | |||
pattern = re.compile(r"TMCoreSemVer = \"(?P<version>([0-9.]+)+)\"") | |||
with open("version/version.go", "rt") as version_file: | |||
for line in version_file: | |||
m = pattern.search(line) | |||
if m: | |||
return m.group('version') | |||
return None | |||
if __name__ == "__main__": | |||
parser = argparse.ArgumentParser() | |||
parser.add_argument("--version", help="Version number to bump, e.g.: v1.0.0", required=True, type=semver) | |||
args = parser.parse_args() | |||
found = re.match('(v[0-9]+\.[0-9]+)(\.(.+))?', args.version) | |||
majorminorprefix = found.group(1) | |||
patch = found.group(3) | |||
if patch is None: | |||
patch = "0-new" | |||
if re.match('[0-9]+$',patch) is None: | |||
patchfound = re.match('([0-9]+)',patch) | |||
patch = int(patchfound.group(1)) | |||
else: | |||
patch = int(patch) + 1 | |||
expected_version = "{0}.{1}".format(majorminorprefix, patch) | |||
# if we're doing a release | |||
if expected_version != "v0.0.0": | |||
cur_version = get_tendermint_version() | |||
if not cur_version: | |||
print("Failed to obtain Tendermint version from version/version.go") | |||
sys.exit(1) | |||
expected_version_noprefix = expected_version.lstrip("v") | |||
if expected_version_noprefix != "0.0.0" and expected_version_noprefix != cur_version: | |||
print("Expected version/version.go#TMCoreSemVer to be {0}, but was {1}".format(expected_version_noprefix, cur_version)) | |||
sys.exit(1) | |||
print(expected_version) |
@ -1,61 +0,0 @@ | |||
#!/usr/bin/env python | |||
# Create a draft release on GitHub. By default in the tendermint/tendermint repo. | |||
# Optimized for CircleCI | |||
import argparse | |||
import httplib | |||
import json | |||
import os | |||
from base64 import b64encode | |||
def request(org, repo, data): | |||
user_and_pass = b64encode(b"{0}:{1}".format(os.environ['GITHUB_USERNAME'], os.environ['GITHUB_TOKEN'])).decode("ascii") | |||
headers = { | |||
'User-Agent': 'tenderbot', | |||
'Accept': 'application/vnd.github.v3+json', | |||
'Authorization': 'Basic %s' % user_and_pass | |||
} | |||
conn = httplib.HTTPSConnection('api.github.com', timeout=5) | |||
conn.request('POST', '/repos/{0}/{1}/releases'.format(org,repo), data, headers) | |||
response = conn.getresponse() | |||
if response.status < 200 or response.status > 299: | |||
print("{0}: {1}".format(response.status, response.reason)) | |||
conn.close() | |||
raise IOError(response.reason) | |||
responsedata = response.read() | |||
conn.close() | |||
return json.loads(responsedata) | |||
def create_draft(org,repo,branch,version): | |||
draft = { | |||
'tag_name': version, | |||
'target_commitish': '{0}'.format(branch), | |||
'name': '{0} (WARNING: ALPHA SOFTWARE)'.format(version), | |||
'body': '<a href=https://github.com/{0}/{1}/blob/{2}/CHANGELOG.md#{3}>https://github.com/{0}/{1}/blob/{2}/CHANGELOG.md#{3}</a>'.format(org,repo,branch,version.replace('.','')), | |||
'draft': True, | |||
'prerelease': False | |||
} | |||
data=json.dumps(draft) | |||
return request(org, repo, data) | |||
if __name__ == "__main__": | |||
parser = argparse.ArgumentParser() | |||
parser.add_argument("--org", default="tendermint", help="GitHub organization") | |||
parser.add_argument("--repo", default="tendermint", help="GitHub repository") | |||
parser.add_argument("--branch", default=os.environ.get('CIRCLE_BRANCH'), help="Branch to build from, e.g.: v1.0") | |||
parser.add_argument("--version", default=os.environ.get('CIRCLE_TAG'), help="Version number for binary, e.g.: v1.0.0") | |||
args = parser.parse_args() | |||
if not os.environ.has_key('GITHUB_USERNAME'): | |||
raise parser.error('environment variable GITHUB_USERNAME is required') | |||
if not os.environ.has_key('GITHUB_TOKEN'): | |||
raise parser.error('environment variable GITHUB_TOKEN is required') | |||
release = create_draft(args.org,args.repo,args.branch,args.version) | |||
print(release["id"]) | |||
@ -1,52 +0,0 @@ | |||
#!/usr/bin/env python | |||
# Open a PR against the develop branch. --branch required. | |||
# Optimized for CircleCI | |||
import json | |||
import os | |||
import argparse | |||
import httplib | |||
from base64 import b64encode | |||
def request(org, repo, data): | |||
user_and_pass = b64encode(b"{0}:{1}".format(os.environ['GITHUB_USERNAME'], os.environ['GITHUB_TOKEN'])).decode("ascii") | |||
headers = { | |||
'User-Agent': 'tenderbot', | |||
'Accept': 'application/vnd.github.v3+json', | |||
'Authorization': 'Basic %s' % user_and_pass | |||
} | |||
conn = httplib.HTTPSConnection('api.github.com', timeout=5) | |||
conn.request('POST', '/repos/{0}/{1}/pulls'.format(org,repo), data, headers) | |||
response = conn.getresponse() | |||
if response.status < 200 or response.status > 299: | |||
print(response) | |||
conn.close() | |||
raise IOError(response.reason) | |||
responsedata = response.read() | |||
conn.close() | |||
return json.loads(responsedata) | |||
if __name__ == "__main__": | |||
parser = argparse.ArgumentParser() | |||
parser.add_argument("--org", default="tendermint", help="GitHub organization. Defaults to tendermint.") | |||
parser.add_argument("--repo", default="tendermint", help="GitHub repository. Defaults to tendermint.") | |||
parser.add_argument("--head", help="The name of the branch where your changes are implemented.", required=True) | |||
parser.add_argument("--base", help="The name of the branch you want the changes pulled into.", required=True) | |||
parser.add_argument("--title", default="Security release {0}".format(os.environ.get('CIRCLE_TAG')), help="The title of the pull request.") | |||
args = parser.parse_args() | |||
if not os.environ.has_key('GITHUB_USERNAME'): | |||
raise parser.error('GITHUB_USERNAME not set.') | |||
if not os.environ.has_key('GITHUB_TOKEN'): | |||
raise parser.error('GITHUB_TOKEN not set.') | |||
if os.environ.get('CIRCLE_TAG') is None: | |||
raise parser.error('CIRCLE_TAG not set.') | |||
result = request(args.org, args.repo, data=json.dumps({'title':"{0}".format(args.title),'head':"{0}".format(args.head),'base':"{0}".format(args.base),'body':"<Please fill in details.>"})) | |||
print(result['html_url']) |
@ -1,28 +0,0 @@ | |||
#!/bin/sh | |||
# github-public-newbranch.bash - create public branch from the security repository | |||
set -euo pipefail | |||
# Create new branch | |||
BRANCH="${CIRCLE_TAG:-v0.0.0}-security-`date -u +%Y%m%d%H%M%S`" | |||
# Check if the patch release exist already as a branch | |||
if [ -n "`git branch | grep '${BRANCH}'`" ]; then | |||
echo "WARNING: Branch ${BRANCH} already exists." | |||
else | |||
echo "Creating branch ${BRANCH}." | |||
git branch "${BRANCH}" | |||
fi | |||
# ... and check it out | |||
git checkout "${BRANCH}" | |||
# Add entry to public repository | |||
git remote add tendermint-origin git@github.com:tendermint/tendermint.git | |||
# Push branch and tag to public repository | |||
git push tendermint-origin | |||
git push tendermint-origin --tags | |||
# Create a PR from the public branch to the assumed release branch in public (release branch has to exist) | |||
python -u scripts/release_management/github-openpr.py --head "${BRANCH}" --base "${BRANCH:%.*}" |
@ -1,53 +0,0 @@ | |||
#!/usr/bin/env python | |||
# Publish an existing GitHub draft release. --id required. | |||
# Optimized for CircleCI | |||
import json | |||
import os | |||
import argparse | |||
import httplib | |||
from base64 import b64encode | |||
def request(org, repo, id, data): | |||
user_and_pass = b64encode(b"{0}:{1}".format(os.environ['GITHUB_USERNAME'], os.environ['GITHUB_TOKEN'])).decode("ascii") | |||
headers = { | |||
'User-Agent': 'tenderbot', | |||
'Accept': 'application/vnd.github.v3+json', | |||
'Authorization': 'Basic %s' % user_and_pass | |||
} | |||
conn = httplib.HTTPSConnection('api.github.com', timeout=5) | |||
conn.request('POST', '/repos/{0}/{1}/releases/{2}'.format(org,repo,id), data, headers) | |||
response = conn.getresponse() | |||
if response.status < 200 or response.status > 299: | |||
print(response) | |||
conn.close() | |||
raise IOError(response.reason) | |||
responsedata = response.read() | |||
conn.close() | |||
return json.loads(responsedata) | |||
if __name__ == "__main__": | |||
parser = argparse.ArgumentParser() | |||
parser.add_argument("--org", default="tendermint", help="GitHub organization") | |||
parser.add_argument("--repo", default="tendermint", help="GitHub repository") | |||
parser.add_argument("--id", help="GitHub release ID", required=True, type=int) | |||
parser.add_argument("--version", default=os.environ.get('CIRCLE_TAG'), help="Version number for the release, e.g.: v1.0.0") | |||
args = parser.parse_args() | |||
if not os.environ.has_key('GITHUB_USERNAME'): | |||
raise parser.error('GITHUB_USERNAME not set.') | |||
if not os.environ.has_key('GITHUB_TOKEN'): | |||
raise parser.error('GITHUB_TOKEN not set.') | |||
try: | |||
result = request(args.org, args.repo, args.id, data=json.dumps({'draft':False,'tag_name':"{0}".format(args.version)})) | |||
except IOError as e: | |||
print(e) | |||
result = request(args.org, args.repo, args.id, data=json.dumps({'draft':False,'tag_name':"{0}-autorelease".format(args.version)})) | |||
print(result['name']) |
@ -1,68 +0,0 @@ | |||
#!/usr/bin/env python | |||
# Upload a file to a GitHub draft release. --id and --file are required. | |||
# Optimized for CircleCI | |||
import json | |||
import os | |||
import re | |||
import argparse | |||
import mimetypes | |||
import httplib | |||
from base64 import b64encode | |||
def request(baseurl, path, mimetype, mimeencoding, data): | |||
user_and_pass = b64encode(b"{0}:{1}".format(os.environ['GITHUB_USERNAME'], os.environ['GITHUB_TOKEN'])).decode("ascii") | |||
headers = { | |||
'User-Agent': 'tenderbot', | |||
'Accept': 'application/vnd.github.v3.raw+json', | |||
'Authorization': 'Basic %s' % user_and_pass, | |||
'Content-Type': mimetype, | |||
'Content-Encoding': mimeencoding | |||
} | |||
conn = httplib.HTTPSConnection(baseurl, timeout=5) | |||
conn.request('POST', path, data, headers) | |||
response = conn.getresponse() | |||
if response.status < 200 or response.status > 299: | |||
print(response) | |||
conn.close() | |||
raise IOError(response.reason) | |||
responsedata = response.read() | |||
conn.close() | |||
return json.loads(responsedata) | |||
if __name__ == "__main__": | |||
parser = argparse.ArgumentParser() | |||
parser.add_argument("--id", help="GitHub release ID", required=True, type=int) | |||
parser.add_argument("--file", default="/tmp/workspace/tendermint_{0}_{1}_{2}.zip".format(os.environ.get('CIRCLE_TAG'),os.environ.get('GOOS'),os.environ.get('GOARCH')), help="File to upload") | |||
parser.add_argument("--return-id-only", help="Return only the release ID after upload to GitHub.", action='store_true') | |||
args = parser.parse_args() | |||
if not os.environ.has_key('GITHUB_USERNAME'): | |||
raise parser.error('GITHUB_USERNAME not set.') | |||
if not os.environ.has_key('GITHUB_TOKEN'): | |||
raise parser.error('GITHUB_TOKEN not set.') | |||
mimetypes.init() | |||
filename = os.path.basename(args.file) | |||
mimetype,mimeencoding = mimetypes.guess_type(filename, strict=False) | |||
if mimetype is None: | |||
mimetype = 'application/zip' | |||
if mimeencoding is None: | |||
mimeencoding = 'utf8' | |||
with open(args.file,'rb') as f: | |||
asset = f.read() | |||
result = request('uploads.github.com', '/repos/tendermint/tendermint/releases/{0}/assets?name={1}'.format(args.id, filename), mimetype, mimeencoding, asset) | |||
if args.return_id_only: | |||
print(result['id']) | |||
else: | |||
print(result['browser_download_url']) | |||
@ -1,35 +0,0 @@ | |||
#!/usr/bin/env python | |||
# Create SHA256 summaries from all ZIP files in a folder | |||
# Optimized for CircleCI | |||
import re | |||
import os | |||
import argparse | |||
import zipfile | |||
import hashlib | |||
BLOCKSIZE = 65536 | |||
if __name__ == "__main__": | |||
parser = argparse.ArgumentParser() | |||
parser.add_argument("--folder", default="/tmp/workspace", help="Folder to look for, for ZIP files") | |||
parser.add_argument("--shafile", default="/tmp/workspace/SHA256SUMS", help="SHA256 summaries File") | |||
args = parser.parse_args() | |||
for filename in os.listdir(args.folder): | |||
if re.search('\.zip$',filename) is None: | |||
continue | |||
if not os.path.isfile(os.path.join(args.folder, filename)): | |||
continue | |||
with open(args.shafile,'a+') as shafile: | |||
hasher = hashlib.sha256() | |||
with open(os.path.join(args.folder, filename),'r') as f: | |||
buf = f.read(BLOCKSIZE) | |||
while len(buf) > 0: | |||
hasher.update(buf) | |||
buf = f.read(BLOCKSIZE) | |||
shafile.write("{0} {1}\n".format(hasher.hexdigest(),filename)) | |||
@ -1,44 +0,0 @@ | |||
#!/usr/bin/env python | |||
# ZIP one file as "tendermint" into a ZIP like tendermint_VERSION_OS_ARCH.zip | |||
# Use environment variables CIRCLE_TAG, GOOS and GOARCH for easy input parameters. | |||
# Optimized for CircleCI | |||
import os | |||
import argparse | |||
import zipfile | |||
import hashlib | |||
BLOCKSIZE = 65536 | |||
def zip_asset(file,destination,arcname,version,goos,goarch): | |||
filename = os.path.basename(file) | |||
output = "{0}/{1}_{2}_{3}_{4}.zip".format(destination,arcname,version,goos,goarch) | |||
with zipfile.ZipFile(output,'w') as f: | |||
f.write(filename=file,arcname=arcname) | |||
f.comment=filename | |||
return output | |||
if __name__ == "__main__": | |||
parser = argparse.ArgumentParser() | |||
parser.add_argument("--file", default="build/tendermint_{0}_{1}".format(os.environ.get('GOOS'),os.environ.get('GOARCH')), help="File to zip") | |||
parser.add_argument("--destination", default="build", help="Destination folder for files") | |||
parser.add_argument("--version", default=os.environ.get('CIRCLE_TAG'), help="Version number for binary, e.g.: v1.0.0") | |||
parser.add_argument("--goos", default=os.environ.get('GOOS'), help="GOOS parameter") | |||
parser.add_argument("--goarch", default=os.environ.get('GOARCH'), help="GOARCH parameter") | |||
args = parser.parse_args() | |||
if args.version is None: | |||
raise parser.error("argument --version is required") | |||
if args.goos is None: | |||
raise parser.error("argument --goos is required") | |||
if args.goarch is None: | |||
raise parser.error("argument --goarch is required") | |||
file = zip_asset(args.file,args.destination,"tendermint",args.version,args.goos,args.goarch) | |||
print(file) | |||