Browse Source

Release management using CircleCI (#3498)

* Release management using CircleCI

* Changelog updated
pull/3438/head
Greg Szabo 6 years ago
committed by Ismail Khoffi
parent
commit
9199f3f613
13 changed files with 578 additions and 9 deletions
  1. +126
    -2
      .circleci/config.yml
  2. +2
    -0
      CHANGELOG_PENDING.md
  3. +2
    -2
      DOCKER/Dockerfile
  4. +6
    -5
      Makefile
  5. +65
    -0
      scripts/release_management/README.md
  6. +37
    -0
      scripts/release_management/bump-semver.py
  7. +60
    -0
      scripts/release_management/github-draft.py
  8. +52
    -0
      scripts/release_management/github-openpr.py
  9. +28
    -0
      scripts/release_management/github-public-newbranch.bash
  10. +53
    -0
      scripts/release_management/github-publish.py
  11. +68
    -0
      scripts/release_management/github-upload.py
  12. +35
    -0
      scripts/release_management/sha-files.py
  13. +44
    -0
      scripts/release_management/zip-file.py

+ 126
- 2
.circleci/config.yml View File

@ -3,7 +3,7 @@ version: 2
defaults: &defaults
working_directory: /go/src/github.com/tendermint/tendermint
docker:
- image: circleci/golang:1.12.0
- image: circleci/golang
environment:
GOBIN: /tmp/workspace/bin
@ -14,6 +14,9 @@ docs_update_config: &docs_update_config
environment:
AWS_REGION: us-east-1
release_management_docker: &release_management_docker
machine: true
jobs:
setup_dependencies:
<<: *defaults
@ -192,7 +195,7 @@ jobs:
name: run localnet and exit on failure
command: |
set -x
docker run --rm -v "$PWD":/go/src/github.com/tendermint/tendermint -w /go/src/github.com/tendermint/tendermint golang:1.11.4 make build-linux
docker run --rm -v "$PWD":/go/src/github.com/tendermint/tendermint -w /go/src/github.com/tendermint/tendermint golang make build-linux
make localnet-start &
./scripts/localnet-blocks-test.sh 40 5 10 localhost
@ -256,6 +259,105 @@ jobs:
echo "Website build started"
fi
prepare_build:
<<: *defaults
steps:
- checkout
- run:
name: Get next release number
command: |
export LAST_TAG="`git describe --tags --abbrev=0 --match "${CIRCLE_BRANCH}.*"`"
echo "Last tag: ${LAST_TAG}"
if [ -z "${LAST_TAG}" ]; then
export LAST_TAG="${CIRCLE_BRANCH}"
echo "Last tag not found. Possibly fresh branch or feature branch. Setting ${LAST_TAG} as tag."
fi
export NEXT_TAG="`python -u scripts/release_management/bump-semver.py --version "${LAST_TAG}"`"
echo "Next tag: ${NEXT_TAG}"
echo "export CIRCLE_TAG=\"${NEXT_TAG}\"" > release-version.source
- run:
name: Build dependencies
command: |
make get_tools get_vendor_deps
- persist_to_workspace:
root: .
paths:
- "release-version.source"
- save_cache:
key: v1-release-deps-{{ .Branch }}-{{ .Revision }}
paths:
- "vendor"
build_artifacts:
<<: *defaults
parallelism: 4
steps:
- checkout
- restore_cache:
keys:
- v1-release-deps-{{ .Branch }}-{{ .Revision }}
- attach_workspace:
at: /tmp/workspace
- run:
name: Build artifact
command: |
# Setting CIRCLE_TAG because we do not tag the release ourselves.
source /tmp/workspace/release-version.source
if test ${CIRCLE_NODE_INDEX:-0} == 0 ;then export GOOS=linux GOARCH=amd64 && export OUTPUT=build/tendermint_${GOOS}_${GOARCH} && make build && python -u scripts/release_management/zip-file.py ;fi
if test ${CIRCLE_NODE_INDEX:-0} == 1 ;then export GOOS=darwin GOARCH=amd64 && export OUTPUT=build/tendermint_${GOOS}_${GOARCH} && make build && python -u scripts/release_management/zip-file.py ;fi
if test ${CIRCLE_NODE_INDEX:-0} == 2 ;then export GOOS=windows GOARCH=amd64 && export OUTPUT=build/tendermint_${GOOS}_${GOARCH} && make build && python -u scripts/release_management/zip-file.py ;fi
if test ${CIRCLE_NODE_INDEX:-0} == 3 ;then export GOOS=linux GOARCH=arm && export OUTPUT=build/tendermint_${GOOS}_${GOARCH} && make build && python -u scripts/release_management/zip-file.py ;fi
- persist_to_workspace:
root: build
paths:
- "*.zip"
- "tendermint_linux_amd64"
release_artifacts:
<<: *defaults
steps:
- checkout
- attach_workspace:
at: /tmp/workspace
- run:
name: Deploy to GitHub
command: |
# Setting CIRCLE_TAG because we do not tag the release ourselves.
source /tmp/workspace/release-version.source
echo "---"
ls -la /tmp/workspace/*.zip
echo "---"
python -u scripts/release_management/sha-files.py
echo "---"
cat /tmp/workspace/SHA256SUMS
echo "---"
export RELEASE_ID="`python -u scripts/release_management/github-draft.py`"
echo "Release ID: ${RELEASE_ID}"
#Todo: Parallelize uploads
export GOOS=linux GOARCH=amd64 && python -u scripts/release_management/github-upload.py --id "${RELEASE_ID}"
export GOOS=darwin GOARCH=amd64 && python -u scripts/release_management/github-upload.py --id "${RELEASE_ID}"
export GOOS=windows GOARCH=amd64 && python -u scripts/release_management/github-upload.py --id "${RELEASE_ID}"
export GOOS=linux GOARCH=arm && python -u scripts/release_management/github-upload.py --id "${RELEASE_ID}"
python -u scripts/release_management/github-upload.py --file "/tmp/workspace/SHA256SUMS" --id "${RELEASE_ID}"
python -u scripts/release_management/github-publish.py --id "${RELEASE_ID}"
release_docker:
<<: *release_management_docker
steps:
- checkout
- attach_workspace:
at: /tmp/workspace
- run:
name: Deploy to Docker Hub
command: |
# Setting CIRCLE_TAG because we do not tag the release ourselves.
source /tmp/workspace/release-version.source
cp /tmp/workspace/tendermint_linux_amd64 DOCKER/tendermint
docker build --label="tendermint" --tag="tendermint/tendermint:${CIRCLE_TAG}" --tag="tendermint/tendermint:latest" "DOCKER"
docker login -u "${DOCKERHUB_USER}" --password-stdin <<< "${DOCKERHUB_PASS}"
docker push "tendermint/tendermint"
docker logout
workflows:
version: 2
test-suite:
@ -292,3 +394,25 @@ workflows:
- upload_coverage:
requires:
- test_cover
release:
jobs:
- prepare_build
- build_artifacts:
requires:
- prepare_build
- release_artifacts:
requires:
- prepare_build
- build_artifacts
filters:
branches:
only:
- /v[0-9]+\.[0-9]+/
- release_docker:
requires:
- prepare_build
- build_artifacts
filters:
branches:
only:
- /v[0-9]+\.[0-9]+/

+ 2
- 0
CHANGELOG_PENDING.md View File

@ -18,4 +18,6 @@
### IMPROVEMENTS:
- [CircleCI] \#3497 Move release management to CircleCI
### BUG FIXES:

+ 2
- 2
DOCKER/Dockerfile View File

@ -1,5 +1,5 @@
FROM alpine:3.7
MAINTAINER Greg Szabo <greg@tendermint.com>
FROM alpine:3.9
LABEL maintainer="hello@tendermint.com"
# Tendermint will be looking for the genesis file in /tendermint/config/genesis.json
# (unless you change `genesis_file` in config.toml). You can put your config.toml and


+ 6
- 5
Makefile View File

@ -6,6 +6,7 @@ GOTOOLS = \
github.com/square/certstrap
GOBIN?=${GOPATH}/bin
PACKAGES=$(shell go list ./...)
OUTPUT?=build/tendermint
INCLUDE = -I=. -I=${GOPATH}/src -I=${GOPATH}/src/github.com/gogo/protobuf/protobuf
BUILD_TAGS?='tendermint'
@ -19,13 +20,13 @@ check: check_tools get_vendor_deps
### Build Tendermint
build:
CGO_ENABLED=0 go build $(BUILD_FLAGS) -tags $(BUILD_TAGS) -o build/tendermint ./cmd/tendermint/
CGO_ENABLED=0 go build $(BUILD_FLAGS) -tags $(BUILD_TAGS) -o $(OUTPUT) ./cmd/tendermint/
build_c:
CGO_ENABLED=1 go build $(BUILD_FLAGS) -tags "$(BUILD_TAGS) gcc" -o build/tendermint ./cmd/tendermint/
CGO_ENABLED=1 go build $(BUILD_FLAGS) -tags "$(BUILD_TAGS) gcc" -o $(OUTPUT) ./cmd/tendermint/
build_race:
CGO_ENABLED=0 go build -race $(BUILD_FLAGS) -tags $(BUILD_TAGS) -o build/tendermint ./cmd/tendermint
CGO_ENABLED=0 go build -race $(BUILD_FLAGS) -tags $(BUILD_TAGS) -o $(OUTPUT) ./cmd/tendermint
install:
CGO_ENABLED=0 go install $(BUILD_FLAGS) -tags $(BUILD_TAGS) ./cmd/tendermint
@ -109,7 +110,7 @@ draw_deps:
get_deps_bin_size:
@# Copy of build recipe with additional flags to perform binary size analysis
$(eval $(shell go build -work -a $(BUILD_FLAGS) -tags $(BUILD_TAGS) -o build/tendermint ./cmd/tendermint/ 2>&1))
$(eval $(shell go build -work -a $(BUILD_FLAGS) -tags $(BUILD_TAGS) -o $(OUTPUT) ./cmd/tendermint/ 2>&1))
@find $(WORK) -type f -name "*.a" | xargs -I{} du -hxs "{}" | sort -rh | sed -e s:${WORK}/::g > deps_bin_size.log
@echo "Results can be found here: $(CURDIR)/deps_bin_size.log"
@ -261,7 +262,7 @@ check_dep:
### Docker image
build-docker:
cp build/tendermint DOCKER/tendermint
cp $(OUTPUT) DOCKER/tendermint
docker build --label=tendermint --tag="tendermint/tendermint" DOCKER
rm -rf DOCKER/tendermint


+ 65
- 0
scripts/release_management/README.md View File

@ -0,0 +1,65 @@
# 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.

+ 37
- 0
scripts/release_management/bump-semver.py View File

@ -0,0 +1,37 @@
#!/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
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
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
print("{0}.{1}".format(majorminorprefix, patch))

+ 60
- 0
scripts/release_management/github-draft.py View File

@ -0,0 +1,60 @@
#!/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,version):
draft = {
'tag_name': version,
'target_commitish': 'master',
'name': '{0} (WARNING: ALPHA SOFTWARE)'.format(version),
'body': '<a href=https://github.com/{0}/{1}/blob/master/CHANGELOG.md#{2}>https://github.com/{0}/{1}/blob/master/CHANGELOG.md#{2}</a>'.format(org,repo,version.replace('v','').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("--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.version)
print(release["id"])

+ 52
- 0
scripts/release_management/github-openpr.py View File

@ -0,0 +1,52 @@
#!/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'])

+ 28
- 0
scripts/release_management/github-public-newbranch.bash View File

@ -0,0 +1,28 @@
#!/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:%.*}"

+ 53
- 0
scripts/release_management/github-publish.py View File

@ -0,0 +1,53 @@
#!/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'])

+ 68
- 0
scripts/release_management/github-upload.py View File

@ -0,0 +1,68 @@
#!/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'])

+ 35
- 0
scripts/release_management/sha-files.py View File

@ -0,0 +1,35 @@
#!/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))

+ 44
- 0
scripts/release_management/zip-file.py View File

@ -0,0 +1,44 @@
#!/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)

Loading…
Cancel
Save