diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 000000000..5e130a16c --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,24 @@ +name: release + +on: + # TODO: remove + workflow_dispatch: + +jobs: + publish_artifacts: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-go@v2 + with: + go-version: '1.17.x' + - run: | + ./hack/release_build.sh \ + -a linux/amd64 -a linux/arm64 -a linux/armhf -a linux/armel -a linux/386 -a linux/s390x \ + -a freebsd/amd64 -a freebsd/arm64 -a freebsd/armhf -a freebsd/armel -a freebsd/386 \ + -a darwin/arm64 -a darwin/amd64 + # TODO: enable this + # ./hack/release_sign.sh -S A135FAC32CC7DAE364F972CED3456C900C6869E1 + - uses: actions/upload-artifact@v2 + with: + path: ./release/*/* \ No newline at end of file diff --git a/.gitignore b/.gitignore index aced88369..95eaa3b5a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,4 @@ /umoci.cov* /.cache /release -*.swp -dist \ No newline at end of file +*.swp \ No newline at end of file diff --git a/goreleaser.yaml b/goreleaser.yaml deleted file mode 100644 index 7f9a50a8e..000000000 --- a/goreleaser.yaml +++ /dev/null @@ -1,37 +0,0 @@ -builds: - - main: ./cmd/umoci - flags: - - -tags - ldflags: - - -X {{.ModulePath}}.gitCommit={{.Commit}} -X {{.ModulePath}}.version={{.Version}} - - -s -w "{{if eq .Os "linux"}} -buildmode=pie {{end}}" - env: - - CGO_ENABLED=0 - goarch: - - amd64 - - arm - - arm64 - - 386 - - s390x - goos: - - linux - - darwin - - freebsd - -archives: - - name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}" - replacements: - 386: i386 -checksum: - name_template: "checksums.txt" - -signs: - - cmd: gpg - artifacts: all - args: ["--armor", "--output", "${signature}", "--detach-sign", "${artifact}"] - -# will remove once the PR is ready -release: - github: - owner: thesayyn - name: umoci diff --git a/hack/release.sh b/hack/release.sh deleted file mode 100755 index bb8753b36..000000000 --- a/hack/release.sh +++ /dev/null @@ -1,139 +0,0 @@ -#!/bin/bash -# release.sh: configurable signed-artefact release script -# Copyright (C) 2016-2020 SUSE LLC -# -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -set -Eeuo pipefail -source "$(dirname "$BASH_SOURCE")/readlinkf.sh" - -## ---> -# Project-specific options and functions. In *theory* you shouldn't need to -# touch anything else in this script in order to use this elsewhere. -project="umoci" -root="$(readlinkf_posix "$(dirname "${BASH_SOURCE}")/..")" - -# These functions allow you to configure how the defaults are computed. -function get_arch() { go env GOARCH || uname -m; } -function get_version() { cat "$root/VERSION" ; } - -# Any pre-configuration steps should be done here -- for instance ./configure. -function setup_project() { true ; } - -# This function takes an output path as an argument, where the built -# (preferably static) binary should be placed. -function build_project() { - tmprootfs="$(mktemp -dt "$project-build.XXXXXX")" - - make -C "$root" BUILD_DIR="$tmprootfs" COMMIT_NO= "$project.static" - mv "$tmprootfs/$project.static" "$1" - rm -rf "$tmprootfs" -} -# End of the easy-to-configure portion. -## <--- - -# Print usage information. -function usage() { - echo "usage: release.sh [-h] [-v ] [-c ] [-o ]" >&2 - echo " [-H ] [-S ]" >&2 -} - -# Log something to stderr. -function log() { - echo "[*]" "$@" >&2 -} - -# Log something to stderr and then exit with 0. -function quit() { - log "$@" - exit 0 -} - -# Conduct a sanity-check to make sure that GPG provided with the given -# arguments can sign something. Inability to sign things is not a fatal error. -function gpg_cansign() { - gpg "$@" --clear-sign /dev/null -} - -# When creating releases we need to build (ideally static) binaries, an archive -# of the current commit, and generate detached signatures for both. -keyid="" -version="" -arch="" -commit="HEAD" -hashcmd="sha256sum" -while getopts ":h:v:c:o:S:H:" opt; do - case "$opt" in - S) - keyid="$OPTARG" - ;; - c) - commit="$OPTARG" - ;; - o) - outputdir="$OPTARG" - ;; - v) - version="$OPTARG" - ;; - H) - hashcmd="$OPTARG" - ;; - h) - usage ; exit 0 - ;; - \:) - echo "Missing argument: -$OPTARG" >&2 - usage ; exit 1 - ;; - \?) - echo "Invalid option: -$OPTARG" >&2 - usage ; exit 1 - ;; - esac -done - -# Run project setup first... -( set -x ; setup_project ) - -# Generate the defaults for version and so on *after* argument parsing and -# setup_project, to avoid calling get_version() needlessly. -version="${version:-$(get_version)}" -arch="${arch:-$(get_arch)}" -outputdir="${outputdir:-release/$version}" - -log "[[ $project ]]" -log "version: $version" -log "commit: $commit" -log "output_dir: $outputdir" -log "key: ${keyid:-(default)}" -log "hash_cmd: $hashcmd" - -# Make explicit what we're doing. -set -x - -# Make the release directory. -rm -rf "$outputdir" && mkdir -p "$outputdir" - -# Build project. -build_project "$outputdir/$project.$arch" - -# Generate new archive. -git archive --format=tar --prefix="$project-$version/" "$commit" | xz > "$outputdir/$project.tar.xz" - -# Generate sha256 checksums for both. -( cd "$outputdir" ; "$hashcmd" "$project".{"$arch",tar.xz} > "$project.$hashcmd" ; ) - -# Set up the gpgflags. -gpgflags=() -[[ -z "$keyid" ]] || gpgflags+=("--default-key=$keyid") -gpg_cansign "${gpgflags[@]}" || quit "Could not find suitable GPG key, skipping signing step." - -# Sign everything. -gpg "${gpgflags[@]}" --detach-sign --armor "$outputdir/$project.$arch" -gpg "${gpgflags[@]}" --detach-sign --armor "$outputdir/$project.tar.xz" -gpg "${gpgflags[@]}" --clear-sign --armor \ - --output "$outputdir/$project.$hashcmd"{.tmp,} && \ - mv "$outputdir/$project.$hashcmd"{.tmp,} diff --git a/hack/release_build.sh b/hack/release_build.sh new file mode 100755 index 000000000..05ae73bc4 --- /dev/null +++ b/hack/release_build.sh @@ -0,0 +1,169 @@ +#!/bin/bash +# release.sh: configurable signed-artefact release script +# Copyright (C) 2016-2020 SUSE LLC +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +set -Eeuo pipefail +source "$(dirname "$BASH_SOURCE")/readlinkf.sh" + +## ---> +# Project-specific options and functions. In *theory* you shouldn't need to +# touch anything else in this script in order to use this elsewhere. +project="umoci" +root="$(readlinkf_posix "$(dirname "${BASH_SOURCE}")/..")" + + +# This function takes an output path as an argument, where the built +# (preferably static) binary should be placed. +function build_project() { + builddir="$(dirname "$1")" + shift + tmprootfs="$(mktemp -dt "$project-build.XXXXXX")" + + for osarch in $@; do + IFS='/' read -ra OSARCH <<< "$osarch" + local OS=${OSARCH[0]} + local ARCH=${OSARCH[1]} + log "building for $OS/$ARCH" + + set_cross_env $OS $ARCH + make -C "$root" BUILD_DIR="$tmprootfs" COMMIT_NO= "$project.static" + mv "$tmprootfs/$project.static" "$builddir/${project}_${OS}_$ARCH" + rm -rf "$tmprootfs" + done +} +# End of the easy-to-configure portion. +## <--- + +# Print usage information. +function usage() { + echo "usage: release_build.sh [-a ]... [-c ] [-H ]" >&2 + echo " [-r ] [-v ]" >&2 + exit 1 +} + +# Log something to stderr. +function log() { + echo "[*]" "$@" >&2 +} + +# Log something to stderr and then exit with 0. +function bail() { + log "$@" + exit 0 +} + + +function set_cross_env() { + GOOS="$1" + GOARCH="$2" + # it might be set from prev iterations + unset GOARM + + case $2 in + armel) + GOARCH=arm + GOARM=6 + ;; + armhf) + GOARCH=arm + GOARM=7 + ;; + # since we already checked the archs we do not need to declare + # a case for them + esac + export GOOS GOARCH GOARM +} + +# used to validate arch and os strings +supported_oses=(linux darwin freebsd) +supported_archs=(amd64 arm64 armhf armel 386 s390x) + +function assert_os_arch_support() { + IFS='/' read -ra OSARCH <<< "$1" + if [[ ! "${supported_oses[*]}" =~ "${OSARCH[0]}" ]]; then + bail "unsupported os $1. expected one of: ${supported_oses[@]}" + fi + if [[ ! "${supported_archs[*]}" =~ "${OSARCH[1]}" ]]; then + bail "unsupported arch $1. expected one of: ${supported_archs[@]}" + fi +} + + + +# When creating releases we need to build (ideally static) binaries, an archive +# of the current commit, and generate detached signatures for both. +keyid="" +version="" +commit="HEAD" +hashcmd="sha256sum" +# define os/arch targets to build for +declare -a osarch + + +while getopts "a:c:H:hr:v:" opt; do + case "$opt" in + a) + assert_os_arch_support "$OPTARG" + osarch+=($OPTARG) + ;; + c) + commit="$OPTARG" + ;; + H) + hashcmd="$OPTARG" + ;; + h) + usage + ;; + r) + releasedir="$OPTARG" + ;; + v) + version="$OPTARG" + ;; + :) + echo "Missing argument: -$OPTARG" >&2 + usage + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + usage + ;; + esac +done + + +# Generate the defaults for version and so on *after* argument parsing and +# setup_project, to avoid calling get_version() needlessly. +version="${version:-$(<"$root/VERSION")}" +releasedir="${releasedir:-release/$version}" +hashcmd="${hashcmd:-sha256sum}" +# Suffixes of files to checksum/sign. +suffixes=(tar.xz ${supported_archs[@]}) + +log "creating $project release in '$releasedir'" +log " version: $version" +log " commit: $commit" +log " hash: $hashcmd" + +# Make explicit what we're doing. +#set -x + +# Make the release directory. +rm -rf "$releasedir" && mkdir -p "$releasedir" + +# Build project. +build_project "$releasedir/$project" "${osarch[@]}" + +# Generate new archive. +git archive --format=tar --prefix="$project-$version/" "$commit" | xz > "$releasedir/$project.tar.xz" + +# Generate sha256 checksums for both. +( + cd "$releasedir" + "$hashcmd" $(tree -fai | grep ${suffixes[@]/#/-e } | tr '\n' ' ') > "$project.$hashcmd" +) \ No newline at end of file diff --git a/hack/release_sign.sh b/hack/release_sign.sh new file mode 100755 index 000000000..83399a578 --- /dev/null +++ b/hack/release_sign.sh @@ -0,0 +1,107 @@ +#!/bin/bash +# Copyright (C) 2017 SUSE LLC. +# Copyright (C) 2017-2021 Open Containers Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -Eeuo pipefail +source "$(dirname "$BASH_SOURCE")/readlinkf.sh" + +project="umoci" +root="$(readlinkf_posix "$(dirname "${BASH_SOURCE}")/..")" + + +# Print usage information. +function usage() { + echo "usage: release_sign.sh [-S ] [-H ]" >&2 + echo " [-r ] [-v ]" >&2 + exit 1 +} + +# Log something to stderr. +function log() { + echo "[*] $*" >&2 +} + +# Log something to stderr and then exit with 0. +function bail() { + log "$@" + exit 0 +} + +# Conduct a sanity-check to make sure that GPG provided with the given +# arguments can sign something. Inability to sign things is not a fatal error. +function gpg_cansign() { + gpg "$@" --clear-sign /dev/null +} + +# When creating releases we need to build static binaries, an archive of the +# current commit, and generate detached signatures for both. +keyid="" +version="" +releasedir="" +hashcmd="" + +while getopts "H:hr:S:v:" opt; do + case "$opt" in + H) + hashcmd="$OPTARG" + ;; + h) + usage + ;; + r) + releasedir="$OPTARG" + ;; + S) + keyid="$OPTARG" + ;; + v) + version="$OPTARG" + ;; + :) + echo "Missing argument: -$OPTARG" >&2 + usage + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + usage + ;; + esac +done + +version="${version:-$(<"$root/VERSION")}" +releasedir="${releasedir:-release/$version}" +hashcmd="${hashcmd:-sha256sum}" + +log "signing $project release in '$releasedir'" +log " key: ${keyid:-DEFAULT}" +log " hash: $hashcmd" + +# Make explicit what we're doing. +set -x + +# Set up the gpgflags. +gpgflags=() +[[ "$keyid" ]] && gpgflags=(--default-key "$keyid") +gpg_cansign "${gpgflags[@]:-}" || bail "Could not find suitable GPG key, skipping signing step." + + +# Sign everything. +for bin in "$releasedir/$project"_*; do + [[ "$(basename "$bin")" == "$project.$hashcmd" ]] && continue # skip hash + gpg "${gpgflags[@]}" --detach-sign --armor "$bin" +done +gpg "${gpgflags[@]}" --clear-sign --armor \ + --output "$releasedir/$project.$hashcmd"{.tmp,} && + mv "$releasedir/$project.$hashcmd"{.tmp,} \ No newline at end of file