You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

201 lines
4.9 KiB

  1. #!/bin/bash
  2. # symbol prefixes:
  3. # g_ -> global
  4. # l_ - local variable
  5. # f_ -> function
  6. set -euo pipefail
  7. GITIAN_CACHE_DIRNAME='.gitian-builder-cache'
  8. GO_RELEASE='1.13.3'
  9. GO_TARBALL="go${GO_RELEASE}.linux-amd64.tar.gz"
  10. GO_TARBALL_URL="https://dl.google.com/go/${GO_TARBALL}"
  11. # Defaults
  12. DEFAULT_SIGN_COMMAND='gpg --detach-sign'
  13. DEFAULT_TENDERMINT_SIGS=${TENDERMINT_SIGS:-'tendermint.sigs'}
  14. DEFAULT_GITIAN_REPO='https://github.com/tendermint/gitian-builder'
  15. DEFAULT_GBUILD_FLAGS=''
  16. DEFAULT_SIGS_REPO='https://github.com/tendermint/tendermint.sigs'
  17. # Overrides
  18. SIGN_COMMAND=${SIGN_COMMAND:-${DEFAULT_SIGN_COMMAND}}
  19. GITIAN_REPO=${GITIAN_REPO:-${DEFAULT_GITIAN_REPO}}
  20. GBUILD_FLAGS=${GBUILD_FLAGS:-${DEFAULT_GBUILD_FLAGS}}
  21. # Globals
  22. g_workdir=''
  23. g_gitian_cache=''
  24. g_cached_gitian=''
  25. g_cached_go_tarball=''
  26. g_sign_identity=''
  27. g_sigs_dir=''
  28. g_flag_commit=''
  29. f_help() {
  30. cat >&2 <<EOF
  31. Usage: $(basename $0) [-h] PLATFORM
  32. Launch a gitian build from the current source directory for the given PLATFORM.
  33. The following platforms are supported:
  34. darwin
  35. linux
  36. windows
  37. all
  38. Options:
  39. -h display this help and exit
  40. -c clone the signatures repository and commit signatures;
  41. ignored if sign identity is not supplied
  42. -s IDENTITY sign build as IDENTITY
  43. If a GPG identity is supplied via the -s flag, the build will be signed and verified.
  44. The signature will be saved in '${DEFAULT_TENDERMINT_SIGS}/'. An alternative output directory
  45. for signatures can be supplied via the environment variable \$TENDERMINT_SIGS.
  46. The default signing command used to sign the build is '$DEFAULT_SIGN_COMMAND'.
  47. An alternative signing command can be supplied via the environment
  48. variable \$SIGN_COMMAND.
  49. EOF
  50. }
  51. f_builddir() {
  52. printf '%s' "${g_workdir}/gitian-build-$1"
  53. }
  54. f_prep_build() {
  55. local l_platforms \
  56. l_os \
  57. l_builddir
  58. l_platforms="$1"
  59. if [ -n "${g_flag_commit}" -a ! -d "${g_sigs_dir}" ]; then
  60. git clone ${DEFAULT_SIGS_REPO} "${g_sigs_dir}"
  61. fi
  62. for l_os in ${l_platforms}; do
  63. l_builddir="$(f_builddir ${l_os})"
  64. f_echo_stderr "Preparing build directory $(basename ${l_builddir}), restoring files from cache"
  65. cp -ar "${g_cached_gitian}" "${l_builddir}" >&2
  66. mkdir "${l_builddir}/inputs/"
  67. cp -v "${g_cached_go_tarball}" "${l_builddir}/inputs/"
  68. done
  69. }
  70. f_build() {
  71. local l_descriptor
  72. l_descriptor=$1
  73. bin/gbuild --commit tendermint="$g_commit" ${GBUILD_FLAGS} "$l_descriptor"
  74. libexec/stop-target || f_echo_stderr "warning: couldn't stop target"
  75. }
  76. f_sign_verify() {
  77. local l_descriptor
  78. l_descriptor=$1
  79. bin/gsign -p "${SIGN_COMMAND}" -s "${g_sign_identity}" --destination="${g_sigs_dir}" --release=${g_release} ${l_descriptor}
  80. bin/gverify --destination="${g_sigs_dir}" --release="${g_release}" ${l_descriptor}
  81. }
  82. f_commit_sig() {
  83. local l_release_name
  84. l_release_name=$1
  85. pushd "${g_sigs_dir}"
  86. git add . || echo "git add failed" >&2
  87. git commit -m "Add ${l_release_name} reproducible build" || echo "git commit failed" >&2
  88. popd
  89. }
  90. f_prep_docker_image() {
  91. pushd $1
  92. bin/make-base-vm --docker --suite bionic --arch amd64
  93. popd
  94. }
  95. f_ensure_cache() {
  96. g_gitian_cache="${g_workdir}/${GITIAN_CACHE_DIRNAME}"
  97. [ -d "${g_gitian_cache}" ] || mkdir "${g_gitian_cache}"
  98. g_cached_go_tarball="${g_gitian_cache}/${GO_TARBALL}"
  99. if [ ! -f "${g_cached_go_tarball}" ]; then
  100. f_echo_stderr "${g_cached_go_tarball}: cache miss, caching..."
  101. curl -L "${GO_TARBALL_URL}" --output "${g_cached_go_tarball}"
  102. fi
  103. g_cached_gitian="${g_gitian_cache}/gitian-builder"
  104. if [ ! -d "${g_cached_gitian}" ]; then
  105. f_echo_stderr "${g_cached_gitian}: cache miss, caching..."
  106. git clone ${GITIAN_REPO} "${g_cached_gitian}"
  107. fi
  108. }
  109. f_demangle_platforms() {
  110. case "${1}" in
  111. all)
  112. printf '%s' 'darwin linux windows' ;;
  113. linux|darwin|windows)
  114. printf '%s' "${1}" ;;
  115. *)
  116. echo "invalid platform -- ${1}"
  117. exit 1
  118. esac
  119. }
  120. f_echo_stderr() {
  121. echo $@ >&2
  122. }
  123. while getopts ":cs:h" opt; do
  124. case "${opt}" in
  125. h) f_help ; exit 0 ;;
  126. c) g_flag_commit=y ;;
  127. s) g_sign_identity="${OPTARG}" ;;
  128. esac
  129. done
  130. shift "$((OPTIND-1))"
  131. g_platforms=$(f_demangle_platforms "${1}")
  132. g_workdir="$(pwd)"
  133. g_commit="$(git rev-parse HEAD)"
  134. g_sigs_dir=${TENDERMINT_SIGS:-"${g_workdir}/${DEFAULT_TENDERMINT_SIGS}"}
  135. f_ensure_cache
  136. f_prep_docker_image "${g_cached_gitian}"
  137. f_prep_build "${g_platforms}"
  138. export USE_DOCKER=1
  139. for g_os in ${g_platforms}; do
  140. g_release="$(git describe --tags --abbrev=9 | sed 's/^v//')-${g_os}"
  141. g_descriptor="${g_workdir}/scripts/gitian-descriptors/gitian-${g_os}.yml"
  142. [ -f ${g_descriptor} ]
  143. g_builddir="$(f_builddir ${g_os})"
  144. pushd "${g_builddir}"
  145. f_build "${g_descriptor}"
  146. if [ -n "${g_sign_identity}" ]; then
  147. f_sign_verify "${g_descriptor}"
  148. fi
  149. popd
  150. if [ -n "${g_sign_identity}" -a -n "${g_flag_commit}" ]; then
  151. [ -d "${g_sigs_dir}/.git/" ] && f_commit_sig ${g_release} || f_echo_stderr "couldn't commit, ${g_sigs_dir} is not a git clone"
  152. fi
  153. done
  154. exit 0