1function tag_release { 2 # Arguments: 3 # $1 - Path to top level consul source 4 # $2 - Version string to use for tagging the release 5 # $3 - Alternative GPG key id used for signing the release commit (optional) 6 # 7 # Returns: 8 # 0 - success 9 # * - error 10 # 11 # Notes: 12 # If the RELEASE_UNSIGNED environment variable is set then no gpg signing will occur 13 14 if ! test -d "$1" 15 then 16 err "ERROR: '$1' is not a directory. tag_release must be called with the path to the top level source as the first argument'" 17 return 1 18 fi 19 20 if test -z "$2" 21 then 22 err "ERROR: tag_release must be called with a version number as the second argument" 23 return 1 24 fi 25 26 # determine whether the gpg key to use is being overridden 27 local gpg_key=${HASHICORP_GPG_KEY} 28 if test -n "$3" 29 then 30 gpg_key=$3 31 fi 32 33 pushd "$1" > /dev/null 34 local ret=0 35 36 local branch_to_tag=$(git_branch) || ret=1 37 38 # perform an usngined release if requested (mainly for testing locally) 39 if test ${ret} -ne 0 40 then 41 err "ERROR: Failed to determine git branch to tag" 42 elif is_set "$RELEASE_UNSIGNED" 43 then 44 ( 45 git commit --allow-empty -a -m "Release v${2}" && 46 git tag -a -m "Version ${2}" "v${2}" "${branch_to_tag}" 47 ) 48 ret=$? 49 # perform a signed release (official releases should do this) 50 elif have_gpg_key ${gpg_key} 51 then 52 ( 53 git commit --allow-empty -a --gpg-sign=${gpg_key} -m "Release v${2}" && 54 git tag -a -m "Version ${2}" -s -u ${gpg_key} "v${2}" "${branch_to_tag}" 55 ) 56 ret=$? 57 # unsigned release not requested and gpg key isn't useable 58 else 59 err "ERROR: GPG key ${gpg_key} is not in the local keychain - to continue set RELEASE_UNSIGNED=1 in the env" 60 ret=1 61 fi 62 popd > /dev/null 63 return $ret 64} 65 66function package_binaries { 67 # Arguments: 68 # $1 - Path to the directory containing the built binaries 69 # $2 - Destination path of the packaged binaries 70 # $3 - Version 71 # 72 # Returns: 73 # 0 - success 74 # * - error 75 76 local sdir="$1" 77 local ddir="$2" 78 local vers="$3" 79 local ret=0 80 81 82 if ! test -d "${sdir}" 83 then 84 err "ERROR: '$1' is not a directory. package_binaries must be called with the path to the directory containing the binaries" 85 return 1 86 fi 87 88 rm -rf "${ddir}" > /dev/null 2>&1 89 mkdir -p "${ddir}" >/dev/null 2>&1 90 for platform in $(find "${sdir}" -mindepth 1 -maxdepth 1 -type d ) 91 do 92 local os_arch=$(basename $platform) 93 local dest="${ddir}/${CONSUL_PKG_NAME}_${vers}_${os_arch}.zip" 94 status "Compressing ${os_arch} directory into ${dest}" 95 pushd "${platform}" > /dev/null 96 zip "${ddir}/${CONSUL_PKG_NAME}_${vers}_${os_arch}.zip" ./* 97 ret=$? 98 popd > /dev/null 99 100 if test "$ret" -ne 0 101 then 102 break 103 fi 104 done 105 106 return ${ret} 107} 108 109function package_release_one { 110 # Arguments: 111 # $1 - Path to the top level Consul source 112 # $2 - Version to use in the names of the zip files (optional) 113 # $3 - Subdirectory under pkg/dist to use (optional) 114 # 115 # Returns: 116 # 0 - success 117 # * - error 118 119 if ! test -d "$1" 120 then 121 err "ERROR: '$1' is not a directory. package_release must be called with the path to the top level source as the first argument'" 122 return 1 123 fi 124 125 local sdir="$1" 126 local ret=0 127 local vers="$2" 128 local extra_dir_name="$3" 129 local extra_dir="" 130 131 if test -n "${extra_dir_name}" 132 then 133 extra_dir="${extra_dir_name}/" 134 fi 135 136 if test -z "${vers}" 137 then 138 vers=$(get_version "${sdir}" true false) 139 ret=$? 140 if test "$ret" -ne 0 141 then 142 err "ERROR: failed to determine the version." 143 return $ret 144 fi 145 fi 146 147 package_binaries "${sdir}/pkg/bin/${extra_dir}" "${sdir}/pkg/dist/${extra_dir}" "${vers}" 148 return $? 149} 150 151function package_release { 152 # Arguments: 153 # $1 - Path to the top level Consul source 154 # $2 - Version to use in the names of the zip files (optional) 155 # 156 # Returns: 157 # 0 - success 158 # * - error 159 160 package_release_one "$1" "$2" "" 161 return $? 162} 163 164function shasum_release { 165 # Arguments: 166 # $1 - Path to the dist directory 167 # $2 - Version of the release 168 # 169 # Returns: 170 # 0 - success 171 # * - failure 172 173 local sdir="$1" 174 local vers="$2" 175 176 if ! test -d "$1" 177 then 178 err "ERROR: sign_release requires a path to the dist dir as the first argument" 179 return 1 180 fi 181 182 if test -z "${vers}" 183 then 184 err "ERROR: sign_release requires a version to be specified as the second argument" 185 return 1 186 fi 187 188 local hfile="${CONSUL_PKG_NAME}_${vers}_SHA256SUMS" 189 190 shasum_directory "${sdir}" "${sdir}/${hfile}" 191 return $? 192} 193 194function sign_release { 195 # Arguments: 196 # $1 - Path to distribution directory 197 # $2 - Version 198 # $2 - Alternative GPG key to use for signing 199 # 200 # Returns: 201 # 0 - success 202 # * - failure 203 204 local sdir="$1" 205 local vers="$2" 206 207 if ! test -d "${sdir}" 208 then 209 err "ERROR: sign_release requires a path to the dist dir as the first argument" 210 return 1 211 fi 212 213 if test -z "${vers}" 214 then 215 err "ERROR: sign_release requires a version to be specified as the second argument" 216 return 1 217 fi 218 219 local hfile="${CONSUL_PKG_NAME}_${vers}_SHA256SUMS" 220 221 status_stage "==> Signing ${hfile}" 222 gpg_detach_sign "${1}/${hfile}" "$3" || return 1 223 return 0 224} 225 226function check_release_one { 227 # Arguments: 228 # $1 - Path to the release files 229 # $2 - Version to expect 230 # $3 - boolean whether to expect the signature file 231 # $4 - Release Name (optional) 232 # 233 # Returns: 234 # 0 - success 235 # * - failure 236 237 declare -i ret=0 238 239 declare -a expected_files 240 241 declare log_extra="" 242 243 if test -n "$4" 244 then 245 log_extra="for $4 " 246 fi 247 248 expected_files+=("${CONSUL_PKG_NAME}_${2}_SHA256SUMS") 249 echo "check sig: $3" 250 if is_set "$3" 251 then 252 expected_files+=("${CONSUL_PKG_NAME}_${2}_SHA256SUMS.sig") 253 fi 254 255 expected_files+=("${CONSUL_PKG_NAME}_${2}_darwin_386.zip") 256 expected_files+=("${CONSUL_PKG_NAME}_${2}_darwin_amd64.zip") 257 expected_files+=("${CONSUL_PKG_NAME}_${2}_freebsd_386.zip") 258 expected_files+=("${CONSUL_PKG_NAME}_${2}_freebsd_amd64.zip") 259 expected_files+=("${CONSUL_PKG_NAME}_${2}_freebsd_arm.zip") 260 expected_files+=("${CONSUL_PKG_NAME}_${2}_linux_386.zip") 261 expected_files+=("${CONSUL_PKG_NAME}_${2}_linux_amd64.zip") 262 expected_files+=("${CONSUL_PKG_NAME}_${2}_linux_arm.zip") 263 expected_files+=("${CONSUL_PKG_NAME}_${2}_linux_arm64.zip") 264 expected_files+=("${CONSUL_PKG_NAME}_${2}_solaris_amd64.zip") 265 expected_files+=("${CONSUL_PKG_NAME}_${2}_windows_386.zip") 266 expected_files+=("${CONSUL_PKG_NAME}_${2}_windows_amd64.zip") 267 268 declare -a found_files 269 270 status_stage "==> Verifying release contents ${log_extra}- ${2}" 271 debug "Expecting Files:" 272 for fname in "${expected_files[@]}" 273 do 274 debug " $fname" 275 done 276 277 pushd "$1" > /dev/null 278 for actual_fname in $(ls) 279 do 280 local found=0 281 for i in "${!expected_files[@]}" 282 do 283 local expected_fname="${expected_files[i]}" 284 if test "${expected_fname}" == "${actual_fname}" 285 then 286 # remove from the expected_files array 287 unset 'expected_files[i]' 288 289 # append to the list of found files 290 found_files+=("${expected_fname}") 291 292 # mark it as found so we dont error 293 found=1 294 break 295 fi 296 done 297 298 if test $found -ne 1 299 then 300 err "ERROR: Release build has an extra file: ${actual_fname}" 301 ret=1 302 fi 303 done 304 305 for fname in "${expected_files[@]}" 306 do 307 err "ERROR: Release build is missing a file: $fname" 308 ret=1 309 done 310 311 if test $ret -eq 0 312 then 313 if ! shasum -c -s "${CONSUL_PKG_NAME}_${2}_SHA256SUMS" 314 then 315 err "ERROR: Failed SHA-256 hash verification" 316 shasum -c "${CONSUL_PKG_NAME}_${2}_SHA256SUMS" 317 ret=1 318 fi 319 fi 320 321 if test $ret -eq 0 && is_set "${3}" 322 then 323 if ! gpg --verify "${CONSUL_PKG_NAME}_${2}_SHA256SUMS.sig" "${CONSUL_PKG_NAME}_${2}_SHA256SUMS" > /dev/null 2>&1 324 then 325 err "ERROR: Failed GPG verification of SHA256SUMS signature" 326 ret=1 327 fi 328 fi 329 330 if test $ret -eq 0 331 then 332 status "Release build contents:" 333 for fname in "${found_files[@]}" 334 do 335 echo " $fname" 336 done 337 fi 338 339 popd > /dev/null 340 341 return $ret 342} 343 344function check_release { 345 # Arguments: 346 # $1 - Path to the release files 347 # $2 - Version to expect 348 # $3 - boolean whether to expect the signature file 349 # 350 # Returns: 351 # 0 - success 352 # * - failure 353 354 check_release_one "$1" "$2" "$3" 355 return ${ret} 356} 357 358 359function build_consul_release { 360 build_consul "$1" "" "$2" 361} 362 363function build_release { 364 # Arguments: (yeah there are lots) 365 # $1 - Path to the top level Consul source 366 # $2 - boolean whether to tag the release yet 367 # $3 - boolean whether to build the binaries 368 # $4 - boolean whether to generate the sha256 sums 369 # $5 - version to set within version.go and the changelog 370 # $6 - release date to set within the changelog 371 # $7 - release version to set 372 # $8 - alternative gpg key to use for signing operations (optional) 373 # 374 # Returns: 375 # 0 - success 376 # * - error 377 378 debug "Source Dir: $1" 379 debug "Tag Release: $2" 380 debug "Build Release: $3" 381 debug "Sign Release: $4" 382 debug "Version: $5" 383 debug "Release Date: $6" 384 debug "Release Vers: $7" 385 debug "GPG Key: $8" 386 387 if ! test -d "$1" 388 then 389 err "ERROR: '$1' is not a directory. build_release must be called with the path to the top level source as the first argument'" 390 return 1 391 fi 392 393 if test -z "$2" -o -z "$3" -o -z "$4" 394 then 395 err "ERROR: build_release requires 4 arguments to be specified: <path to consul source> <tag release bool?> <build binaries bool?> <shasum 256 bool?>" 396 return 1 397 fi 398 399 local sdir="$1" 400 local do_tag="$2" 401 local do_build="$3" 402 local do_sha256="$4" 403 local gpg_key="$8" 404 405 if test -z "${gpg_key}" 406 then 407 gpg_key=${HASHICORP_GPG_KEY} 408 fi 409 410 if ! is_set "${RELEASE_UNSIGNED}" 411 then 412 if ! have_gpg_key "${gpg_key}" 413 then 414 err "ERROR: Aborting build because no useable GPG key is present. Set RELEASE_UNSIGNED=1 to bypass this check" 415 return 1 416 fi 417 fi 418 419 if ! is_git_clean "${sdir}" true && ! is_set "${ALLOW_DIRTY_GIT}" 420 then 421 err "ERROR: Refusing to build because Git is dirty. Set ALLOW_DIRTY_GIT=1 in the environment to proceed anyways" 422 return 1 423 fi 424 425 local set_vers="$5" 426 local set_date="$6" 427 local set_release="$7" 428 429 if test -z "${set_vers}" 430 then 431 set_vers=$(get_version "${sdir}" false false) 432 set_release=$(parse_version "${sdir}" true false true) 433 fi 434 435 if is_set "${do_tag}" && ! set_release_mode "${sdir}" "${set_vers}" "${set_date}" "${set_release}" 436 then 437 err "ERROR: Failed to put source into release mode" 438 return 1 439 fi 440 441 local vers="$(get_version ${sdir} true false)" 442 if test $? -ne 0 443 then 444 err "Please specify a version (couldn't find one based on build tags)." 445 return 1 446 fi 447 448 # Make sure we arent in dev mode 449 unset CONSUL_DEV 450 451 if is_set "${do_build}" 452 then 453 status_stage "==> Refreshing Docker Build Images" 454 refresh_docker_images "${sdir}" 455 if test $? -ne 0 456 then 457 err "ERROR: Failed to refresh docker images" 458 return 1 459 fi 460 461 status_stage "==> Building Legacy UI for version ${vers}" 462 build_ui_legacy "${sdir}" "${UI_LEGACY_BUILD_TAG}" 463 if test $? -ne 0 464 then 465 err "ERROR: Failed to build the legacy ui" 466 return 1 467 fi 468 469 status_stage "==> Building UI for version ${vers}" 470 # passing the version to override the version determined via tags 471 build_ui "${sdir}" "${UI_BUILD_TAG}" "${vers}" 472 if test $? -ne 0 473 then 474 err "ERROR: Failed to build the ui" 475 return 1 476 fi 477 status "UI Built with Version: $(ui_version "${sdir}/pkg/web_ui/v2/index.html")" 478 479 status_stage "==> Building Static Assets for version ${vers}" 480 build_assetfs "${sdir}" "${GO_BUILD_TAG}" 481 if test $? -ne 0 482 then 483 err "ERROR: Failed to build the static assets" 484 return 1 485 fi 486 487 if is_set "${do_tag}" 488 then 489 git add "${sdir}/agent/bindata_assetfs.go" 490 if test $? -ne 0 491 then 492 err "ERROR: Failed to git add the assetfs file" 493 return 1 494 fi 495 fi 496 fi 497 498 if is_set "${do_tag}" 499 then 500 status_stage "==> Tagging version ${vers}" 501 tag_release "${sdir}" "${vers}" "${gpg_key}" 502 if test $? -ne 0 503 then 504 err "ERROR: Failed to tag the release" 505 return 1 506 fi 507 508 update_git_env "${sdir}" 509 fi 510 511 if is_set "${do_build}" 512 then 513 status_stage "==> Building Consul for version ${vers}" 514 build_consul_release "${sdir}" "${GO_BUILD_TAG}" 515 if test $? -ne 0 516 then 517 err "ERROR: Failed to build the Consul binaries" 518 return 1 519 fi 520 521 status_stage "==> Packaging up release binaries" 522 package_release "${sdir}" "${vers}" 523 if test $? -ne 0 524 then 525 err "ERROR: Failed to package the release binaries" 526 return 1 527 fi 528 fi 529 530 status_stage "==> Generating SHA 256 Hashes for Binaries" 531 shasum_release "${sdir}/pkg/dist" "${vers}" 532 if test $? -ne 0 533 then 534 err "ERROR: Failed to generate SHA 256 hashes for the release" 535 return 1 536 fi 537 538 if is_set "${do_sha256}" 539 then 540 sign_release "${sdir}/pkg/dist" "${vers}" "${gpg_key}" 541 if test $? -ne 0 542 then 543 err "ERROR: Failed to sign the SHA 256 hashes file" 544 return 1 545 fi 546 fi 547 548 check_release "${sdir}/pkg/dist" "${vers}" "${do_sha256}" 549 return $? 550} 551