github.com/opencontainers/umoci@v0.4.8-0.20240508124516-656e4836fb0d/hack/release.sh (about) 1 #!/bin/bash 2 # release.sh: configurable signed-artefact release script 3 # Copyright (C) 2016-2020 SUSE LLC 4 # 5 # This Source Code Form is subject to the terms of the Mozilla Public 6 # License, v2.0. If a copy of the MPL was not distributed with this 7 # file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 9 set -Eeuo pipefail 10 # shellcheck source=./readlinkf.sh 11 source "$(dirname "${BASH_SOURCE[0]}")/readlinkf.sh" 12 13 ## ---> 14 # Project-specific options and functions. In *theory* you shouldn't need to 15 # touch anything else in this script in order to use this elsewhere. 16 project="umoci" 17 root="$(readlinkf_posix "$(dirname "${BASH_SOURCE[0]}")/..")" 18 19 # These functions allow you to configure how the defaults are computed. 20 function get_os() { go env GOOS ; } 21 function get_arch() { go env GOARCH ; } 22 function get_version() { cat "$root/VERSION" ; } 23 24 # Any pre-configuration steps should be done here -- for instance ./configure. 25 function setup_project() { true ; } 26 27 # This function takes an output path as an argument, where the built 28 # (preferably static) binary should be placed. 29 function build_project() { 30 tmprootfs="$(mktemp -dt "$project-build.XXXXXX")" 31 32 make -C "$root" GOOS="$GOOS" GOARCH="$GOARCH" BUILD_DIR="$tmprootfs" COMMIT_NO= "$project.static" 33 mv "$tmprootfs/$project.static" "$1" 34 rm -rf "$tmprootfs" 35 } 36 # End of the easy-to-configure portion. 37 ## <--- 38 39 # Print usage information. 40 function usage() { 41 echo "usage: release.sh [-h] [-v <version>] [-c <commit>] [-o <output-dir>]" >&2 42 echo " [-H <hashcmd>] [-S <gpg-key>]" >&2 43 } 44 45 # Log something to stderr. 46 function log() { 47 echo "[*]" "$@" >&2 48 } 49 50 # Log something to stderr and then exit with 0. 51 function quit() { 52 log "$@" 53 exit 0 54 } 55 56 # Conduct a sanity-check to make sure that GPG provided with the given 57 # arguments can sign something. Inability to sign things is not a fatal error. 58 function gpg_cansign() { 59 gpg "$@" --clear-sign </dev/null >/dev/null 60 } 61 62 # When creating releases we need to build (ideally static) binaries, an archive 63 # of the current commit, and generate detached signatures for both. 64 keyid="" 65 version="" 66 targets=("$(get_os)/$(get_arch)") 67 commit="HEAD" 68 hashcmd="sha256sum" 69 while getopts ":a:c:H:h:o:S:t:v:" opt; do 70 case "$opt" in 71 a) 72 targets+=("$(get_os)/$OPTARG") 73 ;; 74 c) 75 commit="$OPTARG" 76 ;; 77 H) 78 hashcmd="$OPTARG" 79 ;; 80 h) 81 usage ; exit 0 82 ;; 83 o) 84 outputdir="$OPTARG" 85 ;; 86 S) 87 keyid="$OPTARG" 88 ;; 89 t) 90 targets+=("$OPTARG") 91 ;; 92 v) 93 version="$OPTARG" 94 ;; 95 :) 96 echo "Missing argument: -$OPTARG" >&2 97 usage ; exit 1 98 ;; 99 \?) 100 echo "Invalid option: -$OPTARG" >&2 101 usage ; exit 1 102 ;; 103 esac 104 done 105 106 # Run project setup first... 107 ( set -x ; setup_project ) 108 109 # Generate the defaults for version and so on *after* argument parsing and 110 # setup_project, to avoid calling get_version() needlessly. 111 version="${version:-$(get_version)}" 112 outputdir="${outputdir:-release/$version}" 113 114 log "[[ $project ]]" 115 log "targets: ${targets[*]}" 116 log "version: $version" 117 log "commit: $commit" 118 log "output_dir: $outputdir" 119 log "key: ${keyid:-(default)}" 120 log "hash_cmd: $hashcmd" 121 122 # Make explicit what we're doing. 123 set -x 124 125 # Make the release directory. 126 rm -rf "$outputdir" && mkdir -p "$outputdir" 127 128 # Build project. 129 for target in "${targets[@]}"; do 130 target="${target//\//.}" 131 os="$(cut -d. -f1 <<<"$target")" 132 arch="$(cut -d. -f2 <<<"$target")" 133 GOOS="$os" GOARCH="$arch" build_project "$outputdir/$project.$target" 134 done 135 136 # Generate new archive. 137 git archive --format=tar --prefix="$project-$version/" "$commit" | xz > "$outputdir/$project.tar.xz" 138 139 # Generate sha256 checksums for both. 140 ( cd "$outputdir" ; "$hashcmd" "$project".* > "$project.$hashcmd" ; ) 141 142 # Set up the gpgflags. 143 gpgflags=() 144 [[ -z "$keyid" ]] || gpgflags+=("--default-key=$keyid") 145 gpg_cansign "${gpgflags[@]}" || quit "Could not find suitable GPG key, skipping signing step." 146 147 # Sign everything. 148 for target in "${targets[@]}"; do 149 target="${target//\//.}" 150 gpg "${gpgflags[@]}" --detach-sign --armor "$outputdir/$project.$target" 151 done 152 gpg "${gpgflags[@]}" --detach-sign --armor "$outputdir/$project.tar.xz" 153 gpg "${gpgflags[@]}" --clear-sign --armor \ 154 --output "$outputdir/$project.$hashcmd"{.tmp,} && \ 155 mv "$outputdir/$project.$hashcmd"{.tmp,}