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,}