diff options
author | Brian Olson <brian.olson@algorand.com> | 2019-06-11 09:26:39 -0400 |
---|---|---|
committer | Brian Olson <brian.olson@algorand.com> | 2019-06-11 09:26:39 -0400 |
commit | ef889726afc4da12d161bfb6936edbe97777f58c (patch) | |
tree | 06181a6a6db9fa9812ffd533592f77e38d214fdb | |
parent | a9c28959fbd4e4bd3e2d8c4fa37152d01fdf4274 (diff) |
new release build processorigin/bolson/goal2-638-release-build
-rw-r--r-- | .travis.yml | 4 | ||||
-rwxr-xr-x | scripts/build/stable.sh | 6 | ||||
-rwxr-xr-x | scripts/build_deb.sh | 7 | ||||
-rwxr-xr-x | scripts/build_package.sh | 9 | ||||
-rwxr-xr-x | scripts/build_packages.sh | 23 | ||||
-rwxr-xr-x | scripts/build_release.sh | 149 | ||||
-rw-r--r-- | scripts/build_release_centos_docker.sh | 42 | ||||
-rw-r--r-- | scripts/build_release_local.sh | 77 | ||||
-rw-r--r-- | scripts/build_release_setup.sh | 123 | ||||
-rwxr-xr-x | scripts/build_rpm.sh | 7 | ||||
-rw-r--r-- | scripts/centos-build.Dockerfile | 6 | ||||
-rwxr-xr-x | scripts/get_latest_go.py | 91 | ||||
-rwxr-xr-x | scripts/release_deb.sh | 79 | ||||
-rwxr-xr-x | scripts/reverse_hex_timestamp | 6 |
14 files changed, 606 insertions, 23 deletions
diff --git a/.travis.yml b/.travis.yml index 77526206a..6baae5b47 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,9 +16,9 @@ stages: - name: build_release if: branch =~ /^rel\// AND type != pull_request - name: deploy - if: branch =~ /^rel\// AND type != pull_request + if: branch =~ /^rel\/nightly/ AND type != pull_request - name: release - if: branch =~ /^rel\// AND type != pull_request + if: branch =~ /^rel\/nightly/ AND type != pull_request jobs: include: diff --git a/scripts/build/stable.sh b/scripts/build/stable.sh index 1e8923895..e4ad652bd 100755 --- a/scripts/build/stable.sh +++ b/scripts/build/stable.sh @@ -39,5 +39,9 @@ git commit -m "Build ${BUILD_NUMBER}" git push TAG=rel/stable-$(scripts/compute_build_number.sh -f) -git tag -a ${TAG} -m "Genesis Timestamp: $(cat ./genesistimestamp.dat)" +if [ ! -z "${SIGNING_KEY_ADDR}" ]; then + git tag -s -u "${SIGNING_KEY_ADDR}" ${TAG} -m "Genesis Timestamp: $(cat ./genesistimestamp.dat)" +else + git tag -a ${TAG} -m "Genesis Timestamp: $(cat ./genesistimestamp.dat)" +fi git push origin ${TAG} diff --git a/scripts/build_deb.sh b/scripts/build_deb.sh index 6d4116cd5..7c743d0ce 100755 --- a/scripts/build_deb.sh +++ b/scripts/build_deb.sh @@ -27,7 +27,12 @@ cd ${REPO_DIR} echo "Building debian package for '${OS} - ${ARCH}'" -env GOOS=${OS} GOARCH=${ARCH} scripts/build_prod.sh +if [ -z "${NO_BUILD}" ]; then + env GOOS=${OS} GOARCH=${ARCH} scripts/build_prod.sh +else + echo "already built" + true +fi VER=$(./scripts/compute_build_number.sh -f) diff --git a/scripts/build_package.sh b/scripts/build_package.sh index fe5bfd7f9..e5cd02e8a 100755 --- a/scripts/build_package.sh +++ b/scripts/build_package.sh @@ -21,6 +21,8 @@ if [ ! "$#" -eq 3 ]; then exit 1 fi +set -x + OS=$1 ARCH=$2 PKG_ROOT=$3 @@ -36,7 +38,12 @@ cd ${REPO_DIR} echo "Building package for '${OS} - ${ARCH}'" -env GOOS=${OS} GOARCH=${ARCH} scripts/build_prod.sh +if [ -z "${NO_BUILD}" ]; then + env GOOS=${OS} GOARCH=${ARCH} scripts/build_prod.sh +else + echo "already built" + true +fi if [ $? -ne 0 ]; then echo 'Error building! Aborting...' diff --git a/scripts/build_packages.sh b/scripts/build_packages.sh index 0ec9c89de..adac93ab0 100755 --- a/scripts/build_packages.sh +++ b/scripts/build_packages.sh @@ -19,6 +19,8 @@ if [ "$#" -eq 0 ]; then exit 1 fi +set -x + export GOPATH=$(go env GOPATH) cd ${GOPATH}/src/github.com/algorand/go-algorand @@ -47,9 +49,9 @@ export TIMESTAMP=${TIMESTAMP} # To ensure deterministic availability of testnet (stable) builds, prefix the packages # with "pending_" so updater will not detect the package before we rename it. GATE_PREFIX="" -if [[ "${CHANNEL}" = "stable" || "${CHANNEL}" = "nightly" ]]; then - GATE_PREFIX="pending_" -fi +# if [[ "${CHANNEL}" = "stable" || "${CHANNEL}" = "nightly" ]]; then +# GATE_PREFIX="pending_" +# fi VERSION_COMPONENTS=(${FULLVERSION//\./ }) export BUILDNUMBER=${VERSION_COMPONENTS[2]} @@ -126,17 +128,7 @@ for var in "${VARIATION_ARRAY[@]}"; do exit 1 fi pushd ${DEBTMP} - tar -zcf ${PKG_ROOT}/${GATE_PREFIX}deb_${CHANNEL}_${PKG_NAME}_${FULLVERSION}.tar.gz *.deb >/dev/null 2>&1 - popd - fi - - # If Linux package, build RPM package as well - if [ $(scripts/ostype.sh) = "linux" ]; then - RPMTMP=$(mktemp -d 2>/dev/null || mktemp -d -t "rpmtmp") - trap "rm -rf ${RPMTMP}" 0 - scripts/build_rpm.sh ${RPMTMP} - pushd ${RPMTMP} - tar -zcf ${PKG_ROOT}/${GATE_PREFIX}rpm_${CHANNEL}_${PKG_NAME}_${FULLVERSION}.tar.gz */*.rpm >/dev/null 2>&1 + cp -p *.deb ${PKG_ROOT}/${GATE_PREFIX}algorand_${CHANNEL}_${PKG_NAME}_${FULLVERSION}.deb popd fi @@ -146,9 +138,6 @@ for var in "${VARIATION_ARRAY[@]}"; do cp ${PKG_ROOT}/${GATE_PREFIX}node_${CHANNEL}_${PKG_NAME}_${FULLVERSION}.tar.gz ${PKG_ROOT}/${GATE_PREFIX}node_${CHANNEL}-telem_${PKG_NAME}_${FULLVERSION}.tar.gz cp ${PKG_ROOT}/${GATE_PREFIX}install_${CHANNEL}_${PKG_NAME}_${FULLVERSION}.tar.gz ${PKG_ROOT}/${GATE_PREFIX}install_${CHANNEL}-telem_${PKG_NAME}_${FULLVERSION}.tar.gz cp ${PKG_ROOT}/${GATE_PREFIX}tools_${CHANNEL}_${PKG_NAME}_${FULLVERSION}.tar.gz ${PKG_ROOT}/${GATE_PREFIX}tools_${CHANNEL}-telem_${PKG_NAME}_${FULLVERSION}.tar.gz - if [ $(scripts/ostype.sh) = "linux" ]; then - cp ${PKG_ROOT}/${GATE_PREFIX}deb_${CHANNEL}_${PKG_NAME}_${FULLVERSION}.tar.gz ${PKG_ROOT}/${GATE_PREFIX}deb_${CHANNEL}-telem_${PKG_NAME}_${FULLVERSION}.tar.gz - fi fi done done diff --git a/scripts/build_release.sh b/scripts/build_release.sh new file mode 100755 index 000000000..967cb5d35 --- /dev/null +++ b/scripts/build_release.sh @@ -0,0 +1,149 @@ +#!/bin/bash +# +# This script needs to be run in a terminal with a human watching to +# be prompted for GPG key password at a couple points. +# +# Externally settable env vars: +# S3_PREFIX= where to upload build artifacts +# AWS_EFS_MOUNT= NFS to mount for `aptly` persistent state and scratch storage +# SIGNING_KEY_ADDR= dev@algorand.com or similar for GPG key +# RSTAMP= `scripts/reverse_hex_timestamp` +# AWS_ACCESS_KEY_ID= +# AWS_SECRET_ACCESS_KEY= + +date "+build_release start %Y%m%d_%H%M%S" + +set -e +set -x + +if [ -z "${S3_PREFIX}" ]; then + S3_PREFIX=s3://algorand-builds +fi + +# persistent storage of repo manager scratch space is on EFS +if [ ! -z "${AWS_EFS_MOUNT}" ]; then + if mount|grep -q /data; then + echo /data already mounted + else + sudo mkdir -p /data + sudo mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport "${AWS_EFS_MOUNT}":/ /data + # make environment for release_deb.sh + sudo mkdir -p /data/_aptly + sudo chown -R ${USER} /data/_aptly + export APTLY_DIR=/data/_aptly + fi +fi + +export GOPATH=${HOME}/go +export PATH=${HOME}/gpgbin:${GOPATH}/bin:/usr/local/go/bin:${PATH} + +cd ${GOPATH}/src/github.com/algorand/go-algorand +export RELEASE_GENESIS_PROCESS=true +export TRANSITION_TELEMETRY_BUILDS=true +PLATFORM=$(./scripts/osarchtype.sh) +PLATFORM_SPLIT=(${PLATFORM//\// }) +OS=${PLATFORM_SPLIT[0]} +ARCH=${PLATFORM_SPLIT[1]} +export BRANCH=rel/stable +export CHANNEL=$(./scripts/compute_branch_channel.sh ${BRANCH}) +export PKG_ROOT=${HOME}/node_pkg +export VARIATIONS="base" +# tell underlying 'build' scripts we already built +export NO_BUILD=true +if [ -z "${RSTAMP}" ]; then + RSTAMP=$(scripts/reverse_hex_timestamp) +fi + +# Update version file for this build +BUILD_NUMBER= +if [ -e buildnumber.dat ]; then + BUILD_NUMBER=$(cat ./buildnumber.dat) +else + BUILD_NUMBER=0 +fi +BUILD_NUMBER=$((${BUILD_NUMBER} + 1)) +echo ${BUILD_NUMBER} > ./buildnumber.dat +export FULLVERSION=$(./scripts/compute_build_number.sh -f) + + +# Build! +scripts/configure_dev.sh + +make ${GOPATH}/src/github.com/algorand/go-algorand/crypto/lib/libsodium.a + +make build + +scripts/build_packages.sh "${PLATFORM}" + +# Tag Source +git add -A +git commit -m "Build ${BUILD_NUMBER}" + +TAG=${BRANCH}-${FULLVERSION} +if [ ! -z "${SIGNING_KEY_ADDR}" ]; then + git tag -s -u "${SIGNING_KEY_ADDR}" ${TAG} -m "Genesis Timestamp: $(cat ./genesistimestamp.dat)" +else + git tag -s ${TAG} -m "Genesis Timestamp: $(cat ./genesistimestamp.dat)" +fi +git push origin ${TAG} + +git archive --prefix=algorand-${FULLVERSION}/ "${TAG}" | gzip > ${PKG_ROOT}/algorand_${CHANNEL}_source_${FULLVERSION}.tar.gz + +# Run RPM bulid in Centos7 Docker container +sg docker "docker build -t algocentosbuild - < scripts/centos-build.Dockerfile" + +# cleanup our libsodium build +if [ -f ${GOPATH}/src/github.com/algorand/go-algorand/crypto/libsodium-fork/Makefile ]; then + (cd ${GOPATH}/src/github.com/algorand/go-algorand/crypto/libsodium-fork && make distclean) +fi +rm -rf ${GOPATH}/src/github.com/algorand/go-algorand/crypto/lib + +# do the RPM build +sg docker "docker run --mount type=bind,src=${GOPATH}/src,dst=/root/go/src --mount type=bind,src=${HOME},dst=/root/subhome --mount type=bind,src=/usr/local/go,dst=/usr/local/go -a stdout -a stderr algocentosbuild /root/go/src/github.com/algorand/go-algorand/scripts/build_release_centos_docker.sh" + + +# create *.sig gpg signatures +cd ${PKG_ROOT} +for i in *.tar.gz *.deb *.rpm; do + gpg --detach-sign "${i}" +done +HASHFILE=hashes_${CHANNEL}_${OS}_${ARCH}_${FULLVERSION} +rm -f "${HASHFILE}" +touch "${HASHFILE}" +md5sum *.tar.gz *.deb *.rpm >> "${HASHFILE}" +shasum -a 256 *.tar.gz *.deb *.rpm >> "${HASHFILE}" +shasum -a 512 *.tar.gz *.deb *.rpm >> "${HASHFILE}" +gpg --detach-sign "${HASHFILE}" +gpg --clearsign "${HASHFILE}" + +echo RSTAMP=${RSTAMP} > "${HOME}/rstamp" +aws s3 sync --quiet --exclude dev\* --exclude master\* --exclude nightly\* --exclude stable\* --acl public-read ./ ${S3_PREFIX}/${CHANNEL}/${RSTAMP}_${FULLVERSION}/ + +# copy .rpm file to intermediate yum repo scratch space, actual publish manually later +if [ ! -d /data/yumrepo ]; then + sudo mkdir -p /data/yumrepo + sudo chown ${USER} /data/yumrepo +fi +cp -p -n *.rpm *.rpm.sig /data/yumrepo + +cd ${HOME} +STATUSFILE=build_status_${CHANNEL}_${FULLVERSION} +echo "ami-id:" > "${STATUSFILE}" +curl --silent http://169.254.169.254/latest/meta-data/ami-id >> "${STATUSFILE}" +cat <<EOF>>"${STATUSFILE}" + + +dpkg-l: +EOF +dpkg -l >>"${STATUSFILE}" +gpg --clearsign "${STATUSFILE}" +gzip "${STATUSFILE}.asc" +aws s3 cp --quiet "${STATUSFILE}.asc.gz" "s3://algorand-devops-misc/buildlog/${RSTAMP}/${STATUSFILE}.asc.gz" + +# use aptly to push .deb to its serving repo +# Leave .deb publishing to manual step after we do more checks on the release artifacts. +# ${GOPATH}/src/github.com/algorand/go-algorand/scripts/release_deb.sh ${PKG_ROOT}/*deb + +# TODO: manually post rpm to repo + +date "+build_release finish %Y%m%d_%H%M%S" diff --git a/scripts/build_release_centos_docker.sh b/scripts/build_release_centos_docker.sh new file mode 100644 index 000000000..e6f09fa01 --- /dev/null +++ b/scripts/build_release_centos_docker.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# build centos rpm from inside docker +# +# mount src from outside +# --mount type=bind,src=${GOPATH}/src,dst=/root/go/src +# +# mount golang install from outside +# --mount type=bind,src=/usr/local/go,dst=/usr/local/go +# +# output copied to /root/subhome/node_pkg +# --mount type=bind,src=${HOME},dst=/root/subhome + +set -e +set -x + +export HOME=/root +mkdir -p ${HOME}/go +mkdir -p ${HOME}/go/bin +export GOPATH=${HOME}/go +export PATH=${GOPATH}/bin:/usr/local/go/bin:${PATH} + +go install golang.org/x/lint/golint +go install github.com/golang/dep/cmd/dep +go install golang.org/x/tools/cmd/stringer +go install github.com/go-swagger/go-swagger/cmd/swagger + + +cd ${GOPATH}/src/github.com/algorand/go-algorand + +# definitely rebuild libsodium which could link to external C libraries +if [ -f ${GOPATH}/src/github.com/algorand/go-algorand/crypto/libsodium-fork/Makefile ]; then + (cd ${GOPATH}/src/github.com/algorand/go-algorand/crypto/libsodium-fork && make distclean) +fi +rm -rf ${GOPATH}/src/github.com/algorand/go-algorand/crypto/lib +make ${GOPATH}/src/github.com/algorand/go-algorand/crypto/lib/libsodium.a + +make build + +RPMTMP=$(mktemp -d 2>/dev/null || mktemp -d -t "rpmtmp") +trap "rm -rf ${RPMTMP}" 0 +scripts/build_rpm.sh ${RPMTMP} +cp -p ${RPMTMP}/*/*.rpm /root/subhome/node_pkg diff --git a/scripts/build_release_local.sh b/scripts/build_release_local.sh new file mode 100644 index 000000000..3e12a8783 --- /dev/null +++ b/scripts/build_release_local.sh @@ -0,0 +1,77 @@ +#!/bin/bash + +echo "this is a file of commands to copy and paste to run build_release.sh on an AWS EC2 instance" +exit 1 + +# use AWS console to create a new t3.large with the latest official Ubuntu 18.04 + +# ec2 public address here: +TARGET= + +cd ${GOPATH}/src/github.com/algorand/go-algorand + +git fetch +git checkout rel/stable +git merge origin/rel/stable +scp -p ${GOPATH}/src/github.com/algorand/go-algorand/scripts/build_release_setup.sh ubuntu@${TARGET}:~/ + +# upload the latest public key +GTMPDIR=$(mktemp -d 2>/dev/null || mktemp -d -t "rpmtmp") +gpg --export --armor -o "${GTMPDIR}/key.gpg" sa@algorand.com +scp -p "${GTMPDIR}/key.gpg" "ubuntu@${TARGET}:~/key.gpg" +rm -rf ${GTMPDIR} + +ssh -A ubuntu@${TARGET} bash build_release_setup.sh + +# setup GPG key forwarding https://wiki.gnupg.org/AgentForwarding +umask 0077 +mkdir -p ${HOME}/.gnupg +touch ${HOME}/.gnupg/gpg-agent.conf +if grep -q extra-socket ${HOME}/.gnupg/gpg-agent.conf; then + echo "already have extra-socket" +else + cat <<EOF>>${HOME}/.gnupg/gpg-agent.conf +extra-socket ${HOME}/.gnupg/S.gpg-agent.extra +default-cache-ttl 3600 +EOF +fi +umask 0002 + +# this will require your key password, and export a private key file protected by the same password + +# warm up your local gpg-agent +gpg --clearsign +type some stuff +^D + + +# TODO: use simpler expression when we can rely on gpg 2.2 on ubuntu >= 18.04 +#REMOTE_GPG_SOCKET=$(ssh ubuntu@${TARGET} gpgconf --list-dir agent-socket) +REMOTE_GPG_SOCKET=$(ssh ubuntu@${TARGET} "gpgconf --list-dirs|grep agent-socket|awk -F: '{ print \$2 }'") +LOCAL_GPG_SOCKET=$(gpgconf --list-dir agent-extra-socket) +ssh -A -R "${REMOTE_GPG_SOCKET}:${LOCAL_GPG_SOCKET}" ubuntu@${TARGET} + +# set AWS credentials so we can upload to S3 and connect to EFS +export AWS_ACCESS_KEY_ID= +export AWS_SECRET_ACCESS_KEY= + +# where we store persistent scratch space for aptly +export AWS_EFS_MOUNT= + +# build_release.sh needs to be run in a terminal with a human watching +# to be prompted for GPG key password at a couple points. +# It can still steal the outer terminal from within piping the output to tee. Nifty, huh? +BUILDTIMESTAMP=$(cat "${HOME}/buildtimestamp") +(bash "${HOME}/go/src/github.com/algorand/go-algorand/scripts/build_release.sh" 2>&1)|tee -a "buildlog_${BUILDTIMESTAMP}" +if [ -f "${HOME}/rstamp" ]; then + . "${HOME}/rstamp" +fi +if [ -z "${RSTAMP}" ]; then + RSTAMP=$(${HOME}/go/src/github.com/algorand/go-algorand/scripts/reverse_hex_timestamp) +fi +if [ -z "${RSTAMP}" ]; then + echo "could not figure out RSTAMP, script must have failed early" + exit 1 +fi +gzip buildlog_* +aws s3 cp buildlog_*.gz s3://algorand-devops-misc/buildlog/${RSTAMP}/ diff --git a/scripts/build_release_setup.sh b/scripts/build_release_setup.sh new file mode 100644 index 000000000..9b52d5582 --- /dev/null +++ b/scripts/build_release_setup.sh @@ -0,0 +1,123 @@ +#!/bin/bash +# +# Externally settable env vars: +# GIT_REPO_PATH= something to `git clone` from +# GIT_CHECKOUT_LABEL= something to `git checkout` and build from (branch or tag or hash) +# SIGNING_KEY_ADDR= dev@algorand.com or similar for GPG key + +if [ -z "${BUILDTIMESTAMP}" ]; then + date "+%Y%m%d_%H%M%S" > "${HOME}/buildtimestamp" + BUILDTIMESTAMP=$(cat "${HOME}/buildtimestamp") + export BUILDTIMESTAMP + echo run "${0}" with output to ${HOME}/buildlog_${BUILDTIMESTAMP} + (bash "${0}" 2>&1) | tee ${HOME}/buildlog_${BUILDTIMESTAMP} + exit 0 +fi + +date "+setup start %Y%m%d_%H%M%S" + +set -e +set -x + +if [ -z "${GIT_REPO_PATH}" ]; then + GIT_REPO_PATH=git@github.com:algorand/go-algorand.git +fi + +if [ -z "${GIT_CHECKOUT_LABEL}" ]; then + GIT_CHECKOUT_LABEL="rel/stable" +fi + +sudo apt-get update +sudo apt-get upgrade -y + +if [ -f /etc/lsb-release ]; then + . /etc/lsb-release +fi + +mkdir -p ${HOME}/go +mkdir -p ${HOME}/gpgbin + +if [ "${DISTRIB_ID}" = "Ubuntu" ]; then + if [ "${DISTRIB_RELEASE}" = "16.04" ]; then + echo "WARNING: Ubuntu 16.04 is DEPRECATED" + sudo apt-get install -y autoconf awscli docker.io g++ fakeroot git gnupg2 gpgv2 make nfs-common python3 rpm sqlite3 + cat <<EOF>${HOME}/gpgbin/gpg +#!/bin/bash +exec /usr/bin/gpg2 "\$@" +EOF + cat <<EOF>${HOME}/gpgbin/gpgv +#!/bin/bash +exec /usr/bin/gpgv2 "\$@" +EOF + chmod +x ${HOME}/gpgbin/* + elif [ "${DISTRIB_RELEASE}" = "18.04" ]; then + sudo apt-get install -y autoconf awscli docker.io git gpg nfs-common python3 rpm sqlite3 + else + echo "don't know how to build on Ubuntu ${DISTRIB_RELEASE}" + exit 1 + fi +else + echo "don't know how to build non Ubuntu, /etc/lsb-release[DISTRIB_ID]=${DISTRIB_ID}" + exit 1 +fi + +export GOPATH=${HOME}/go +export PATH=${HOME}/gpgbin:${GOPATH}/bin:/usr/local/go/bin:${PATH} + +# please keep packages sorted + +# This real name and email must precisely match GPG key +git config --global user.name "Algorand developers" +git config --global user.email dev@algorand.com + +# configure GnuPG to rely on forwarded remote gpg-agent +umask 0077 +mkdir -p "${HOME}/.gnupg" +touch "${HOME}/.gnupg/gpg.conf" +if grep -q no-autostart "${HOME}/.gnupg/gpg.conf"; then + echo "" +else + echo "no-autostart" >> "${HOME}/.gnupg/gpg.conf" +fi + +if [ -f "${HOME}/key.gpg" ]; then + gpg --import "${HOME}/key.gpg" +fi +# we had a tight umask for gpg setup, but need wider for git clone below +umask 0002 + +# allow ssh to clobber unix domain sockets for gpg-agent forwarding +if grep -q ^StreamLocalBindUnlink /etc/ssh/sshd_config; then + echo already have StreamLocalBindUnlink sshd config +else + sudo bash -c "echo 'StreamLocalBindUnlink yes' >> /etc/ssh/sshd_config" + sudo systemctl restart sshd +fi + +sudo usermod -a -G docker ubuntu +sg docker "docker pull centos:7" + +# Check out +mkdir -p ${GOPATH}/src/github.com/algorand +if [ ! -d "${GOPATH}/src/github.com/algorand/go-algorand/.git" ]; then + (cd ${GOPATH}/src/github.com/algorand && git clone "${GIT_REPO_PATH}") +fi +cd ${GOPATH}/src/github.com/algorand/go-algorand +git checkout "${GIT_CHECKOUT_LABEL}" + +# Install latest Go +cd $HOME +# TODO: make a config file in root of repo with single source of truth for Go major-minor version +if [ ! -e /usr/local/go/bin/go ]; then + python3 ${GOPATH}/src/github.com/algorand/go-algorand/scripts/get_latest_go.py --version-prefix=1.12 + # $HOME will be interpreted by the outer shell to create the string passed to sudo bash + sudo bash -c "cd /usr/local && tar zxf ${HOME}/go*.tar.gz" +fi + +cat<<EOF>> "${HOME}/.bashrc" +export EDITOR=vi +export GOPATH=\${HOME}/go +export PATH=\${HOME}/gpgbin:\${GOPATH}/bin:/usr/local/go/bin:\${PATH} +EOF + +date "+setup finish %Y%m%d_%H%M%S" diff --git a/scripts/build_rpm.sh b/scripts/build_rpm.sh index 24318e847..2f2991524 100755 --- a/scripts/build_rpm.sh +++ b/scripts/build_rpm.sh @@ -19,7 +19,12 @@ cd ${REPO_DIR} echo "Building RPM package" -./scripts/build_prod.sh +if [ -z "${NO_BUILD}" ]; then + env GOOS=${OS} GOARCH=${ARCH} scripts/build_prod.sh +else + echo "already built" + true +fi VER=$(./scripts/compute_build_number.sh -f) diff --git a/scripts/centos-build.Dockerfile b/scripts/centos-build.Dockerfile new file mode 100644 index 000000000..310d85222 --- /dev/null +++ b/scripts/centos-build.Dockerfile @@ -0,0 +1,6 @@ +FROM centos:7 +WORKDIR /root +RUN yum install -y epel-release https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm +RUN yum install -y autoconf awscli git gnupg2 nfs-utils python36 sqlite3 boost-devel expect jq libtool gcc-c++ libstdc++-devel libstdc++-static rpmdevtools + +ENTRYPOINT ["/bin/bash"] diff --git a/scripts/get_latest_go.py b/scripts/get_latest_go.py new file mode 100755 index 000000000..c3b70aa39 --- /dev/null +++ b/scripts/get_latest_go.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 + +# use just stdlib so we can run with nothing more than `apt-get install -y python3` +import hashlib +import http.client +import json +import os +import re +import shutil +import subprocess +import sys + + +version_re = re.compile(r'\D+([0-9][.0-9]+)') + +def parseversion(x): + m = version_re.match(x) + return m.group(1).split('.') + +def get(): + # curl 'https://golang.org/dl/?mode=json' + conn = http.client.HTTPSConnection('golang.org') + conn.request('GET', '/dl/?mode=json') + response = conn.getresponse() + jsblob = response.read() + # Python <= 3.5 json.loads() doesn't take bytes + if isinstance(jsblob, bytes): + jsblob = jsblob.decode('utf-8') + return json.loads(jsblob) + +def loadfile(path): + # curl -o golang_dl.json 'https://golang.org/dl/?mode=json' + # DRYRUN=1 python3 get_latest_go.py golang_dl.json + with open(path) as fin: + return json.load(fin) + +def main(): + import argparse + ap = argparse.ArgumentParser() + ap.add_argument('--json', help='pre-downloaded json from https://golang.org/dl/?mode=json') + ap.add_argument('--version-prefix', help='e.g. 1.12 and get the latest 1.12.x') + args = ap.parse_args() + if args.json: + ob = loadfile(args.json) + else: + ob = get() + ob = filter(lambda x: x['stable'], ob) + if args.version_prefix: + ob = list(ob) + filtered_versions = [] + for v in ob: + m = version_re.match(v['version']) + if m: + version_string = m.group(1) + if version_string.startswith(args.version_prefix): + filtered_versions.append(v) + if not filtered_versions: + sys.stderr.write('--version-prefix {!r} filtered out all versions: {!r}\n'.format(args.version_prefix, [v['version'] for v in ob])) + sys.exit(1) + ob = filtered_versions + orderedbyversion = sorted([(parseversion(v['version']),v) for v in ob], reverse=True) + newest = orderedbyversion[0][1] + files = list(filter(lambda x: x['arch']=='amd64' and x['os']=='linux', newest['files'])) + fname = files[0]['filename'] + sha256 = files[0]['sha256'] + url = 'https://dl.google.com/go/{}'.format(fname) + + # e.g. https://dl.google.com/go/go1.12.5.linux-amd64.tar.gz + if os.environ.get('DRYRUN'): + sys.stdout.write('curl -L -O {}\n{}\n'.format(url, sha256)) + else: + sys.stdout.write('fetching {}\n'.format(url)) + subprocess.run(['curl', '-L', '-O', url]) + fhash = hashlib.sha256() + with open(fname, 'rb') as fin: + bb = bytearray(64*1024) + while True: + got = fin.readinto(bb) + if got == 0: + break + fhash.update(bb[:got]) + dldigest = fhash.hexdigest() + if dldigest != sha256: + sys.stderr.write('hash mismatch, wanted {} got {}\n'.format(sha256, dldigest)) + os.unlink(fname) + sys.stdout.write('Done\n') + return + + +if __name__ == '__main__': + main() diff --git a/scripts/release_deb.sh b/scripts/release_deb.sh new file mode 100755 index 000000000..ce16cd006 --- /dev/null +++ b/scripts/release_deb.sh @@ -0,0 +1,79 @@ +#!/bin/bash +# +# Usage: release_deb.sh *.deb +# +# To run on an ephemeral instance, mount AWS EFS somewhere and use it: +# APTLY_DIR=/large/persistent/filesystem ./release_deb.sh *.deb + + +set -e +set -x + +if [ -z "${APTLY_DIR}" ]; then + APTLY_DIR=${HOME}/.aptly +fi + +if [ -z "${APTLY_S3_NAME}" ]; then + APTLY_S3_NAME=algorand-releases +fi + +cat <<EOF>${HOME}/.aptly.conf +{ + "rootDir": "${APTLY_DIR}", + "downloadConcurrency": 4, + "downloadSpeedLimit": 0, + "architectures": [], + "dependencyFollowSuggests": false, + "dependencyFollowRecommends": false, + "dependencyFollowAllVariants": false, + "dependencyFollowSource": false, + "dependencyVerboseResolve": false, + "gpgDisableSign": false, + "gpgDisableVerify": false, + "gpgProvider": "gpg", + "downloadSourcePackages": false, + "skipLegacyPool": true, + "ppaDistributorID": "ubuntu", + "ppaCodename": "", + "skipContentsPublishing": false, + "FileSystemPublishEndpoints": {}, + "S3PublishEndpoints": { + "algorand-releases": { + "region":"us-east-1", + "bucket":"algorand-releases", + "acl":"public-read", + "prefix":"deb" + }, + "algorand-dev-deb-repo": { + "region":"us-east-1", + "bucket":"algorand-dev-deb-repo", + "acl":"public-read", + "prefix":"deb" + } + }, + "SwiftPublishEndpoints": {} +} +EOF + +mkdir -p $GOPATH/src/github.com/aptly-dev +git clone https://github.com/aptly-dev/aptly $GOPATH/src/github.com/aptly-dev/aptly || true +(cd $GOPATH/src/github.com/aptly-dev/aptly && git fetch) +# As of 2019-06-06 release tag v1.3.0 is 2018-May, GnuPG 2 support was added in October but they haven't tagged a new release yet. Hash below seems to work so far. +(cd $GOPATH/src/github.com/aptly-dev/aptly && git checkout e2d6a53de5ee03814b3fe19a8954a09a5c2969b9) +(cd $GOPATH/src/github.com/aptly-dev/aptly && make install) + +FIRSTTIME= +if aptly repo create -distribution=stable -component=main algorand; then + FIRSTTIME=1 +fi +aptly repo add algorand "$@" +SNAPSHOT=algorand-$(date +%Y%m%d_%H%M%S) +aptly snapshot create ${SNAPSHOT} from repo algorand +if [ ! -z "${FIRSTTIME}" ]; then + echo "first publish" + aptly publish snapshot ${SNAPSHOT} "s3:${APTLY_S3_NAME}:" +else + echo "publish snapshot ${SNAPSHOT}" + aptly publish switch stable "s3:${APTLY_S3_NAME}:" ${SNAPSHOT} +fi + diff --git a/scripts/reverse_hex_timestamp b/scripts/reverse_hex_timestamp new file mode 100755 index 000000000..a9f7cd3bc --- /dev/null +++ b/scripts/reverse_hex_timestamp @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 +# a reverse hex timestamp is useful for putting newest things first in S3 bucket object sort order +import sys +import time + +sys.stdout.write('{:08x}'.format(0xfffffffff - int(time.time()))) |