chore: build releases on a single Linux runner (switch to rcodesign) (#3890)

* chore: build, sign and notarize darwin binaries on linux

* chore: download rcodesign during release

* chore: change nfpm install to be a download instead of compile

* chore: delete apple cert secrets after build

* fix: fix dependencies in archive.sh and build_go.sh

* chore: reduce output from rcodesign
This commit is contained in:
Dean Sheather
2022-09-08 04:56:46 +10:00
committed by GitHub
parent ac279b3483
commit a79e34c0c7
8 changed files with 199 additions and 232 deletions

View File

@ -10,11 +10,9 @@
# If the --output parameter is not set, the default output path is the binary
# path (minus any .exe suffix) plus the format extension ".zip" or ".tar.gz".
#
# If --sign-darwin is specified, the zip file is signed with the `codesign`
# utility and then notarized using the `gon` utility, which may take a while.
# $AC_APPLICATION_IDENTITY must be set and the signing certificate must be
# imported for this to work. Also, the input binary must already be signed with
# the `codesign` tool.
# If --sign-darwin is specified, the zip file will be notarized using
# ./notarize_darwin.sh, which may take a while. Read that file for more details
# on the requirements.
#
# If the --agpl parameter is specified, only the AGPL license is included in the
# outputted archive.
@ -82,11 +80,6 @@ if [[ ! -f "$1" ]]; then
fi
input_file="$(realpath "$1")"
sign_darwin="$([[ "$sign_darwin" == 1 ]] && [[ "$os" == "darwin" ]] && echo 1 || echo 0)"
if [[ "$sign_darwin" == 1 ]] && [[ "${AC_APPLICATION_IDENTITY:-}" == "" ]]; then
error "AC_APPLICATION_IDENTITY must be set when --sign-darwin or CODER_SIGN_DARWIN=1 is supplied"
fi
# Check dependencies
if [[ "$format" == "zip" ]]; then
dependencies zip
@ -94,8 +87,11 @@ fi
if [[ "$format" == "tar.gz" ]]; then
dependencies tar
fi
sign_darwin="$([[ "$sign_darwin" == 1 ]] && [[ "$os" == "darwin" ]] && echo 1 || echo 0)"
if [[ "$sign_darwin" == 1 ]]; then
dependencies jq codesign gon
dependencies rcodesign
requiredenvs AC_APIKEY_ISSUER_ID AC_APIKEY_ID AC_APIKEY_FILE
fi
# Determine default output path.
@ -139,7 +135,7 @@ rm -rf "$temp_dir"
if [[ "$sign_darwin" == 1 ]]; then
log "Notarizing archive..."
execrelative ./sign_darwin.sh "$output_path"
execrelative ./notarize_darwin.sh "$output_path"
fi
echo "$output_path"

View File

@ -16,9 +16,9 @@
# builds) and the absolute path to the binary will be printed to stdout on
# completion.
#
# If the --sign-darwin parameter is specified and the OS is darwin, binaries
# will be signed using the `codesign` utility. $AC_APPLICATION_IDENTITY must be
# set and the signing certificate must be imported for this to work.
# If the --sign-darwin parameter is specified and the OS is darwin, the output
# binary will be signed using ./sign_darwin.sh. Read that file for more details
# on the requirements.
#
# If the --agpl parameter is specified, builds only the AGPL-licensed code (no
# Coder enterprise features).
@ -65,9 +65,6 @@ while true; do
shift
;;
--sign-darwin)
if [[ "${AC_APPLICATION_IDENTITY:-}" == "" ]]; then
error "AC_APPLICATION_IDENTITY must be set when --sign-darwin is supplied"
fi
sign_darwin=1
shift
;;
@ -92,7 +89,8 @@ fi
# Check dependencies
dependencies go
if [[ "$sign_darwin" == 1 ]]; then
dependencies codesign
dependencies rcodesign
requiredenvs AC_CERTIFICATE_FILE AC_CERTIFICATE_PASSWORD_FILE
fi
build_args=(
@ -133,13 +131,7 @@ CGO_ENABLED=0 GOOS="$os" GOARCH="$arch" GOARM="$arm_version" go build \
"$cmd_path" 1>&2
if [[ "$sign_darwin" == 1 ]] && [[ "$os" == "darwin" ]]; then
codesign \
-f -v \
-s "$AC_APPLICATION_IDENTITY" \
--timestamp \
--options runtime \
"$output_path" \
1>&2
execrelative ./sign_darwin.sh "$output_path" 1>&2
fi
echo "$output_path"

View File

@ -81,6 +81,21 @@ dependencies() {
fi
}
requiredenvs() {
local fail=0
for env in "$@"; do
if [[ "${!env:-}" == "" ]]; then
log "ERROR: The '$env' environment variable is required, but is not set."
fail=1
fi
done
if [[ "$fail" == 1 ]]; then
log
error "One or more required environment variables are not set, check above log output for more details."
fi
}
# maybedryrun prints the given program and flags, and then, if the first
# argument is 0, executes it. The reason the first argument should be 0 is that
# it is expected that you have a dry_run variable in your script that is set to

72
scripts/notarize_darwin.sh Executable file
View File

@ -0,0 +1,72 @@
#!/usr/bin/env bash
# This script notarizes the provided zip file using an Apple Developer account.
#
# Usage: ./notarize_darwin.sh path/to/zipfile.zip
#
# The provided zip file must contain a coder binary that has already been signed
# using ./sign_darwin.sh.
#
# On success, all of the contained binaries inside the input zip file will
# notarized. This does not make any changes to the zip or contained files
# itself, but GateKeeper checks will pass for the binaries inside the zip file
# as long as the device is connected to the internet to download the
# notarization ticket from Apple.
#
# You can check if a binary is notarized by running the following command on a
# Mac:
# spctl --assess -vvv -t install path/to/binary
#
# Depends on the rcodesign utility. Requires the following environment variables
# to be set:
# - $AC_APIKEY_ISSUER_ID: The issuer UUID of the Apple App Store Connect API
# key.
# - $AC_APIKEY_ID: The key ID of the Apple App Store Connect API key.
# - $AC_APIKEY_FILE: The path to the private key P8 file of the Apple App Store
# Connect API key.
set -euo pipefail
# shellcheck source=scripts/lib.sh
source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
# Check dependencies
dependencies rcodesign
requiredenvs AC_APIKEY_ISSUER_ID AC_APIKEY_ID AC_APIKEY_FILE
# Encode the notarization key components into a JSON file for easily calling
# `rcodesign notary-submit`.
key_file="$(mktemp)"
chmod 600 "$key_file"
trap 'rm -f "$key_file"' EXIT
rcodesign encode-app-store-connect-api-key \
"$AC_APIKEY_ISSUER_ID" \
"$AC_APIKEY_ID" \
"$AC_APIKEY_FILE" \
>"$key_file"
# The notarization process is very fragile and heavily dependent on Apple's
# notarization server not returning server errors, so we retry this step twice
# with a delay of 30 seconds between attempts.
rc=0
for i in $(seq 1 2); do
# -v is quite verbose, the default output is pretty good on it's own. Adding
# -v makes it dump the credentials used for uploading to Apple's S3 bucket.
rcodesign notary-submit \
--api-key-path "$key_file" \
--wait \
"$@" \
1>&2 && rc=0 && break || rc=$?
log "rcodesign exit code: $rc"
if [[ $i -lt 5 ]]; then
log
log "Retrying notarization in 30 seconds"
log
sleep 30
else
log
log "Giving up :("
fi
done
exit $rc

View File

@ -1,62 +1,39 @@
#!/usr/bin/env bash
# This script notarizes the provided zip file.
# This script signs the provided darwin binary with an Apple Developer
# certificate.
#
# Usage: ./publish_release.sh [--version 1.2.3] [--dry-run] path/to/asset1 path/to/asset2 ...
# Usage: ./sign_darwin.sh path/to/binary
#
# The provided zip file must contain a coder binary that has already been signed
# using the codesign tool.
# On success, the input file will be signed using the Apple Developer
# certificate.
#
# On success, the input file will be successfully signed and notarized.
# You can check if a binary is signed by running the following command on a Mac:
# codesign -dvv path/to/binary
#
# Depends on codesign and gon utilities. Requires the $AC_APPLICATION_IDENTITY
# environment variable to be set.
# You can also run the following command to verify the signature on other
# systems, but it may be less accurate:
# rcodesign verify path/to/binary
#
# Depends on the rcodesign utility. Requires the following environment variables
# to be set:
# - $AC_CERTIFICATE_FILE: The path to the Apple Developer P12 certificate file.
# - $AC_CERTIFICATE_PASSWORD_FILE: The path to the file containing the password
# for the Apple Developer certificate.
set -euo pipefail
# shellcheck source=scripts/lib.sh
source "$(dirname "${BASH_SOURCE[0]}")/lib.sh"
if [[ "${AC_APPLICATION_IDENTITY:-}" == "" ]]; then
error "AC_APPLICATION_IDENTITY must be set for ./sign_darwin.sh"
fi
# Check dependencies
dependencies jq codesign gon
dependencies rcodesign
requiredenvs AC_CERTIFICATE_FILE AC_CERTIFICATE_PASSWORD_FILE
output_path="$1"
# Create the gon config.
config="$(mktemp -d)/gon.json"
jq -r --null-input --arg path "$output_path" '{
"notarize": [
{
"path": $path,
"bundle_id": "com.coder.cli"
}
]
}' >"$config"
# Sign the zip file with our certificate.
codesign -s "$AC_APPLICATION_IDENTITY" -f -v --timestamp --options runtime "$output_path"
# Notarize the signed zip file.
#
# The notarization process is very fragile and heavily dependent on Apple's
# notarization server not returning server errors, so we retry this step twice
# with a delay of a minute between attempts.
rc=0
for i in $(seq 1 2); do
gon "$config" && rc=0 && break || rc=$?
log "gon exit code: $rc"
if [[ $i -lt 5 ]]; then
log
log "Retrying notarization in 60 seconds"
log
sleep 60
else
log
log "Giving up :("
fi
done
exit $rc
# -v is quite verbose, the default output is pretty good on it's own.
rcodesign sign \
--binary-identifier "com.coder.cli" \
--p12-file "$AC_CERTIFICATE_FILE" \
--p12-password-file "$AC_CERTIFICATE_PASSWORD_FILE" \
--code-signature-flags runtime \
"$@" \
1>&2